From c0816f96333dc7f6836a0bf895fa6bf06209575d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Falc=C3=B3n?= Date: Sun, 12 Jul 2026 19:04:31 +0200 Subject: [PATCH] ci: gate PR titles via the required linter job (#671) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem The standalone `pr-title.yml` workflow produced a `Conventional PR title` status check, but that context was **not** in `main`'s branch-protection required list (`tests`, `linter`, `static-analysis`, `browser-tests`, `performance-tests`). Auto-merge only waits on required checks, so a **failing** title check never blocked a merge — which is exactly what happened. ## Fix Fold the same validation into the `linter` job, which is already a required check. A bad PR title now fails `linter` → blocks the merge (and auto-merge waits). The standalone workflow is removed as redundant. Since required checks live in branch protection (not in the repo — no config-as-code here), hanging the validation off an already-required job is the only way to enforce it via a PR. ## Trade-off The title re-validates on `push`/`synchronize` rather than on the `edited` event, so correcting a bad title after opening a PR needs a new push (a re-run won't pick up the edited title). Acceptable for the simpler, single-mechanism setup. --- .github/workflows/ci.yml | 30 ++++++++++++++++++++++++++++++ .github/workflows/pr-title.yml | 34 ---------------------------------- 2 files changed, 30 insertions(+), 34 deletions(-) delete mode 100644 .github/workflows/pr-title.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f483354e..7ecb5c39 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -235,6 +235,9 @@ jobs: linter: runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read steps: - uses: actions/checkout@v4 @@ -273,6 +276,33 @@ jobs: - name: Frontend Tests run: bun run test + # Gates merges on a Conventional-Commit PR title. Lives in the linter + # job (a required check) so a bad title blocks the merge, unlike the old + # standalone workflow whose check wasn't required. Skipped on push since + # there's no PR title to validate then. + - name: Conventional PR title + if: github.event_name == 'pull_request' + uses: amannn/action-semantic-pull-request@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + types: | + feat + fix + chore + docs + style + refactor + perf + test + build + ci + revert + requireScope: false + subjectPattern: ^(?![A-Z]).+$ + subjectPatternError: | + Subject must not start with uppercase. Use: feat: add checkout, fix(billing): handle retry. + performance-tests: runs-on: ubuntu-latest services: diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml deleted file mode 100644 index b57bf661..00000000 --- a/.github/workflows/pr-title.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: PR title - -on: - pull_request: - types: [opened, edited, synchronize, reopened, ready_for_review] - -jobs: - semantic-pr-title: - name: Conventional PR title - runs-on: ubuntu-latest - permissions: - pull-requests: read - steps: - - name: Validate PR title - uses: amannn/action-semantic-pull-request@v5 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - types: | - feat - fix - chore - docs - style - refactor - perf - test - build - ci - revert - requireScope: false - subjectPattern: ^(?![A-Z]).+$ - subjectPatternError: | - Subject must not start with uppercase. Use: feat: add checkout, fix(billing): handle retry.