プライベートな Git サブモジュールがあるプロジェクトを Vercel にデプロイする方法

2024-05-26 15:38 (23 months ago)
Submodule Alchemy
この記事をテーマにした曲を再生

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>

アーカイブ