diff --git a/@commitlint/rules/src/signed-off-by.test.ts b/@commitlint/rules/src/signed-off-by.test.ts index 8cf2a6683f..29fc665501 100644 --- a/@commitlint/rules/src/signed-off-by.test.ts +++ b/@commitlint/rules/src/signed-off-by.test.ts @@ -7,6 +7,15 @@ const messages = { without: `test: subject\nbody\nfooter\n\n`, inSubject: `test: subject Signed-off-by:\nbody\nfooter\n\n`, inBody: `test: subject\nbody Signed-off-by:\nfooter\n\n`, + withSignoffAndComments: `test: subject + +message body + +Signed-off-by: + +# Please enter the commit message for your changes. Lines starting +# with '#' will be ignored, and an empty message aborts the commit. +`, }; const parsed = { @@ -15,6 +24,7 @@ const parsed = { without: parse(messages.without), inSubject: parse(messages.inSubject), inBody: parse(messages.inBody), + withSignoffAndComments: parse(messages.withSignoffAndComments), }; test('empty against "always signed-off-by" should fail', async () => { @@ -57,6 +67,16 @@ test('without against "never signed-off-by" should succeed', async () => { expect(actual).toEqual(expected); }); +test('trailing comments should be ignored', async () => { + const [actual] = signedOffBy( + await parsed.withSignoffAndComments, + 'always', + 'Signed-off-by:' + ); + const expected = true; + expect(actual).toEqual(expected); +}); + test('inSubject against "always signed-off-by" should fail', async () => { const [actual] = signedOffBy( await parsed.inSubject, diff --git a/@commitlint/rules/src/signed-off-by.ts b/@commitlint/rules/src/signed-off-by.ts index 38d68b068f..674a206197 100644 --- a/@commitlint/rules/src/signed-off-by.ts +++ b/@commitlint/rules/src/signed-off-by.ts @@ -7,7 +7,14 @@ export const signedOffBy: SyncRule = ( when = 'always', value = '' ) => { - const lines = toLines(parsed.raw).filter(Boolean); + const lines = toLines(parsed.raw).filter( + (ln) => + // skip comments + !ln.startsWith('#') && + // ignore empty lines + Boolean(ln) + ); + const last = lines[lines.length - 1]; const negated = when === 'never';