Skip to content

Parse the DR rebuild publisher step instead of scanning workflow text #2941

Description

@devantler

🤖 Generated by the Agentic Engineer

Evidence. validateDRWorkflow establishes the DR rebuild's publication wiring by scanning workflow text, not by parsing it. containsLine(job, "uses: ./.github/actions/deploy-prod/publish-platform-manifests") is satisfied by that string appearing anywhere in the job — including inside a comment or a block scalar. Reported by CodeRabbit as a P1 during review of #2939, and verified here: the symbols carrying this (validateDRWorkflow, extractJob, containsExactLine, containsLine) are untouched by that PR, so this is pre-existing rather than a regression it introduced.

Impact. The disaster-recovery route can be pointed at a different publisher while the validator still finds the expected text and reports success — so DR delivery could publish through logic this contract never checks, which is the exact drift the shared-action requirement exists to prevent. The same reasoning applies to the credential assertions (ghcr-token, hcloud-token), which are matched the same way and so are not proven to sit on the publishing step at all.

Why this is its own issue. #2939 converted the direct-push and merge-queue routes from text scanning to parsing and enforced-step checks. This is the same class at the third route, outside that PR's diff, and #2939 is already at review round 10 on a single concern.

Expected behaviour. Parse dr-rebuild.yaml, locate jobs.rebuild.steps, and require an enforced step (neither skipped nor failure-suppressed) whose uses value equals nestedPublisherAction — reusing requireEnforcedStep/usesAction, which #2939 already introduced for exactly this. Assert with.ghcr-token and with.hcloud-token on that same step rather than anywhere in the job.

Acceptance criteria.

  • validateDRWorkflow resolves the rebuild job and its publisher step through the YAML parser, not string containment.
  • The publisher step's uses is matched by equality, and the two credentials are asserted on that step.
  • The step is proven enforced (no if: skip, no continue-on-error).
  • Ablations covering: the real uses replaced while the expected text survives in a comment; the same in a block scalar; credentials moved to a different step; the publisher step skipped/failure-suppressed. Each must be refused.
  • The permission assertions (id-token/packages/attestations: write) move to parsed lookups too, or the issue records why they stay textual.

Size. Small — the parsing helpers and requireEnforcedStep already exist from #2939; this is applying them to the third route.

Activity

  1. moved this to 📥 Backlog in 🌊 Project Boardon Aug 4, 2026
  2. coderabbitai commented on Aug 4, 2026

    @coderabbitai
    Contributor
    🔗 Related PRs

    #2622 - fix(ci): heal cancelled merge-group deploys [merged]
    #2753 - fix(aws): allow EKS version discovery [merged]
    #2825 - fix(ci): queue prod deploys instead of dropping the pending one [merged]
    #2830 - feat(ci): publish Kubescape posture findings to Code Scanning [merged]
    #2930 - feat(ci): verify published evidence before promoting the prod digest [merged]


    📝 Issue Planner

    Check the box below or use the @coderabbitai plan command to generate an implementation plan and prompts that you can use with your favorite coding assistant.

    • Create Plan

    🧪 Issue enrichment is currently in open beta.

    You can configure auto-planning by selecting labels in the issue_enrichment configuration.

    To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

    issue_enrichment:
      auto_enrich:
        enabled: false

    💬 Have feedback or questions? Drop into our discord!

  3. self-assigned this
    on Aug 6, 2026
  4. moved this from 📥 Backlog to 👀 In Review in 🌊 Project Boardon Aug 6, 2026
  5. moved this from 👀 In Review to ✅ Done in 🌊 Project Boardon Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Fields

No fields configured for Security.

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions