CIで実行した静的解析の結果をMerge Requestのコメントとして書き込みたいというニーズは多くあります。 これを容易に叶えてくれるプロダクトがreviewdogです。
問題
このreviewdogをGitLab CI/CDに設定したのですが、以下の様なエラーが出て失敗してしまうのです。
reviewdog: fail to get diff: failed to get merge-base commit: exit status 1
解決法とその理由
これが最善なのか、他に方法がないのかというとなかなか答えに窮しますが、以下のようにして解決できました。
要するに、ジョブの変数としてGIT_STRATEGY
、GIT_DEPTH
を設定するということです。
unittest: (snip) variables: GIT_STRATEGY: clone GIT_DEPTH: 0 script: (snip)
この意図なのですが、前提としてreviewdogではfeature branchとtarget branchの共通の祖先を探すべくgit merge-base
を実行します。
func (g *MergeRequestDiff) gitDiff(_ context.Context, baseSha, targetSha string) ([]byte, error) { b, err := exec.Command("git", "merge-base", targetSha, baseSha).Output() if err != nil { return nil, fmt.Errorf("failed to get merge-base commit: %w", err) }
従ってreviewdogの動作前提は、CIランナーのGitローカルリポジトリの中に、その両branchとそれらのコミットが存在していることです。
GitLabでのリポジトリ取得仕様
GitLab Runnerがリモートリポジトリからコンテンツをどのように取得するかは、 Choose the default Git strategyに定められています。
プロジェクトのCI/CDの設定として位置付けられており、各CIジョブは特別な指定がなければこの設定に従います。 以下がデフォルト設定。
reviewdogの動作前提を満たす
Reviewdogの動作前提を満たすためには、確実にcloneし、取得する歴史も無制限にしてやれば良いでしょう。 もちろん巨大な歴史を持つリポジトリなら軽々に判断できない話ですが、今回ぼくが使うリポジトリの歴史は大したことがありません。
これらを設定するのがGIT_STRATEGY
、GIT_DEPTH
という2つの変数です。ドキュメントは以下。
GIT_STRATEGY
はclone
、fetch
、none
を指定できます。
clone
を指定すると無条件でgit clone
してくれるため、GitLab Runnerのローカル状態がどうであっても、target branchを取得することが保証されます。
GIT_DEPTH
はいわゆるShallow Cloneを行うか否かで、"0"
を指定することでShallow Copyを無効にしています。