docs: Guide release recovery through roll-forward#1821
Conversation
Direct recovery toward a new valid release because an older broken release cannot gain attestations for its historical commit from a later workflow run.
📝 WalkthroughWalkthroughThe release recovery runbook now targets native CLI tag and attestation mismatches, prescribes rolling forward to a new release, defines valid rerun conditions, and documents operational handling for approvals, concurrency, release deletion, and permissions. ChangesNative CLI release recovery
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Include asset download, rerun, approval, and concurrency guidance so the recovery runbook can be followed without inferring missing operational commands.
9fd18f5
into
feature/release-pipeline-hardening-integration
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/release-recovery-runbook.md`:
- Around line 3-8: Update the Purpose section of the release-recovery runbook to
state that the asset remains downloadable but cannot be verified or used by the
dispatcher because attestation verification rejects it. Replace the inaccurate
“cannot be downloaded” wording while preserving the recovery guidance to publish
the next valid release.
- Around line 26-35: Update the release verification step to match its stated
coverage: explicitly verify that the package release pins the new runner tag,
and enumerate and attest every published release asset rather than checking only
`<new-asset>`. Keep the runner tag and publish-run `headSha` comparisons, or
narrow the step’s prose if those checks cannot be implemented.
- Around line 60-85: Update the “When rerun recovery is valid” section to state
that GitHub permits workflow reruns only within 30 days of the original run.
Instruct operators to use the roll-forward procedure after 30 days, even when
all other rerun conditions are satisfied.
- Around line 47-51: Update the release recovery runbook guidance to state that
fresh runs attest the triggering commit/ref and reruns preserve the original
GITHUB_SHA and GITHUB_REF; for tag-triggered releases, identify the tag commit
rather than the current branch head.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 0171b318-ab2a-4b05-97e0-069c9d4d30db
📒 Files selected for processing (1)
docs/release-recovery-runbook.md
| ## Purpose | ||
|
|
||
| In `recovery-target` mode, the release target is an earlier commit than the | ||
| workflow run's `GITHUB_SHA`. GitHub rejects the Actions `GITHUB_TOKEN` when it | ||
| tries to create a tag or release for that different commit, even when the token | ||
| has `contents: write`. This is neither a missing permission nor a tag ruleset | ||
| failure. | ||
| Use this runbook when a native CLI release has a tag commit that differs from | ||
| the `sourceRepositoryDigest` in its asset attestations. Such a release cannot | ||
| be downloaded by the dispatcher. Recover by publishing the next valid release; | ||
| do not try to repair the broken release in place. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Describe the dispatcher failure accurately.
The asset remains downloadable; the dispatcher rejects it during attestation verification. Replace “cannot be downloaded” with “cannot be verified or used by the dispatcher” to avoid sending operators toward the wrong diagnosis.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/release-recovery-runbook.md` around lines 3 - 8, Update the Purpose
section of the release-recovery runbook to state that the asset remains
downloadable but cannot be verified or used by the dispatcher because
attestation verification rejects it. Replace the inaccurate “cannot be
downloaded” wording while preserving the recovery guidance to publish the next
valid release.
| 3. Verify the new runner release and the package release that pins it. The | ||
| runner tag commit, every asset's attestation digest, and the publish run's | ||
| `headSha` must match. | ||
|
|
||
| ```sh | ||
| gh run download <run-id> --repo <owner>/<repo> \ | ||
| -n native-cli-release-input -D <native-release-input-dir> | ||
| gh release create <tag> --repo <owner>/<repo> \ | ||
| --draft --title <tag> \ | ||
| --notes-file <native-release-input-dir>/release-input/release-notes.md \ | ||
| --target <release-commit-sha> | ||
| gh run view <publish-run-id> --repo <owner>/<repo> --json headSha --jq .headSha | ||
| gh api repos/<owner>/<repo>/commits/<new-runner-tag> --jq .sha | ||
| gh attestation verify <new-asset> --repo <owner>/<repo> --format json \ | ||
| | jq -r '.[].verificationResult.signature.certificate.sourceRepositoryDigest' | ||
| ``` |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Verify the package pin and every published asset.
This step claims to verify the package release and “every asset,” but the commands inspect only one <new-asset> and never confirm that the package release pins the new runner tag. Add explicit package-pin verification and a loop/list of all release assets, or narrow the prose to the checks actually performed.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/release-recovery-runbook.md` around lines 26 - 35, Update the release
verification step to match its stated coverage: explicitly verify that the
package release pins the new runner tag, and enumerate and attest every
published release asset rather than checking only `<new-asset>`. Keep the runner
tag and publish-run `headSha` comparisons, or narrow the step’s prose if those
checks cannot be implemented.
| 1. Rerunning a workflow replays the workflow definition from the original | ||
| commit. If that workflow definition was itself broken, rerunning it repeats | ||
| the failure. | ||
| 2. A new workflow run attests its own `github.sha`, which is the current branch | ||
| head. It cannot create attestations for an earlier release commit. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show the relevant section of the runbook with line numbers.
sed -n '35,70p' docs/release-recovery-runbook.md | cat -n
# Search for any other references to github.sha / GITHUB_SHA in the repo.
rg -n "github\.sha|GITHUB_SHA|GITHUB_REF|rerun" docs .github . -g '!**/node_modules/**' || trueRepository: hatayama/unity-cli-loop
Length of output: 10525
🌐 Web query:
GitHub Actions rerun workflow job GITHUB_SHA GITHUB_REF github.sha semantics tag-triggered workflow run
💡 Result:
When you rerun a GitHub Actions workflow or a specific job within a workflow, the system uses the exact same GITHUB_SHA and GITHUB_REF that were associated with the initial trigger of that workflow run [1][2]. These values are immutable for the duration of the workflow run, regardless of any subsequent changes to the branch or tag in the repository [1][3]. Key semantics to keep in mind regarding these environment variables: 1. Rerun Behavior: Because reruns utilize the original context, they do not "re-fetch" or re-evaluate the triggering commit or reference [1][4]. This ensures consistency, as the rerun operates on the exact codebase version that was initially intended to be tested [1][2]. 2. GITHUB_SHA Semantics: The value of GITHUB_SHA depends on the event that triggered the workflow [5][6]. - For push events, it is the SHA of the commit that triggered the push. - For pull_request events, it often refers to a temporary merge commit created by GitHub (e.g., refs/remotes/pull/:pr_number/merge), rather than the head commit of the source branch [6]. If you require the specific head SHA of a pull request, use github.event.pull_request.head.sha instead [6]. 3. Tag-Triggered Workflows: When a workflow is triggered by a tag (e.g., via a push event that includes a tag), GITHUB_REF will contain the reference to that tag (e.g., refs/tags/my-tag). During a rerun, this reference remains fixed to the specific tag that originally triggered the workflow [1][7]. In summary, rerunning a workflow is a "replay" of the original trigger context, ensuring that environment variables like GITHUB_SHA and GITHUB_REF remain consistent with the original run [1][4].
Citations:
- 1: https://docs.github.com/en/actions/how-tos/manage-workflow-runs/re-run-workflows-and-jobs
- 2: https://docs.github.com/en/enterprise-cloud@latest/actions/how-tos/manage-workflow-runs/re-run-workflows-and-jobs
- 3: https://github.com/github/docs/blob/main/content/actions/how-tos/manage-workflow-runs/re-run-workflows-and-jobs.md
- 4: https://devops.stackexchange.com/questions/19635/github-actions-is-github-sha-stable-for-the-life-of-a-complex-workflow
- 5: https://docs.github.com/en/actions/reference/workflows-and-actions/variables
- 6: GITHUB_SHA on PRs refers to the merge commit, not the actual commit which triggered the PR github/docs#15302
- 7: https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows
Use the triggering commit/ref, not “current branch head”. Fresh workflow runs attest the commit that triggered the run, and reruns preserve the original GITHUB_SHA and GITHUB_REF. For tag-triggered releases, that is the tag commit, not a branch head.
🧰 Tools
🪛 LanguageTool
[uncategorized] ~50-~50: The official name of this software platform is spelled with a capital “H”.
Context: .... 2. A new workflow run attests its own github.sha, which is the current branch he...
(GITHUB)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/release-recovery-runbook.md` around lines 47 - 51, Update the release
recovery runbook guidance to state that fresh runs attest the triggering
commit/ref and reruns preserve the original GITHUB_SHA and GITHUB_REF; for
tag-triggered releases, identify the tag commit rather than the current branch
head.
| ## When rerun recovery is valid | ||
|
|
||
| Rerun only when all of the following are true: | ||
|
|
||
| - The original failed run's `headSha` is the intended release commit. | ||
| - The workflow definition at that commit is known to be healthy. | ||
| - The release tag and draft release, if they exist, point at that same commit. | ||
|
|
||
| Check the original run before rerunning it: | ||
|
|
||
| ```sh | ||
| gh run view <run-id> --repo <owner>/<repo> --json headSha,workflowName,url | ||
| gh api repos/<owner>/<repo>/commits/<release-tag> --jq .sha | ||
| gh run view <run-id> --repo <owner>/<repo> --log-failed | ||
| ``` | ||
|
|
||
| If the run used an older workflow revision that lacks a required fix, or its | ||
| head SHA differs from the intended release commit, do not rerun it. Use the | ||
| roll-forward procedure instead. | ||
|
|
||
| When all conditions hold, rerun the failed jobs from the original run and | ||
| approve the `cli-release` environment if GitHub requests approval: | ||
|
|
||
| ```sh | ||
| gh run rerun <run-id> --repo <owner>/<repo> --failed | ||
| ``` |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
GitHub Actions rerun workflow jobs 30-day rerun window documentation
💡 Result:
According to official GitHub Actions documentation, you can re-run a workflow run, all failed jobs, or specific individual jobs up to 30 days after the initial run [1][2]. It is important to note that the ability to re-run a job is dependent on the existence of the workflow's logs [3]. While the re-run window is capped at 30 days, the retention period for the logs themselves—which determines whether the run is still accessible for a re-run—can vary [4]. By default, logs and artifacts are retained for 90 days, but this can be configured by organizations to range from 1 to 400 days for private repositories, or 1 to 90 days for public repositories [4]. Even if log retention is extended beyond 30 days, the ability to initiate a re-run remains restricted to the 30-day window following the initial execution [1][2]. Additionally, there is a limit on the number of times a workflow can be re-run: a single workflow run can be re-run a maximum of 50 times, which includes both full re-runs and re-runs of specific subsets of jobs [1][5][6].
Citations:
- 1: https://docs.github.com/en/actions/how-tos/manage-workflow-runs/re-run-workflows-and-jobs
- 2: https://docs.github.com/en/enterprise-cloud@latest/actions/how-tos/manage-workflow-runs/re-run-workflows-and-jobs
- 3: https://stackoverflow.com/questions/71137237/how-do-i-rerun-an-old-workflow-in-github-actions-after-30-days-of-its-initial-ru
- 4: https://docs.github.com/en/organizations/managing-organization-settings/configuring-the-retention-period-for-github-actions-artifacts-and-logs-in-your-organization
- 5: https://docs.github.com/en/actions/reference/limits
- 6: https://github.blog/changelog/2026-04-10-actions-workflows-are-limited-to-50-reruns/
Include the 30-day rerun limit. In docs/release-recovery-runbook.md:60-85, add that GitHub only allows rerunning a workflow run within 30 days of the original run; after that, use the roll-forward procedure even if the other conditions still hold.
🧰 Tools
🪛 LanguageTool
[style] ~62-~62: Consider removing “of” to be more concise
Context: ...erun recovery is valid Rerun only when all of the following are true: - The original fai...
(ALL_OF_THE)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/release-recovery-runbook.md` around lines 60 - 85, Update the “When
rerun recovery is valid” section to state that GitHub permits workflow reruns
only within 30 days of the original run. Instruct operators to use the
roll-forward procedure after 30 days, even when all other rerun conditions are
satisfied.
Summary
User Impact
Changes
Verification
Refs: release pipeline recurrence-prevention plan, PR-3