package scripts_test import ( "os" "os/exec" "path/filepath" "strings" "testing" ) func TestCoverageGatePolicyProfileCanBeExplicitlyOmitted(t *testing.T) { root, err := filepath.Abs(filepath.Join("..", "..")) if err != nil { t.Fatalf("Abs(repo root) error = %v", err) } binDir := t.TempDir() fakeGoPath := filepath.Join(binDir, "go") const fakeGo = `#!/bin/sh set -eu case "$1" in build) shift output= while [ "$#" -gt 0 ]; do case "$1" in -o) output="$2" shift 2 ;; *) shift ;; esac done cat > "$output" <<'EOF' #!/bin/sh printf '%s\n' "$@" > "$COVERAGE_ARGS_LOG" EOF chmod +x "$output" ;; list) printf '%s\n' "example.com/coverage-fixture" ;; *) printf 'unexpected fake go command: %s\n' "$1" >&2 exit 2 ;; esac ` if err := os.WriteFile(fakeGoPath, []byte(fakeGo), 0o755); err != nil { t.Fatalf("WriteFile(fake go) error = %v", err) } baseEnv := make([]string, 0, len(os.Environ())+2) for _, value := range os.Environ() { if strings.HasPrefix(value, "PATH=") || strings.HasPrefix(value, "COVERAGE_DIFF_PROFILE=") || strings.HasPrefix(value, "COVERAGE_ARGS_LOG=") { continue } baseEnv = append(baseEnv, value) } baseEnv = append(baseEnv, "PATH="+binDir+":"+os.Getenv("PATH")) runGate := func(t *testing.T, diffProfile *string) []string { t.Helper() argsLog := filepath.Join(t.TempDir(), "args.log") cmd := exec.Command( "sh", "./scripts/policy/check-coverage-gate.sh", "--base-ref", "HEAD", ) cmd.Dir = root cmd.Env = append(append([]string{}, baseEnv...), "COVERAGE_ARGS_LOG="+argsLog) if diffProfile != nil { cmd.Env = append(cmd.Env, "COVERAGE_DIFF_PROFILE="+*diffProfile) } output, runErr := cmd.CombinedOutput() if runErr != nil { t.Fatalf("coverage gate error = %v\noutput:\n%s", runErr, output) } data, readErr := os.ReadFile(argsLog) if readErr != nil { t.Fatalf("ReadFile(args log) error = %v", readErr) } return strings.Fields(string(data)) } assertDiffProfiles := func(t *testing.T, args []string, want ...string) { t.Helper() var got []string for i := 0; i+1 < len(args); i++ { if args[i] == "--diff-profile" { got = append(got, args[i+1]) i++ } } if strings.Join(got, "\n") != strings.Join(want, "\n") { t.Fatalf("diff profiles = %q, want %q; args = %q", got, want, args) } } t.Run("unset keeps strict policy profile", func(t *testing.T) { assertDiffProfiles( t, runGate(t, nil), "coverage-policy.txt", "coverage.txt", ) }) t.Run("explicit empty omits only policy profile", func(t *testing.T) { empty := "" assertDiffProfiles(t, runGate(t, &empty), "coverage.txt") }) } // TestCoverageWorkflowShardsAndBaselineCache pins the full-suite coverage // architecture: the candidate profile is produced by disjoint per-shard // helper jobs and reassembled before enforcement, and the merge-base profile // is reused only through an exact-key cache written by a green main push of // that same commit. Near-miss reuse (restore-keys) would compare the // candidate against the wrong commit and must never appear. func TestCoverageWorkflowShardsAndBaselineCache(t *testing.T) { root, err := filepath.Abs(filepath.Join("..", "..")) if err != nil { t.Fatalf("Abs(repo root) error = %v", err) } data, err := os.ReadFile(filepath.Join(root, ".github", "workflows", "ci.yml")) if err != nil { t.Fatalf("ReadFile(ci.yml) error = %v", err) } admission := string(data) for _, want := range []string{ "group: ci-${{ github.workflow }}-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || format('push-{0}', github.sha) }}", "cancel-in-progress: true", } { if !strings.Contains(admission, want) { t.Errorf("CI workflow missing latest-PR/exact-main producer contract %q", want) } } for _, forbidden := range []string{ "format('pr-{0}-{1}-{2}'", "github.event.pull_request.number || github.ref", } { if strings.Contains(admission, forbidden) { t.Errorf("CI workflow retains a stale concurrency identity %q", forbidden) } } currentStart := strings.Index(admission, "\n coverage-current:\n") fullStart := strings.Index(admission, "\n coverage-current-full:\n") supportingStart := strings.Index(admission, "\n coverage-supporting:\n") baselineStart := strings.Index(admission, "\n coverage-baseline:\n") metadataStart := strings.Index(admission, "\n coverage-main-metadata:\n") gateStart := strings.Index(admission, "\n coverage:\n") policyStart := strings.Index(admission, "\n policy:\n") if currentStart < 0 || fullStart <= currentStart || supportingStart <= fullStart || baselineStart <= supportingStart || metadataStart <= baselineStart || gateStart <= metadataStart || policyStart <= gateStart { t.Fatal("CI workflow missing ordered coverage job boundaries") } currentJob := admission[currentStart:fullStart] if !strings.Contains(currentJob, "needs.lint.outputs.full_suite != 'true'") { t.Error("coverage-current must be scoped-tier only; the full suite belongs to the shard matrix") } if strings.Contains(currentJob, "./ ./cmd/... ./internal/... ./skills/...") { t.Error("coverage-current must not retain the retired single serial full-suite run") } fullJob := admission[fullStart:supportingStart] for _, want := range []string{ "needs.lint.outputs.full_suite == 'true'", "fail-fast: false", " - app", " - cli", " - generators", " - helpers", " - remaining", `./scripts/ci/test-packages.sh list-coverage "$COVERAGE_SHARD"`, "go test -count=1 -p 1", `-coverprofile="coverage-shard-$COVERAGE_SHARD.txt"`, "-covermode=atomic", "name: coverage-current-shard-${{ matrix.shard }}", } { if !strings.Contains(fullJob, want) { t.Errorf("coverage-current-full missing shard contract %q", want) } } baselineJob := admission[baselineStart:metadataStart] if !strings.Contains(baselineJob, "timeout-minutes: 30") { t.Error("coverage-baseline must retain enough headroom for an authoritative cold-cache fallback") } cachePath := "coverage-cache.txt" baselineKey := "dws-coverage-full-v2-${{ env.COVERAGE_BASE_REF }}-go${{ steps.setup-go.outputs.go-version }}" for _, want := range []string{ "uses: actions/cache/restore@v4", "uses: actions/cache/save@v4", "path: " + cachePath, "key: " + baselineKey, "if: steps.baseline-cache.outputs.cache-hit != 'true'", "cp coverage-cache.txt coverage-base.txt", "cp coverage-base.txt coverage-cache.txt", } { if !strings.Contains(baselineJob, want) { t.Errorf("coverage-baseline missing cache contract %q", want) } } if strings.Count(baselineJob, "key: "+baselineKey) != 2 { t.Error("coverage-baseline restore and save must use the identical exact cache key") } if strings.Count(baselineJob, "path: "+cachePath) != 2 { t.Error("coverage-baseline restore and save must use the identical cache path/version") } if strings.Contains(baselineJob, "restore-keys") { t.Error("coverage baseline cache must stay exact-key; prefix restore-keys can resurrect a wrong-commit baseline") } metadataJob := admission[metadataStart:gateStart] for _, want := range []string{ "github.event_name == 'push'", "needs.lint.outputs.changelog_only == 'true' || needs.lint.outputs.docs_only == 'true'", "timeout-minutes: 30", "fetch-depth: 0", "PUSH_BEFORE_SHA: ${{ github.event.before }}", "PUSH_AFTER_SHA: ${{ github.event.after }}", "git merge-base --is-ancestor \"$PUSH_BEFORE_SHA\" \"$PUSH_AFTER_SHA\"", "git diff --name-only --no-renames -z", `^\.changes/[a-z0-9][a-z0-9._-]*\.md$`, `^\.changes/released/[0-9]+\.[0-9]+\.[0-9]+(-beta\.[1-9][0-9]*)?/[a-z0-9][a-z0-9._-]*\.md$`, "Refusing coverage-cache promotion for unreviewed change-fragment path", "Refusing coverage-cache promotion for executable path", "COVERAGE_SOURCE_REF=$PUSH_BEFORE_SHA", "id: metadata-current-cache", "id: metadata-source-cache", "key: dws-coverage-full-v2-${{ env.COVERAGE_SOURCE_REF }}-go${{ steps.setup-go-metadata.outputs.go-version }}", "go test -count=1 -p 1", "./ ./cmd/... ./internal/... ./skills/...", "key: dws-coverage-full-v2-${{ github.sha }}-go${{ steps.setup-go-metadata.outputs.go-version }}", "id: metadata-target-cache-verification", "lookup-only: true", "fail-on-cache-miss: true", "EXACT_CACHE_HIT: ${{ steps.metadata-target-cache-verification.outputs.cache-hit }}", `run: test "$EXACT_CACHE_HIT" = true`, } { if !strings.Contains(metadataJob, want) { t.Errorf("metadata-only main cache producer missing contract %q", want) } } if strings.Contains(metadataJob, "restore-keys") { t.Error("metadata-only main cache promotion must use exact source and target keys") } if strings.Count(metadataJob, "path: "+cachePath) != 4 { t.Error("metadata-only producer must restore target/source, save, and verify through the shared cache version path") } gateJob := admission[gateStart:policyStart] for _, want := range []string{ "- coverage-main-metadata", "MAIN_METADATA_RESULT: ${{ needs.coverage-main-metadata.result }}", "main_metadata_expected=success", `"main metadata cache:$MAIN_METADATA_RESULT:$main_metadata_expected"`, "pattern: coverage-current-*", "merge-multiple: true", "for shard in app cli generators helpers remaining; do", "test ! -f coverage.txt", `test "$(head -n 1 "$profile")" = "mode: atomic"`, "github.event_name == 'push'", "cp coverage.txt coverage-cache.txt", "path: " + cachePath, "key: dws-coverage-full-v2-${{ github.sha }}-go${{ steps.setup-go.outputs.go-version }}", "name: Verify push coverage cache exists", "id: push-cache-verification", "lookup-only: true", "fail-on-cache-miss: true", "EXACT_CACHE_HIT: ${{ steps.push-cache-verification.outputs.cache-hit }}", `run: test "$EXACT_CACHE_HIT" = true`, `"current shards:$CURRENT_FULL_RESULT:$current_full_expected"`, } { if !strings.Contains(gateJob, want) { t.Errorf("coverage gate missing shard assembly contract %q", want) } } if strings.Count(gateJob, "path: "+cachePath) != 2 { t.Error("green main push must save and verify the candidate profile through the same cache path/version as baseline restore") } } func TestFormulaCoverageBaselinePromotionContract(t *testing.T) { root, err := filepath.Abs(filepath.Join("..", "..")) if err != nil { t.Fatalf("Abs(repo root) error = %v", err) } promotionData, err := os.ReadFile(filepath.Join(root, ".github", "workflows", "coverage-baseline-promotion.yml")) if err != nil { t.Fatalf("ReadFile(coverage-baseline-promotion.yml) error = %v", err) } promotion := string(promotionData) for _, want := range []string{ "repository_dispatch:", "types: [coverage-baseline-promote]", "checks: write", "contents: read", "group: coverage-baseline-promotion-${{ github.event.client_payload.target_sha }}", "cancel-in-progress: false", "queue: max", "github.repository == 'DingTalk-Real-AI/dingtalk-workspace-cli'", "timeout-minutes: 30", "context.payload.client_payload?.target_sha", "context.payload.client_payload?.source_run_id", "context.payload.client_payload?.check_run_id", "targetCommit.parents.length !== 1", "targetCommit.author?.login !== 'github-actions[bot]'", "targetCommit.committer?.login !== 'github-actions[bot]'", "files.length !== 1", "Formula/dingtalk-workspace-cli.rb", "Formula/dingtalk-workspace-cli-beta.rb", "[skip ci", "await requireSuccessfulAdmission(parentSha, 'Formula parent')", "await requireSuccessfulAdmission(targetSha, 'Formula target')", "for (let attempt = 1; attempt <= 6; attempt += 1)", "setTimeout(resolve, 5000)", "run.app?.slug !== 'github-actions'", "run.conclusion !== 'success'", "basehead: `${targetSha}...${branch.commit.sha}`", "['ahead', 'identical'].includes(containment.status)", "promotionCheck.name !== 'Coverage Baseline Cache'", "promotionCheck.external_id !== promotionExternalId", "promotionCheck.status !== 'queued'", "core.setOutput('check_run_id', String(checkRunId))", "name: Mark Formula cache promotion in progress", "status: 'in_progress'", "persist-credentials: false", "ref: ${{ steps.validate-target.outputs.target_sha }}", "test \"$(git rev-parse HEAD^)\" = \"$PARENT_SHA\"", "id: target-cache", "id: parent-cache", "key: dws-coverage-full-v2-${{ steps.validate-target.outputs.parent_sha }}-go${{ steps.setup-go.outputs.go-version }}", "go test -count=1 -p 1", "./ ./cmd/... ./internal/... ./skills/...", "key: dws-coverage-full-v2-${{ steps.validate-target.outputs.target_sha }}-go${{ steps.setup-go.outputs.go-version }}", "lookup-only: true", "fail-on-cache-miss: true", "id: formula-target-cache-verification", "EXACT_CACHE_HIT: ${{ steps.formula-target-cache-verification.outputs.cache-hit }}", `run: test "$EXACT_CACHE_HIT" = true`, "name: Complete Formula cache promotion acknowledgement", "PROMOTION_JOB_STATUS: ${{ job.status }}", "conclusion: succeeded ? 'success' : 'failure'", } { if !strings.Contains(promotion, want) { t.Errorf("Formula baseline promotion missing contract %q", want) } } for _, want := range []string{ "actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683", "actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff", "actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830", "actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830", } { if !strings.Contains(promotion, want) { t.Errorf("Formula baseline promotion must pin trusted action %q", want) } } for _, forbidden := range []string{ "pull_request:", "pull_request_target:", "push:", "workflow_dispatch:", "restore-keys", "HOMEBREW_PR_TOKEN", "RELEASE_GOVERNANCE_TOKEN", "contents: write", } { if strings.Contains(promotion, forbidden) { t.Errorf("Formula baseline promotion must not contain %q", forbidden) } } validateIndex := strings.Index(promotion, "name: Validate Formula-only main target") checkoutIndex := strings.Index(promotion, "name: Check out validated Formula-only target") if validateIndex < 0 || checkoutIndex <= validateIndex { t.Error("Formula target must be fully validated before it is checked out or executed") } ackReadIndex := strings.Index(promotion, "const {data: promotionCheck} = await github.rest.checks.get") ackOutputIndex := strings.Index(promotion, "core.setOutput('check_run_id', String(checkRunId))") targetReadIndex := strings.Index(promotion, "const {data: targetCommit} = await github.rest.repos.getCommit") if ackReadIndex < 0 || ackOutputIndex <= ackReadIndex || targetReadIndex <= ackOutputIndex { t.Error("Formula acknowledgement must be identity-checked and bound to the finalizer before target validation") } if strings.Count(promotion, "path: coverage-cache.txt") != 4 { t.Error("Formula promotion must restore target/source, save, and verify through the shared cache version path") } releaseData, err := os.ReadFile(filepath.Join(root, ".github", "workflows", "release.yml")) if err != nil { t.Fatalf("ReadFile(release.yml) error = %v", err) } release := string(releaseData) publishStart := strings.Index(release, " publish-release:\n") sealStart := strings.Index(release, " - name: Seal Formula-only Code Admission contexts\n") if publishStart < 0 || sealStart <= publishStart { t.Fatal("release workflow missing Formula-only seal start") } if !strings.Contains(release[publishStart:sealStart], "timeout-minutes: 30") { t.Error("publish-release must not be extended by cache acknowledgement polling") } sealEnd := strings.Index(release[sealStart:], "\n - name: Reverify exact immutable npm package\n") if sealEnd < 0 { t.Fatal("release workflow missing Formula-only seal boundaries") } seal := release[sealStart : sealStart+sealEnd] for _, want := range []string{ `core.setOutput("coverage_baseline_required", "true")`, `core.setOutput("coverage_baseline_commit", commit)`, } { if !strings.Contains(seal, want) { t.Errorf("Formula seal missing cache-promotion dispatch contract %q", want) } } for _, forbidden := range []string{ "for (let attempt = 1; attempt <= 180; attempt += 1)", "github.rest.checks.get", "promotionComplete", "Coverage Baseline Cache", "github.rest.repos.createDispatchEvent", } { if strings.Contains(seal, forbidden) { t.Errorf("irreversible publish-release must not wait on cache through %q", forbidden) } } confirmationStart := strings.Index(release, " coverage-baseline-confirmation:\n") deliveryGateStart := strings.Index(release, " release-delivery-gate:\n") if confirmationStart < 0 || deliveryGateStart <= confirmationStart { t.Fatal("release workflow missing independent Formula baseline confirmation job") } confirmation := release[confirmationStart:deliveryGateStart] for _, want := range []string{ "if (!['true', 'false'].includes(rawRequired))", "github.rest.checks.create", "name: 'Coverage Baseline Cache'", "status: 'queued'", "external_id: expectedExternalId", "github.rest.repos.createDispatchEvent", "event_type: 'coverage-baseline-promote'", "check_run_id: String(promotionCheck.id)", "conclusion: 'failure'", "for (let attempt = 1; attempt <= 180; attempt += 1)", "github.rest.checks.get", "currentCheck.name !== 'Coverage Baseline Cache'", "currentCheck.conclusion !== 'success'", "setTimeout(resolve, 10000)", "Formula baseline promotion timed out", } { if !strings.Contains(confirmation, want) { t.Errorf("independent Formula baseline confirmation missing %q", want) } } } func TestCoverageBaselineRepairContract(t *testing.T) { root, err := filepath.Abs(filepath.Join("..", "..")) if err != nil { t.Fatalf("Abs(repo root) error = %v", err) } data, err := os.ReadFile(filepath.Join(root, ".github", "workflows", "coverage-baseline-repair.yml")) if err != nil { t.Fatalf("ReadFile(coverage-baseline-repair.yml) error = %v", err) } workflow := string(data) for _, want := range []string{ "pull_request_target:", "branches: [main]", "types: [closed]", "workflow_run:", "workflows: [CI]", "types: [completed]", "repository_dispatch:", "types: [coverage-baseline-repair]", "schedule:", `cron: "23 * * * *"`, "workflow_dispatch:", "group: coverage-baseline-repair-${{ github.event_name == 'pull_request_target' && github.event.pull_request.merge_commit_sha || github.event_name == 'workflow_run' && github.event.workflow_run.head_sha || github.event_name == 'repository_dispatch' && github.event.client_payload.merge_commit_sha || github.sha }}", "cancel-in-progress: false", "queue: max", } { if !strings.Contains(workflow, want) { t.Errorf("coverage baseline repair missing workflow contract %q", want) } } dispatchStart := strings.Index(workflow, "\n dispatch-merged-pr:\n") failedDispatchStart := strings.Index(workflow, "\n dispatch-failed-ci:\n") repairStart := strings.Index(workflow, "\n repair:\n") if dispatchStart < 0 || failedDispatchStart <= dispatchStart || repairStart <= failedDispatchStart { t.Fatal("coverage baseline repair is missing ordered merged-PR, failed-CI, and producer jobs") } dispatcher := workflow[dispatchStart:failedDispatchStart] for _, want := range []string{ "github.event_name == 'pull_request_target'", "github.event.pull_request.merged == true", "github.repository == 'DingTalk-Real-AI/dingtalk-workspace-cli'", "actions: read", "contents: write", "pull-requests: read", "actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b", "context.payload.repository?.default_branch !== 'main'", "currentPull.state === 'closed'", "currentPull.merged === true", "typeof currentPull.merged_at === 'string'", "const baseRef = eventPull?.base?.ref;", "baseRef !== 'main'", "currentPull.base?.ref === 'main'", "isStableMergedPRIdentity(", "currentPull.head?.sha === headSha", "currentPull.merge_commit_sha === mergeCommitSha", "for (let attempt = 1; attempt <= 6; attempt += 1)", "setTimeout(resolve, 5000)", "basehead: `${targetSha}...${branch.commit.sha}`", "['ahead', 'identical'].includes(comparison.status)", "for (let attempt = 1; attempt <= 12; attempt += 1)", "github.rest.actions.getWorkflow", "workflow_id: '.github/workflows/ci.yml'", "ciWorkflow.name !== 'CI'", "ciWorkflow.path !== '.github/workflows/ci.yml'", "ciWorkflow.state !== 'active'", "github.rest.actions.listWorkflowRunsForRepo", "branch: 'main'", "event: 'push'", "run.name === 'CI'", "run.workflow_id === ciWorkflow.id", "run.path === ciWorkflow.path", "run.event === 'push'", "run.head_sha === mergeCommitSha", "run.head_branch === 'main'", "['queued', 'in_progress', 'completed'].includes(run.status)", "setTimeout(resolve, 5000)", "repair dispatch is unnecessary", "github.rest.repos.createDispatchEvent", "event_type: 'coverage-baseline-repair'", "source: 'merged_pr'", "pull_number: String(pullNumber)", "head_sha: headSha", "merge_commit_sha: mergeCommitSha", } { if !strings.Contains(dispatcher, want) { t.Errorf("merged-PR repair dispatcher missing %q", want) } } ciWorkflowLookup := strings.Index(dispatcher, "github.rest.actions.getWorkflow") pushRunLookup := strings.Index(dispatcher, "github.rest.actions.listWorkflowRunsForRepo") repairDispatch := strings.Index(dispatcher, "github.rest.repos.createDispatchEvent") if ciWorkflowLookup < 0 || pushRunLookup <= ciWorkflowLookup || repairDispatch <= pushRunLookup { t.Error("merged-PR dispatcher must bind the fixed CI workflow before exhausting exact push-run lookup and dispatch") } stableIdentityCheck := strings.Index(dispatcher, "if (!isStableMergedPRIdentity(") mainContainmentCheck := strings.Index(dispatcher, "await requireMainContainment(mergeCommitSha)") if stableIdentityCheck < 0 || mainContainmentCheck <= stableIdentityCheck || repairDispatch <= mainContainmentCheck { t.Error("merged-PR dispatcher must prove stable PR identity and main containment before dispatch") } for _, forbidden := range []string{ "actions/checkout@", "actions/cache/", "actions/setup-go@", "go test ", "github.event.pull_request.head.ref", "currentPull.base.sha", "base_sha", "secrets.", } { if strings.Contains(dispatcher, forbidden) { t.Errorf("privileged pull_request_target dispatcher must not contain %q", forbidden) } } failedDispatcher := workflow[failedDispatchStart:repairStart] for _, want := range []string{ "github.event_name == 'workflow_run'", "github.repository == 'DingTalk-Real-AI/dingtalk-workspace-cli'", "github.event.workflow_run.name == 'CI'", "github.event.workflow_run.event == 'push'", "github.event.workflow_run.head_branch == 'main'", "github.event.workflow_run.status == 'completed'", "github.event.workflow_run.conclusion != 'success'", "actions: read", "contents: write", "actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b", "context.payload.repository?.default_branch !== 'main'", "eventRun?.name !== 'CI'", "eventRun?.event !== 'push'", "eventRun?.head_branch !== 'main'", "eventRun?.status !== 'completed'", "conclusion === 'success'", "github.rest.actions.getWorkflow", "workflow_id: '.github/workflows/ci.yml'", "github.rest.actions.getWorkflowRun", "eventRun.workflow_id !== ciWorkflow.id", "currentRun.workflow_id !== ciWorkflow.id", "currentRun.name !== 'CI'", "currentRun.event !== 'push'", "currentRun.head_branch !== 'main'", "currentRun.head_sha !== headSha", "currentRun.run_attempt !== runAttempt", "currentRun.status !== 'completed'", "currentRun.conclusion !== conclusion", "currentRun.repository?.full_name !== upstream", "currentRun.head_repository?.full_name !== upstream", "github.rest.repos.createDispatchEvent", "event_type: 'coverage-baseline-repair'", "source: 'failed_ci'", "workflow_run_id: String(runID)", "workflow_run_attempt: String(runAttempt)", "workflow_conclusion: conclusion", "merge_commit_sha: headSha", } { if !strings.Contains(failedDispatcher, want) { t.Errorf("failed-CI repair dispatcher missing %q", want) } } failedRunRead := strings.Index(failedDispatcher, "github.rest.actions.getWorkflowRun") failedRepairDispatch := strings.Index(failedDispatcher, "github.rest.repos.createDispatchEvent") if failedRunRead < 0 || failedRepairDispatch <= failedRunRead { t.Error("workflow_run dispatcher must API-bind the exact failed CI run before repository dispatch") } for _, forbidden := range []string{ "actions/checkout@", "actions/cache/", "actions/setup-go@", "go test ", "secrets.", } { if strings.Contains(failedDispatcher, forbidden) { t.Errorf("privileged workflow_run dispatcher must not contain %q", forbidden) } } producer := workflow[repairStart:] for _, want := range []string{ "github.event_name == 'repository_dispatch' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'", "timeout-minutes: 35", "actions: read", "contents: read", "pull-requests: read", "id: resolve-target", "context.eventName === 'repository_dispatch'", "payload.source === 'merged_pr'", "payload.pull_number", "payload.head_sha", "payload.merge_commit_sha", "currentPull.state === 'closed'", "currentPull.merged === true", "typeof currentPull.merged_at === 'string'", "currentPull.base?.ref === 'main'", "isStableMergedPRIdentity(", "currentPull.head?.sha === headSha", "currentPull.merge_commit_sha === mergeCommitSha", "payload.source === 'failed_ci'", "payload.workflow_run_id", "payload.workflow_run_attempt", "payload.workflow_conclusion", "github.rest.actions.getWorkflow", "workflow_id: '.github/workflows/ci.yml'", "github.rest.actions.getWorkflowRun", "ciWorkflow.name !== 'CI'", "ciWorkflow.path !== '.github/workflows/ci.yml'", "currentRun.id !== workflowRunID", "currentRun.workflow_id !== ciWorkflow.id", "currentRun.name !== 'CI'", "currentRun.event !== 'push'", "currentRun.head_branch !== 'main'", "currentRun.head_sha !== targetSha", "currentRun.run_attempt !== workflowRunAttempt", "currentRun.status !== 'completed'", "currentRun.conclusion !== workflowConclusion", "coverage-baseline-repair payload has an unknown source", "context.ref !== 'refs/heads/main'", "targetSha = context.sha", "for (let attempt = 1; attempt <= 6; attempt += 1)", "basehead: `${targetSha}...${branch.commit.sha}`", "core.setOutput('target_sha', targetSha)", "actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683", "fetch-depth: 0", "persist-credentials: false", "ref: ${{ steps.resolve-target.outputs.target_sha }}", `run: test "$(git rev-parse HEAD)" = "$TARGET_SHA"`, "actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff", "id: target-cache", "actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830", "key: dws-coverage-full-v2-${{ steps.resolve-target.outputs.target_sha }}-go${{ steps.setup-go.outputs.go-version }}", "go test -count=1 -p 1", "./ ./cmd/... ./internal/... ./skills/...", "actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830", "id: target-cache-verification", "lookup-only: true", "fail-on-cache-miss: true", "EXACT_CACHE_HIT: ${{ steps.target-cache-verification.outputs.cache-hit }}", `run: test "$EXACT_CACHE_HIT" = true`, } { if !strings.Contains(producer, want) { t.Errorf("trusted coverage repair producer missing %q", want) } } for _, forbidden := range []string{ "restore-keys", "github.event.pull_request.head.ref", "currentPull.base.sha", "base_sha", "HOMEBREW_PR_TOKEN", "RELEASE_GOVERNANCE_TOKEN", "REVIEWER_ROUTER_APP_PRIVATE_KEY", "contents: write", } { if strings.Contains(producer, forbidden) { t.Errorf("trusted coverage repair producer must not contain %q", forbidden) } } if strings.Count(producer, "path: coverage-cache.txt") != 3 { t.Error("coverage repair must restore, save, and independently verify one exact cache path/version") } if strings.Count(producer, "key: dws-coverage-full-v2-${{ steps.resolve-target.outputs.target_sha }}-go${{ steps.setup-go.outputs.go-version }}") != 3 { t.Error("coverage repair restore, save, and verification must share one exact target key") } stablePayloadIdentityCheck := strings.Index(producer, "if (!isStableMergedPRIdentity(") mainPayloadContainmentCheck := strings.Index(producer, "await requireMainContainment(targetSha)") resolvedTargetOutput := strings.Index(producer, "core.setOutput('target_sha', targetSha)") if stablePayloadIdentityCheck < 0 || mainPayloadContainmentCheck <= stablePayloadIdentityCheck || resolvedTargetOutput <= mainPayloadContainmentCheck { t.Error("merged-PR producer must prove stable payload identity and main containment before resolving checkout target") } validateIndex := strings.Index(producer, "name: Resolve trusted main repair target") checkoutIndex := strings.Index(producer, "name: Check out exact protected-main target") if validateIndex < 0 || checkoutIndex <= validateIndex { t.Error("repository_dispatch input must be fully bound to its protected-main source before checkout") } }