公開したサイトを動かし続ける
本番に何が乗っているのか分からなくなったところから、送る前に止める・戻せるように残す・止まったら見つけるの3 つを足しました。読み終えると、公開したあとに何が起きるのかと、自分のサイトなら何を残しておけばいいかが分かります。
確認しようとしたら、版を刻んでいるはずのファイルがありませんでした。過去に deploy.sh を通さず手で上げたことがあって、そのとき刻印が残らなかったからです。いま公開されているものがどの時点のものか、自分でも分からない。
Claude Code に頼めば直してもらえます。ただ、直したものが本当に本番へ届いたか、届いた先で壊れていないかは、頼んだ側が見るしかありません。
公開に使っている deploy.sh は、Claude Code に Astro サイトを作らせた記録でそのまま出てきた 65 行が始まりです。困るたびに足していって、2026 年 10 月 8 日時点で 600 行あります。足したところが、そのまま公開後に困ったことの一覧になっています。 大きく分けると、送る前に止める分・戻せるように残す分・止まったら見つける分の3 つです。
送る前に止める
公開用に書き出した HTML は、見た目だけでは分からない形で壊れることがあります。そこでこのサイトでは、公開先へ送る前に、書き出したファイルそのものを検査します。
書き出した HTML を、送る前に見る
このサイトの scripts/smoke-dist.sh は、書き出した HTML を調べます。この検査が実際に公開を止めたのは、2026 年 9 月時点で 2 件。 ひとつは、SNS に貼ったときのサムネイル画像の指定が、途中までの住所(相対パス)で出力されていたこと。止まっていなければ、SNS に貼った瞬間サムネイルの出ないページが、そのまま公開されていました。 もうひとつは、ページの本文を囲む枠が二重になっていたことです。
deploy.sh は、この検査が失敗したという結果を受け取ると、送るのを中止します。
本番へ送る前に、確認用のサイトと照合する
deploy.sh は、staging(本番に出す前に自分だけで確かめる、もう 1 つのサイト)と本番で扱いを分けています。作業中の変更が残っているとき、staging では警告を出して続けます。本番では拒否します。
本番へ送るときは、staging に出ている version.json(どの時点のものを送ったかを書いた小さなファイル)とも照合します。staging で確認した中身と違えば、そこで止まります。 緊急のときだけ飛ばせますが、そのときは理由を 1 行書かないと進まず、その理由が version.json に残ります。
戻せるように残す
冒頭の「何が乗っているか分からない」に戻ります。直す前に「いまどうなっているか」が分からないと、直しようがありません。ここから、送るたびに版を刻んで、戻せる形で残すようにしました。
これはこのサイトの送信スクリプトの記録です。ほかのサイトに同じファイルがあるわけではありません。 ただ、困りごとのほうは公開先が変わっても同じです。
| 公開したあとに困ること | このサイトでしていること |
|---|---|
| いま本番に何が乗っているか分からない | deploy.sh status で、staging と本番それぞれの時点を出す |
| 知らないうちに中身が変わっていないか | deploy.sh drift で、送ったときの記録といまのファイルを突き合わせる |
| 間違えて上げた、を取り消したい | deploy.sh rollback で、送る前に取ったバックアップへ戻す |
この章を直している最中に deploy.sh status を打つと、こう出ます(コミットの説明は途中で切り、本番側の一覧は 2 件だけ残しました)。
── デプロイ状態(2026-10-08 21:04) ──
ローカル HEAD : 317263a9(frontend 未コミット変更: なし)
staging : ecb42038 2026-10-08T20:59:56+0900 ← サイト変更 2 件が未反映
317263a9 fix(guide): keep-it-running の見出しを図に合わせ、…
ba2229f1 docs(guide): config の CLAUDE.md を見本の抜粋として扱い、…
prod : b7445dd5 2026-09-18T00:34:15+0900 ← サイト変更 21 件が未反映
317263a9 fix(guide): keep-it-running の見出しを図に合わせ、…
ba2229f1 docs(guide): config の CLAUDE.md を見本の抜粋として扱い、…
(以下 19 件を省略)
staging にはまだ 2 件、本番には 21 件、届いていない変更があります。 冒頭の「何が乗っているか分からない」は、打てば 1 回で答えの出る問いに変わりました。
やっていることは、結局この3 つです。送った時点を書いた小さなファイルを 1 つ置く。送ったときのファイルの状態を控える。送る前のものを別名で残す。 スクリプトが無くても、この3 つが残っていれば同じことは追えます。
控えているのは、サーバーに置いてあるファイルそのものから計算した、中身が 1 文字でも違えば変わる短い値(ハッシュ)です。drift は、その記録といまのファイルを突き合わせます。誰かが気づかないうちに中身を変えていれば、一致しません。
version.json が無いときは、deploy.sh を通した版か追えません。何が乗っているか分からない状態を、正常な公開として扱わないためです。
止まったら見つける
これは机上の心配ではありません。 サイトの話ではありませんが、同じリポジトリで動かしている、毎時 30 分にデータを取りに行く処理が、2 回分(約 2 時間)無言で止まっていたことがあります。スクリプトが起動した直後に死んだので、ログには 1 行も残りませんでした。 気づいたのは、人に指摘されたときです。
自分で確認するときだけ分かる仕組みでは、確認を忘れた日に弱くなります。そこでこのサイトでは GitHub Actions(GitHub 側で処理を自動で走らせる仕組み。時刻を決めて毎日走らせることもできます)に、staging と本番の /version.json を毎日 1 回取りに行く処理を置いています。
毎日走らせる時刻の設定 .github/workflows/site-deploy-status.yml
on:
schedule:
- cron: "0 22 * * *" # 毎日 07:10 JST 目安(UTC 22:00)。本番版の追跡漏れを早期検知
workflow_dispatch: 設定は UTC の 22 時ちょうど、日本時間の朝 7 時です。コメントに 07:10 と書いてあるのは、この手の定時実行が定刻には走らないので実際はそれくらい、という見込みです。
取れたファイルに書かれている時点が、リポジトリに残っている履歴の中に本当にあるかまで確かめます。取得できない、404 で見つからない、履歴に無い時点だった。このどれかなら失敗にします。
この仕組みは見に行くだけで、ここから公開することはありません。 見に行くのも公開されている URL だけなので、GitHub にサーバーのパスワードを預けなくても動きます。
ただし、届く範囲には限りがあります。Slack など専用の連絡先へ通知しているわけではなく、GitHub Actions を失敗にして気づく形なので、GitHub からの通知を受け取っていなければ失敗しても気づけません。見ているのもサイトの側だけで、さきほどの 2 時間の停止は、これでは捕まりません。
止まったことに気づく仕組みを、止まってから作ろうとして間に合わなかったのが、その 2 時間です。
止める・残す・見つけるを置いておく
公開した日より、そのあとのほうが長い。 3 つがどこに効いているかを見てください。

私の場合、この3 つを置いてから、直すときに「いま何が起きているか」から始められるようになりました。 壊れないと信じる代わりに置いたものです。
履歴を残して前の状態に戻せる仕組み(Git)そのものは、GitHub とは何かに書きました。