feat: enforce Conventional Commits for PR titles and retire CHANGELOG.md#7469
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates the project’s contribution/release process by enforcing Conventional Commits formatting for PR titles in CI and removing the legacy manual changelog workflow.
Changes:
- Added a CI step to validate PR titles against an allowed Conventional Commits type list.
- Introduced
scripts/check_pr_title.jsand removed the oldscripts/validate_changelog.js+CHANGELOG.md. - Updated contributor and release documentation to describe Conventional Commits and changelog/release-note expectations.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
.github/workflows/osrm-backend.yml |
Adds PR title validation step; removes changelog validation invocation. |
scripts/check_pr_title.js |
New Node script to validate PR title format. |
scripts/validate_changelog.js |
Deleted (no longer validating CHANGELOG.md). |
docs/releasing.md |
Replaces changelog-based breaking-change guidance with Conventional Commits guidance; updates release steps. |
CONTRIBUTING.md |
Adds PR-title Conventional Commits guidance and references release notes/changelog removal. |
CHANGELOG.md |
Deleted (retiring manual changelog). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| run: | | ||
| PR_TITLE="${{ github.event.pull_request.title }}" node ./scripts/check_pr_title.js |
There was a problem hiding this comment.
The PR title is injected into a bash assignment with double quotes. If the PR title itself contains a double quote, this step will produce invalid shell syntax and fail (or potentially alter the value). Prefer passing the title via the step-level env: block (e.g., env: { PR_TITLE: ${{ github.event.pull_request.title }} }) and then run node ./scripts/check_pr_title.js.
| run: | | |
| PR_TITLE="${{ github.event.pull_request.title }}" node ./scripts/check_pr_title.js | |
| env: | |
| PR_TITLE: ${{ github.event.pull_request.title }} | |
| run: | | |
| node ./scripts/check_pr_title.js |
| - name: Run checks | ||
| run: | | ||
| ./scripts/check_taginfo.py taginfo.json profiles/car.lua | ||
| # Check that code formatting is up to date | ||
| ./scripts/format.sh && ./scripts/error_on_dirty.sh "Run './scripts/format.sh' locally and commit the changes." |
There was a problem hiding this comment.
PR description says references to manual CHANGELOG.md maintenance were removed, but .github/PULL_REQUEST_TEMPLATE.md still asks for a CHANGELOG.md entry. Either update the template (preferred) or adjust the PR description to reflect what is actually changed in this PR.
| // Conventional Commits format: type[optional scope][optional !]: description | ||
| // Examples: | ||
| // feat: add new feature | ||
| // feat!: breaking change | ||
| // feat(scope): add feature with scope | ||
| // feat(scope)!: breaking change with scope | ||
| const conventionalCommitPattern = /^(feat|fix|docs|style|refactor|perf|test|ci|chore|build)(?:\([^\)]+\))?!?:\s.+/; | ||
|
|
||
| if (!conventionalCommitPattern.test(prTitle)) { |
There was a problem hiding this comment.
The current regex accepts a title with no real description (e.g., feat: ) because :\s.+ allows whitespace-only content. Tighten the pattern to require a non-whitespace character in the description (and consider trimming before validation) so empty/blank descriptions are rejected.
| // Conventional Commits format: type[optional scope][optional !]: description | |
| // Examples: | |
| // feat: add new feature | |
| // feat!: breaking change | |
| // feat(scope): add feature with scope | |
| // feat(scope)!: breaking change with scope | |
| const conventionalCommitPattern = /^(feat|fix|docs|style|refactor|perf|test|ci|chore|build)(?:\([^\)]+\))?!?:\s.+/; | |
| if (!conventionalCommitPattern.test(prTitle)) { | |
| const normalizedPrTitle = prTitle.trim(); | |
| // Conventional Commits format: type[optional scope][optional !]: description | |
| // Examples: | |
| // feat: add new feature | |
| // feat!: breaking change | |
| // feat(scope): add feature with scope | |
| // feat(scope)!: breaking change with scope | |
| const conventionalCommitPattern = /^(feat|fix|docs|style|refactor|perf|test|ci|chore|build)(?:\([^\)]+\))?!?:\s*\S.*$/; | |
| if (!conventionalCommitPattern.test(normalizedPrTitle)) { |
| const ALLOWED_TYPES = ['feat', 'fix', 'docs', 'style', 'refactor', 'perf', 'test', 'ci', 'chore', 'build']; | ||
|
|
||
| const prTitle = process.env.PR_TITLE; | ||
| if (!prTitle) { | ||
| console.error('Error: PR_TITLE environment variable not set'); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| // Conventional Commits format: type[optional scope][optional !]: description | ||
| // Examples: | ||
| // feat: add new feature | ||
| // feat!: breaking change | ||
| // feat(scope): add feature with scope | ||
| // feat(scope)!: breaking change with scope | ||
| const conventionalCommitPattern = /^(feat|fix|docs|style|refactor|perf|test|ci|chore|build)(?:\([^\)]+\))?!?:\s.+/; | ||
|
|
There was a problem hiding this comment.
ALLOWED_TYPES duplicates the type list embedded in conventionalCommitPattern, which can drift if one is updated without the other. Consider building the regex from ALLOWED_TYPES (and updating the comment/error text) so there is a single source of truth for allowed types.
| ## Release Notes | ||
|
|
||
| Release notes are automatically generated from commit history using Conventional Commits metadata. When you tag a release, the changelog is derived from commits since the last version, categorized by type: | ||
| - **feat** → Features | ||
| - **fix** → Bug Fixes | ||
| - **perf** → Performance Improvements | ||
| - **docs** → Documentation | ||
|
|
||
| Commits marked with `!` or containing `BREAKING CHANGE:` are highlighted as breaking changes. | ||
|
|
There was a problem hiding this comment.
This doc states release notes are "automatically generated from commit history using Conventional Commits metadata", but the current release workflow uses ncipollo/release-action with omitBody: true and no generateReleaseNotes option, so no notes are actually generated from commits. Please either update the workflow to generate release notes accordingly or adjust this section to match current release automation.
|
|
||
| ### Release Notes | ||
|
|
||
| Every pull request's commit message (following Conventional Commits) is automatically used to generate release notes. There is no manual changelog to maintain. |
There was a problem hiding this comment.
This section says PR titles are validated, but later claims "Every pull request's commit message ... is automatically used to generate release notes". There’s no commit-message validation added here and the current release workflow doesn’t generate notes from Conventional Commits, so this is misleading. Please align the text with what CI/release automation actually enforces (PR title only) or add the missing automation.
| Every pull request's commit message (following Conventional Commits) is automatically used to generate release notes. There is no manual changelog to maintain. | |
| Pull request titles should follow Conventional Commits, as described above. This is what our CI validates. |
| - `feat(profiles)!: remove deprecated car profile option` | ||
| - `feat(api)!: change response format` (breaking change with scope) | ||
|
|
||
| **Breaking Changes:** Use the `!` suffix before the colon (e.g., `feat!:`) or add a `BREAKING CHANGE:` footer in the PR description. |
There was a problem hiding this comment.
The guidance says breaking changes can be indicated with a BREAKING CHANGE: footer in the PR description, but the CI check introduced here only validates the PR title and won’t verify that footer exists. Either remove that PR-description footer guidance or enhance the check to validate github.event.pull_request.body as well.
| **Breaking Changes:** Use the `!` suffix before the colon (e.g., `feat!:`) or add a `BREAKING CHANGE:` footer in the PR description. | |
| **Breaking Changes:** Use the `!` suffix before the colon in the pull request title (e.g., `feat!:`). |
Address review feedback on PR #7469: - Pass PR title via env variable instead of shell assignment (safer) - Build regex from ALLOWED_TYPES to avoid duplication - Require non-whitespace description (reject 'feat: ') - Update CONTRIBUTING.md to clarify PR-title-only validation - Update PR template to remove CHANGELOG.md entry requirement - Add Conventional Commits section to docs/releasing.md Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2a3b342 to
df6a5bb
Compare
Summary
This PR implements Conventional Commits enforcement for PR titles and retires the manual CHANGELOG.md file.
Changes
CI Enhancements
format-taginfo-docsCI jobfeat,fix,docs,style,refactor,perf,test,ci,chore,buildCode Changes
scripts/check_pr_title.js- Node.js script for PR title validationCHANGELOG.md- Retired manual changelog (1184 lines)scripts/validate_changelog.js- No longer neededDocumentation Updates
Benefits
Testing
Example PR Titles
Valid:
feat: add new routing algorithmfix(api): resolve nearest endpoint crashInvalid (will be rejected):
awesome: new featurefeat add new feature