From 6651d1c71acf368f5c54efbe7ca5cc197eb508f0 Mon Sep 17 00:00:00 2001 From: Khaliq Date: Thu, 8 Oct 2026 16:12:13 -0700 Subject: [PATCH 1/2] =?UTF-8?q?ci:=20trunk=20guard=20=E2=80=94=20only=20tr?= =?UTF-8?q?unk=20may=20merge=20into=20main?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Brings relay in line with the org policy already live in agentrelay.com, cloud, relayfile, relayfile-cloud, relaycast and relay-desktop (agentrelay.com#182): feature branches merge into `trunk`, and only the trunk -> main PR targets main. This is the guard half only. relay has 19 workflows triggered on pull_request with heterogeneous filters, so restricting CI to the trunk -> main PR is a separate per-workflow decision for the policy owner — see the PR body. Approved by Khaliq. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/trunk-guard.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/trunk-guard.yml diff --git a/.github/workflows/trunk-guard.yml b/.github/workflows/trunk-guard.yml new file mode 100644 index 0000000000..e2c4c2893c --- /dev/null +++ b/.github/workflows/trunk-guard.yml @@ -0,0 +1,17 @@ +name: Trunk guard + +# Only the `trunk` branch may merge into main. Feature branches merge into +# `trunk`; CI runs only on the trunk -> main PR. +on: + pull_request: + branches: [main] + +jobs: + only-trunk-merges-to-main: + if: github.head_ref != 'trunk' + runs-on: ubuntu-latest + timeout-minutes: 1 + steps: + - run: | + echo "::error::Only the 'trunk' branch may merge into main. Retarget this PR to 'trunk'." + exit 1 From a6d6fc803fb49dcb721aedce0cb82d7b9c13fdfc Mon Sep 17 00:00:00 2001 From: Khaliq Date: Thu, 8 Oct 2026 16:30:35 -0700 Subject: [PATCH 2/2] fix(ci): reject fork branches named trunk in the guard Devin, Codex and Cursor Bugbot all flagged the same hole: github.head_ref is only the branch NAME, with no repository identity, so a pull request from a fork whose head branch is also called `trunk` skipped the job and passed the guard without its commits ever going through this repo's protected trunk. Require github.event.pull_request.head.repo.full_name == github.repository as well as the branch name. NOTE: the same hole exists in the guard already merged in agentrelay.com, cloud, relayfile, relayfile-cloud, relaycast and relay-desktop, which this file was copied from. Flagged to the policy owner for the same fix. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/trunk-guard.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/trunk-guard.yml b/.github/workflows/trunk-guard.yml index e2c4c2893c..f3bb522b5a 100644 --- a/.github/workflows/trunk-guard.yml +++ b/.github/workflows/trunk-guard.yml @@ -1,17 +1,23 @@ name: Trunk guard -# Only the `trunk` branch may merge into main. Feature branches merge into -# `trunk`; CI runs only on the trunk -> main PR. +# Only the `trunk` branch of THIS repository may merge into main. Feature +# branches merge into `trunk`; CI runs only on the trunk -> main PR. +# +# The head-repo check is load-bearing: `github.head_ref` is just the branch +# name, so a fork whose head branch is also called `trunk` would otherwise +# skip the guard and merge straight into main. on: pull_request: branches: [main] jobs: only-trunk-merges-to-main: - if: github.head_ref != 'trunk' + if: >- + github.event.pull_request.head.repo.full_name != github.repository + || github.head_ref != 'trunk' runs-on: ubuntu-latest timeout-minutes: 1 steps: - run: | - echo "::error::Only the 'trunk' branch may merge into main. Retarget this PR to 'trunk'." + echo "::error::Only the 'trunk' branch of ${{ github.repository }} may merge into main. Retarget this PR to 'trunk'." exit 1