Skip to content

docs: Guide release recovery through roll-forward#1821

Merged
hatayama merged 2 commits into
feature/release-pipeline-hardening-integrationfrom
docs/release-recovery-roll-forward
Jul 17, 2026
Merged

docs: Guide release recovery through roll-forward#1821
hatayama merged 2 commits into
feature/release-pipeline-hardening-integrationfrom
docs/release-recovery-roll-forward

Conversation

@hatayama

@hatayama hatayama commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Summary

  • Make roll-forward the primary recovery for broken native CLI releases.

User Impact

  • Operators have an executable recovery path that produces a valid next release instead of retrying an unrecoverable historical version.

Changes

  • Document the beta.48 to beta.49 roll-forward recovery.
  • Define the narrow conditions under which rerunning an original workflow is valid.
  • Explain why a broken historical release cannot be revived by a later run.

Verification

  • git diff --check passed.
  • Documentation-only change; no automated test applies.

Refs: release pipeline recurrence-prevention plan, PR-3

Review in cubic

Direct recovery toward a new valid release because an older broken release cannot gain attestations for its historical commit from a later workflow run.
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The 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.

Changes

Native CLI release recovery

Layer / File(s) Summary
Roll-forward recovery procedure
docs/release-recovery-runbook.md
Defines the attestation mismatch trigger, next-version release procedure, and verification of runner tags, asset attestations, and publish run headSha values.
Recovery validity and limitations
docs/release-recovery-runbook.md
Explains why historical broken releases cannot be revived and documents the conditions and approval steps for valid reruns.
Operational recovery notes
docs/release-recovery-runbook.md
Documents dispatcher restrictions, concurrency handling, release deletion timing, tag-ruleset permissions, and package pin behavior.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main documentation change: guiding release recovery through roll-forward.
Description check ✅ Passed The description is directly related to the runbook rewrite and accurately reflects the roll-forward recovery changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/release-recovery-roll-forward

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Include asset download, rerun, approval, and concurrency guidance so the recovery runbook can be followed without inferring missing operational commands.
@hatayama
hatayama merged commit 9fd18f5 into feature/release-pipeline-hardening-integration Jul 17, 2026
1 of 2 checks passed
@hatayama
hatayama deleted the docs/release-recovery-roll-forward branch July 17, 2026 14:51

@coderabbitai coderabbitai Bot 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.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 74d020f and ca1cb73.

📒 Files selected for processing (1)
  • docs/release-recovery-runbook.md

Comment on lines +3 to +8
## 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.

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.

🎯 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.

Comment on lines +26 to 35
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'
```

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.

🗄️ 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.

Comment on lines +47 to +51
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.

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.

🎯 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/**' || true

Repository: 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:


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.

Comment on lines +60 to +85
## 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
```

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.

🎯 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:


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.

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.

1 participant