Skip to content

Commit

Permalink
fix(core): do not assume workspace inputs cause all projects to be af… (
Browse files Browse the repository at this point in the history
  • Loading branch information
FrozenPandaz committed Apr 2, 2024
1 parent 5f255c5 commit 9419bad
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { WholeFileChange } from '../../file-utils';
import {
getTouchedProjects,
getImplicitlyTouchedProjects,
extractGlobalFilesFromInputs,
} from './workspace-projects';

function getFileChanges(files: string[]) {
Expand Down Expand Up @@ -84,6 +83,9 @@ describe('getImplicitlyTouchedProjects', () => {
beforeEach(() => {
nxJson = {
npmScope: 'nrwl',
namedInputs: {
files: ['{workspaceRoot}/a.txt'],
},
projects: {},
};
});
Expand All @@ -95,6 +97,11 @@ describe('getImplicitlyTouchedProjects', () => {
namedInputs: {
projectSpecificFiles: ['{workspaceRoot}/a.txt'],
},
targets: {
build: {
inputs: ['projectSpecificFiles'],
},
},
},
b: {
root: 'b',
Expand Down Expand Up @@ -125,25 +132,44 @@ describe('getImplicitlyTouchedProjects', () => {
'a',
]);
});
});

describe('extractGlobalFilesFromInputs', () => {
it('should return list of global files from nx.json', () => {
const globalFiles = extractGlobalFilesFromInputs({
namedInputs: {
one: [
'{workspaceRoot}/global1.txt',
{ fileset: '{workspaceRoot}/global2.txt' },
'{projectRoot}/local.txt',
],
it('should return projects which have touched files in their target inputs which are named inputs defined in nx.json', () => {
const graph = buildProjectGraphNodes({
a: {
root: 'a',
targets: {
build: {
inputs: ['files'],
},
},
},
targetDefaults: {
build: {
inputs: ['{workspaceRoot}/global3.txt'],
b: {
root: 'b',
},
});
let fileChanges = getFileChanges(['a.txt']);
expect(getImplicitlyTouchedProjects(fileChanges, graph, nxJson)).toEqual([
'a',
]);
});

it('should not return projects which have touched files inputs which are not used by its targets', () => {
const graph = buildProjectGraphNodes({
a: {
root: 'a',
namedInputs: {
files: ['{workspaceRoot}/a.txt'],
},
targets: {},
},
b: {
root: 'b',
},
});
expect(globalFiles).toEqual(['global1.txt', 'global2.txt', 'global3.txt']);
let fileChanges = getFileChanges(['a.txt']);
expect(getImplicitlyTouchedProjects(fileChanges, graph, nxJson)).toEqual(
[]
);
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { minimatch } from 'minimatch';
import { TouchedProjectLocator } from '../affected-project-graph-models';
import { NxJsonConfiguration } from '../../../config/nx-json';
import {
createProjectRootMappings,
findProjectForPath,
} from '../../utils/find-project-for-path';
import { InputDefinition } from '../../../config/workspace-json-project-json';

export const getTouchedProjects: TouchedProjectLocator = (
touchedFiles,
Expand All @@ -27,22 +27,21 @@ export const getImplicitlyTouchedProjects: TouchedProjectLocator = (
nxJson
): string[] => {
const implicits = {};
const globalFiles = [...extractGlobalFilesFromInputs(nxJson), 'nx.json'];
globalFiles.forEach((file) => {
implicits[file] = '*' as any;
});

Object.values(projectGraphNodes || {}).forEach((node) => {
[
...extractFilesFromNamedInputs(node.data.namedInputs),
...extractFilesFromTargetInputs(node.data.targets),
].forEach((input) => {
implicits[input] ??= [];
const namedInputs = {
...nxJson.namedInputs,
...node.data.namedInputs,
};
extractFilesFromTargetInputs(node.data.targets, namedInputs).forEach(
(input) => {
implicits[input] ??= [];

if (Array.isArray(implicits[input])) {
implicits[input].push(node.name);
if (Array.isArray(implicits[input])) {
implicits[input].push(node.name);
}
}
});
);
});

const touched = new Set<string>();
Expand All @@ -66,35 +65,33 @@ export const getImplicitlyTouchedProjects: TouchedProjectLocator = (
return Array.from(touched);
};

export function extractGlobalFilesFromInputs(nxJson: NxJsonConfiguration) {
const globalFiles = [];
globalFiles.push(...extractFilesFromNamedInputs(nxJson.namedInputs));
globalFiles.push(...extractFilesFromTargetInputs(nxJson.targetDefaults));
return globalFiles;
}

function extractFilesFromNamedInputs(namedInputs: any) {
const files = [];
for (const inputs of Object.values(namedInputs || {})) {
files.push(...extractFilesFromInputs(inputs));
}
return files;
}

function extractFilesFromTargetInputs(targets: any) {
function extractFilesFromTargetInputs(
targets: any,
namedInputs: Record<string, Array<string | InputDefinition>>
) {
const globalFiles = [];
for (const target of Object.values(targets || {})) {
if ((target as any).inputs) {
globalFiles.push(...extractFilesFromInputs((target as any).inputs));
globalFiles.push(
...extractFilesFromInputs((target as any).inputs, namedInputs)
);
}
}
return globalFiles;
}

function extractFilesFromInputs(inputs: any) {
function extractFilesFromInputs(
inputs: any,
namedInputs: Record<string, Array<string | InputDefinition>>
) {
const globalFiles = [];
for (const input of inputs) {
if (typeof input === 'string' && input.startsWith('{workspaceRoot}/')) {
if (typeof input === 'string' && input in namedInputs) {
return extractFilesFromInputs(namedInputs[input], namedInputs);
} else if (
typeof input === 'string' &&
input.startsWith('{workspaceRoot}/')
) {
globalFiles.push(input.substring('{workspaceRoot}/'.length));
} else if (input.fileset && input.fileset.startsWith('{workspaceRoot}/')) {
globalFiles.push(input.fileset.substring('{workspaceRoot}/'.length));
Expand Down

0 comments on commit 9419bad

Please sign in to comment.