Skip to content

ci: enforce conventional commit PR titles#16

Merged
so0k merged 1 commit into
mainfrom
ci-pr-title-lint
Jun 1, 2026
Merged

ci: enforce conventional commit PR titles#16
so0k merged 1 commit into
mainfrom
ci-pr-title-lint

Conversation

@so0k
Copy link
Copy Markdown
Contributor

@so0k so0k commented Jun 1, 2026

Why

The repo is now squash-merge only, with the squash commit subject taken from the PR title (squash_merge_commit_title=PR_TITLE). release-please derives the version bump + changelog from that subject — so a non-conventional PR title would silently break versioning (e.g. produce no release, or the wrong bump).

This adds a pr-title check that validates every PR title against Conventional Commits, using amannn/action-semantic-pull-request@v6.1.1.

Details

  • Trigger: pull_request_target (so it also runs on fork PRs); it only reads the title via the API — no PR code is checked out, so there's no untrusted-code risk. permissions: pull-requests: read.
  • Allowed types kept in sync with release-please: feat, fix, docs, chore, ci, refactor, perf, test, build, revert.
  • Subject must start lowercase.
  • Also documents the squash + conventional-title strategy in CLAUDE.md.

Follow-up (your call)

Add conventional PR title to main's required status checks so it's a hard gate. release-please's own PRs (chore(main): release X.Y.Z) pass it, so it's safe to require.

@so0k so0k enabled auto-merge (squash) June 1, 2026 07:58
@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Enforce Conventional Commit PR titles via GitHub workflow

✨ Enhancement 📝 Documentation

Grey Divider

Walkthroughs

Description
• Add GitHub workflow to enforce Conventional Commit PR titles
• Validate PR titles against allowed types (feat, fix, docs, chore, ci, refactor, perf, test, build,
  revert)
• Require lowercase subject start to match release-please expectations
• Document PR title requirements and squash-merge strategy in CLAUDE.md
Diagram
flowchart LR
  PR["Pull Request"] -- "title validation" --> Workflow["pr-title Workflow"]
  Workflow -- "checks against types" --> Semantic["Semantic PR Action"]
  Semantic -- "validates format" --> Result["Pass/Fail Status"]
  Result -- "feeds into" --> ReleasePlease["release-please"]
  ReleasePlease -- "derives version bump" --> Release["Release"]

Loading

Grey Divider

File Changes

1. .github/workflows/pr-title.yml ✨ Enhancement +49/-0

Add PR title validation workflow

• New workflow file that validates PR titles are Conventional Commits
• Uses amannn/action-semantic-pull-request@v6.1.1 action for validation
• Triggers on PR open, edit, reopen, and synchronize events
• Enforces allowed types (feat, fix, docs, chore, ci, refactor, perf, test, build, revert)
• Requires subject to start with lowercase letter via regex pattern

.github/workflows/pr-title.yml


2. CLAUDE.md 📝 Documentation +2/-0

Document PR title and release strategy

• Added section explaining that PR titles are load-bearing for release automation
• Documents squash-merge strategy and PR title Conventional Commit requirement
• Clarifies which commit types trigger releases (fix, feat, BREAKING CHANGE) vs. non-release types
• References the new pr-title workflow enforcement mechanism

CLAUDE.md


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented Jun 1, 2026

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (1)

Context used
✅ Compliance rules (platform): 151 rules

Grey Divider


Action required

1. Subject regex too permissive 🐞 Bug ≡ Correctness
Description
The subjectPattern only rejects an initial ASCII uppercase letter, so subjects starting with
digits/whitespace/punctuation still pass even though the workflow error text (and CLAUDE.md) says
the subject must start with a lowercase letter. This creates a policy/behavior mismatch where
non-conforming PR titles can be accepted and then become the squash-merge commit subject used by
release automation.
Code

.github/workflows/pr-title.yml[R45-49]

Evidence
The workflow uses ^(?![A-Z]).+$, which allows any first character other than A-Z, but the
configured error message and repo docs both state that the subject must start with a lowercase
letter.

.github/workflows/pr-title.yml[45-49]
CLAUDE.md[68-71]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The workflow claims to require that the Conventional Commit subject starts with a lowercase letter, but the current regex only forbids starting with `A-Z`, allowing many non-lowercase starts (e.g., digits, spaces, `_`). This makes enforcement weaker than the documented policy.

## Issue Context
- The repo uses the PR title as the squash-merge commit subject.
- The workflow error message explicitly says “must start with a lowercase letter”.

## Fix Focus Areas
- .github/workflows/pr-title.yml[45-49]

### Suggested change
- Replace `subjectPattern: ^(?![A-Z]).+$` with something that actually enforces the intent, e.g.:
 - `subjectPattern: ^[a-z].+$`
- Alternatively, if the intent is only “must not start uppercase”, update `subjectPatternError` (and comments/docs) to match the actual rule.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. CLAUDE.md has long line 📘 Rule violation ⚙ Maintainability
Description
A newly added documentation line is far longer than ~120 characters, reducing readability and making
diffs harder to review. This violates the guideline to wrap long lines at semantic boundaries.
Code

CLAUDE.md[70]

Evidence
PR Compliance ID 782552 requires lines exceeding ~120 characters to be broken at semantic
boundaries. CLAUDE.md line 70 is a single, very long line that should be wrapped into multiple
shorter lines.

Rule 782552: Break lines exceeding ~120 characters at semantic boundaries
CLAUDE.md[70-70]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A newly added line in `CLAUDE.md` exceeds the ~120 character limit and should be wrapped at semantic boundaries.

## Issue Context
The compliance rule requires breaking long lines (approximately >120 characters) into multiple lines to improve readability and reviewability.

## Fix Focus Areas
- CLAUDE.md[70-70]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Unpinned action tag used 🐞 Bug ⛨ Security
Description
The pull_request_target workflow invokes amannn/action-semantic-pull-request pinned by a mutable
tag (v6.1.1), which increases supply-chain risk because the action code could change without a PR
to this repo. While permissions are already minimized, best practice is to pin third-party actions
to an immutable commit SHA for workflows that run in the base-repo context.
Code

.github/workflows/pr-title.yml[R13-31]

Evidence
The workflow is triggered by pull_request_target and calls a third-party action by tag, meaning
the executed code is not pinned to an immutable revision.

.github/workflows/pr-title.yml[13-31]
.github/workflows/pr-title.yml[17-19]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The workflow references a third-party GitHub Action by tag, which is not immutable. Pinning to a commit SHA reduces the blast radius of upstream compromises/retags.

## Issue Context
- This workflow runs on `pull_request_target` (base-repo context) and uses a token (even though permissions are read-only).
- Existing mitigations (no checkout, limited permissions) are good; this is additional hardening.

## Fix Focus Areas
- .github/workflows/pr-title.yml[13-31]

### Suggested change
- Change:
 - `uses: amannn/action-semantic-pull-request@v6.1.1`
- To:
 - `uses: amannn/action-semantic-pull-request@<full_commit_sha>`
- Optionally add an inline comment noting the corresponding version tag for readability.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@so0k so0k merged commit a8ccec9 into main Jun 1, 2026
2 checks passed
@so0k so0k deleted the ci-pr-title-lint branch June 1, 2026 07:59
Comment thread .github/workflows/pr-title.yml
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.

1 participant