ci: reject breaking marker on non-breaking PR types (#39584)

Reject the breaking marker `!` on `build`, `chore`, `ci`, `docs`,
`style` and `test` PR titles, since these types never change user-facing
behavior. The check runs in `lint-pr-title`, so it fails before labels
are synced and such PRs never get `pr/breaking`.

Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
bircniandsilverwind authored and GitHub committed 2026-10-07 03:08:08 +02:00
1 parent 26475404d4
commit 9b1d6f47f1
2 files changed
+8 -2

No files matched your search

+1 -1
View File
@@ -175,7 +175,7 @@ PR titles must follow the [Conventional Commits](https://www.conventionalcommits
type(scope)!: subject
```
The scope in parentheses is optional. A `!` immediately before the colon marks a [breaking change](https://www.conventionalcommits.org/en/v1.0.0/#summary): either `type!:` or `type(scope)!:` (not `type!(scope):`).
The scope in parentheses is optional. A `!` immediately before the colon marks a [breaking change](https://www.conventionalcommits.org/en/v1.0.0/#summary): either `type!:` or `type(scope)!:` (not `type!(scope):`). Do not mark `build`, `chore`, `ci`, `docs`, `style`, or `test` as breaking.
Use one of these types:
+7 -1
View File
@@ -18,6 +18,7 @@ const allowedTypes = [
type CommitType = typeof allowedTypes[number];
const allowedTypesList = allowedTypes.join(', ');
const nonBreakingTypes = new Set<CommitType>(['build', 'chore', 'ci', 'docs', 'style', 'test']);
const titlePattern = new RegExp(`^(${allowedTypes.join('|')})(\\([\\w/.-]+\\))?(!)?: .+$`);
function parsePrTitle(title: string): {type: CommitType, scope: string, breaking: boolean} | null {
@@ -86,12 +87,17 @@ function lintPrTitle(): void {
console.error('Missing PR_TITLE');
exit(1);
}
if (!parsePrTitle(env.PR_TITLE)) {
const parsed = parsePrTitle(env.PR_TITLE);
if (!parsed) {
console.error(`Invalid PR title: ${env.PR_TITLE}`);
console.error('Expected format: type(scope): subject (scope optional, append "!" for breaking changes)');
console.error(`Allowed types: ${allowedTypesList}`);
exit(1);
}
if (parsed.breaking && nonBreakingTypes.has(parsed.type)) {
console.error(`Type "${parsed.type}" cannot be marked as breaking (remove "!" from the title)`);
exit(1);
}
}
// Command: sync the title-derived labels onto the PR via the GitHub API.