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..8de57ad 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,33 @@ 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: + +```text +(): +``` + +**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.