リリース復旧ランブック
リリースシーケンスが途中で失敗したときにリポジトリを動作する状態へ復元するための復旧手順。段階ごとの診断付き。
このランブックは、その場でのクリーンスレート式リリースシーケンスが途中で
失敗したときに、ahmed-g-gad/apothem を動作する状態へ復元します。リリース
中に公開リポジトリが削除または再作成されることはありません。復旧は、
リリース固有の履歴セーフティタグ、メンテナーのローカルクローン、および
下流のパッケージマネージャの状態に依存します。
1. ステージの分類
| ステージ | アクション | 失敗モード | 復旧パス |
|---|---|---|---|
| 1 | 履歴セーフティタグを取得してプッシュする | タグが存在しない、署名されていない、または誤ったグラフを指している | main を移動する前に、スカッシュ前のマージポイントからタグを再作成する |
| 2 | CI、監査フォートレス、パッケージ状態、変更履歴を検証する | いずれかのゲートが失敗する | 停止し、ローカルで修正する。main を移動しない |
| 3 | main を署名済みの単一リリースコミットへ移動する | force-with-lease が失敗する、コミットが署名されていない、またはコミットメッセージが誤っている | ローカルの main を意図した署名済みコミットへリセットし、新しいリースで再試行する |
| 4 | GitHub Release、Pages、npm、メタデータを公開する | いずれかのパブリッシャーまたは検証面が失敗する | リリースコミットは保持する。失敗を記録したうえで、失敗したパブリッシャーだけを再実行する |
すべての復旧アクションは冪等です。クリーンな状態で実行すると何も起こりません。 部分的な状態で実行すると、期待されるステージ後の状態に復元されます。
2. セーフティタグの復旧
履歴の書き換えを行う前にセーフティタグを検証します。
git fetch origin --tags
git show --summary --show-signature <history-safety-tag>
git merge-base --is-ancestor origin/main <history-safety-tag>期待される結果: タグが存在し、タグが署名されている場合は署名検証が成功し、
スカッシュ前の完全なグラフがタグから到達可能であること。タグがローカルには
存在しないがリモートには存在する場合は、それを取得します。リモートに存在
しない場合は、リリースを停止し、main に触れる前に再作成します。
git tag -s <history-safety-tag> <pre-squash-commit>
git push origin <history-safety-tag>3. メインブランチの復旧
公開された main の状態を診断します。
gh api repos/ahmed-g-gad/apothem/commits/main \
--jq '.sha, .commit.message, .commit.verification.verified, .commit.verification.reason'カットオーバー後に期待される結果: メッセージがちょうど
release: Apothem <release-version> であり、verification.verified が true
であること。
force-with-lease のプッシュが GitHub を変更する前に失敗した場合は、リモートを そのままにし、それを取得し、署名済みリリースコミットをローカルで再構築し、 リースが一致してからのみ再試行します。
git fetch origin main
git push --force-with-lease=main:<expected-remote-sha> origin mainプッシュが署名なしまたは未検証のコミットで着地した場合は、ローカルの署名 設定を修正し、同じツリーからリリースコミットを再作成し、リース付きで再び force-push します。セーフティタグは削除しないでください。
4. パブリッシャーの復旧
各パブリッシャーは、GitHub のリリースコミットが検証された後に独立して再試行 されます。
| 面 | 診断 | 復旧 |
|---|---|---|
| GitHub Release | gh release view <release-tag> --json tagName,isDraft,isPrerelease,assets | 不正な形式のドラフトのみを削除する。それ以外の場合は、gh release upload --clobber で欠落したアセットをアップロードする |
| リリースタグ | git ls-remote origin refs/tags/<release-tag> と git tag -v <release-tag> | タグが存在しないか署名されていない場合は、同じ SHA から -a -s で再タグ付けする。別のコミットに対してタグ名を再利用しない |
| npm | npm view @ahmed-g-gad/apothem version と npx @ahmed-g-gad/apothem@<version> --version | @ahmed-g-gad/apothem の npm Trusted Publishing を確認したうえで、<release-tag> に対して publish-npm.yml を再実行する |
| Pages | gh run list --workflow=publish-static-site.yml --limit=1 と curl -sSI https://apothem.ahmedgad.com/ | publish-static-site.yml を再実行する。CNAME が依然として ahmed-g-gad.github.io に解決することを検証する |
| GitHub メタデータ | gh repo view ahmed-g-gad/apothem --json description,homepageUrl,repositoryTopics,visibility | 説明、ホームページ、トピックをその場でパッチする。リポジトリを再作成しない |
5. ロールバック
ロールバックは最終手段です。まずは的を絞ったパブリッシャーの復旧を優先します。
単一のリリースコミットを取り消す必要がある場合は、セーフティタグから main
を復元します。
git fetch origin --tags
git switch main
git reset --hard <history-safety-tag>
git push --force-with-lease origin mainロールバック後は、CI を再実行し、GitHub がドリフトを報告した場合はブランチ 保護を再適用し、ロールバックをリリースをブロックするインシデントとして記録 します。リリースアーティファクトが引き続き有効な場合にのみリリースタグを 保持します。そうでない場合は、再試行する前に不正な形式のリリースとタグを 削除します。
6. 相互参照
- Pages の構成:
site/content/docs/runbooks/pages-enablement.mdx。 - リリース手順:
site/content/docs/runbooks/release-cycle.mdx。 - パッケージングレシピ:
packaging/README.md。 - 復旧アンカー: リリース固有の履歴セーフティタグ。