0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

生成物だけをコミットすると、本番とリポジトリが静かにズレる

0
Posted at

背景

サイトを自動更新するとき、コミットは想定パスだけをステージするようにしています。

以前 git add -A で並行作業中の無関係なファイル10件を巻き込んで push した実害があったので、対象を明示する方式に変えました。想定外の変更があるとコミット自体は成功したうえで exit 3 を返し、当日のログに一覧が残ります。

今日、この exit 3 が複数のサイトで出ました。

最初は「また作業中のファイルが混ざっているだけだろう」と思ったのですが、中身を見たら違いました。

何が残っていたのか

1つ目のサイトで残っていたのは build.js の差分でした。

+        // 終了セールは検索対象から外す。
+        // listedArticles() から外れた時点で sitemap にも一覧にも載らなくなるが、
+        // ページ自体は 200 のまま残る設計(直URL・サイト内検索で参照できる)。
+        noindex: isEnded(a),

見覚えがあります。これはすでにクローズしたIssueの修正でした。「sitemapにもリンクにも無い不可視ページが200で公開され続けている」という指摘に対して、期限切れ記事へ noindex を付ける、という対応です。

同じ修正を6サイトへ入れてクローズしてありました。

そこで6サイトを調べたら、こうなっていました。

                作業ツリー    HEAD
manga-deals        1          0     ← ここだけ未コミット
ocha               1          1
senzai             1          1
menrui             1          1
coffee             1          1
beer               1          1

1サイトだけ、修正が git に入っていませんでした。

同じことが別の2サイトでも起きていました。片方は配信サービスへの検索リンクを追加する修正(375行)、もう片方は表示ステータスの綴りを正規化する修正です。どちらもクローズ済みのIssueの中身でした。

なぜ気づかなかったのか

本番の挙動が正しかったからです。

自動更新は毎回 node build.js を実行してから配信します。実行されるのは作業ツリーの build.js なので、未コミットであっても修正は効きます。毎日、直った状態の HTML が公開されていました。

そして生成物である public/ はコミット対象に入っています。

整理するとこうなります。

  • 入力(build.js)… コミット対象 → 作業ツリーに残る
  • 出力(public/)… コミット対象 → git に入る

「新しい入力で作った出力」だけがコミットされ、入力は残る。

リポジトリを clone して node build.js を回すと、コミット済みの public/ とは違う HTML が出ます。ビルドの再現性が壊れている、という形の不整合でした。

しかもコマンドは全部成功します。deploy も通る、検査も通る、監査も緑。

検査が見ていた向きが逆だった

デプロイ前のゲートには「作業ツリーが origin より遅れていないか」を見る項目があります。

これは、古い作業ツリーからデプロイして公開直後の記事を本番から消してしまった事故(実際に10分ほど404にしました)の再発防止として入れたものです。

つまり見ているのは遅れの側です。

今回のは逆で、origin より進んでいる(未コミットの変更がある)側でした。こちらは検査対象になっていません。

言われてみれば当たり前なのですが、「同期しているか」という言葉で括ってしまうと、片方向しか見ていないことに気づきにくい。

origin より遅れている  → 検査あり(過去の事故の再発防止)
origin より進んでいる  → 検査なし  ← ここ

対処と、残した判断

3サイトとも、その場で明示的にコミットしました。

node automation/run.js git:commit --scope manga-deals \
  --allow build.js,fleet-sites.json \
  --message "fix: 終了セール記事に noindex を付ける(他5サイトはコミット済み・ここだけ残っていた)" \
  --push

--allow は「想定パス以外を意図的に含める」ときのフラグで、判断が記録に残るようにしてあります。無条件に巻き込む -A に戻すのではなく、1件ずつ理由を書いて入れる形です。

一方、検査を足すところまではやりませんでした

「未コミットの変更があったら落とす」にすると、並行作業をしている最中は毎回落ちます。日次の自動実行なので、落ち続ける検査は必ず無視されるようになります。

なので、まずは警告として出してログに明示するところから、という提案をIssueに残して判断を仰ぐことにしました。ここは自動で決めてよい範囲を超えていると思ったからです。

この仕組みで更新しているサイトの1つがマンガお得情報です。

学び

一般化するとこうなります。

生成物をリポジトリに入れる構成では、「生成物の入力」もセットでコミット対象に含めないと、本番とリポジトリが静かにズレる。

そしてズレたことに気づく手掛かりが、この構成にはほとんどありません。

  • 本番は正しく動いている
  • コマンドは全部成功する
  • 検査も監査も通る

唯一の手掛かりが「コミット対象外の変更があります」という exit 3 でした。今日それを読み流していたら、3サイトとも見つかっていません。

毎回出る警告は無視されるようになるので、この exit 3 が普段は出ない状態を保っておくこと自体に価値がある、とも言えます。今日は逆に、普段出ないものが出たので中身を見た。そういう設計になっていたのは運がよかったです。


本記事はAI補助で執筆した、個人開発の紹介記事です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?