-
Notifications
You must be signed in to change notification settings - Fork 119
Expand file tree
/
Copy pathcommitlint.config.js
More file actions
87 lines (77 loc) · 2.72 KB
/
Copy pathcommitlint.config.js
File metadata and controls
87 lines (77 loc) · 2.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
const { execSync } = require('child_process');
function getNxProjects() {
try {
const output = execSync('npx nx show projects --json', {
encoding: 'utf-8',
stdio: ['pipe', 'pipe', 'pipe'],
});
return JSON.parse(output);
} catch {
return [];
}
}
const validProjects = new Set(getNxProjects());
module.exports = {
extends: ['@commitlint/config-conventional'],
defaultIgnores: true,
rules: {
'scope-case': [0],
'body-max-length': [0],
'body-max-line-length': [0],
'scope-full-name-for-versioning': [2, 'always'],
},
plugins: [
{
rules: {
'scope-full-name-for-versioning': (parsed) => {
const { type, scope, header, notes } = parsed;
// Detect breaking change: header `!:` marker OR BREAKING CHANGE footer
const isBreaking =
!!(header && header.includes('!:')) ||
!!(notes && notes.some((n) => n.title === 'BREAKING CHANGE'));
const isVersioningType = ['feat', 'fix'].includes(type);
// Non-versioning, non-breaking commits can use any scope
if (!isBreaking && !isVersioningType) {
return [true];
}
// Scope required for versioning commits
if (!scope) {
const commitType = isBreaking ? 'breaking (!)/feat/fix' : 'feat/fix';
return [
false,
`Scope required for ${commitType} commits.\n` +
`Use: ${type}(@redhat-cloud-services/utilities): ...`
];
}
// Extract scope from raw header as fallback when parser strips it
// (e.g. @commitlint/lint default parser may not handle `!` marker)
let resolvedScope = scope;
if (!resolvedScope && header) {
const match = header.match(/^\w+\(([^)]+)\)/);
if (match) {
resolvedScope = match[1];
}
}
if (!resolvedScope) {
return [true];
}
const scopes = resolvedScope.split(',');
for (const s of scopes) {
const trimmed = s.trim();
if (!validProjects.has(trimmed)) {
const commitType = isBreaking ? 'breaking (!)/feat/fix' : 'feat/fix';
const hint = trimmed.startsWith('@redhat-cloud-services/')
? `Project "${trimmed}" not found. Run: npx nx show projects`
: `Use full project name like: ${type}(@redhat-cloud-services/utilities)${isBreaking ? '!' : ''}: ...`;
return [
false,
`Scope "${trimmed}" must be a full Nx project name for ${commitType} commits.\n${hint}`,
];
}
}
return [true];
},
},
},
],
};