From e4e3a9b823d095afc6e4e1e16e1cb3634ed5ee1a Mon Sep 17 00:00:00 2001 From: Damien Storm Date: Wed, 22 Oct 2025 11:51:34 -0400 Subject: [PATCH 1/3] ci: add PR title validation workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement automated enforcement of Conventional Commits specification for pull request titles using GitHub Actions. Changes: - Add pr-title-lint workflow using amannn/action-semantic-pull-request - Configure validation for standard commit types matching commitlint - Add sticky comments to guide contributors on invalid titles - Update CONTRIBUTING.md with PR title format requirements - Add PR template header with title format examples and guidance This ensures PR titles follow the same conventions as commits, which is especially important when using squash merge strategy where the PR title becomes the final commit message. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .github/pull_request_template.md | 15 ++++++ .github/workflows/pr-title-lint.yml | 72 +++++++++++++++++++++++++++++ CONTRIBUTING.md | 27 ++++++++++- 3 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/pr-title-lint.yml diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 4ad06ca..444684c 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,3 +1,18 @@ + + ## Why? diff --git a/.github/workflows/pr-title-lint.yml b/.github/workflows/pr-title-lint.yml new file mode 100644 index 0000000..2c303aa --- /dev/null +++ b/.github/workflows/pr-title-lint.yml @@ -0,0 +1,72 @@ +name: Lint PR Title + +on: + pull_request: + types: [opened, edited, synchronize, reopened] + +jobs: + lint-pr-title: + runs-on: ubuntu-latest + permissions: + pull-requests: write + statuses: write + steps: + - uses: amannn/action-semantic-pull-request@v5 + id: lint_pr_title + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + # Match commitlint config-conventional types + types: | + feat + fix + docs + style + refactor + perf + test + build + ci + chore + revert + # Allow optional scope + requireScope: false + # Subject should not start with uppercase (matches conventional commits) + subjectPattern: ^(?![A-Z]).+$ + subjectPatternError: | + The subject "{subject}" found in the pull request title "{title}" + didn't match the configured pattern. Please ensure that the subject + doesn't start with an uppercase character. + + # Add comment when PR title is invalid + - uses: marocchino/sticky-pull-request-comment@v2 + if: always() && (steps.lint_pr_title.outputs.error_message != null) + with: + header: pr-title-lint-error + message: | + 👋 Thank you for opening this pull request! + + We require PR titles to follow the [Conventional Commits specification](https://www.conventionalcommits.org/). + + **Error details:** + ``` + ${{ steps.lint_pr_title.outputs.error_message }} + ``` + + **Valid format:** `(): ` + + **Valid types:** `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore`, `revert` + + **Examples:** + - `feat(auth): add login button to navigation` + - `fix: resolve race condition in async handler` + - `docs: update installation instructions` + + Please update your PR title and the check will run automatically. + + # Delete comment when PR title is fixed + - uses: marocchino/sticky-pull-request-comment@v2 + if: ${{ steps.lint_pr_title.outputs.error_message == null }} + with: + header: pr-title-lint-error + delete: true diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 39c8150..c5b55cd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -140,7 +140,7 @@ Semantic versioning and releases are automated in CI using `python-semantic-rele ## Pull Requests - Keep PRs focused and well scoped. -- Use a conventional title (e.g., `feat: add new prompt`). +- **PR titles must follow Conventional Commits format** (e.g., `feat: add new feature`). This is enforced by an automated check. - PR description template: ```markdown @@ -154,6 +154,31 @@ Semantic versioning and releases are automated in CI using `python-semantic-rele - Ensure all checks pass (pre-commit) before requesting review. - Reference related issues where applicable. +### PR Title Format + +PR titles are validated automatically and must follow this format: + +``` +(): +``` + +**Valid types:** `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore`, `revert` + +**Examples:** +- `feat(auth): add login button to navigation` +- `fix: resolve race condition in async handler` +- `docs: update installation instructions` +- `chore: bump dependencies and run pre-commit` + +The description should: +- Start with a lowercase letter +- Be concise and descriptive +- Use imperative mood (e.g., "add" not "added" or "adds") + +**Breaking changes:** Add `!` after the type (e.g., `feat!: drop Python 3.10 support`) + +If the automated check fails, update your PR title and it will re-run automatically. + ## Issue Templates Use the GitHub issue templates under `.github/ISSUE_TEMPLATE/` for bug reports, feature requests, and questions. These templates prompt for summary, context/repro, and related prompt/workflow information. From fe2cb5a3dc68a690bb652494f1c7453feb6d433b Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Wed, 22 Oct 2025 23:25:21 +0000 Subject: [PATCH 2/3] docs: fix markdown linting error in CONTRIBUTING.md Add 'text' language tag to code fence block to satisfy markdownlint requirements. Co-authored-by: Damien Storm --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c5b55cd..a0cce26 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -158,7 +158,7 @@ Semantic versioning and releases are automated in CI using `python-semantic-rele PR titles are validated automatically and must follow this format: -``` +```text (): ``` From 09456bf41f0105f34a2111c09635023fc5bb01ca Mon Sep 17 00:00:00 2001 From: Damien Storm Date: Wed, 22 Oct 2025 20:02:17 -0400 Subject: [PATCH 3/3] chore: more linter fixes --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a0cce26..8de57ad 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -165,12 +165,14 @@ PR titles are validated automatically and must follow this format: **Valid types:** `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore`, `revert` **Examples:** + - `feat(auth): add login button to navigation` - `fix: resolve race condition in async handler` - `docs: update installation instructions` - `chore: bump dependencies and run pre-commit` The description should: + - Start with a lowercase letter - Be concise and descriptive - Use imperative mood (e.g., "add" not "added" or "adds")