2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GitHub ActionsでCloudflare Workers + D1のCI/CDを組んだ

2
Posted at

はじめに

React + Hono + Cloudflare Workers + D1 で作っている近況共有アプリに、GitHub Actions の CI/CD を入れました。

やりたかったことはシンプルです。

develop へ入れる前に壊れていないか確認する
main へ入れる前にも確認する
main に入ったら本番へデプロイする

今回は、次のような運用にしました。

feature branch -> develop
  CI: lint / build / migration check

develop -> main PR
  CI: lint / build / migration check

main push
  CD: D1 migration apply / Workers deploy / smoke test

今回の構成

アプリの構成はざっくりこんな感じです。

Frontend: React + Vite
API: Hono
Runtime: Cloudflare Workers
DB: Cloudflare D1
Migration: Drizzle
Deploy: Wrangler

package.json にはもともと次のような script がありました。

{
  "scripts": {
    "build": "tsc -b && vite build",
    "lint": "eslint .",
    "db:generate": "drizzle-kit generate",
    "cf:typegen": "wrangler types"
  }
}

ここに migration の整合性チェック用として db:check を追加しました。

{
  "scripts": {
    "db:check": "drizzle-kit check"
  }
}

drizzle-kit check は、Drizzle の migration メタデータに破綻がないか確認するために使っています。

CIでやること

CIでは、本番へ出す前の最低限の確認をします。

npm ci
npm run lint
npm run build
npm run db:check

テストがある場合はここに npm test も入れる想定です。

今回作った CI workflow は次のような形です。

name: CI

on:
  pull_request:
    branches:
      - develop
      - main
  push:
    branches:
      - develop

permissions:
  contents: read

concurrency:
  group: ci-${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  verify:
    name: Build, lint, and migration check
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm

      - name: Install dependencies
        run: npm ci

      - name: Lint
        run: npm run lint

      - name: Build
        run: npm run build

      - name: Check Drizzle migrations
        run: npm run db:check

pull_requestdevelopmain 向けにしています。

日常開発では develop へ入れる前に確認し、リリース時には main へ入れる前にも同じ確認をします。

pushdevelop だけにしています。

main への push は CD 側で deploy まで行うため、CI専用workflowではなく deploy workflow に寄せています。

CDでやること

CDは main に入ったときだけ動かします。

本番反映では、次の順番にしました。

npm ci
npm run lint
npm run build
npm run db:check
npx wrangler d1 migrations apply kinkyo-note-db --remote
npx wrangler deploy
curl /api/health

deploy前にも lint / build / migration check をもう一度走らせています。

PR時点でCIは通っているはずですが、main に入った実際のコードで確認してからデプロイしたいので、CD側でも同じチェックを入れています。

workflow は次のようにしました。

name: Deploy

on:
  push:
    branches:
      - main
  workflow_dispatch:

permissions:
  contents: read

concurrency:
  group: production-deploy
  cancel-in-progress: false

jobs:
  deploy:
    name: Deploy to Cloudflare Workers
    runs-on: ubuntu-latest
    environment: production

    env:
      CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
      CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm

      - name: Install dependencies
        run: npm ci

      - name: Lint
        run: npm run lint

      - name: Build
        run: npm run build

      - name: Check Drizzle migrations
        run: npm run db:check

      - name: Apply D1 migrations
        run: npx wrangler d1 migrations apply kinkyo-note-db --remote

      - name: Deploy Worker
        run: npx wrangler deploy

      - name: Smoke test
        run: |
          curl --fail --retry 5 --retry-delay 3 \
            https://kinkyo-note.bobu2784.workers.dev/api/health

workflow_dispatch も入れているので、必要なら手動でもデプロイできます。

GitHub Secretsを登録する

GitHub Actions から Cloudflare へデプロイするには、Cloudflare の認証情報が必要です。

GitHub の repository secrets に次の2つを登録しました。

CLOUDFLARE_API_TOKEN
CLOUDFLARE_ACCOUNT_ID

GitHub では次の場所から登録できます。

Settings
-> Secrets and variables
-> Actions
-> New repository secret

CLOUDFLARE_API_TOKEN は Cloudflare 側で作った API token です。

今回必要な権限は、ざっくり次の2つです。

Account -> Workers Scripts -> Edit
Account -> D1 -> Edit

wrangler deploy で Workers をデプロイし、wrangler d1 migrations apply で D1 migration を適用するためです。

CLOUDFLARE_ACCOUNT_ID は Cloudflare の対象アカウントIDです。

production Environmentを作る

GitHub Actions の deploy job では、次のように environment: production を指定しています。

environment: production

そのため、GitHub 側で production Environment を作りました。

Settings
-> Environments
-> New environment
-> production

ここでは、デプロイ前に承認を挟むために Required reviewers を有効にしました。

Required reviewers: ON
Reviewer: 自分

これで、main に merge されたあと、deploy job が本番反映の直前で承認待ちになります。

個人開発なので Prevent self-review はOFFにしています。

また、production environment を使えるブランチは main のみに制限しました。

Deployment branches and tags
  Selected branches and tags
  main

これで、誤って別ブランチから production deploy されるのを防げます。

Cloudflare側のSecretsとは別

ここで少しややこしいのが、GitHub Secrets と Cloudflare Worker Secrets は別物という点です。

GitHub Secrets は、GitHub Actions が Cloudflare にデプロイするために使います。

CLOUDFLARE_API_TOKEN
CLOUDFLARE_ACCOUNT_ID

一方で、アプリが実行時に使う秘密情報は Cloudflare Workers 側に設定します。

たとえば今回のアプリでは、LINEログインやセッションで次のような値が必要です。

LINE_CHANNEL_SECRET
SESSION_SECRET

これは GitHub Actions のためではなく、Worker runtime のための secret です。

設定する場合は、Cloudflare dashboard か wrangler secret put を使います。

npx wrangler secret put LINE_CHANNEL_SECRET
npx wrangler secret put SESSION_SECRET

D1 migrationをCDに含める

今回は main への反映時に、D1 migration も自動で適用するようにしました。

npx wrangler d1 migrations apply kinkyo-note-db --remote

--remote を付けることで、ローカルD1ではなくCloudflare上のD1に対して migration を適用します。

wrangler d1 migrations apply は、通常は確認プロンプトが出ます。

ただし CI/CD のような非対話環境では確認ステップがスキップされるため、GitHub Actions 上でも実行できます。

Smoke testを入れる

デプロイ後に、最低限APIが生きているか確認するため /api/health を叩いています。

curl --fail --retry 5 --retry-delay 3 \
  https://kinkyo-note.bobu2784.workers.dev/api/health

--fail を付けているので、HTTPエラーなら workflow が失敗します。

--retry も付けて、デプロイ直後の一時的な揺れを少し吸収します。

本当はログインや投稿まで含めたE2Eテストがあるとより安心ですが、まずは軽い smoke test から始めました。

branch protectionも設定したい

workflow を作っただけだと、main へ直接pushできる設定のままかもしれません。

運用としては、GitHub の branch protection も設定した方が安全です。

おすすめは次のような設定です。

main
  PR必須
  CI成功必須
  直接push禁止

develop
  PR必須
  CI成功必須

これで、CIを通っていないコードが main に入るのを防ぎやすくなります。

まとめ

今回のCI/CDでは、次のように役割を分けました。

develop向けPR
  日常開発の品質チェック

main向けPR
  リリース直前の品質チェック

main push
  本番DB migration
  Workers deploy
  smoke test

最初から複雑なパイプラインにせず、まずは次の4つを押さえる形にしました。

lint
build
migration check
deploy + health check

Cloudflare Workers + D1 の構成でも、GitHub Actions と Wrangler を使えば、比較的シンプルにCI/CDを組めました。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?