デプロイ失敗から Git のタグが2種類あることを知った話
はじめに
開発エンジニアのくっしーと申します。猫が好きです。
クラウド製品の開発チームで、インフラ構築や CI/CD に関わっています。
この記事では Git タグの種類と仕様について、
デプロイ時の失敗談を交えながら紹介します。
この記事の中に、少しでもお役に立てる内容があれば幸いです。
この記事で伝えたい情報(忙しい人向け)
Git のタグは下記の2種類がある。
lightweight タグ:コミットへの参照。それ自体は SHA を持たない。
annotated タグ:データオブジェクト。独自の SHA を持つ。
接尾辞 ^{} で非タグオブジェクト(コミット)の SHA を取得できる。
注意
本筋に絡まない箇所はかなり省略・簡略化しています。
チームでの Git とデプロイ運用について
私のチームでは製品のコード管理に Git を利用しており、
ブランチは開発用とデプロイ用に分け、下図のように運用しています。
v1.0.0 タグの追加時は下記の git tag コマンドを利用しました。
git tag v1.0.0 bz6sebw
デプロイは下記の2つのフェイズに分けています。
(時間のかかるビルドを事前に対応しておくための施策です。)
ビルド処理:コードをビルドして成果物置き場にアップロード
デプロイ処理:ビルド成果物を稼働用の環境にアップロード
下図は v1.0.0 デプロイの処理フローです。滞りなく完了しました。
v1.0.1 デプロイでは Git の GUI クライアントの画面からタグを付けました。
そして、後続のデプロイ処理は失敗してしまいました。
デプロイ処理が失敗した経緯
v1.0.1 のデプロイ処理はビルド成果物の検索部分で失敗していました。
調査の結果、失敗の経緯は以下の通りでした。
v1.0.1 タグはそれ自体に SHA が付いていた(≠ コミットの SHA)。
ビルド処理ではコミットの SHA を取得できており、
ビルド成果物にもコミットの SHA が識別用メタデータとして付いた。デプロイ処理では v1.0.1 タグ自体の SHA を取得してしまい、
ビルド成果物が見つからず失敗した。
下図は v1.0.1 デプロイの処理フローです。
ここで改めて Git のドキュメント(下記リンク参照)を確認したところ、
Git タグには下記の2種類があることがわかりました。
lightweight タグ:コミットへの参照。それ自体は SHA を持たない。
annotated タグ:データオブジェクト。独自の SHA を持つ。
ドキュメントの記述通り、下記のように git tag コマンドをオプション無しで実行した場合は lightweight になりました。
git tag v1.0.0 bz6sebw
また、v1.0.1 のタグ付けに利用した Git GUI クライアントでは、
作成したタグは annotated になっていました。(lightweight では作成不可)
解決策
接尾辞 ^{} を利用することで、非タグオブジェクトの SHA を取得できます。
今回は下記のように ^{} を追加することで、
意図通りコミットの SHA を取得することができました。
git rev-parse HEAD^{}
git rev-parse FETCH_HEAD^{}
明示的にコミットの SHA を取得するという意味合いを含めて、
HEAD の利用箇所(ビルド処理、今回問題無し)にも追加しています。
また、現在はデプロイ用の lightweight タグ付け処理をスクリプト化して、
基本的にそちらを利用していただく運用としています。
作業担当者の環境依存による操作結果のズレを避けるためです。
(対象のリポジトリが多いため、時短の目的もあります。)
あとがき
デプロイ失敗を通して、Git タグの種類と仕様に関する知見を得られました。
タグ付け方法によってタグの種類が異なっていたこと、
特定の場合にだけタグの種類に起因する挙動変化があったことは、
この知見が無いと回避できない落とし穴のように思えました。
この記事をお読みになった方が落とし穴を飛び越せれば、
もしくは早期に脱出できれば幸いです。
最後までお読みいただきありがとうございました。