diff --git a/tools/@aws-cdk/prlint/lint.ts b/tools/@aws-cdk/prlint/lint.ts index aaf1c8f0389c1..53e1d877f8fb9 100644 --- a/tools/@aws-cdk/prlint/lint.ts +++ b/tools/@aws-cdk/prlint/lint.ts @@ -306,6 +306,9 @@ export class PullRequestLinter { validationCollector.validateRuleSet({ testRuleSet: [ { test: validateTitlePrefix } ] }); + validationCollector.validateRuleSet({ + testRuleSet: [ { test: validateTitleScope } ] + }) validationCollector.validateRuleSet({ exemption: shouldExemptBreakingChange, @@ -446,6 +449,29 @@ function hasLabel(pr: GitHubPr, labelName: string): boolean { return result; }; +/** + * Check that the PR title uses the typical convention for package names. + * + * For example, "fix(s3)" is preferred over "fix(aws-s3)". + */ +function validateTitleScope(pr: GitHubPr): TestResult { + const result = new TestResult(); + // Specific commit types are handled by `validateTitlePrefix`. This just checks whether + // the scope includes an `aws-` prefix or not. + // Group 1: Scope with parens - "(aws-)" + // Group 2: Scope name - "aws-" + // Group 3: Preferred scope name - "" + const titleRe = /^\w+(\((aws-([\w_-]+))\))?: /; + const m = titleRe.exec(pr.title); + if (m) { + result.assessFailure( + !!(m[2] && m[3]), + `The title of the pull request should omit 'aws-' from the name of modified packages. Use '${m[3]}' instead of '${m[2]}'.`, + ); + } + return result; +} + function assertStability(pr: GitHubPr, _files: GitHubFile[]): TestResult { const title = pr.title; const body = pr.body; diff --git a/tools/@aws-cdk/prlint/test/lint.test.ts b/tools/@aws-cdk/prlint/test/lint.test.ts index ca417917af878..d498f857d54a0 100644 --- a/tools/@aws-cdk/prlint/test/lint.test.ts +++ b/tools/@aws-cdk/prlint/test/lint.test.ts @@ -58,6 +58,63 @@ describe('breaking changes format', () => { }); }); +describe('commit message format', () => { + test('valid scope', async () => { + const issue = { + number: 1, + title: 'chore(s3): some title', + body: '', + labels: [], + }; + const prLinter = configureMock(issue, undefined); + expect(await prLinter.validate()).resolves; + }); + + test('invalid scope with aws- prefix', async () => { + const issue = { + number: 1, + title: 'fix(aws-s3): some title', + body: '', + labels: [{ name: 'pr-linter/exempt-test' }, { name: 'pr-linter/exempt-integ-test' }], + }; + const prLinter = configureMock(issue, undefined); + await expect(prLinter.validate()).rejects.toThrow(/The title of the pull request should omit 'aws-' from the name of modified packages. Use 's3' instead of 'aws-s3'./); + }); + + test('valid scope with aws- in summary and body', async () => { + const issue = { + number: 1, + title: 'docs(s3): something aws-s3', + body: 'something aws-s3', + labels: [], + }; + const prLinter = configureMock(issue, undefined); + expect(await prLinter.validate()).resolves; + }); + + test('valid with missing scope', async () => { + const issue = { + number: 1, + title: 'docs: something aws-s3', + body: '', + labels: [], + }; + const prLinter = configureMock(issue, undefined); + expect(await prLinter.validate()).resolves; + }); + + test.each(['core', 'prlint', 'awslint'])('valid scope for packages that dont use aws- prefix', async (scope) => { + const issue = { + number: 1, + title: `chore(${scope}): some title`, + body: '', + labels: [] + }; + const prLinter = configureMock(issue, undefined); + expect(await prLinter.validate()).resolves; + }) +}); + describe('ban breaking changes in stable modules', () => { test('breaking change in stable module', async () => { const issue = {