プライベートな Git サブモジュールがあるプロジェクトを Vercel にデプロイする方法
Vercel のビルド時は、プライベートリポジトリとなっているサブモジュールを取得できない。
Github上の Vercel のアプリに権限を付与してもできない。
Fine-grained personal access token を使って HTTP で取得させる必要がある。
1. Fine-grained personal access token を作る
https://github.com/settings/tokens?type=beta
上記ページから、 Generate new token をクリック。

Repository access は、 Only select repositories を選択し、必要最低限のリポジトリを選択する。
Repository permissions は Contents の Read-only のみ付与する。

Generate token ボタンを押して生成する。
2. Vercel の環境変数に登録する
Vercel のプロジェクトの Settings → Environment Variables に登録する。私は GITHUB_PAT という名前で登録した。

3. ビルドスクリプトを作る
sh/build-for-vercel.sh という名前で作成する。
推奨: GIT_ASKPASS を使う方法
URL にトークンを直接埋め込む方法はセキュリティリスクがあるため、GIT_ASKPASS を使う方法を推奨する。
GIT_ASKPASS は、git が認証情報を必要とするときに自動実行されるスクリプトを指定する環境変数。
トークンが URL や git config に残らないため安全。
#!/usr/bin/env bash
cd $(dirname $0)/../ || exit
set -e
if [ -z "${GITHUB_PAT}" ]; then
echo "環境変数 GITHUB_PAT が設定されていません。Github の Fine-grained トークンを再生成して、Vercel の環境変数 GITHUB_PAT に登録してください。"
echo "https://github.com/settings/tokens?type=beta"
exit 1
fi
# GIT_ASKPASS でトークンを渡す (URL にトークンを含めない)
ASKPASS_SCRIPT="$(mktemp)"
trap 'rm -f "${ASKPASS_SCRIPT}"' EXIT
cat > "${ASKPASS_SCRIPT}" <<'SCRIPT'
#!/usr/bin/env bash
case "$1" in
*Username*) echo "x-access-token" ;;
*Password*) echo "${GITHUB_PAT}" ;;
*) echo ;;
esac
SCRIPT
chmod 700 "${ASKPASS_SCRIPT}"
export GIT_ASKPASS="${ASKPASS_SCRIPT}"
export GIT_TERMINAL_PROMPT=0
git submodule set-url <my-submodule> "https://github.com/ytyng/<my-submodule>.git"
git submodule sync
git submodule update --init
# 本来のビルドスクリプト
npm run generate
ポイント:
GIT_ASKPASSに指定した一時スクリプトが、git の認証要求に対して自動的にトークンを返すtrapでビルド完了後に一時スクリプトを自動削除- サブモジュール URL にトークンを含めないため、git config にトークンが残らない
GIT_TERMINAL_PROMPT=0で対話的なプロンプトを無効化
以前の方法 (非推奨)
以下は URL にトークンを直接埋め込む方法。動作はするがセキュリティリスクがあるため、上記の GIT_ASKPASS を使う方法を推奨する。
#!/usr/bin/env bash
cd $(dirname $0)/../ || exit
if [ -z "${GITHUB_PAT}" ]; then
echo "環境変数 GITHUB_PAT が設定されていません。Github の vercel-submodule トークンを再生成して、Vercel の環境変数 GITHUB_PAT に登録してください。"
echo "https://github.com/settings/tokens?type=beta"
echo "https://vercel.com/<my-own-projects>/<project-name>/settings/environment-variables"
exit 1
fi
git submodule set-url <my-submodule> "https://${GITHUB_PAT}@github.com/ytyng/<my-submodule>.git"
git submodule sync
git submodule update --init
# 本来のビルドスクリプト
npm run generate
4. vercel.json を書く
今回は Nuxt の静的コンテンツ生成なのでこのような形になる
{
"buildCommand": "sh/build-for-vercel.sh",
"outputDirectory": ".output/public"
}
注意
ビルドの最初で、どうしても
Warning: Failed to fetch one or more git submodules
の警告が出てしまうが、気にしない。

補足
submodule update ではなくクローンしなおしても動く。
rm -r <my-submodule>
git clone --depth 1 --branch main "https://${GITHUB_PAT}@github.com/ytyng/<my-submodule>.git" <my-submodule>
開発相談をお待ちしています。