Skip to content

feat(ci): Disclose Hotfix workflow - #11361

Open
basvandijk wants to merge 3 commits into
masterfrom
bas/disclose-hotfix-workflow
Open

feat(ci): Disclose Hotfix workflow#11361
basvandijk wants to merge 3 commits into
masterfrom
bas/disclose-hotfix-workflow

Conversation

@basvandijk

@basvandijk basvandijk commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

Adds a workflow_dispatch workflow that discloses a security hotfix built and deployed from the private dfinity/ic-private repository: it pushes the exact elected commit to this repository as the same hotfix-* branch, authenticated as the "Push to RC Branch" GitHub App. The push triggers Release Testing, which re-builds the commit, re-uploads its artifacts (rclone --checksum --immutable: identical bytes ⇒ no-op, differing bytes ⇒ hard failure) and mints the build-provenance attestation that release workflows and the mainnet-revisions updater verify CDN downloads against (attestation stack: #11323#11324#11325#11326).

Runs of this workflow have to be approved by either DRE or Infra.

Flow

  1. Validate inputs before touching any credential: confirm checkbox must be ticked (boolean required: true does not enforce this, same pattern as ci-kickoff-manual.yml), branch must match hotfix-<suffix> of [A-Za-z0-9._-]+ (/ excluded: branch protections and triggers match hotfix-* with fnmatch, where * does not cross /), commit must be a full 40-hex sha.
  2. Mint an app installation token for dfinity/ic + dfinity/ic-private (same action pin as schedule-rc.yml).
  3. Validate remote state via ls-remote only: the ic-private branch must exist with its tip exactly at the requested commit; on dfinity/ic the branch must be absent (proceed), already at the commit (succeed as a no-op) or anything else (fail loudly — never move an existing branch).
  4. Checkout dfinity/ic@master, fetch the branch from ic-private, re-check the tip (closes the validate→fetch race), reject non-commit objects, warn if the tree lacks the attest-uploads job (the run then can't mint an attestation).
  5. Push create-only: --force-with-lease="refs/heads/<branch>:" (empty expected value = the ref must not exist, so the push can create but never move/fast-forward); a concurrent creation at the same commit is treated as a benign race; post-verify with ls-remote.
  6. Report in the step summary: outcome, the triggered Release Testing run URL, and the operational reminders (uploads must be rclone no-ops; "immutable file modified" = incident signal for the infra team, never retry around it or touch CDN objects; no further pushes to the branch until attest-uploads is green).

Why the tip must be exact

The attestation binds to the branch tip that Release Testing builds. A descendant or different commit would attest the wrong sha — hence exact-tip validation, the create-only lease, and the per-branch concurrency group (queued re-runs re-validate and converge to no-op/conflict instead of racing).

Environment / prerequisites

  • The DISCLOSE_HOTFIX environment exists (2026-08-27) with required reviewers (dfinity/dre + dfinity/infra), a master-only deployment branch policy (a Write user dispatching a modified copy of this workflow from a side branch cannot reach the credentials) and environment-scoped copies of the app credentials. It is separate from PUSH_TO_RC_BRANCH because required reviewers there would leave schedule-rc's nightly cron hanging.
  • Org-admin prerequisite done (2026-08-27): the "Push to RC Branch" app has access to dfinity/ic-private (Contents: read).
  • In ic-private the synced workflow copy stays inert (if: github.repository == 'dfinity/ic').

Validation

  • The exact run blocks (extracted from the YAML) were replayed against scratch bare repos: happy path creates the ref at exactly the commit; re-run is a no-op; existing-at-different-commit (including an ancestor — the silent-fast-forward case) is rejected both by the precheck and independently by the lease; private-tip-moved-after-validation aborts at the FETCH_HEAD re-check; benign/hostile create races behave as designed; public-hotfix-x, hotfix-a/b, hotfix-a..b, short shas and an unchecked confirm all fail input validation. 24/24 passed.
  • actionlint (1.7.12) and shellcheck clean.
  • Post-merge drill (after the attestation stack lands): disclose a scratch hotfix-attest-drill-* branch from ic-private at a post-stack commit; confirm push → Release Testing → rclone no-ops → attest-uploads mints; re-dispatch with identical inputs (no-op) and with a different commit (conflict failure); delete the branch.

Operator usage

Actions UI → Disclose Hotfix → branch + commit + confirm, or:

gh workflow run disclose-hotfix.yml -R dfinity/ic -f branch=hotfix-... -f commit=<40-hex> -f confirm=true

🤖 Generated with Claude Code

Publishes a security hotfix built in dfinity/ic-private by pushing its
exact elected commit to dfinity/ic as the same hotfix-* branch,
authenticated as the "Push to RC Branch" GitHub App. The push triggers
Release Testing, which re-builds the commit, re-uploads byte-identically
(rclone --checksum --immutable) and mints the build-provenance
attestation that consumers verify CDN downloads against.

The push is create-only (--force-with-lease with an empty expected
value) and validates that the ic-private branch tip is exactly the
requested commit; a branch already disclosed at that commit is a no-op,
any other state fails loudly. The DISCLOSE_HOTFIX environment gates the
app credentials behind required reviewers and a master-only deployment
branch policy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a manually dispatched workflow for safely disclosing private security hotfix branches to the public repository.

Changes:

  • Validates hotfix branch and commit inputs.
  • Uses a GitHub App token to verify and create the public branch safely.
  • Reports disclosure status and the downstream Release Testing run.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .github/workflows/disclose-hotfix.yml Outdated
Comment thread .github/workflows/disclose-hotfix.yml Outdated
Comment thread .github/workflows/disclose-hotfix.yml Outdated
Comment thread .github/workflows/disclose-hotfix.yml Outdated
basvandijk and others added 2 commits August 27, 2026 20:46
The DISCLOSE_HOTFIX required reviewers approve the run before any step
executes, and GitHub surfaces workflow_dispatch inputs neither in the
run list nor in the approval dialog, so without a run-name a reviewer
approves app-credential access without seeing which branch and commit
they are disclosing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- The attest-uploads precondition now matches the top-level job key
  instead of a bare substring, so comments, needs: references or
  commented-out jobs no longer satisfy it (Copilot).
- The Release Testing run-URL poll filters by branch and event=push in
  addition to head_sha, so it cannot select a run for another branch or
  a prior workflow_dispatch at the same commit (Copilot).
- Incident-signal wording now names the infra team, and the header names
  the reviewer teams (basvandijk).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

@basvandijk
basvandijk marked this pull request as ready for review August 27, 2026 21:00
@basvandijk
basvandijk requested a review from a team as a code owner August 27, 2026 21:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants