Skip to content

Commit 11879ad

Browse files
authored
feat: add support for Nx monorepos via @commitlint/config-nx-scopes (conventional-changelog#2995)
1 parent 78a8935 commit 11879ad

21 files changed

+525
-5
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# commitlint-config-nx-scopes
2+
3+
> Alias of [@commitlint/config-nx-scopes](https://www.npmjs.com/package/@commitlint/config-nx-scopes)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require('@commitlint/config-nx-scopes');
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2022 - present Florian Guitton
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"name": "commitlint-config-nx-scopes",
3+
"version": "16.0.0",
4+
"description": "Shareable commitlint config enforcing nx project names as scopes",
5+
"files": [
6+
"index.js"
7+
],
8+
"scripts": {
9+
"deps": "dep-check",
10+
"pkg": "pkg-check"
11+
},
12+
"repository": {
13+
"type": "git",
14+
"url": "https://github.com/conventional-changelog/commitlint.git",
15+
"directory": "@alias/commitlint-config-nx-scopes"
16+
},
17+
"keywords": [
18+
"conventional-changelog",
19+
"commitlint",
20+
"commitlint-config",
21+
"nx"
22+
],
23+
"author": "Florian Guitton <[email protected]>",
24+
"license": "MIT",
25+
"bugs": {
26+
"url": "https://github.com/conventional-changelog/commitlint/issues"
27+
},
28+
"homepage": "https://commitlint.js.org/",
29+
"engines": {
30+
"node": ">=v12"
31+
},
32+
"dependencies": {
33+
"@commitlint/config-nx-scopes": "^16.0.0"
34+
},
35+
"devDependencies": {
36+
"@commitlint/utils": "^16.0.0"
37+
},
38+
"gitHead": "70f7f4688b51774e7ac5e40e896cdaa3f132b2bc"
39+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"extends": "@nrwl/workspace/presets/core.json",
3+
"npmScope": "secretarium",
4+
"affected": {
5+
"defaultBase": "main"
6+
},
7+
"cli": {
8+
"defaultCollection": "@nrwl/react"
9+
},
10+
"tasksRunnerOptions": {
11+
"default": {
12+
"runner": "@nrwl/nx-cloud",
13+
"options": {
14+
"cacheableOperations": [
15+
"build",
16+
"lint",
17+
"test",
18+
"e2e"
19+
]
20+
}
21+
}
22+
},
23+
"generators": {
24+
"@nrwl/react": {
25+
"application": {
26+
"style": "css",
27+
"linter": "eslint",
28+
"babel": true
29+
},
30+
"component": {
31+
"style": "css"
32+
},
33+
"library": {
34+
"style": "css",
35+
"linter": "eslint"
36+
}
37+
}
38+
},
39+
"defaultProject": "a"
40+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "a",
3+
"version": "1.0.0"
4+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"root": "nx/a",
3+
"sourceRoot": "nx/a/src",
4+
"projectType": "library",
5+
"targets": {
6+
"lint": {
7+
"executor": "@nrwl/linter:eslint",
8+
"outputs": [
9+
"{options.outputFile}"
10+
],
11+
"options": {
12+
"lintFilePatterns": [
13+
"nx/a/**/*.ts"
14+
]
15+
}
16+
},
17+
"test": {
18+
"executor": "@nrwl/jest:jest",
19+
"outputs": [
20+
"coverage/nx/a"
21+
],
22+
"options": {
23+
"jestConfig": "nx/a/jest.config.js",
24+
"passWithNoTests": true
25+
}
26+
}
27+
},
28+
"tags": []
29+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "b",
3+
"version": "1.0.0"
4+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"root": "nx/b",
3+
"sourceRoot": "nx/b/src",
4+
"projectType": "library",
5+
"targets": {
6+
"lint": {
7+
"executor": "@nrwl/linter:eslint",
8+
"outputs": [
9+
"{options.outputFile}"
10+
],
11+
"options": {
12+
"lintFilePatterns": [
13+
"nx/b/**/*.ts"
14+
]
15+
}
16+
},
17+
"test": {
18+
"executor": "@nrwl/jest:jest",
19+
"outputs": [
20+
"coverage/nx/b"
21+
],
22+
"options": {
23+
"jestConfig": "nx/b/jest.config.js",
24+
"passWithNoTests": true
25+
}
26+
}
27+
},
28+
"tags": []
29+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "basic",
3+
"version": "1.0.0",
4+
"devDependencies": {
5+
"@nrwl/tao": "^13.0.0"
6+
}
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"version": 2,
3+
"projects": {
4+
"a": "nx/a",
5+
"b": "nx/b"
6+
}
7+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"npmScope": "empty",
3+
"affected": {
4+
"defaultBase": "main"
5+
},
6+
"cli": {
7+
"defaultCollection": "@nrwl/workspace"
8+
},
9+
"implicitDependencies": {
10+
"package.json": {
11+
"dependencies": "*",
12+
"devDependencies": "*"
13+
},
14+
".eslintrc.json": "*"
15+
},
16+
"tasksRunnerOptions": {
17+
"default": {
18+
"runner": "@nrwl/workspace/tasks-runners/default",
19+
"options": {
20+
"cacheableOperations": [
21+
"build",
22+
"lint",
23+
"test",
24+
"e2e"
25+
]
26+
}
27+
}
28+
},
29+
"targetDependencies": {
30+
"build": [
31+
{
32+
"target": "build",
33+
"projects": "dependencies"
34+
}
35+
]
36+
}
37+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "empty",
3+
"version": "1.0.0",
4+
"devDependencies": {
5+
"@nrwl/tao": "^13.0.0"
6+
}
7+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"version": 2,
3+
"projects": {}
4+
}

@commitlint/config-nx-scopes/index.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
const {Workspaces} = require('@nrwl/tao/src/shared/workspace');
2+
3+
module.exports = {
4+
utils: {getProjects},
5+
rules: {
6+
'scope-enum': (ctx) =>
7+
getProjects(ctx).then((packages) => [2, 'always', packages]),
8+
},
9+
};
10+
11+
function getProjects(context) {
12+
return Promise.resolve()
13+
.then(() => {
14+
const ctx = context || {};
15+
const cwd = ctx.cwd || process.cwd();
16+
const ws = new Workspaces(cwd);
17+
const workspace = ws.readWorkspaceConfiguration();
18+
return Object.entries(workspace.projects || {}).map(
19+
([name, project]) => ({
20+
name,
21+
...project,
22+
})
23+
);
24+
})
25+
.then((projects) => {
26+
return projects
27+
.filter((project) => project.targets)
28+
.map((project) => project.name)
29+
.map((name) => (name.charAt(0) === '@' ? name.split('/')[1] : name));
30+
});
31+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import {npm} from '@commitlint/test';
2+
import config from '.';
3+
4+
test('exports rules key', () => {
5+
expect(config).toHaveProperty('rules');
6+
});
7+
8+
test('rules hold object', () => {
9+
expect(config).toMatchObject({
10+
rules: expect.any(Object),
11+
});
12+
});
13+
14+
test('rules contain scope-enum', () => {
15+
expect(config).toMatchObject({
16+
rules: {
17+
'scope-enum': expect.anything(),
18+
},
19+
});
20+
});
21+
22+
test('scope-enum is function', () => {
23+
expect(config).toMatchObject({
24+
rules: {
25+
'scope-enum': expect.any(Function),
26+
},
27+
});
28+
});
29+
30+
test('scope-enum does not throw for missing context', async () => {
31+
const {'scope-enum': fn} = config.rules;
32+
await expect(fn()).resolves.toBeTruthy();
33+
});
34+
35+
test('scope-enum has expected severity', async () => {
36+
const {'scope-enum': fn} = config.rules;
37+
const [severity] = await fn();
38+
expect(severity).toBe(2);
39+
});
40+
41+
test('scope-enum has expected modifier', async () => {
42+
const {'scope-enum': fn} = config.rules;
43+
const [, modifier] = await fn();
44+
expect(modifier).toBe('always');
45+
});
46+
47+
test('returns empty value for empty nx repository', async () => {
48+
const {'scope-enum': fn} = config.rules;
49+
const cwd = await npm.bootstrap('fixtures/empty', __dirname);
50+
const [, , value] = await fn({cwd});
51+
expect(value).toEqual([]);
52+
});
53+
54+
test('returns expected value for basic nx repository', async () => {
55+
const {'scope-enum': fn} = config.rules;
56+
const cwd = await npm.bootstrap('fixtures/basic', __dirname);
57+
58+
const [, , value] = await fn({cwd});
59+
expect(value).toEqual(['a', 'b']);
60+
});
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2022 - present Florian Guitton
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

0 commit comments

Comments
 (0)