Overotakuted

by saitolumesaitolume

Vercel のプレビューデプロイを monorepo の特定のパッケージが変更されたときだけ実行する

📅 2021/6/6 ・ ☕ 2 min read

背景

Vercel には単一の Git リポジトリから複数のプロジェクトを作る機能があります。

Monorepos – Vercel

この機能を利用すれば、monorepo (モノレポ、モノリポ) でも Pull Request 作成時に自動的にプレビュー環境を生成することができます。

しかし、1 つのパッケージしか変更していない Pull Request でも、同じリポジトリに対応している全てのプロジェクトのプレビュー環境を生成するという問題があります。

無料枠で Vercel を使用している場合は、複数のデプロイを同時に実行することができないため、開発速度の低下に繋がります。今回はこの問題を解決します。

方法

Vercel の Ignore Build Step で、対象のパッケージに変更がない場合はビルドをスキップします。

Projects - Vercel Documentation

Ignore Build Step は設定されたコマンドの exit code を参照して、1 で終了したときはビルドを続行して、0 で終了したときはビルドをスキップしてデプロイ状態を Canceled にする機能です。

公式ドキュメントには、スクリプトや環境変数、フォルダ及びワークスペースを参照する例が載っています。

How do I use the "Ignored Build Step" field on Vercel? - Vercel Support Article

やること

1. 変更を検知するシェルスクリプトを作成

#!/bin/bash

if [[ "$VERCEL_ENV" != "preview" ]]; then
    exit 1;
fi

GLOB=${@}
PREV_MERGE_COMMIT=`git rev-list --grep "Merge pull request" -n 1 HEAD`

eval "git diff --quiet $PREV_MERGE_COMMIT HEAD -- $GLOB"

git rev-list によるコミットログの検索によって前回の merge commit を取得して、そこから最新状態までの差分を確認するスクリプトです。 本番環境にデプロイするときはビルドを実行したいので、プレビュー環境のときだけスクリプトを実行します。

--quit オプションを有効にすることで、すべての出力を表示せず、差分が存在するときは exit code を 1 にして終了することができます。

2. Ignored Build Step にシェルスクリプトを設定

対象プロジェクトの Settings > Git > Ignored Build Step を開きます。

Ignored Build Step

COMMAND にスクリプトを実行するコマンドを入力することで、glob で指定したパスのパッケージが前回の merge commit から変更されていないときはビルドをスキップすることができます。

bash ../../scripts/check_ignore_build_step.sh glob

対象のパッケージが依存しているパッケージの変更も検知したいときは、glob. ../{deps1, deps2} のように書くことで対応できます。

3. デプロイを実行

デプロイ実行後のコンソールに "The Deployment has been canceled as a result of running the command defined in the "Ignored Build Step" setting." というメッセージが表示されていたら成功です。

Vercel のデプロイ Overview

おまけ

なぜ main ブランチとの比較をしないのかという指摘を受けそうなので補足しておきます。

理由は、ビルドを実行する環境では、なぜかブランチが強制的に master になる上に、他のブランへの参照が失われているからです。

master ブランチしか表示されていない git branch の結果