fix(core): target defaults should be able to apply to multiple targets with the same executor (#21438)

This commit is contained in:
Craigory Coppola 2024-02-01 18:30:43 -06:00 committed by GitHub
parent 2781800e36
commit c4b9a82319
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 110 additions and 33 deletions

View File

@ -233,4 +233,67 @@ describe('target-defaults plugin', () => {
}
`);
});
describe('executor key', () => {
it('should support multiple targets with the same executor', () => {
memfs.vol.fromJSON(
{
'project.json': JSON.stringify({
name: 'root',
targets: {
echo: {
executor: 'nx:run-commands',
options: {
command: 'echo 1',
},
},
echo2: {
executor: 'nx:run-commands',
options: {
command: 'echo 2',
},
},
},
}),
},
'/root'
);
context.nxJsonConfiguration.targetDefaults = {
'nx:run-commands': {
options: {
cwd: '{projectRoot}',
},
},
};
expect(createNodesFn('project.json', undefined, context))
.toMatchInlineSnapshot(`
{
"projects": {
".": {
"targets": {
"echo": {
"options": {
"cwd": "{projectRoot}",
},
},
"echo2": {
"options": {
"cwd": "{projectRoot}",
},
},
"nx:run-commands": {
"options": {
"cwd": "{projectRoot}",
},
Symbol(ONLY_MODIFIES_EXISTING_TARGET): true,
},
},
},
},
}
`);
});
});
});

View File

@ -67,6 +67,7 @@ export const TargetDefaultsPlugin: NxPluginV2 = {
return true;
}),
...Object.keys(projectJson?.targets ?? {}),
...Object.keys(packageJson?.nx?.targets ?? {}),
]);
const executorToTargetMap = getExecutorToTargetMap(
@ -74,27 +75,31 @@ export const TargetDefaultsPlugin: NxPluginV2 = {
projectJson
);
const newTargets: Record<
const modifiedTargets: Record<
string,
TargetConfiguration & { [ONLY_MODIFIES_EXISTING_TARGET]?: boolean }
> = {};
for (const defaultSpecifier in targetDefaults) {
const targetName =
executorToTargetMap.get(defaultSpecifier) ?? defaultSpecifier;
newTargets[targetName] = structuredClone(
targetDefaults[defaultSpecifier]
);
// TODO: Remove this after we figure out a way to define new targets
// in target defaults
if (!projectDefinedTargets.has(targetName)) {
newTargets[targetName][ONLY_MODIFIES_EXISTING_TARGET] = true;
const targetNames =
executorToTargetMap.get(defaultSpecifier) ?? new Set();
targetNames.add(defaultSpecifier);
for (const targetName of targetNames) {
modifiedTargets[targetName] = structuredClone(
targetDefaults[defaultSpecifier]
);
// TODO: Remove this after we figure out a way to define new targets
// in target defaults
if (!projectDefinedTargets.has(targetName)) {
modifiedTargets[targetName][ONLY_MODIFIES_EXISTING_TARGET] = true;
}
}
}
return {
projects: {
[root]: {
targets: newTargets,
targets: modifiedTargets,
},
},
};
@ -106,20 +111,20 @@ function getExecutorToTargetMap(
packageJson: PackageJson,
projectJson: ProjectConfiguration
) {
const executorToTargetMap = new Map<string, string>();
if (packageJson?.scripts) {
for (const script in packageJson.scripts) {
executorToTargetMap.set('nx:run-script', script);
}
}
if (projectJson?.targets) {
for (const target in projectJson.targets) {
if (projectJson.targets[target].executor) {
executorToTargetMap.set(projectJson.targets[target].executor, target);
} else if (projectJson.targets[target].command) {
executorToTargetMap.set('nx:run-commands', target);
}
}
const executorToTargetMap = new Map<string, Set<string>>();
const targets = Object.keys({
...projectJson?.targets,
...packageJson?.scripts,
...packageJson?.nx?.targets,
});
for (const target of targets) {
const executor =
projectJson?.targets?.[target]?.executor ??
packageJson?.nx?.targets?.[target]?.executor ??
'nx:run-script';
const targetsForExecutor = executorToTargetMap.get(executor) ?? new Set();
targetsForExecutor.add(target);
executorToTargetMap.set(executor, targetsForExecutor);
}
return executorToTargetMap;
}

View File

@ -403,6 +403,21 @@ describe('project-configuration-utils', () => {
`);
});
});
describe('cache', () => {
it('should not be merged for incompatible targets', () => {
const result = mergeTargetConfigurations(
{
executor: 'foo',
},
{
executor: 'bar',
cache: true,
}
);
expect(result.cache).not.toBeDefined();
});
});
});
describe('mergeProjectConfigurationIntoRootMap', () => {

View File

@ -4,7 +4,6 @@ import { readJsonFile } from './fileutils';
import {
buildTargetFromScript,
PackageJson,
PackageJsonTargetConfiguration,
readModulePackageJson,
readTargetsFromPackageJson,
} from './package-json';
@ -36,7 +35,7 @@ describe('buildTargetFromScript', () => {
script: 'other',
},
executor: 'custom:execute',
} as PackageJsonTargetConfiguration,
},
},
});

View File

@ -7,16 +7,11 @@ import {
import { readJsonFile } from './fileutils';
import { getNxRequirePaths } from './installation-directory';
export type PackageJsonTargetConfiguration = Omit<
TargetConfiguration,
'executor'
>;
export interface NxProjectPackageJsonConfiguration {
implicitDependencies?: string[];
tags?: string[];
namedInputs?: { [inputName: string]: (string | InputDefinition)[] };
targets?: Record<string, PackageJsonTargetConfiguration>;
targets?: Record<string, TargetConfiguration>;
includedScripts?: string[];
}