ジンです。
初めてNext.js Bundle Analysisを使ったCIの改修に取り組んだので、解決方法や調べてわかったことをまとめました。
何をやったのか、この記事は何の話なのか
PRを作成した時にそのPRのベースブランチをヘッドブランチとしたPRが存在しない場合、ヘッドブランチとベースブランチのバンドルサイズの比較ができずCIが落ちてしまう問題に対して、PRに解決方法のコメントを残すことによって担当者が自ら解決できるようにした。
目次
CI改修で解決したいこと、CIが失敗する原因
解決したいこと
Next.js Bundle Analysisを使ったCIが失敗した時、どう解消するべきかについてその都度チーム内で発生する会話を繰り返さず、担当者が解決できる仕組みを作りたい。
よく起きる失敗の原因かつ、今回カバーする原因
PRを作成した時にそのPRのベースブランチをヘッドブランチとしたPRが存在しない場合、ベースブランチの計算されたバンドルサイズがGitHub ActionsのArtifactに存在しておらず、ヘッドブランチとベースブランチのバンドルサイズの比較ができず失敗して落ちる。
例)作業ブランチ→集約ブランチへ向けてPRを作成した時に、集約ブランチをベースブランチとしたPRが作られていない場合、集約ブランチの計算されたバンドルサイズがGitHub ActionsのArtifactに存在しておらず、作業ブランチと集約ブランチのバンドルサイズの比較ができず失敗して落ちる。
サンプルコードと見る、比較まわりの流れとCIが失敗するケース
バンドルサイズ計算〜バンドルサイズの比較まわりの流れ
- ヘッドブランチのバンドルサイズを計算
- 出力されたヘッドブランチのバンドルサイズのファイルをGitHub ActionsのArtifactにアップロード
- GitHub ActionsのArtifactに保存されているベースブランチのバンドルサイズをダウンロード
- ヘッドブランチのバンドルサイズとダウンロードしたベースブランチのバンドルサイズを比較
nextjs-bundle-analysisのサンプルコード
## 1. ヘッドブランチのバンドルサイズを計算
- name: Analyze bundle
## バンドルサイズを計算し、.next/analyze/__bundle_analysis.jsonというパスで出力
## ref: https://github.com/hashicorp/nextjs-bundle-analysis/blob/main/report.js
run: npx -p nextjs-bundle-analysis report
## 2. 出力されたヘッドブランチのバンドルサイズのファイルをGitHub ActionsのArtifactにアップロード
- name: Upload bundle
uses: actions/upload-artifact@v3
with:
name: bundle
path: .next/analyze/__bundle_analysis.json
## 3. GitHub ActionsのArtifactに保存されているベースブランチのバンドルサイズをダウンロード
- name: Download base branch bundle stats
uses: dawidd6/action-download-artifact@v2
if: success() && github.event.number
with:
workflow: nextjs_bundle_analysis.yml
branch: ${{ github.event.pull_request.base.ref }}
path: .next/analyze/base
## 4. ヘッドブランチのバンドルサイズとダウンロードしたベースブランチのバンドルサイズを比較
- name: Compare with base branch bundle
if: success() && github.event.number
run: ls -laR .next/analyze/base && npx -p nextjs-bundle-analysis compare
CIが失敗するケース
今回カバーする失敗のケースは、3のベースブランチのバンドルサイズをダウンロードするステップで、事前にバンドルサイズの計算がなされていない(計算されたファイルが存在せずダウンロードできない)時に起きる。
実際のGitHub Actions上のエラー
Error: no matching workflow run found with any artifacts?
##[debug]Node Action run completed with exit code 1
##[debug]Set output found_artifact = false
##[debug]Finishing: Download base branch bundle stats
解決方法
CIが何らかの理由で失敗し、かつPRのベースブランチをヘッドブランチとしたPRが存在しない場合、CIが実行されたPRのベースブランチをヘッドブランチとしたPRを作成するよう促すコメントをPRに残す、以下のステップを実装した。
1. ベースブランチからのPRがあるかチェックするステップ
- name: Check if PR exists from base branch
continue-on-error: true ## このステップが失敗してもCI実行を継続する
run:
echo "BASE_BRANCH=${{ github.base_ref }}" >> $GITHUB_ENV ## 環境変数としてベースブランチの名前をBASE_BRANCHに代入
if [ ${{ github.base_ref }} = "develop" ]; then ## もしベースブランチがdevelopの場合このステップをスキップする
echo "Skipping PR check for develop branch"
else
PR_NUMBER=$(gh pr list --head $BASE_BRANCH --json number -q ".[].number") ## ベースブランチがヘッドブランチとして作成されているPRの数を取得
echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV ## 環境変数として上で取得したPRの数をPR_NUMBERに代入
if [ -z "$PR_NUMBER" ]; then ## もしPR_NUMBER変数が空の場合、No PR foundと出力
echo "No PR found"
fi
fi
2. ベースブランチからのPRの作成を促すステップ
- name: PR from base branch reminder comment
if: ${{ failure() && env.PR_NUMBER == '' }} ## CIが失敗し、かつ環境変数PR_NUMBERも空の場合
uses: marocchino/sticky-pull-request-comment@v2 ## PRにコメントするライブラリ
with:
header: next-bundle-analysis ## このヘッダーがついたコメントを更新する
message: 'Error: マージ先のブランチ( ${{ env.BASE_BRANCH }} )からのPRが作成されていません。作成後、再実行してください。' ## PRのベースブランチをヘッドブランチとしたPRの作成を促すコメントを残す
記事を読むときの事前知識とか(おまけ)
1. GitHub Actions
GitHub Actionsを使用すると、ワールドクラスのCI / CDですべてのソフトウェアワークフローを簡単に自動化できます。 GitHubから直接コードをビルド、テスト、デプロイでき、コードレビュー、ブランチ管理、問題のトリアージを希望どおりに機能させます。
GitHub上でワークフローを自動的に実行させることができるサービスです。
僕は社内のドキュメントや、チーム内で『GitHub CI/CD実践ガイド ――持続可能なソフトウェア開発を支えるGitHub Actionsの設計と運用』についての勉強会があったのでそれを主に参照して進めていました。
計算したバンドルサイズを出力した結果を保存するArtifactについては、ジョブ間でデータを共有することのできる機能です。
2. Next.js Bundle Analysis
Analyzes each PR's impact on your next.js app's bundle size and displays it using a comment. Optionally supports performance budgets.
それぞれのPRがバンドルサイズに与える影響を分析し、コメントを使用して表示します。
※@next/bundle-analyzerとは別のツールです。僕はずっと混同していました。
わかりやすい記事:
バンドル(bundle)とは
例えば開発体験向上のためなどコンポーネントごとにファイルを分割しますが、ブラウザ側がファイルを読み込む時には複雑な依存関係を紐解きながらブラウザに最適化された1ファイルへとひとまとめにします。そのプロセスがバンドルです。
3. sticky-pull-request-comment
Create a comment on a pull request, if it exists update that comment. This library runs with GitHub Actions.
PRにコメントを作成し、もしすでに存在している場合はコメントを更新するという、GitHub Actions上で動作するツールです。
わかりやすい記事:
4. WFの改修に取り掛かるまでのあれこれ
Q. 実際にどう動いているのかを確認するには?
A. workflowのymlファイルを確認する。読めない部分もあったので、Copilotと会話しながら読んでいました。
Q. 実際にコケたWFのログを探すには?
A. リポジトリのActionsタブ > 左のワークフローの一覧から確認したいものを選択 > 実行結果一覧右のステータスからfailureを選択
Q. 気をつけたことは?
A. CIも他のソースコード同様、既存のものと記法を揃える。一番楽だし、レビュアーの負担も減る。
あとがき
シェルスクリプトの記法みたいですが、まだわからないことがちらほら。精進します。