Skip to content

Commit a4ea9bc

Browse files
AgentEnderFrozenPandaz
authored andcommitted
fix(core): don't cache full dependency configuration when expanding target name (#27308)
<!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> <!-- If this is a particularly complex change or feature addition, you can request a dedicated Nx release for this pull request branch. Mention someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they will confirm if the PR warrants its own release for testing purposes, and generate it for you if appropriate. --> ## Current Behavior There is a cache that maps target pattern -> dependency configuration, but the dependency configuration contains more than just the target name. This results in retrieving cached dependency configurations that contain the wrong projects to run. ## Expected Behavior The cache maps target pattern -> target names, which we can then map to the full dependency configuration with the extra info we know. ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes # (cherry picked from commit 26f46c2)
1 parent aba87f8 commit a4ea9bc

File tree

5 files changed

+547
-16
lines changed

5 files changed

+547
-16
lines changed

packages/nx/src/project-graph/utils/project-configuration-utils.spec.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1878,6 +1878,46 @@ describe('project-configuration-utils', () => {
18781878
// other source map entries should be left unchanged
18791879
expect(sourceMap['targets']).toEqual(['dummy', 'dummy.ts']);
18801880
});
1881+
1882+
it('should not overwrite dependsOn', () => {
1883+
const sourceMap: Record<string, SourceInformation> = {
1884+
targets: ['dummy', 'dummy.ts'],
1885+
'targets.build': ['dummy', 'dummy.ts'],
1886+
'targets.build.options': ['dummy', 'dummy.ts'],
1887+
'targets.build.options.command': ['dummy', 'dummy.ts'],
1888+
'targets.build.options.cwd': ['project.json', 'nx/project-json'],
1889+
'targets.build.dependsOn': ['project.json', 'nx/project-json'],
1890+
};
1891+
const result = mergeTargetDefaultWithTargetDefinition(
1892+
'build',
1893+
{
1894+
name: 'myapp',
1895+
root: 'apps/myapp',
1896+
targets: {
1897+
build: {
1898+
executor: 'nx:run-commands',
1899+
options: {
1900+
command: 'echo',
1901+
cwd: '{workspaceRoot}',
1902+
},
1903+
dependsOn: [],
1904+
},
1905+
},
1906+
},
1907+
{
1908+
options: {
1909+
command: 'tsc',
1910+
cwd: 'apps/myapp',
1911+
},
1912+
dependsOn: ['^build'],
1913+
},
1914+
sourceMap
1915+
);
1916+
1917+
// Command was defined by a core plugin so it should
1918+
// not be replaced by target default
1919+
expect(result.dependsOn).toEqual([]);
1920+
});
18811921
});
18821922
});
18831923

packages/nx/src/tasks-runner/create-task-graph.spec.ts

Lines changed: 313 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import { DependencyType, ProjectGraph } from '../config/project-graph';
1+
import {
2+
DependencyType,
3+
ProjectGraph,
4+
ProjectGraphProjectNode,
5+
} from '../config/project-graph';
6+
import { ProjectConfiguration } from '../config/workspace-json-project-json';
27
import { createTaskGraph } from './create-task-graph';
38

49
describe('createTaskGraph', () => {
@@ -1677,4 +1682,311 @@ describe('createTaskGraph', () => {
16771682
'lib3:build',
16781683
]);
16791684
});
1685+
1686+
it('should handle multiple dependsOn task groups', () => {
1687+
const taskGraph = createTaskGraph(
1688+
{
1689+
nodes: {
1690+
a: {
1691+
name: 'a',
1692+
type: 'app',
1693+
data: {
1694+
root: 'a-root',
1695+
targets: {
1696+
deploy: {
1697+
executor: 'nx:run-commands',
1698+
dependsOn: [{ target: 'build' }],
1699+
},
1700+
build: {
1701+
executor: 'nx:run-commands',
1702+
dependsOn: [{ target: 'compile' }],
1703+
},
1704+
compile: {
1705+
executor: 'nx:run-commands',
1706+
dependsOn: ['^compile'],
1707+
},
1708+
},
1709+
},
1710+
},
1711+
b: {
1712+
name: 'b',
1713+
type: 'lib',
1714+
data: {
1715+
root: 'b-root',
1716+
targets: {
1717+
deploy: {
1718+
executor: 'nx:run-commands',
1719+
dependsOn: [{ target: 'build' }],
1720+
},
1721+
build: {
1722+
executor: 'nx:run-commands',
1723+
dependsOn: [{ target: 'compile' }],
1724+
},
1725+
compile: {
1726+
executor: 'nx:run-commands',
1727+
dependsOn: ['^compile'],
1728+
},
1729+
},
1730+
},
1731+
},
1732+
c: {
1733+
name: 'c',
1734+
type: 'lib',
1735+
data: {
1736+
root: 'c-root',
1737+
targets: {
1738+
deploy: {
1739+
executor: 'nx:run-commands',
1740+
dependsOn: [{ target: 'build' }],
1741+
},
1742+
build: {
1743+
executor: 'nx:run-commands',
1744+
dependsOn: [{ target: 'compile' }],
1745+
},
1746+
compile: {
1747+
executor: 'nx:run-commands',
1748+
dependsOn: ['^compile'],
1749+
},
1750+
},
1751+
},
1752+
},
1753+
d: {
1754+
name: 'd',
1755+
type: 'lib',
1756+
data: {
1757+
root: 'd-root',
1758+
targets: {
1759+
deploy: {
1760+
executor: 'nx:run-commands',
1761+
dependsOn: [{ target: 'build' }],
1762+
},
1763+
build: {
1764+
executor: 'nx:run-commands',
1765+
dependsOn: [{ target: 'compile' }],
1766+
},
1767+
compile: {
1768+
executor: 'nx:run-commands',
1769+
dependsOn: ['^compile'],
1770+
},
1771+
},
1772+
},
1773+
},
1774+
},
1775+
dependencies: {
1776+
a: [],
1777+
b: [
1778+
{
1779+
source: 'b',
1780+
target: 'd',
1781+
type: 'static',
1782+
},
1783+
],
1784+
c: [
1785+
{
1786+
source: 'c',
1787+
target: 'd',
1788+
type: 'static',
1789+
},
1790+
],
1791+
d: [],
1792+
},
1793+
},
1794+
{},
1795+
['a', 'b'],
1796+
['deploy'],
1797+
null,
1798+
{}
1799+
);
1800+
1801+
expect(taskGraph.dependencies['a:deploy']).toEqual(['a:build']);
1802+
expect(taskGraph.dependencies['a:build']).toEqual(['a:compile']);
1803+
expect(taskGraph.dependencies['a:compile']).toEqual([]);
1804+
expect(taskGraph.dependencies['b:deploy']).toEqual(['b:build']);
1805+
expect(taskGraph.dependencies['b:build']).toEqual(['b:compile']);
1806+
expect(taskGraph.dependencies['b:compile']).toEqual(['d:compile']);
1807+
expect(taskGraph.dependencies['d:compile']).toEqual([]);
1808+
});
1809+
1810+
it('should handle deep dependsOn groups', () => {
1811+
const taskGraph = createTaskGraph(
1812+
new GraphBuilder()
1813+
.addProjectConfiguration({
1814+
name: 'app-1',
1815+
targets: {
1816+
deploy: {
1817+
executor: 'foo',
1818+
dependsOn: ['build'],
1819+
},
1820+
build: {
1821+
executor: 'foo',
1822+
dependsOn: ['^build', 'codegen'],
1823+
},
1824+
codegen: {
1825+
executor: 'foo',
1826+
},
1827+
},
1828+
})
1829+
.addProjectConfiguration({
1830+
name: 'app-2',
1831+
targets: {
1832+
deploy: {
1833+
executor: 'foo',
1834+
dependsOn: ['build'],
1835+
},
1836+
build: {
1837+
executor: 'foo',
1838+
dependsOn: [
1839+
'^build',
1840+
{
1841+
target: 'codegen',
1842+
params: 'forward',
1843+
},
1844+
],
1845+
},
1846+
codegen: {
1847+
executor: 'foo',
1848+
},
1849+
},
1850+
})
1851+
.addProjectConfiguration({
1852+
name: 'app-3',
1853+
targets: {
1854+
deploy: {
1855+
executor: 'foo',
1856+
dependsOn: ['build'],
1857+
},
1858+
build: {
1859+
executor: 'foo',
1860+
dependsOn: [
1861+
'^build',
1862+
{
1863+
target: 'codegen',
1864+
params: 'forward',
1865+
},
1866+
],
1867+
},
1868+
codegen: {
1869+
executor: 'foo',
1870+
},
1871+
},
1872+
})
1873+
.addProjectConfiguration({
1874+
name: 'lib-1',
1875+
targets: {
1876+
build: {
1877+
executor: 'foo',
1878+
dependsOn: ['^build', 'codegen'],
1879+
},
1880+
codegen: {
1881+
executor: 'foo',
1882+
},
1883+
},
1884+
})
1885+
.addProjectConfiguration({
1886+
name: 'lib-2',
1887+
targets: {
1888+
build: {
1889+
executor: 'foo',
1890+
dependsOn: ['^build', 'codegen'],
1891+
},
1892+
codegen: {
1893+
executor: 'foo',
1894+
},
1895+
},
1896+
})
1897+
.addDependencies({
1898+
'app-1': ['lib-1'],
1899+
'app-2': ['lib-2'],
1900+
'app-3': ['lib-2'],
1901+
'lib-1': ['lib-2'],
1902+
'lib-2': [],
1903+
})
1904+
.build(),
1905+
{},
1906+
['app-1', 'app-2', 'app-3'],
1907+
['deploy', 'test'],
1908+
null,
1909+
{},
1910+
false
1911+
);
1912+
1913+
expect(taskGraph.dependencies).toMatchInlineSnapshot(`
1914+
{
1915+
"app-1:build": [
1916+
"lib-1:build",
1917+
"app-1:codegen",
1918+
],
1919+
"app-1:codegen": [],
1920+
"app-1:deploy": [
1921+
"app-1:build",
1922+
],
1923+
"app-2:build": [
1924+
"lib-2:build",
1925+
"app-2:codegen",
1926+
],
1927+
"app-2:codegen": [],
1928+
"app-2:deploy": [
1929+
"app-2:build",
1930+
],
1931+
"app-3:build": [
1932+
"lib-2:build",
1933+
"app-3:codegen",
1934+
],
1935+
"app-3:codegen": [],
1936+
"app-3:deploy": [
1937+
"app-3:build",
1938+
],
1939+
"lib-1:build": [
1940+
"lib-2:build",
1941+
"lib-1:codegen",
1942+
],
1943+
"lib-1:codegen": [],
1944+
"lib-2:build": [
1945+
"lib-2:codegen",
1946+
],
1947+
"lib-2:codegen": [],
1948+
}
1949+
`);
1950+
});
16801951
});
1952+
1953+
class GraphBuilder {
1954+
nodes: Record<string, ProjectGraphProjectNode> = {};
1955+
deps: Record<string, string[]> = {};
1956+
1957+
addProjectConfiguration(
1958+
project: Omit<ProjectConfiguration, 'root'>,
1959+
type?: ProjectGraph['nodes'][string]['type']
1960+
) {
1961+
const t = type ?? 'lib';
1962+
this.nodes[project.name] = {
1963+
name: project.name,
1964+
type: t,
1965+
data: { ...project, root: `${t}/${project.name}` },
1966+
};
1967+
return this;
1968+
}
1969+
1970+
addDependencies(deps: Record<string, string[]>) {
1971+
for (const source of Object.keys(deps)) {
1972+
if (!this.deps[source]) {
1973+
this.deps[source] = [];
1974+
}
1975+
this.deps[source].push(...deps[source]);
1976+
}
1977+
return this;
1978+
}
1979+
1980+
build(): ProjectGraph {
1981+
return {
1982+
nodes: this.nodes,
1983+
dependencies: Object.fromEntries(
1984+
Object.entries(this.deps).map(([k, v]) => [
1985+
k,
1986+
v.map((d) => ({ source: k, target: d, type: 'static' })),
1987+
])
1988+
),
1989+
externalNodes: {},
1990+
};
1991+
}
1992+
}

0 commit comments

Comments
 (0)