From 6c0b977487e942e1e5c803d33e2003ccf1c9587c Mon Sep 17 00:00:00 2001 From: Shaun Smith <51304449+smith-xyz@users.noreply.github.com> Date: Fri, 30 Oct 2026 14:36:36 -0400 Subject: [PATCH] ci: retire auto-merge workflow Active development is cooling off and Qodo covers review, so the unattended-merge path is no longer worth a standing pull_request_target workflow with a write token. Required checks still gate every merge - they now just need a click. --- .github/workflows/auto-merge.yml | 93 -------------------------------- CONTRIBUTING.md | 2 +- 2 files changed, 1 insertion(+), 94 deletions(-) delete mode 100644 .github/workflows/auto-merge.yml diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml deleted file mode 100644 index 62a4c7d..0000000 --- a/.github/workflows/auto-merge.yml +++ /dev/null @@ -1,93 +0,0 @@ -# Arms GitHub's native auto-merge so a green PR lands unattended: the required -# checks gate it, no human click. Arming belongs to people with write access: -# - apply the `automerge` label (labelling needs triage or better), or -# - tick the test checkbox in the PR body - -# "- [x] A person reviewed each changed test and the behaviour change is intended" -# "- [x] No existing test changed" / "- [x] Tests change only on purpose" -# honoured only for authors with write access to the repo (checked through the -# API, see below), so an outside contributor cannot arm their own merge by typing. -# Tighter than traust-core: a breaking change (`type(scope)!:`) is armed only by the label, and -# paths in CODEOWNERS (the framework's shape) still wait for a code owner's approval. -# Merge commit only, matching the repo convention (pins point at PR commits). -# Never disarms: undoing is the UI's "Disable auto-merge", so a PR armed by hand -# is never clobbered by a body edit. -# -# pull_request_target: a write token for fork PRs too. Safe because nothing is -# checked out - the body is only pattern-matched, never evaluated. -# -# Takes effect once this file is on the DEFAULT branch: pull_request_target is a -# privileged trigger, and those only fire when the workflow exists on the default -# branch. Here that is `main`, while code lives on `development` - so the file has -# to be on `main` to run at all. (Same rule silently disables review-after-merge.yml.) -name: auto-merge - -on: - pull_request_target: - types: [opened, edited, reopened, ready_for_review, synchronize, labeled] - -permissions: - contents: write - pull-requests: write - -concurrency: - group: auto-merge-${{ github.event.pull_request.number }} - cancel-in-progress: true - -jobs: - arm: - if: >- - github.event.pull_request.state == 'open' && - github.event.pull_request.draft == false && - github.event.pull_request.base.ref == 'development' - runs-on: ubuntu-latest - steps: - - name: Arm auto-merge - env: - GH_TOKEN: ${{ github.token }} - GH_REPO: ${{ github.repository }} - PR: ${{ github.event.pull_request.number }} - AUTHOR: ${{ github.event.pull_request.user.login }} - LABELS: ${{ join(github.event.pull_request.labels.*.name, ',') }} - TITLE: ${{ github.event.pull_request.title }} - BODY: ${{ github.event.pull_request.body }} - run: | - set -euo pipefail - - case ",$LABELS," in *,automerge,*) labelled=yes ;; *) labelled=no ;; esac - ticked=no - if grep -qiE '^- \[[xX]\].*(a person reviewed each changed test|no existing tests? (changed|were edited)|tests? change only on purpose)' <<<"${BODY:-}"; then - ticked=yes - fi - - if [ "$labelled" = no ] && grep -qE '^[a-z]+(\([^)]*\))?!:' <<<"$TITLE"; then - echo "not armed: breaking change; a person applies the automerge label once it's reviewed" - exit 0 - fi - - if [ "$labelled" = no ] && [ "$ticked" = no ]; then - echo "not armed: no automerge label and no test checkbox ticked" - exit 0 - fi - # The body is written by the PR author, so the checkbox only counts for - # someone who can push here. author_association cannot answer that: it - # reports CONTRIBUTOR for every fork PR, an org admin's included. Ask the - # API for the author's actual permission instead (200 + "admin" for a - # fork PR from a repo admin). - if [ "$labelled" = no ]; then - permission=$(gh api "repos/$GH_REPO/collaborators/$AUTHOR/permission" \ - --jq '.permission' 2>/dev/null || true) - case "$permission" in - admin | maintain | write) ;; - *) - echo "not armed: $AUTHOR has '${permission:-no}' access, so the checkbox does not count; apply the automerge label instead" - exit 0 - ;; - esac - fi - - if [ "$(gh pr view "$PR" --json autoMergeRequest --jq '.autoMergeRequest != null')" = "true" ]; then - echo "auto-merge already enabled on #$PR" - exit 0 - fi - gh pr merge "$PR" --auto --merge - echo "auto-merge armed on #$PR: merge commit, lands when the required checks pass" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 53cb86c..33d012f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -72,7 +72,7 @@ GitHub Actions (`.github/workflows/ci.yml`) on every PR, in the merge queue and | `e2e` | `make e2e`: the generated client against `traust-server` built from core at `CORE_REF` | | `guardrails` | `make guardrails`: the AGENTS.md rules a machine can check, plus commit subjects | -`core-head.yml` runs nightly against core's `development` tip; red means bump `CORE_REF`. `auto-merge.yml` and `review-after-merge.yml` follow traust-core's merge-by-risk flow; paths in `CODEOWNERS` wait for a code owner. +`core-head.yml` runs nightly against core's `development` tip; red means bump `CORE_REF`. `review-after-merge.yml` follows traust-core's merge-by-risk flow; paths in `CODEOWNERS` wait for a code owner. ## Running tests