前提
- github
- リポジトリはprivate
- main ブランチ = master ブランチ
- vercel
- next.jsは使っていてもいなくてもいい
やりたいこと
例えば、github上でmainへのPRをマージしたときに、vercel上では そのコードで 環境変数とドメインだけが異なる本番環境
,デモ環境
,開発環境
の3つの環境がデプロイされるようにしたい
- 本番環境(prod)
- 本番用の環境変数を使い、実際に本番APIと疎通する
- ドメインは a.com とする
- デモ環境(demo)
- デモ環境用の環境変数を使い、デモ環境用APIと疎通する
- ドメインは a.demo.com とする
- to Bの顧客が試す環境というイメージ
- 開発環境(dev)
- 開発用の環境変数を使い、開発環境用APIと疎通する環境
- ドメインは a.dev.com とする
- 開発者が試す環境
AWS Amplifyは1ブランチに対して環境変数などを変えた複数ビルドを構築することができる
しかしVercelは production
preview
develop
deployの概念が思想としてあり、ビルドがどのdeploy typeになるかルールがあるので、単純にはそのようなことができない
解決までの流れとしては、
-
main
と自動で同期されるdemo
,dev
ブランチをつくる - demo, devブランチとドメインを紐付ける
- 環境変数を変えたビルドを作る
- vercelのドメインURLがproduction deployになっているので、demo, devが検索にヒットしうる問題を解決する
となる
1 ブランチ同期
1.1 方法
を使う
sshとhttpsどちらでもcloneできるが、楽なhttpsを使う
# @see https://github.com/marketplace/actions/github-repo-sync
name: Sync branches
on:
push:
branches:
- main
jobs:
sync_branches:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
persist-credentials: false
- name: "force push main to demo"
uses: repo-sync/github-sync@v2
with:
source_repo: https://${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}@github.com/[organization name]/[repository name].git
source_branch: "main"
destination_branch: "demo"
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: "force push main to dev"
uses: repo-sync/github-sync@v2
with:
source_repo: https://${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}@github.com/[organization name]/[repository name].git
source_branch: "main"
destination_branch: "dev"
github_token: ${{ secrets.GITHUB_TOKEN }}
[organization name]/[repository name]
のところは適宜置き換える
1.1.1 github token をURLに入れても安全なのか
には
Before each job begins, GitHub fetches an installation access token for the job. The token expires when the job is finished.
とあるので大丈夫そう
1.2 protected branchにpushしたい場合
GitHubのbranch protection
に設定しているとGitHub Actionsもpush不能になる
1.2.1 回避方法1: Personal access tokenを使う
によると
- uses: actions/checkout@v2
with:
persist-credentials: false
にしておき、 github.token
ではなく personal access token を使えばよいらしい
デプロイに個人のpersonal access tokenを使うのは退職などを考えるとアンチパターンなので、CI用に共有するbotユーザーアカウントを作って使うとよさそう
(試してはいない)
1.2.2 回避方法2: git hooks の pre-pushで防ぐ
GitHubが公式に誤爆push防止できるようになったことで廃れた印象があるが、今回はGitHubに頼らない手段として利用できる
「人間が開発するときにだけpre-pushが入っており誤爆pushを防げて、GitHub Actionsはpushできる」という状態にしたい
これはpackage.jsonのpostinstallで生成すれば雑だが達成できる
1.2.3 その他の回避方法
https://github.com/marketplace/actions/git-sync-action でもできるかも
https://github.com/marketplace/actions/sync-branches はPRを自動生成してくれるaction。PRで同期したい派なら使える
Vercel CLI でやるのは茨の道
2 Custom Domainの設定
にあるように設定すると、demoブランチに対して a.demo.com
のようなURLでアクセスできるようにビルドが紐づく
3 環境変数の異なるビルドを作る
が公式の説明
process.env.VERCEL_GIT_COMMIT_REF
を使う
next.jsを使っている場合はnext.config.jsのenvを経由して切り替えて渡す必要がある
また、余談として
の .env.production
.env.development
は性質が違うので使えない
4 Custom Domainを検索避けしなければいけない場合の対策
Custom Domainを設定すると、
The production domain(s) are defined from the Domains tab of a Project on the Vercel Dashboard.
To add a production domain to a Project, visit Domains from the Project > Overview page, you can read more about this in the custom domains documentation.
とあるように、 production deploy扱い となる
productionとpreviewの違いはレスポンスヘッダーに X-Robots-Tag: no-index
がついて検索避けされるかどうか である
Domain設定したvercelのビルド結果を参照できる3つのURLを見ると実際に以下の違いがあった
-
a.demo.com
みたいに自分でdomain設定したURL-
x-robots-tag: no-index
なし
-
-
リポジトリ名-git-demo-団体名.vercel.app
みたいなvercelが勝手に作るURL-
x-robots-tag: no-index
あり
-
-
リポジトリ名-ハッシュ値-団体名.vercel.app
みたいなvercelが勝手に作るURL-
x-robots-tag: no-index
あり
-
大まかに考えて、回避策としては
- main 起因のビルドでないなら
x-robots-tag: no-index
をつける - main 起因のビルドでないなら
<meta name="robots" content="noindex, nofollow">
をつける - DNS設定でpreview buildのdomainに向ける
が考えられる
4.1 next.jsを使っている場合の回避方法
async headers() {
return process.env.VERCEL_GIT_COMMIT_REF === 'main'
? []
: [
{
source: '/',
headers: [
{
key: 'X-Robots-Tag',
value: 'no-index',
},
],
},
{
source: '/:any*',
headers: [
{
key: 'X-Robots-Tag',
value: 'no-index',
},
],
},
];
},
こういうのを書くとうまく設定された
4.2 DNS設定だけでなんとかする場合(失敗)
https://vercel.com/docs/custom-domains#dns-records
やRoute53などの各々が利用しているところで
a.demo.com
CNAME リポジトリ名-git-demo-団体名.vercel.app
みたいなのを設定すればCustom Domainの設定も要らず、Custom Domainがproduction deployになる問題も楽に回避できるかと思ったが、何故か以下のような画面になって失敗した
感想
- vercelにCustom Domainにもpreview modeを指定する設定がないのが不便に感じる
- 要望出そうかな→feedbackに書いて送ってみた
- vercelのpassword protectionの柔軟性がないこと等も含めてどうしてもうまく運用にマッチしない場合は、amplifyとか別のサービスをdev,demo作成に使うのが良いと思う
- serverless functionに依存していたら使えない
参考資料
- vercelで使える環境変数
- vercelの定義する環境概念
- github actionsで使える環境変数