From ca8a3046de068d3456f8a5ee6202a46b525276d2 Mon Sep 17 00:00:00 2001 From: Jordan Ritter Date: Thu, 16 Jul 2026 14:48:07 -0700 Subject: [PATCH 1/2] chore: Fix Drift: authenticate via copilotkit-devops-bot app token GITHUB_TOKEN-created PRs don't trigger downstream CI and github-actions[bot] can't satisfy main's approval rule, so drift PRs couldn't get real CI or auto-merge. Mint a devops-bot (app-id 1108748) installation token via actions/create-github-app-token and use it for the push, PR create, and merge. App-token PRs trigger pull_request/checks, and devops-bot is a scoped Integration bypass actor on main's ruleset. Because a ruleset bypass actor bypasses the ENTIRE ruleset (no required-checks rule holds the bot's PR), enforce CI-green in the workflow: wait for at least one check to register, watch checks with --fail-fast, and only then merge. --- .github/workflows/fix-drift.yml | 39 +++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/.github/workflows/fix-drift.yml b/.github/workflows/fix-drift.yml index a402bc16..213e38bb 100644 --- a/.github/workflows/fix-drift.yml +++ b/.github/workflows/fix-drift.yml @@ -28,6 +28,12 @@ jobs: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false + - name: Mint app token + id: app-token + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + with: + app-id: '1108748' + private-key: ${{ secrets.DEVOPS_BOT_PRIVATE_KEY }} - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: @@ -136,14 +142,14 @@ jobs: if: steps.autofix.outcome == 'success' && success() && steps.check.outputs.skip != 'true' run: git config --local url."https://x-access-token:${TOKEN}@github.com/".insteadOf "https://github.com/" env: - TOKEN: ${{ secrets.GITHUB_TOKEN }} + TOKEN: ${{ steps.app-token.outputs.token }} # Step 5: Create PR on success - name: Create PR id: pr if: steps.autofix.outcome == 'success' && success() && steps.check.outputs.skip != 'true' env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ steps.app-token.outputs.token }} run: | npx tsx scripts/fix-drift.ts --create-pr PR_URL=$(gh pr list --head "$(git branch --show-current)" --json url --jq '.[0].url') @@ -154,9 +160,34 @@ jobs: - name: Auto-merge PR if: success() && steps.pr.outputs.url != '' env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ steps.app-token.outputs.token }} PR_URL: ${{ steps.pr.outputs.url }} - run: gh pr merge "$PR_URL" --merge --auto + run: | + # Wait for CI to register and pass before merging. A ruleset bypass + # actor bypasses the entire ruleset, so the green gate must live here, + # not in branch protection. `gh pr checks --watch` blocks until all + # checks complete and exits non-zero if any fail; --fail-fast bails on + # first failure. Treat "no checks" as NOT-green: require at least one. + # + # First poll until at least one check is registered (up to ~5 min). + count=0 + for i in $(seq 1 10); do + count=$(gh pr checks "$PR_URL" 2>/dev/null | wc -l) + if [ "$count" -gt 0 ]; then + echo "CI checks registered ($count rows), proceeding to watch" + break + fi + echo "No checks registered yet (attempt $i/10), waiting 30s..." + sleep 30 + done + if [ "$count" -eq 0 ]; then + echo "::error::No CI checks ever registered — not merging" + exit 1 + fi + gh pr checks "$PR_URL" --watch --fail-fast --interval 30 || { + echo "::error::CI checks failed or none present — not merging"; exit 1; + } + gh pr merge "$PR_URL" --merge # Step 7: Slack notification on successful fix - name: Notify Slack on fix success From f3365a6e098e84f1f8a2edb6c9a34ed003bf30f4 Mon Sep 17 00:00:00 2001 From: Jordan Ritter Date: Thu, 16 Jul 2026 14:54:19 -0700 Subject: [PATCH 2/2] fix: scope app token permissions and fix prettier formatting Adds permission-contents and permission-pull-requests inputs to the create-github-app-token step to limit the minted token's scope (fixes zizmor github-app finding). Also converts single-quoted app-id value to double quotes to satisfy prettier. --- .github/workflows/fix-drift.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/fix-drift.yml b/.github/workflows/fix-drift.yml index 213e38bb..022192e4 100644 --- a/.github/workflows/fix-drift.yml +++ b/.github/workflows/fix-drift.yml @@ -32,8 +32,10 @@ jobs: id: app-token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 with: - app-id: '1108748' + app-id: "1108748" private-key: ${{ secrets.DEVOPS_BOT_PRIVATE_KEY }} + permission-contents: write + permission-pull-requests: write - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: