前回、"use client" を含むページが静的に焼けていた話を書きました。
その静的化を進めた結果、今度は CI が落ちました。
ローカルでは npm run lint も npm run build も通っています。
その状態で PR を出したら、GitHub Actions が赤くなりました。
Error: supabaseUrl is required.
at src/utils/supabase/public.ts:6:10
at src/app/[username]/page.tsx:6:20
Error: Failed to collect page data for /[username]
環境変数が無いことは分かっていました
.env.local は .gitignore に入れてあります。正しく入れてあります。
だから CI の環境に Supabase の接続情報はありません。
ここまでは、読めば分かる話でした。
分からなかったのは別のところです。
なぜ、今まで通っていたのか。
CI 自体は前の工程から動いていて、何度も緑になっています。
環境変数が無いのはその頃も同じでした。
焼くには中身が要ります
理由は、この工程で入れた generateStaticParams でした。
前の工程まで、ビルドはデータベースを読んでいません。
ページは動的レンダリングで、DBを引くのはリクエストが来たときです。
だからビルド時には接続情報が要りませんでした。
この工程で「どの username のページを事前に焼くか」を決めるようになりました。
焼く対象を知るには、ビルド時にDBへ問い合わせる必要があります。
順番に書くとこうなります。
- 公開ページを速く配りたいので、事前に焼く
- 焼くには中身が要る
- ビルドが外部サービスへの問い合わせを持つ
CI が教えてくれたのは、設定漏れではありませんでした。
自分が選んだ設計が持ち込んだコストのほうです。
速さと引き換えに、ビルドの依存が1つ増えていました。
対処は env を1ステップに渡すだけでした
GitHub Secrets に2つ登録して、ci.yml の build ステップに渡しました。
- run: npm run lint
- run: npm run build
env:
NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NEXT_PUBLIC_SUPABASE_URL }}
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY }}
lint のほうには渡していません。ESLint はDBを読まないからです。
落ちたのは build だけなので、直すのも build だけにしました。
同じことがデプロイでも起きます。
Vercel でのビルドも同じくDBを引くので、あちらにも同じ2つが要ります。
公開値なのに Secrets に入れました
登録した2つは NEXT_PUBLIC_ で始まっています。
これはブラウザに配られる値なので、実際には秘密ではありません。
Supabase の publishable key は公開前提で、行を守るのは RLS の役目です。
それでも Secrets に入れました。
理由は、キーの値をリポジトリに書かないという方針に例外を作りたくなかったからです。
一度「これは公開値だから直接書いていい」を許すと、
次に本当に秘密のキーが来たときの判断が鈍ると思いました。
判断の回数を増やさない、という意味では横着な決め方です。
ただ、この手の線引きは疲れている日に間違えるので、線を1本にしておきました。
2回目の赤は、意味が違いました
この工程より前に、一度わざとCIを赤くしたことがあります。
コミットメッセージは test: break build to verify CI fails でした。
CIが本当に止めてくれるのかを確かめるために、意図的に壊しています。
| 何が起きたか | |
|---|---|
| 1回目 | 壊したから落ちた。CIが機能している証拠 |
| 2回目 | 壊していないのに落ちた。設計のコストが出てきた |
CIを入れる理由を、自分は「壊れたコードを止めるため」だと思っていました。
1回目はまさにそれです。
2回目に止まったのは、壊れていないコードでした。
教えてくれたのは、選んだ設計が持ち込んだ依存のほうです。
おわりに
「ISR は速い」とだけ覚えていたら、この赤は読めなかったと思います。
速さの対価がどこに出るかまで含めて1セットでした。
ローカルで通ったから大丈夫、という感覚も少し変わりました。
手元には .env.local があります。
自分の環境にあるものは、自分からは見えません。
次回は、この工程でもう1つ引っかかっていた、
dev と build が同じ言葉で別のことを言っていた話を書きます。
