GitHub ActionsからCloudflareへ自動デプロイする【Cloudflare運用記録 #7】
はじめに
こんにちは。
なかのひとカンパニーの archer です。
前回はCloudflare R2について書きました。
ここまでで、
- Workers
- D1
- R2
を使って、WebサービスをCloudflare上で動かす構成を作ってきました。
次にやりたくなったのが、
デプロイも自動化すること
です。
ローカルから毎回、
pnpm deploy
を実行しても公開できます。
ただ、GitHubを中心に開発しているなら、
コードを変更
↓
PR
↓
レビュー
↓
mainへマージ
↓
自動でデプロイ
までつなげたくなります。
そこでGitHub Actionsを使っています。
今回は、GitHub ActionsからCloudflare Workersへ自動デプロイする流れをまとめます。
手動デプロイでも十分ではある
Cloudflare WorkersはWranglerから簡単にデプロイできます。
npx wrangler deploy
OpenNextを使っている自分の構成では、package.jsonにデプロイ処理を用意しています。
{
"scripts": {
"deploy": "opennextjs-cloudflare build && opennextjs-cloudflare deploy"
}
}
そのため、
pnpm deploy
で本番へ反映できます。
個人開発なら、これでも十分です。
ただ、だんだん困ることが出てきます。
デプロイを忘れる
古いブランチからデプロイする
テスト前にデプロイする
ローカル環境によって結果が変わる
人間が毎回操作する以上、どうしてもミスする可能性があります。
だったら、
mainへ入ったものだけ自動でデプロイする
方が分かりやすいと考えました。
GitHub Actionsを間に入れる
現在のイメージはこんな形です。
開発
↓
GitHubへpush
↓
Pull Request
↓
CI
↓
レビュー
↓
mainへマージ
↓
GitHub Actions
↓
Cloudflare Workers
↓
本番
重要なのは、
pushしたら即本番
ではないことです。
PRでは、
- lint
- build
- test
- レビュー
を行います。
そのうえでmainへ入ったものだけ本番へデプロイします。
GitHubを、
本番へ出すための入口
として使っています。
Cloudflareの認証情報を用意する
GitHub ActionsからCloudflareを操作するには認証が必要です。
ローカルでは、
wrangler login
でブラウザ認証できます。
しかしGitHub Actionsではブラウザを開いてログインできません。
そのため、
CLOUDFLARE_API_TOKEN
CLOUDFLARE_ACCOUNT_ID
を使います。
API TokenはCloudflareの管理画面から作成します。
ここで意識しているのは、
必要以上の権限を与えないこと
です。
デプロイに使うTokenなら、デプロイに必要な範囲へ限定します。
複数のCloudflareアカウントを持っている場合も、対象アカウントだけに絞ります。
便利だからといって、
全部Read
全部Write
にはしません。
AI開発運用の記事でも書きましたが、ここはGitHubでもCloudflareでも同じだと思っています。
GitHub Secretsへ保存する
作成した値をソースコードへ直接書いてはいけません。
GitHubのRepository Secretsへ、
CLOUDFLARE_API_TOKEN
CLOUDFLARE_ACCOUNT_ID
を登録します。
Workflowでは、
${{ secrets.CLOUDFLARE_API_TOKEN }}
のように参照できます。
当然ですが、
.env
README
ソースコード
Issue
PR
などへAPI Tokenを貼らないようにします。
個人開発でも、これは変わりません。
Workflowを作る
GitHub ActionsのWorkflowは、
.github/workflows/
に置きます。
たとえば、
.github/workflows/deploy.yml
を作ります。
自分なら、まずこんな形から始めます。
name: Deploy to Cloudflare
on:
push:
branches:
- main
permissions:
contents: read
concurrency:
group: production
cancel-in-progress: true
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Setup pnpm
uses: pnpm/action-setup@v6
with:
version: 10
- name: Setup Node.js
uses: actions/setup-node@v7
with:
node-version: 22
cache: pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Lint
run: pnpm lint
- name: Build
run: pnpm build
- name: Deploy
run: pnpm deploy
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
mainへpushされると、このWorkflowが実行されます。
mainだけデプロイする
ここはかなり重要です。
on:
push:
branches:
- main
としているため、作業ブランチへpushしただけでは本番デプロイされません。
featureブランチ
↓
デプロイしない
main
↓
本番デプロイ
という境界を作れます。
個人開発だと、
「自分しか触らないから大丈夫」
と思いがちです。
自分もそう思います。
でも、自分が一番信用できないこともあります。
なので仕組みで防げるものは仕組みに任せています。
デプロイ前にテストする
Workflowの中では、いきなりデプロイせず、
- name: Lint
run: pnpm lint
- name: Build
run: pnpm build
を先に実行しています。
テストがあるなら、
- name: Test
run: pnpm test
も追加します。
流れとしては、
Install
↓
Lint
↓
Test
↓
Build
↓
Deploy
です。
途中で失敗すればDeployまで進みません。
これによって、
最低限の確認を通過したコードだけ本番へ出す
ことができます。
PRのCIとデプロイは分けてもいい
実際の運用では、
PR用CI
と、
本番Deploy
を別Workflowにする方法もあります。
たとえば、
ci.yml
deploy.yml
です。
PRでは、
lint
build
test
だけ。
mainへ入ったら、
deploy
を実行します。
こうすると役割が分かりやすくなります。
ci.yml
→ この変更は正常か
deploy.yml
→ 正常な変更を本番へ出す
個人的には、規模が大きくなってきたら分ける方が好きです。
concurrencyも入れておく
短時間に複数回mainへpushされることがあります。
たとえば、
commit A
↓
Deploy開始
commit B
↓
Deploy開始
となる場合です。
古いDeployと新しいDeployが並行して動くと分かりにくくなります。
そこで、
concurrency:
group: production
cancel-in-progress: true
を設定できます。
新しい本番デプロイが始まったら、同じグループで動いている古い処理をキャンセルします。
小さい設定ですが、
本番へ何を出しているのか
を分かりやすくするために入れています。
D1 Migrationがある場合
D1を使っていると、アプリだけではなくDB変更が入ることがあります。
たとえば、
migrations/
└─ 0004_add_movie_status.sql
です。
ここで、
mainへ入った
↓
自動でMigration
↓
自動でDeploy
までやることもできます。
ただ、自分はDB変更については少し慎重に考えています。
アプリは再デプロイできます。
DBの変更は、データそのものへ影響します。
そのため、
コードのデプロイ
と、
本番DB変更
は同じものとして扱わない方がいい場合があります。
自動Migrationを使う場合でも、
- どのMigrationが適用されるか
- 破壊的変更がないか
- 失敗した場合どうするか
- バックアップや復旧方法があるか
は確認します。
自動化すると、
安全になる作業と、危険な操作が高速になるだけの作業
があります。
ここは分けて考えたいところです。
GitHub Actionsを選んだ理由
現在のCloudflareには、GitHubリポジトリと直接連携して自動ビルド・デプロイするWorkers Buildsもあります。
それなら、
「GitHub Actionsを使わなくてもいいのでは」
とも思います。
実際、小さなサービスならWorkers Buildsの方が簡単な場合もあります。
自分がGitHub Actionsを使う理由は、
デプロイ以外の確認もGitHub側でまとめたいから
です。
lint
test
build
データ確認
migration確認
deploy
といった処理を、一つの流れとして管理できます。
すでにGitHub中心で開発しているので、
GitHub
↓
Cloudflare
という方向に統一した方が、自分には分かりやすかったです。
デプロイに失敗したらGitHubを見る
自動化すると、デプロイの入口も変わります。
以前なら、
デプロイ失敗
↓
自分のターミナルを見る
でした。
GitHub Actionsなら、
デプロイ失敗
↓
Actions
↓
失敗したJob
↓
失敗したStep
↓
ログ
と追えます。
これも便利です。
成功した履歴も、失敗した履歴もGitHub側に残ります。
誰が
どのcommitを
いつ
本番へ出そうとしたか
を追いやすくなります。
一人で開発していても、数か月後の自分にとっては結構ありがたいです。
今回使ったサービスの料金
今回追加した主な仕組みはGitHub Actionsです。
Cloudflare側では、GitHub ActionsからDeployしたこと自体に特別な追加料金が発生するというより、デプロイ後のWorkersなどの利用量をこれまでと同じように考えます。
GitHub Actions側には実行時間の無料枠があります。
2026年9月時点では、標準のGitHub-hosted runnerについて、
Public Repository
→ 無料
Private Repository
→ プランごとの無料枠
となっています。
代表的には、
| GitHubプラン | Actions無料時間 |
|---|---|
| Free | 2,000分 / 月 |
| Pro | 3,000分 / 月 |
| Team | 3,000分 / 月 |
です。
個人開発で、
1回のCI + Deploy
= 3分
1日5回
= 15分
30日
= 450分
程度なら、無料枠の中でもかなり試せます。
ただし、Next.jsのBuildが長かったり、何度もWorkflowを実行したりすると消費量は増えます。
また、Public RepositoryとPrivate Repositoryでは扱いが違います。
GitHub Actionsの料金体系も変更される可能性があるため、利用量は定期的に確認した方がよさそうです。
※料金・無料枠・制限は2026年9月時点の情報を前提としています。
最新情報はGitHubおよびCloudflareの公式ドキュメントを確認してください。
自動化して感じたこと
GitHub ActionsからCloudflareへデプロイするようになって、一番変わったのは、
公開するという作業を意識しなくなったこと
でした。
以前は、
実装完了
↓
さて、デプロイするか
でした。
今は、
実装完了
↓
PR
↓
確認
↓
Merge
↓
終わり
です。
Mergeした後のデプロイは仕組みがやってくれます。
ほんの数コマンド減っただけとも言えます。
でも、個人開発ではこの小さな面倒が積み重なります。
サービスが増えるほど、
毎回やらなくていいことを増やす
のは重要だと感じています。
まとめ
今回はGitHub ActionsからCloudflare Workersへ自動デプロイする流れについてまとめました。
構成としては、
GitHub
↓
mainへMerge
↓
GitHub Actions
↓
lint / test / build
↓
Cloudflare WorkersへDeploy
↓
本番
です。
使ってみて良かったのは、
- 手動デプロイが不要になる
- mainだけを本番へ出せる
- Deploy前にCIを通せる
- 認証情報をGitHub Secretsで管理できる
- Deploy履歴がGitHubに残る
- CloudflareまでGitHub中心の開発フローに組み込める
というところです。
Cloudflareを使い始めた理由の一つが、
GitHubとの相性の良さ
でした。
Workers、D1、R2を使うだけでも便利ですが、
GitHubへのMergeから本番公開までつながったことで、
最初に感じていた、
「作る」と「公開する」が近い
という感覚がさらに強くなりました。
次回は、
CloudflareのSecretsと環境変数をどう管理するか
について書きます。
ローカル、GitHub Actions、本番Workersで、APIキーなどをどう分けているのかをまとめる予定です。
