From 44a546c601079355a14c6c6b0191bf8d0be8559a Mon Sep 17 00:00:00 2001 From: Mathias Elle Date: Fri, 6 Nov 2026 12:23:38 +0100 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=91=B7=20ci:=20check=20PR=20titles=20?= =?UTF-8?q?for=20Conventional=20Commits?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Release Please ignores PR titles that are not Conventional Commits, so changes silently vanish from the changelog. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/pr-title.yml | 34 ++++++++++++++++++++++++++++++++++ CONTRIBUTING.md | 5 ++++- 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/pr-title.yml diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml new file mode 100644 index 00000000..a4eaba7e --- /dev/null +++ b/.github/workflows/pr-title.yml @@ -0,0 +1,34 @@ +# Release Please builds the changelog from the PR title of squash-merged pull +# requests. A title that is not a Conventional Commit (for example one that +# starts with an emoji) is silently ignored and the change never reaches the +# release notes, so reject it before merging. + +name: PR Title + +on: + pull_request: + types: [opened, edited, synchronize, reopened] + +permissions: + contents: read + +jobs: + conventional-title: + name: Conventional Commit title + runs-on: ubuntu-latest + # The release PR is titled "Next Release " by Release Please. + if: ${{ !startsWith(github.head_ref, 'release-please--') }} + + steps: + # The title is passed via env (never interpolated into the script) and + # only used as regex match data, so it cannot inject shell commands. + - name: Check PR title + env: + PR_TITLE: ${{ github.event.pull_request.title }} + run: | + pattern='^(feat|fix|refactor|perf|docs|style|chore|test|build|ci|revert)(\([a-z0-9._/-]+\))?!?: [^[:space:]].*$' + if [[ ! "$PR_TITLE" =~ $pattern ]]; then + echo "::error title=Invalid PR title::The title must follow Conventional Commits, e.g. 'feat(hyva): add readiness check'. Do not start it with an emoji." + echo "Allowed types: feat, fix, refactor, perf, docs, style, chore, test, build, ci, revert" + exit 1 + fi diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5ecb69ed..25a3efea 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -53,7 +53,9 @@ feat!: remove legacy theme builder API fix!: change command argument order ``` -**Individual Commits**: Your individual commits within the PR can use any format you prefer. We use **squash-merge**, so only the PR title becomes the commit message in the `main` branch. +**Individual Commits**: Your individual commits within the PR can use any format you prefer (including emojis). We use **squash-merge**, so only the PR title becomes the commit message in the `main` branch. + +**PR titles must not start with an emoji.** Release Please cannot parse such titles and silently drops the change from the changelog. The `PR Title` check fails for titles that are not valid Conventional Commits. ### For Maintainers (Direct Commits) @@ -81,6 +83,7 @@ All pull requests are merged using **squash-merge** to maintain a clean, linear - ✅ PR title becomes the commit message - ✅ All PR commits are squashed into a single commit - ✅ Easier to follow project history and revert changes if needed +- ⚠️ Do not use "Create a merge commit" or "Rebase and merge": Release Please then only sees the individual commits and ignores everything that is not a Conventional Commit --- From c0c4a2f887fdabbf16028b5d823c9483bdb6aef9 Mon Sep 17 00:00:00 2001 From: Mathias Elle Date: Fri, 6 Nov 2026 12:40:51 +0100 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=91=B7=20ci:=20restrict=20PR=20title?= =?UTF-8?q?=20exemption=20and=20allow=20any=20scope=20characters?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/pr-title.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml index a4eaba7e..08ff5b89 100644 --- a/.github/workflows/pr-title.yml +++ b/.github/workflows/pr-title.yml @@ -16,8 +16,15 @@ jobs: conventional-title: name: Conventional Commit title runs-on: ubuntu-latest - # The release PR is titled "Next Release " by Release Please. - if: ${{ !startsWith(github.head_ref, 'release-please--') }} + # Only the release PR that the Release Please bot opens from this repository + # is exempt (it is titled "Next Release "). A branch name alone + # must not be enough, otherwise any fork branch could skip the check. + if: >- + ${{ !( + github.event.pull_request.head.repo.full_name == github.repository + && github.event.pull_request.user.login == 'github-actions[bot]' + && startsWith(github.head_ref, 'release-please--') + ) }} steps: # The title is passed via env (never interpolated into the script) and @@ -26,7 +33,7 @@ jobs: env: PR_TITLE: ${{ github.event.pull_request.title }} run: | - pattern='^(feat|fix|refactor|perf|docs|style|chore|test|build|ci|revert)(\([a-z0-9._/-]+\))?!?: [^[:space:]].*$' + pattern='^(feat|fix|refactor|perf|docs|style|chore|test|build|ci|revert)(\([^()]+\))?!?: [^[:space:]].*$' if [[ ! "$PR_TITLE" =~ $pattern ]]; then echo "::error title=Invalid PR title::The title must follow Conventional Commits, e.g. 'feat(hyva): add readiness check'. Do not start it with an emoji." echo "Allowed types: feat, fix, refactor, perf, docs, style, chore, test, build, ci, revert" From aa833689a81d8e0d634bcf25fc43b6005663ef83 Mon Sep 17 00:00:00 2001 From: Mathias Elle Date: Fri, 6 Nov 2026 12:45:04 +0100 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=91=B7=20ci(trunk):=20pin=20pinact=20?= =?UTF-8?q?to=204.1.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pinact 5.0.2 fails with pinact/config-error on every workflow change because the trunk plugins still pass single-dash flags. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .trunk/trunk.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index dbfdf78c..d9466eec 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -37,7 +37,11 @@ lint: paths: - .ddev/web-build/** enabled: - - pinact@5.0.2 + # pinact 5 is not supported by the trunk plugins (v1.11.0 still passes + # single-dash flags), so every workflow change fails with a + # "pinact/config-error". Stay on 4.x until + # https://github.com/trunk-io/plugins/issues/1177 is fixed. + - pinact@4.1.1 - svgo@4.1.0 - taplo@0.10.0 - checkov@3.4.2