Skip to content

Commit 0ec097f

Browse files
MaxKlessFrozenPandaz
authored andcommitted
feat(core): add .nx/polygraph to gitignore in migration and caia (#34659)
(cherry picked from commit aa4f47e)
1 parent 465a6ad commit 0ec097f

6 files changed

Lines changed: 174 additions & 0 deletions

File tree

packages/nx/migrations.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@
136136
"version": "22.1.0-beta.5",
137137
"description": "Updates the nx wrapper.",
138138
"implementation": "./src/migrations/update-22-1-0/update-nx-wrapper"
139+
},
140+
"22-7-0-add-polygraph-to-git-ignore": {
141+
"cli": "nx",
142+
"version": "22.7.0-beta.0",
143+
"description": "Adds .nx/polygraph to .gitignore",
144+
"implementation": "./src/migrations/update-22-7-0/add-polygraph-to-git-ignore"
139145
}
140146
}
141147
}

packages/nx/src/ai/set-up-ai-agents/set-up-ai-agents.spec.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,64 @@ describe('setup-ai-agents generator', () => {
632632
});
633633
});
634634

635+
describe('gitignore', () => {
636+
it('should add .nx/polygraph to .gitignore when it does not exist', async () => {
637+
const options: SetupAiAgentsGeneratorSchema = {
638+
directory: '.',
639+
agents: ['claude'],
640+
};
641+
642+
await setupAiAgentsGenerator(tree, options);
643+
644+
const gitignore = tree.read('.gitignore')?.toString();
645+
expect(gitignore).toContain('.nx/polygraph');
646+
});
647+
648+
it('should add .nx/polygraph to existing .gitignore', async () => {
649+
const options: SetupAiAgentsGeneratorSchema = {
650+
directory: '.',
651+
agents: ['claude'],
652+
};
653+
654+
tree.write('.gitignore', 'node_modules\ndist\n');
655+
656+
await setupAiAgentsGenerator(tree, options);
657+
658+
const gitignore = tree.read('.gitignore')?.toString();
659+
expect(gitignore).toContain('node_modules');
660+
expect(gitignore).toContain('.nx/polygraph');
661+
});
662+
663+
it('should not duplicate if .nx/polygraph is already present', async () => {
664+
const options: SetupAiAgentsGeneratorSchema = {
665+
directory: '.',
666+
agents: ['claude'],
667+
};
668+
669+
tree.write('.gitignore', 'node_modules\n.nx/polygraph\n');
670+
671+
await setupAiAgentsGenerator(tree, options);
672+
673+
const gitignore = tree.read('.gitignore')?.toString();
674+
const matches = gitignore.match(/\.nx\/polygraph/g);
675+
expect(matches).toHaveLength(1);
676+
});
677+
678+
it('should not add if a broader pattern already covers it', async () => {
679+
const options: SetupAiAgentsGeneratorSchema = {
680+
directory: '.',
681+
agents: ['claude'],
682+
};
683+
684+
tree.write('.gitignore', '.nx/\n');
685+
686+
await setupAiAgentsGenerator(tree, options);
687+
688+
const gitignore = tree.read('.gitignore')?.toString();
689+
expect(gitignore).not.toContain('.nx/polygraph');
690+
});
691+
});
692+
635693
describe('empty agents array', () => {
636694
it('should NOT generate any files when agents array is empty', async () => {
637695
const options: SetupAiAgentsGeneratorSchema = {

packages/nx/src/ai/set-up-ai-agents/set-up-ai-agents.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
installPackageToTmp,
2727
readModulePackageJson,
2828
} from '../../utils/package-json';
29+
import { addEntryToGitIgnore } from '../../utils/ignore';
2930
import { ensurePackageHasProvenance } from '../../utils/provenance';
3031
import { workspaceRoot } from '../../utils/workspace-root';
3132
import {
@@ -287,6 +288,12 @@ export async function setupAiAgentsGeneratorImpl(
287288
}
288289
}
289290

291+
addEntryToGitIgnore(
292+
tree,
293+
join(options.directory, '.gitignore'),
294+
'.nx/polygraph'
295+
);
296+
290297
await formatChangedFilesWithPrettierIfAvailable(tree);
291298

292299
// we use the check variable to determine if we should actually make changes or just report what would be changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { createTreeWithEmptyWorkspace } from '../../generators/testing-utils/create-tree-with-empty-workspace';
2+
import { Tree } from '../../generators/tree';
3+
import addPolygraphToGitIgnore from './add-polygraph-to-git-ignore';
4+
5+
describe('add-polygraph-to-git-ignore migration', () => {
6+
let tree: Tree;
7+
8+
beforeEach(() => {
9+
tree = createTreeWithEmptyWorkspace();
10+
});
11+
12+
it('should not create .gitignore if it does not exist', () => {
13+
tree.delete('.gitignore');
14+
15+
addPolygraphToGitIgnore(tree);
16+
17+
expect(tree.exists('.gitignore')).toBe(false);
18+
});
19+
20+
it('should add .nx/polygraph to existing .gitignore', () => {
21+
tree.write('.gitignore', 'node_modules\ndist\n');
22+
23+
addPolygraphToGitIgnore(tree);
24+
25+
const gitignore = tree.read('.gitignore')?.toString();
26+
expect(gitignore).toContain('node_modules');
27+
expect(gitignore).toContain('.nx/polygraph');
28+
});
29+
30+
it('should not duplicate if .nx/polygraph is already present', () => {
31+
tree.write('.gitignore', 'node_modules\n.nx/polygraph\n');
32+
33+
addPolygraphToGitIgnore(tree);
34+
35+
const gitignore = tree.read('.gitignore')?.toString();
36+
const matches = gitignore.match(/\.nx\/polygraph/g);
37+
expect(matches).toHaveLength(1);
38+
});
39+
40+
it('should not add if a broader pattern already covers it', () => {
41+
tree.write('.gitignore', '.nx/\n');
42+
43+
addPolygraphToGitIgnore(tree);
44+
45+
const gitignore = tree.read('.gitignore')?.toString();
46+
expect(gitignore).not.toContain('.nx/polygraph');
47+
});
48+
49+
it('should skip for lerna workspaces without nx.json', () => {
50+
tree.write('.gitignore', 'node_modules\n');
51+
tree.write('lerna.json', '{}');
52+
tree.delete('nx.json');
53+
54+
addPolygraphToGitIgnore(tree);
55+
56+
const gitignore = tree.read('.gitignore')?.toString();
57+
expect(gitignore).not.toContain('.nx/polygraph');
58+
});
59+
60+
it('should not skip for lerna workspaces that also have nx.json', () => {
61+
tree.write('.gitignore', 'node_modules\n');
62+
tree.write('lerna.json', '{}');
63+
// nx.json already exists from createTreeWithEmptyWorkspace
64+
65+
addPolygraphToGitIgnore(tree);
66+
67+
const gitignore = tree.read('.gitignore')?.toString();
68+
expect(gitignore).toContain('.nx/polygraph');
69+
});
70+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Tree } from '../../generators/tree';
2+
import { addEntryToGitIgnore } from '../../utils/ignore';
3+
4+
export default function addPolygraphToGitIgnore(tree: Tree) {
5+
if (!tree.exists('.gitignore')) {
6+
return;
7+
}
8+
// Lerna users that don't use nx.json may not expect .nx directory changes
9+
if (tree.exists('lerna.json') && !tree.exists('nx.json')) {
10+
return;
11+
}
12+
addEntryToGitIgnore(tree, '.gitignore', '.nx/polygraph');
13+
}

packages/nx/src/utils/ignore.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,23 @@ export function getIgnoreObjectForTree(tree: Tree) {
2626

2727
return ig;
2828
}
29+
30+
/**
31+
* Adds an entry to a .gitignore file if it's not already covered by existing patterns.
32+
* Creates the file if it doesn't exist.
33+
*/
34+
export function addEntryToGitIgnore(
35+
tree: Tree,
36+
gitignorePath: string,
37+
entry: string
38+
) {
39+
const gitignore = tree.exists(gitignorePath)
40+
? tree.read(gitignorePath, 'utf-8')
41+
: '';
42+
const ig = ignore();
43+
ig.add(gitignore);
44+
if (!ig.ignores(entry)) {
45+
const updatedLines = gitignore.length ? [gitignore, entry] : [entry];
46+
tree.write(gitignorePath, updatedLines.join('\n'));
47+
}
48+
}

0 commit comments

Comments
 (0)