Skip to content

Commit cefeb74

Browse files
adam-mossmarionebl
authored andcommitted
feat(core): add Signed-off-by rule
1 parent 3b90a4a commit cefeb74

File tree

4 files changed

+101
-0
lines changed

4 files changed

+101
-0
lines changed

Diff for: @commitlint/core/src/rules/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export default {
1818
'scope-enum': require('./scope-enum'),
1919
'scope-max-length': require('./scope-max-length'),
2020
'scope-min-length': require('./scope-min-length'),
21+
'signed-off-by': require('./signed-off-by'),
2122
'subject-case': require('./subject-case'),
2223
'subject-empty': require('./subject-empty'),
2324
'subject-full-stop': require('./subject-full-stop'),

Diff for: @commitlint/core/src/rules/signed-off-by.js

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export default (parsed, when, value) => {
2+
const input = /.*\n(Signed-off-by:).*\n+/g.exec(parsed.raw);
3+
4+
const negated = when === 'never';
5+
const hasSignedOffBy = Boolean(input && input[1] === value);
6+
7+
return [
8+
negated ? !hasSignedOffBy : hasSignedOffBy,
9+
['message', negated ? 'must not' : 'must', 'be signed off']
10+
.filter(Boolean)
11+
.join(' ')
12+
];
13+
};

Diff for: @commitlint/core/src/rules/signed-off-by.test.js

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import test from 'ava';
2+
import parse from '../library/parse';
3+
import check from './signed-off-by';
4+
5+
const messages = {
6+
empty: 'chore:\n',
7+
with: `chore: subject\nbody\nfooter\nSigned-off-by:\n\n`,
8+
without: `chore: subject\nbody\nfooter\n\n`,
9+
inSubject: `chore: subject Signed-off-by:\nbody\nfooter\n\n`,
10+
inBody: `chore: subject\nbody Signed-off-by:\nfooter\n\n`
11+
};
12+
13+
const parsed = {
14+
empty: parse(messages.empty),
15+
with: parse(messages.with),
16+
without: parse(messages.without),
17+
inSubject: parse(messages.inSubject),
18+
inBody: parse(messages.inBody)
19+
};
20+
21+
test('empty against "always signed-off-by" should fail', async t => {
22+
const [actual] = check(await parsed.empty, 'always', 'Signed-off-by:');
23+
const expected = false;
24+
t.is(actual, expected);
25+
});
26+
27+
test('empty against "never signed-off-by" should succeed', async t => {
28+
const [actual] = check(await parsed.empty, 'never', 'Signed-off-by:');
29+
const expected = true;
30+
t.is(actual, expected);
31+
});
32+
33+
test('with against "always signed-off-by" should succeed', async t => {
34+
const [actual] = check(await parsed.with, 'always', 'Signed-off-by:');
35+
const expected = true;
36+
t.is(actual, expected);
37+
});
38+
39+
test('with against "never signed-off-by" should fail', async t => {
40+
const [actual] = check(await parsed.with, 'never', 'Signed-off-by:');
41+
const expected = false;
42+
t.is(actual, expected);
43+
});
44+
45+
test('without against "always signed-off-by" should fail', async t => {
46+
const [actual] = check(await parsed.without, 'always', 'Signed-off-by:');
47+
const expected = false;
48+
t.is(actual, expected);
49+
});
50+
51+
test('without against "never signed-off-by" should succeed', async t => {
52+
const [actual] = check(await parsed.without, 'never', 'Signed-off-by:');
53+
const expected = true;
54+
t.is(actual, expected);
55+
});
56+
57+
test('inSubject against "always signed-off-by" should fail', async t => {
58+
const [actual] = check(await parsed.inSubject, 'always', 'Signed-off-by:');
59+
const expected = false;
60+
t.is(actual, expected);
61+
});
62+
63+
test('inSubject against "never signed-off-by" should succeed', async t => {
64+
const [actual] = check(await parsed.inSubject, 'never', 'Signed-off-by:');
65+
const expected = true;
66+
t.is(actual, expected);
67+
});
68+
69+
test('inBody against "always signed-off-by" should fail', async t => {
70+
const [actual] = check(await parsed.inBody, 'always', 'Signed-off-by:');
71+
const expected = false;
72+
t.is(actual, expected);
73+
});
74+
75+
test('inBody against "never signed-off-by" should succeed', async t => {
76+
const [actual] = check(await parsed.inBody, 'never', 'Signed-off-by:');
77+
const expected = true;
78+
t.is(actual, expected);
79+
});

Diff for: docs/reference-rules.md

+8
Original file line numberDiff line numberDiff line change
@@ -263,3 +263,11 @@ Rule configurations are either of type `array` residing on a key with the rule's
263263
```js
264264
0
265265
```
266+
267+
#### signed-off-by
268+
* **condition**: `message` has `value`
269+
* **rule**: `always`
270+
* **value**
271+
```js
272+
'Signed-off-by:'
273+
```

0 commit comments

Comments
 (0)