Skip to content

feat: enforce Conventional Commits for PR titles and retire CHANGELOG.md#7469

Merged
DennisOSRM merged 1 commit intomasterfrom
feat/conventional-commits-enforcement
Apr 12, 2026
Merged

feat: enforce Conventional Commits for PR titles and retire CHANGELOG.md#7469
DennisOSRM merged 1 commit intomasterfrom
feat/conventional-commits-enforcement

Conversation

@DennisOSRM
Copy link
Copy Markdown
Collaborator

Summary

This PR implements Conventional Commits enforcement for PR titles and retires the manual CHANGELOG.md file.

Changes

CI Enhancements

  • ✅ Added PR title validation to format-taginfo-docs CI job
  • ✅ Enforces standard Conventional Commits types: feat, fix, docs, style, refactor, perf, test, ci, chore, build
  • ✅ CI job fails if PR title is non-compliant (blocks merge)
  • ✅ Removed changelog validation step

Code Changes

  • Created: scripts/check_pr_title.js - Node.js script for PR title validation
  • Deleted: CHANGELOG.md - Retired manual changelog (1184 lines)
  • Deleted: scripts/validate_changelog.js - No longer needed

Documentation Updates

  • CONTRIBUTING.md: Added Conventional Commits section with format, types, and examples
  • docs/releasing.md: Added Conventional Commits section and release notes auto-generation documentation
  • Removed references to manual CHANGELOG.md maintenance

Benefits

  • ✅ Structured commit history for better changelog automation
  • ✅ Enforced consistency across all PRs
  • ✅ Reduced manual maintenance burden
  • ✅ Clear breaking change visibility in commit history

Testing

  • Validated PR title script with 8 test cases (4 valid, 4 invalid)
  • All valid Conventional Commits formats accepted
  • All invalid formats properly rejected with helpful error messages

Example PR Titles

Valid:

  • feat: add new routing algorithm
  • fix(api): resolve nearest endpoint crash

Invalid (will be rejected):

  • awesome: new feature
  • feat add new feature

@DennisOSRM DennisOSRM marked this pull request as ready for review April 12, 2026 09:30
Copilot AI review requested due to automatic review settings April 12, 2026 09:30
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.js and removed the old scripts/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.

Comment thread .github/workflows/osrm-backend.yml Outdated
Comment on lines +117 to +118
run: |
PR_TITLE="${{ github.event.pull_request.title }}" node ./scripts/check_pr_title.js
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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

Copilot uses AI. Check for mistakes.
Comment on lines 119 to 123
- 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."
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment thread scripts/check_pr_title.js Outdated
Comment on lines +15 to +23
// 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)) {
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
// 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)) {

Copilot uses AI. Check for mistakes.
Comment thread scripts/check_pr_title.js
Comment on lines +7 to +22
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.+/;

Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment thread scripts/check_pr_title.js
Comment thread docs/releasing.md Outdated
Comment on lines +37 to +46
## 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.

Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment thread docs/releasing.md Outdated
Comment thread docs/releasing.md Outdated
Comment thread CONTRIBUTING.md Outdated

### 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.
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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.

Copilot uses AI. Check for mistakes.
Comment thread CONTRIBUTING.md Outdated
- `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.
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
**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!:`).

Copilot uses AI. Check for mistakes.
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>
@DennisOSRM DennisOSRM force-pushed the feat/conventional-commits-enforcement branch from 2a3b342 to df6a5bb Compare April 12, 2026 10:44
@DennisOSRM DennisOSRM enabled auto-merge (squash) April 12, 2026 11:19
@DennisOSRM DennisOSRM disabled auto-merge April 12, 2026 11:30
@DennisOSRM DennisOSRM merged commit eec4d76 into master Apr 12, 2026
23 checks passed
@DennisOSRM DennisOSRM deleted the feat/conventional-commits-enforcement branch April 12, 2026 11:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants