Skip to content

fix(agentic-ci): report authorized DCO status#819

Merged
andreatnvidia merged 6 commits into
mainfrom
andreatgretel/fix/agentic-ci-dco-status
Jul 16, 2026
Merged

fix(agentic-ci): report authorized DCO status#819
andreatnvidia merged 6 commits into
mainfrom
andreatgretel/fix/agentic-ci-dco-status

Conversation

@andreatnvidia

@andreatnvidia andreatnvidia commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

📋 Summary

This PR makes maintainer authorization of trusted Agentic CI pull requests satisfy the required DCOAssistant branch-protection context. On PR #816, the successful manually dispatched check ran on the exact head but was not reflected in the required PR check rollup, so this workflow now publishes an explicit commit status on the already validated head SHA.

The authorization path is also hardened by limiting status-write permission to the DCO job and refusing to dispatch privileged workflow definitions that differ from current main.

🔗 Related Issue

N/A - discovered while authorizing PR #816.

🔄 Changes

  • Publish DCOAssistant=success only after the existing PR trust and exact-head validation succeeds.
  • Scope statuses: write to the DCOAssistant job.
  • Link the reported status to the authorization workflow run for auditability.
  • Require the PR-head versions of ci.yml and agentic-ci-authorized-checks.yml to match main before dispatch.
  • See agentic-ci-authorized-checks.yml and authorize-agentic-ci.yml.

🔍 Attention Areas

⚠️ Reviewers: Please verify the status-write boundary, exact-head checks, and privileged-workflow integrity guard.

🧪 Testing

  • .venv/bin/ruff check --fix . passes
  • .venv/bin/ruff format . passes
  • Workflow YAML parsing, diff validation, and relevant pre-commit hooks pass
  • Existing SHA guard rejected a mismatched cross-branch dispatch as expected: run 29373891359
  • Live GitHub API checks confirmed the workflow blob comparison detects a modified authorization workflow while accepting an unchanged CI workflow
  • DCO Assistant passes on the current head
  • Positive status-reporting path requires execution from a trusted Agentic CI PR head
  • Unit tests: N/A - workflow-only change
  • E2E tests: N/A - the positive path will be verified on the next trusted Agentic CI PR

✅ Checklist

  • Follows commit message conventions
  • DCO Assistant passes
  • Branch is current with main
  • Architecture docs updated: N/A - no architecture change

Limit commit-status writes to the DCO authorization job.

Require dispatched workflow definitions to match main before launch.
@andreatnvidia
andreatnvidia marked this pull request as ready for review July 15, 2026 13:24
@andreatnvidia
andreatnvidia requested a review from a team as a code owner July 15, 2026 13:24
@greptile-apps

greptile-apps Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR strengthens the Agentic CI authorization workflow by publishing an explicit DCOAssistant commit status after a trusted PR is successfully validated, and adds an integrity guard that rejects dispatch if ci.yml or agentic-ci-authorized-checks.yml at the PR head SHA differs from main.

  • agentic-ci-authorized-checks.yml: Scopes statuses: write to the DCOAssistant job and posts a GitHub commit status on the validated expected_head_sha only after the pr job confirms both trust and exact-head match.
  • authorize-agentic-ci.yml: Adds a pre-dispatch loop that compares blob SHAs (via the GitHub Contents API) for the two dispatched workflow files between the PR head and main, blocking authorization when they diverge.

Confidence Score: 5/5

Safe to merge. Both changes are additive security hardening with no regressions on the existing validation path.

The commit-status write is gated behind the full trust-and-exact-head validation chain already in place, and the new integrity guard correctly uses GitHub blob SHAs to prevent stale or modified privileged workflow definitions from being dispatched. Job-level permission scoping is applied correctly. No logic errors found.

No files require special attention.

Important Files Changed

Filename Overview
.github/workflows/agentic-ci-authorized-checks.yml Adds a job-scoped statuses: write permission and posts a DCOAssistant=success commit status on the validated head SHA only after the pr job confirms trust and exact-head match. Logic is correct: job-level permissions replace workflow-level permissions, so only statuses: write is active in this job, which is all it needs.
.github/workflows/authorize-agentic-ci.yml Adds a pre-dispatch integrity loop comparing GitHub Contents API blob SHAs for ci.yml and agentic-ci-authorized-checks.yml between the PR head and main. Correctly layers on top of the existing .github/ diff block; authorize-agentic-ci.yml itself is intentionally omitted since it runs from the default branch.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant M as Maintainer
    participant AA as authorize-agentic-ci.yml (main)
    participant GH as GitHub API
    participant AC as agentic-ci-authorized-checks.yml (HEAD_SHA)

    M->>AA: /authorize-agentic-ci comment
    AA->>GH: Check commenter permission
    AA->>GH: Load PR metadata (HEAD_SHA)
    AA->>GH: "Validate PR trust & timeline"
    AA->>GH: Check PR diff for .github/ changes
    loop New: Workflow integrity guard
        AA->>GH: "GET contents/ci.yml?ref=main (blob SHA)"
        AA->>GH: "GET contents/ci.yml?ref=HEAD_SHA (blob SHA)"
        AA->>GH: "GET contents/agentic-ci-authorized-checks.yml?ref=main"
        AA->>GH: "GET contents/agentic-ci-authorized-checks.yml?ref=HEAD_SHA"
        GH-->>AA: SHAs must match or abort
    end
    AA->>GH: "Dispatch ci.yml & agentic-ci-authorized-checks.yml at HEAD_REF"

    Note over AC: Runs at HEAD_SHA via GITHUB_SHA check
    AC->>GH: "Load PR metadata, validate HEAD_SHA == EXPECTED"
    AC->>GH: "Verify GITHUB_SHA == HEAD_SHA"
    AC->>AC: "pr job sets trusted=true output"

    Note over AC: DCOAssistant job (statuses:write only)
    AC->>GH: "POST /repos/.../statuses/HEAD_SHA (state=success, context=DCOAssistant)"
    GH-->>M: Required check DCOAssistant satisfied
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant M as Maintainer
    participant AA as authorize-agentic-ci.yml (main)
    participant GH as GitHub API
    participant AC as agentic-ci-authorized-checks.yml (HEAD_SHA)

    M->>AA: /authorize-agentic-ci comment
    AA->>GH: Check commenter permission
    AA->>GH: Load PR metadata (HEAD_SHA)
    AA->>GH: "Validate PR trust & timeline"
    AA->>GH: Check PR diff for .github/ changes
    loop New: Workflow integrity guard
        AA->>GH: "GET contents/ci.yml?ref=main (blob SHA)"
        AA->>GH: "GET contents/ci.yml?ref=HEAD_SHA (blob SHA)"
        AA->>GH: "GET contents/agentic-ci-authorized-checks.yml?ref=main"
        AA->>GH: "GET contents/agentic-ci-authorized-checks.yml?ref=HEAD_SHA"
        GH-->>AA: SHAs must match or abort
    end
    AA->>GH: "Dispatch ci.yml & agentic-ci-authorized-checks.yml at HEAD_REF"

    Note over AC: Runs at HEAD_SHA via GITHUB_SHA check
    AC->>GH: "Load PR metadata, validate HEAD_SHA == EXPECTED"
    AC->>GH: "Verify GITHUB_SHA == HEAD_SHA"
    AC->>AC: "pr job sets trusted=true output"

    Note over AC: DCOAssistant job (statuses:write only)
    AC->>GH: "POST /repos/.../statuses/HEAD_SHA (state=success, context=DCOAssistant)"
    GH-->>M: Required check DCOAssistant satisfied
Loading

Reviews (4): Last reviewed commit: "Merge branch 'main' into andreatgretel/f..." | Re-trigger Greptile

@github-actions

Copy link
Copy Markdown
Contributor

Code Review — PR #819: fix(agentic-ci): report authorized DCO status

Summary

This is a small, security-focused workflow-only change (20 additions, 0
deletions, 2 files). It does two things:

  1. agentic-ci-authorized-checks.yml — after the pr job confirms the PR
    is a trusted Agentic CI PR on the exact authorized head, the DCOAssistant
    job now publishes an explicit commit status (context=DCOAssistant,
    state=success) on the validated head SHA, so the required branch-protection
    context is reflected in the PR check rollup. Status-write permission is scoped
    to just this job.
  2. authorize-agentic-ci.yml — before dispatching privileged workflows, the
    authorize job now requires the PR-head blob SHAs of ci.yml and
    agentic-ci-authorized-checks.yml to match main, blocking stale or modified
    privileged workflow definitions from being dispatched.

Overall this is a clean, well-reasoned hardening change. The security boundary
holds up under scrutiny:

  • The status is posted only when needs.pr.result == success and
    needs.pr.outputs.trusted == true. The pr job independently re-validates
    that inputs.expected_head_sha equals the live PR head and GITHUB_SHA,
    so the status can only land on a maintainer-authorized, unmoved head.
  • Job-scoped permissions: statuses: write correctly overrides the read-only
    top-level grant for just the DCOAssistant job; the job needs no other scope
    (no checkout, no contents read — it only POSTs a status), so dropping the
    other scopes is appropriate least-privilege.
  • The integrity guard is meaningful and not merely redundant with the existing
    .github/-diff block: a PR whose branch is simply behind main on
    ci.yml would not show ci.yml in its merge-base diff, but the blob-SHA
    comparison catches the stale copy. It also runs from the issue_comment
    context (default branch = main), so the guard code itself is always the
    trusted version.
  • Under GitHub Actions' default bash -eo pipefail, a failed gh api call in
    the guard aborts the step (fail-closed), so a transient API error blocks
    authorization rather than silently passing.

Findings

The findings below are low-to-medium severity robustness/fragility notes. No
correctness bug that would cause a false authorization or a crash on the happy
path was found.

[
  {
    "file": ".github/workflows/authorize-agentic-ci.yml",
    "line": 175,
    "summary": "Integrity-guard baseline is hardcoded to ref=main rather than the PR's actual base branch.",
    "failure_scenario": "If an Agentic CI PR ever targets a branch other than main (e.g. a release/maintenance branch), or the default branch is renamed, the guard compares the head workflows against main's copies. That yields a false block (legitimate PR against a branch whose ci.yml diverged from main) or, worse, a false pass (head matches main but the actual base branch runs a different ci.yml). Today all agentic-ci PRs target main so this is latent, but it couples a security guard to an assumption not enforced anywhere in the file."
  },
  {
    "file": ".github/workflows/authorize-agentic-ci.yml",
    "line": 177,
    "summary": "Guard passes if both `gh api ... --jq '.sha'` calls yield an empty/identical string, since equality is checked without asserting a non-empty SHA was retrieved.",
    "failure_scenario": "The guard relies entirely on `gh api` returning a non-zero exit (fail-closed) whenever a SHA can't be read. For the contents API on a regular file this holds (404 -> non-zero; a file object always has `.sha`). But it is defense-in-depth for a privileged dispatch, so it is worth making the failure explicit: if a future refactor points WORKFLOW_PATH at a directory (contents API returns a JSON array, `.sha` -> null -> empty string for both refs) or an unexpected 200 body lacks `.sha`, the `[ \"$HEAD\" != \"$MAIN\" ]` test compares '' != '' and the guard passes. Adding an explicit `[ -n \"$MAIN_WORKFLOW_SHA\" ]` (and HEAD) check before the comparison would remove the reliance on exit-code behavior."
  }
]

Notes (not blocking)

  • Dual DCOAssistant reporting. dco-assistant.yml also owns a job named
    DCOAssistant (which, for trusted Agentic CI PRs, skips the DCO action but
    still succeeds and reports a check-run of the same name). This PR adds a second
    entity — a commit status — with the identical context string. In practice
    both resolve to success for trusted PRs so there is no rollup conflict, and
    targeting the exact head SHA is precisely the gap chore(agentic-ci): declare pandas, pyarrow, pyyaml as direct interface deps #816 hit. Worth a one-line
    comment in the workflow explaining why the explicit status is needed on top
    of the check-run, so a future maintainer doesn't remove one as "redundant."
  • target_url mixes ${GITHUB_REPOSITORY} with the endpoint's ${REPO}.
    Both expand to github.repository, so this is purely cosmetic — using REPO
    in both places would read more consistently.
  • The status semantically means "authorized," not "DCO verified" — this is
    intentional and matches dco-assistant.yml's existing exemption of trusted
    bot PRs from DCO. Flagging only so it is a conscious, documented choice.

Structural Impact

No pre-computed structural impact analysis was available
(/tmp/structural-impact-819.md did not exist). This PR touches only two files
under .github/workflows/; it introduces no Python code, no import-direction
concerns, and no cross-package dependencies. Blast radius is confined to the
Agentic CI authorization/dispatch path.

Verdict

Approve with minor suggestions (do not merge-block). The change is sound,
well-scoped, and correctly gated; the security boundary and least-privilege
scoping hold up. The two findings are latent robustness/fragility issues in the
new integrity guard rather than live bugs — worth addressing (especially making
the guard assert a non-empty SHA and documenting the hardcoded main baseline
assumption) but not blocking. Per instructions, this review does not post an
approval or change request on the PR.

@andreatnvidia
andreatnvidia merged commit 5a4e7a9 into main Jul 16, 2026
66 checks passed
@andreatnvidia
andreatnvidia deleted the andreatgretel/fix/agentic-ci-dco-status branch July 16, 2026 20:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants