From 354e5cf4b44a9c2d23a21193c554fa650f834f69 Mon Sep 17 00:00:00 2001 From: Alexander Nachtmann Date: Thu, 15 Jan 2026 07:06:06 +0100 Subject: [PATCH 1/3] ci: add upgraded auto-merge workflow with major version protection --- .github/workflows/auto-merge.yml | 136 +++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 .github/workflows/auto-merge.yml diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml new file mode 100644 index 0000000..3a341c8 --- /dev/null +++ b/.github/workflows/auto-merge.yml @@ -0,0 +1,136 @@ +# Auto-merge workflow for trusted PRs +# +# Tiers: +# 1a. Dependabot PRs: Auto-approve + auto-merge for patch/minor +# 1b. Renovate PRs: Auto-approve + auto-merge +# 2. AI Agent fix PRs (copilot/, jules/, claude/): Auto-merge when CI passes +# 3. CodeRabbit approved PRs: Auto-merge when CI passes + +name: Auto-merge + +on: + pull_request_target: + types: [opened, synchronize, reopened, ready_for_review] + pull_request_review: + types: [submitted] + check_suite: + types: [completed] + +permissions: + contents: write + pull-requests: write + +jobs: + dependabot-auto-merge: + name: Dependabot auto-merge + runs-on: ubuntu-latest + if: github.actor == 'dependabot[bot]' + + steps: + - name: Fetch Dependabot metadata + id: metadata + uses: dependabot/fetch-metadata@v2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Auto-approve patch and minor updates + if: steps.metadata.outputs.update-type != 'version-update:semver-major' + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: gh pr review --approve "$PR_URL" + + - name: Enable auto-merge for patch and minor + if: steps.metadata.outputs.update-type != 'version-update:semver-major' + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: gh pr merge --auto --squash "$PR_URL" + + - name: Comment on major updates + if: steps.metadata.outputs.update-type == 'version-update:semver-major' + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + DEP_NAMES: ${{ steps.metadata.outputs.dependency-names }} + PREV_VERSION: ${{ steps.metadata.outputs.previous-version }} + NEW_VERSION: ${{ steps.metadata.outputs.new-version }} + run: | + gh pr comment "$PR_URL" --body "## ⚠️ Major Version Update + + This is a **major version update** that may contain breaking changes. + + **Manual review required.** + + Dependency: \`$DEP_NAMES\` + Update: \`$PREV_VERSION\` → \`$NEW_VERSION\`" + + renovate-auto-merge: + name: Renovate auto-merge + runs-on: ubuntu-latest + if: github.actor == 'renovate[bot]' + + steps: + - name: Auto-approve Renovate PRs + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: gh pr review --approve "$PR_URL" + + - name: Enable auto-merge for Renovate + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: gh pr merge --auto --squash "$PR_URL" + + ai-agent-auto-merge: + name: AI Agent auto-merge + runs-on: ubuntu-latest + if: | + startsWith(github.event.pull_request.head.ref, 'copilot/') || + startsWith(github.event.pull_request.head.ref, 'jules/') || + startsWith(github.event.pull_request.head.ref, 'claude/') + + steps: + - name: Identify AI agent + id: agent + env: + BRANCH: ${{ github.event.pull_request.head.ref }} + run: | + if [[ "$BRANCH" == copilot/* ]]; then + echo "agent=Copilot" >> "$GITHUB_OUTPUT" + elif [[ "$BRANCH" == jules/* ]]; then + echo "agent=Jules" >> "$GITHUB_OUTPUT" + elif [[ "$BRANCH" == claude/* ]]; then + echo "agent=Claude" >> "$GITHUB_OUTPUT" + fi + + - name: Auto-approve AI agent PRs + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + AGENT: ${{ steps.agent.outputs.agent }} + run: | + echo "Auto-approving $AGENT PR" + gh pr review --approve "$PR_URL" --body "✅ Auto-approved: $AGENT autonomous fix PR" + + - name: Enable auto-merge for AI agent PRs + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: gh pr merge --auto --squash "$PR_URL" + + coderabbit-auto-merge: + name: CodeRabbit auto-merge + runs-on: ubuntu-latest + if: | + github.event_name == 'pull_request_review' && + github.event.review.state == 'approved' && + github.event.review.user.login == 'coderabbitai[bot]' + + steps: + - name: Enable auto-merge for CodeRabbit approved PRs + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: gh pr merge --auto --squash "$PR_URL" From 3e67d6497c71a220f46e791a301debaf2e5363c3 Mon Sep 17 00:00:00 2001 From: Alexander Nachtmann Date: Thu, 15 Jan 2026 07:06:28 +0100 Subject: [PATCH 2/3] ci: remove old dependabot-auto-merge.yml (replaced by auto-merge.yml) --- .github/workflows/dependabot-auto-merge.yml | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 .github/workflows/dependabot-auto-merge.yml diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml deleted file mode 100644 index fed5b06..0000000 --- a/.github/workflows/dependabot-auto-merge.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Dependabot auto-merge -on: pull_request - -permissions: - contents: write - pull-requests: write - -jobs: - auto-merge: - runs-on: ubuntu-latest - if: github.actor == 'dependabot[bot]' - steps: - - name: Enable auto-merge - run: gh pr merge --auto --squash "$PR_URL" - env: - PR_URL: ${{ github.event.pull_request.html_url }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} From e25b95eae08d3ac08d74eb94b285f36bae26255e Mon Sep 17 00:00:00 2001 From: Alexander Nachtmann Date: Thu, 15 Jan 2026 08:00:43 +0100 Subject: [PATCH 3/3] fix: apply CodeRabbit suggestions - remove unused trigger + add actor validation - Remove unused check_suite trigger (no job references it) - Add actor validation to AI agent job for security (prevents anyone from creating copilot/jules/claude branches) --- .github/workflows/auto-merge.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml index 3a341c8..5a19875 100644 --- a/.github/workflows/auto-merge.yml +++ b/.github/workflows/auto-merge.yml @@ -13,8 +13,6 @@ on: types: [opened, synchronize, reopened, ready_for_review] pull_request_review: types: [submitted] - check_suite: - types: [completed] permissions: contents: write @@ -87,9 +85,12 @@ jobs: name: AI Agent auto-merge runs-on: ubuntu-latest if: | - startsWith(github.event.pull_request.head.ref, 'copilot/') || - startsWith(github.event.pull_request.head.ref, 'jules/') || - startsWith(github.event.pull_request.head.ref, 'claude/') + (github.actor == 'copilot[bot]' || github.actor == 'jules[bot]' || github.actor == 'claude-code[bot]') && + ( + startsWith(github.event.pull_request.head.ref, 'copilot/') || + startsWith(github.event.pull_request.head.ref, 'jules/') || + startsWith(github.event.pull_request.head.ref, 'claude/') + ) steps: - name: Identify AI agent