diff --git a/docs/generated/manifests/nx-api.json b/docs/generated/manifests/nx-api.json index c7588f5e82..6cbe1cf5fb 100644 --- a/docs/generated/manifests/nx-api.json +++ b/docs/generated/manifests/nx-api.json @@ -3414,6 +3414,16 @@ } }, "migrations": { + "/nx-api/nx/migrations/21-1-0-add-ignore-entries-for-nx-rule-files": { + "description": "Adds **/nx-rules.mdc and **/nx.instructions.md to .gitignore if not present", + "file": "generated/packages/nx/migrations/21-1-0-add-ignore-entries-for-nx-rule-files.json", + "hidden": false, + "name": "21-1-0-add-ignore-entries-for-nx-rule-files", + "version": "21.1.0-beta.2", + "originalFilePath": "/packages/nx", + "path": "/nx-api/nx/migrations/21-1-0-add-ignore-entries-for-nx-rule-files", + "type": "migration" + }, "/nx-api/nx/migrations/release-version-config-changes": { "description": "Updates release version config based on the breaking changes in Nx v21", "file": "generated/packages/nx/migrations/release-version-config-changes.json", diff --git a/docs/generated/packages-metadata.json b/docs/generated/packages-metadata.json index 1079d7dba8..da9e6bf084 100644 --- a/docs/generated/packages-metadata.json +++ b/docs/generated/packages-metadata.json @@ -3390,6 +3390,16 @@ } ], "migrations": [ + { + "description": "Adds **/nx-rules.mdc and **/nx.instructions.md to .gitignore if not present", + "file": "generated/packages/nx/migrations/21-1-0-add-ignore-entries-for-nx-rule-files.json", + "hidden": false, + "name": "21-1-0-add-ignore-entries-for-nx-rule-files", + "version": "21.1.0-beta.2", + "originalFilePath": "/packages/nx", + "path": "nx/migrations/21-1-0-add-ignore-entries-for-nx-rule-files", + "type": "migration" + }, { "description": "Updates release version config based on the breaking changes in Nx v21", "file": "generated/packages/nx/migrations/release-version-config-changes.json", diff --git a/docs/generated/packages/nx/migrations/21-1-0-add-ignore-entries-for-nx-rule-files.json b/docs/generated/packages/nx/migrations/21-1-0-add-ignore-entries-for-nx-rule-files.json new file mode 100644 index 0000000000..1a4c5386e7 --- /dev/null +++ b/docs/generated/packages/nx/migrations/21-1-0-add-ignore-entries-for-nx-rule-files.json @@ -0,0 +1,12 @@ +{ + "name": "21-1-0-add-ignore-entries-for-nx-rule-files", + "version": "21.1.0-beta.2", + "description": "Adds **/nx-rules.mdc and **/nx.instructions.md to .gitignore if not present", + "implementation": "/packages/nx/src/migrations/update-21-1-0/add-gitignore-entry.ts", + "aliases": [], + "hidden": false, + "path": "/packages/nx", + "schema": null, + "type": "migration", + "examplesFile": "" +} diff --git a/packages/nx/migrations.json b/packages/nx/migrations.json index 2d388d7c82..9b2d779417 100644 --- a/packages/nx/migrations.json +++ b/packages/nx/migrations.json @@ -83,6 +83,11 @@ "version": "21.0.0-beta.11", "description": "Updates release changelog config based on the breaking changes in Nx v21", "implementation": "./src/migrations/update-21-0-0/release-changelog-config-changes" + }, + "21-1-0-add-ignore-entries-for-nx-rule-files": { + "version": "21.1.0-beta.2", + "description": "Adds **/nx-rules.mdc and **/nx.instructions.md to .gitignore if not present", + "implementation": "./src/migrations/update-21-1-0/add-gitignore-entry" } } } diff --git a/packages/nx/src/command-line/init/implementation/utils.ts b/packages/nx/src/command-line/init/implementation/utils.ts index 5cda4869d2..61d5efd523 100644 --- a/packages/nx/src/command-line/init/implementation/utils.ts +++ b/packages/nx/src/command-line/init/implementation/utils.ts @@ -222,6 +222,21 @@ export function updateGitIgnore(root: string) { } lines.push('.nx/workspace-data'); } + if (!contents.includes('.cursor/rules/nx-rules.mdc')) { + if (!sepIncluded) { + lines.push('\n'); + sepIncluded = true; + } + lines.push('.cursor/rules/nx-rules.mdc'); + } + if (!contents.includes('.github/instructions/nx.instructions.md')) { + if (!sepIncluded) { + lines.push('\n'); + sepIncluded = true; + } + lines.push('.github/instructions/nx.instructions.md'); + } + writeFileSync(ignorePath, lines.join('\n'), 'utf-8'); } catch {} } diff --git a/packages/nx/src/migrations/update-21-1-0/add-gitignore-entry.spec.ts b/packages/nx/src/migrations/update-21-1-0/add-gitignore-entry.spec.ts new file mode 100644 index 0000000000..46ec2056a6 --- /dev/null +++ b/packages/nx/src/migrations/update-21-1-0/add-gitignore-entry.spec.ts @@ -0,0 +1,33 @@ +import { createTreeWithEmptyWorkspace } from '../../generators/testing-utils/create-tree-with-empty-workspace'; +import addGitignoreEntry from './add-gitignore-entry'; + +describe('addGitignoreEntry migration', () => { + it('should add .cursor/rules/nx-rules.mdc and .github/instructions/nx.instructions.md to .gitignore if not present', async () => { + const tree = createTreeWithEmptyWorkspace(); + tree.write('.gitignore', 'dist\nnode_modules\n'); + await addGitignoreEntry(tree); + const result = tree.read('.gitignore', 'utf-8'); + expect(result).toContain('.cursor/rules/nx-rules.mdc'); + expect(result).toContain('.github/instructions/nx.instructions.md'); + }); + + it('should not add duplicate entries if already present', async () => { + const tree = createTreeWithEmptyWorkspace(); + tree.write( + '.gitignore', + 'dist\n.cursor/rules/nx-rules.mdc\n.github/instructions/nx.instructions.md\n' + ); + await addGitignoreEntry(tree); + const result = tree.read('.gitignore', 'utf-8'); + expect(result.match(/\.cursor\/rules\/nx-rules\.mdc/g)?.length).toBe(1); + expect( + result.match(/\.github\/instructions\/nx\.instructions\.md/g)?.length + ).toBe(1); + }); + + it('should do nothing if .gitignore does not exist', async () => { + const tree = createTreeWithEmptyWorkspace(); + await addGitignoreEntry(tree); + expect(tree.exists('.gitignore')).toBe(false); + }); +}); diff --git a/packages/nx/src/migrations/update-21-1-0/add-gitignore-entry.ts b/packages/nx/src/migrations/update-21-1-0/add-gitignore-entry.ts new file mode 100644 index 0000000000..efe67ec1e3 --- /dev/null +++ b/packages/nx/src/migrations/update-21-1-0/add-gitignore-entry.ts @@ -0,0 +1,24 @@ +import { Tree } from '../../generators/tree'; +import ignore from 'ignore'; + +export default async function addGitignoreEntry(tree: Tree) { + if (!tree.exists('nx.json')) { + return; + } + + const GITIGNORE_ENTRIES = [ + '.cursor/rules/nx-rules.mdc', + '.github/instructions/nx.instructions.md', + ]; + if (!tree.exists('.gitignore')) { + return; + } + let content = tree.read('.gitignore', 'utf-8') || ''; + const ig = ignore().add(content); + for (const entry of GITIGNORE_ENTRIES) { + if (!ig.ignores(entry)) { + content = content.trimEnd() + '\n' + entry + '\n'; + } + } + tree.write('.gitignore', content); +} diff --git a/packages/workspace/src/generators/new/files-integrated-repo/__dot__gitignore b/packages/workspace/src/generators/new/files-integrated-repo/__dot__gitignore index 68a8e969fb..4bef608aa6 100644 --- a/packages/workspace/src/generators/new/files-integrated-repo/__dot__gitignore +++ b/packages/workspace/src/generators/new/files-integrated-repo/__dot__gitignore @@ -40,3 +40,5 @@ Thumbs.db .nx/cache .nx/workspace-data +.cursor/rules/nx-rules.mdc +.github/instructions/nx.instructions.md diff --git a/packages/workspace/src/generators/new/files-package-based-repo/__dot__gitignore b/packages/workspace/src/generators/new/files-package-based-repo/__dot__gitignore index 68a8e969fb..4bef608aa6 100644 --- a/packages/workspace/src/generators/new/files-package-based-repo/__dot__gitignore +++ b/packages/workspace/src/generators/new/files-package-based-repo/__dot__gitignore @@ -40,3 +40,5 @@ Thumbs.db .nx/cache .nx/workspace-data +.cursor/rules/nx-rules.mdc +.github/instructions/nx.instructions.md diff --git a/packages/workspace/src/generators/new/files-root-app/__dot__gitignore b/packages/workspace/src/generators/new/files-root-app/__dot__gitignore index 68a8e969fb..4bef608aa6 100644 --- a/packages/workspace/src/generators/new/files-root-app/__dot__gitignore +++ b/packages/workspace/src/generators/new/files-root-app/__dot__gitignore @@ -40,3 +40,5 @@ Thumbs.db .nx/cache .nx/workspace-data +.cursor/rules/nx-rules.mdc +.github/instructions/nx.instructions.md