👻
GitHub Actionsで高速にgit diffを取る
GitHub Actionsで git diff
を使って差分を取ろうとしたとき、shallow cloneだと取得できません。しかし全部fetchすると時間がかかります。
今回は、最低限のfetchだけを取得して、ちゃんと差分を取れるようにする設定を紹介します。
やりたいこと
- GitHub ActionsでCIを回すときに
git diff
を使って差分を取得したい - でもクローンは最小限(
fetch-depth: 1
)にしたい
解決方法
まずは shallow clone。
- name: Checkout code with shallow clone
uses: actions/checkout@v4
with:
fetch-depth: 1
fetch-tags: false
これだけだと、ベースブランチとの共通祖先(merge base)が手元にないので、このあと追加で最低限のコミットだけ取得します。
- name: Fetch necessary commits
run: |
# Get base and head commit SHAs from the pull_request event payload
BASE_SHA="${{ github.event.pull_request.base.sha }}"
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
echo "Base SHA: ${BASE_SHA}"
echo "Head SHA: ${HEAD_SHA}"
# Use the GitHub Compare API to get the merge base commit SHA
MERGE_BASE_SHA=$(curl -s \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/compare/${BASE_SHA}...${HEAD_SHA}" | jq -r '.merge_base_commit.sha')
# Exit if the merge base SHA is not found
if [ "$MERGE_BASE_SHA" = "null" ] || [ -z "$MERGE_BASE_SHA" ]; then
echo "Error: Could not retrieve merge base commit SHA."
exit 1
fi
echo "Merge base commit SHA: ${MERGE_BASE_SHA}"
echo "MERGE_BASE_SHA=${MERGE_BASE_SHA}" >> $GITHUB_ENV
# Fetch the merge base commit if it is not already present in the shallow clone
git fetch --depth=1 origin ${MERGE_BASE_SHA}
やっていることは以下です。
-
BASE_SHA
とHEAD_SHA
をPull Requestの情報から取得 - GitHubのCompare APIを叩いて、merge baseを特定
- そのmerge baseだけをピンポイントでfetch
git diffを取得する
この後は以下のようにすればgit diffで差分を取得できます。
MERGE_BASE_SHA=${{ env.MERGE_BASE_SHA }}
git diff ${MERGE_BASE_SHA} ${HEAD_SHA}
まとめ
必要な差分だけfetchすれば、CIが速くなりつつ、使い慣れたgit diffで差分を取得できます。
今回紹介した方法はGitHub Actionsで完結するので便利です。
Discussion