ADR 001: Automate Releases via Conventional Commits
- Status: Accepted
- Date: 2026-01-18
- Author: Victoria Cheng
Context and Problem Statement
The current release process relies on manual GitHub labels (release:major, release:minor, release:patch) to trigger version bumps. This approach is error-prone (easy to forget/mislabel), creates manual toil for every release-worthy PR, and fails to enforce a standard for describing changes in history.
Decision Outcome
The release decision will "shift left" to the Pull Request title using the Conventional Commits specification. The GitHub Action will be refactored to parse the PR title and determine the version bump automatically.
Logic
The workflow will parse github.event.pull_request.title using regex:
| PR Title Pattern | Bump Type | Example |
|---|---|---|
!: or BREAKING CHANGE: |
Major | feat!: drop support for Node 14 |
feat: |
Minor | feat: add new input parameter |
fix: |
Patch | fix: typo in readme |
| Others (chore, docs, style) | Skip | chore: update deps |
Alternatives Considered but Rejected
- Keep Manual Labels: Rejected due to high toil and error rates.
- Analyzing Commit Messages: Rejected as parsing the PR title is a simpler, sufficient proxy for the "unit of work" without requiring squashing or complex parsing.
- Semantic Release (JS Tooling): Rejected to avoid Node.js dependencies in favor of a lightweight shell script approach.
Consequences
Positive
- Removes Manual Toil: Eliminates "release anxiety" and manual version bumping.
- Industry Standard: Enforces Conventional Commits for consistent history.
- Shift Left: Validates release intent at the PR stage.
Negative
- Strict Naming: Requires adherence to conventions (typos = no release).
- Team Education: Ambiguous titles (e.g.,
fix: feat) are resolved by strict prefix matching, which may require onboarding.
Verification
- [x] Automated Logic: The workflow echoes the parsed "Bump Type" to GitHub Actions logs for traceability.
- [x] Fail Safe: If a title does not match (e.g.,
features:), no release is created (fail closed).