From 47d09d5a4804e836ead922e478b5dcdc193a5afa Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 14 Jul 2026 05:12:36 +0000 Subject: [PATCH] test(ci): guard the Codex auto-resolve missing-token graceful skip The graceful skip that keeps the request job green when CODEX_TRIGGER_TOKEN is unset (job-env binding + step-level if-guards + warning) had no regression coverage, so it could be silently removed and turn every Codex review into a red check on a merged-but-unconfigured workflow. - Assert the missing-token handling (env binding, both if-guards, warning message) in scripts/check-codex-autofix-workflow.mjs. - Add guard mutation tests that fail if the warning branch or the request step's skip guard is removed. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01NrdqyvKzaovZUX9haKfgjM --- scripts/check-codex-autofix-workflow.mjs | 16 +++++++++++++++ tests/codex-autofix-workflow.test.ts | 26 ++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/scripts/check-codex-autofix-workflow.mjs b/scripts/check-codex-autofix-workflow.mjs index dd881041b..498b62c48 100644 --- a/scripts/check-codex-autofix-workflow.mjs +++ b/scripts/check-codex-autofix-workflow.mjs @@ -136,6 +136,22 @@ for (const requiredCheck of requiredTokenChecks) { } } +// When CODEX_TRIGGER_TOKEN is unset the request job must skip gracefully with a +// warning rather than hard-fail the check, so a merged-but-unconfigured workflow +// never blocks unrelated PRs. +const requiredMissingTokenHandlingChecks = [ + "CODEX_TRIGGER_TOKEN: ${{ secrets.CODEX_TRIGGER_TOKEN }}", + "if: ${{ env.CODEX_TRIGGER_TOKEN == '' }}", + "if: ${{ env.CODEX_TRIGGER_TOKEN != '' }}", + "CODEX_TRIGGER_TOKEN secret is not configured", +]; + +for (const requiredCheck of requiredMissingTokenHandlingChecks) { + if (!workflow.includes(requiredCheck)) { + failures.push(`Codex auto-resolve workflow is missing graceful missing-token handling: ${requiredCheck}`); + } +} + const requiredConcurrencyChecks = [ " concurrency:", " group: codex-autoresolve-${{ github.event.pull_request.number }}", diff --git a/tests/codex-autofix-workflow.test.ts b/tests/codex-autofix-workflow.test.ts index 9a782804d..07f058103 100644 --- a/tests/codex-autofix-workflow.test.ts +++ b/tests/codex-autofix-workflow.test.ts @@ -337,6 +337,32 @@ describe("Codex auto-resolve workflow guard", () => { expect(result.output).toContain("missing trusted duplicate-marker check"); }); + it("rejects removing the missing-token warning branch", () => { + const workflow = originalWorkflow.replace( + ` - name: Warn when the trigger token is not configured + if: \${{ env.CODEX_TRIGGER_TOKEN == '' }} + run: echo "::warning title=Codex auto-resolve::CODEX_TRIGGER_TOKEN secret is not configured; skipping the Codex auto-resolve request. Codex will not be asked to resolve findings until this fine-grained PAT secret is set." +`, + "", + ); + expect(workflow).not.toBe(originalWorkflow); + + const result = runGuard(workflow); + + expect(result.status).toBe(1); + expect(result.output).toContain("graceful missing-token handling"); + }); + + it("rejects removing the graceful-skip guard on the request step", () => { + const workflow = originalWorkflow.replace(" if: ${{ env.CODEX_TRIGGER_TOKEN != '' }}\n", ""); + expect(workflow).not.toBe(originalWorkflow); + + const result = runGuard(workflow); + + expect(result.status).toBe(1); + expect(result.output).toContain("graceful missing-token handling"); + }); + it("rejects workflow-level concurrency that includes unrelated events", () => { const workflow = originalWorkflow.replace( ` concurrency: