🔐

Cloudflare Workers の wrangler.json に環境変数を書かないで管理する

に公開

2022年に書いたもののバージョンアップ版です。 ( 執筆時点でwrangler 4.14.0 )

https://zenn.dev/mr_ozin/articles/645502f4a621d6

これを書いてから色々 Wrangler について色々変わりました。

  • wrangler.toml -> wrangler.json / wrangler.jsonc に変わった
  • wrangler init コマンドが一時期削除予定だったが結局削除されず、コマンドを実行すると create-cloudflare-cli (C3) tool が実行されてプロジェクト作成されるようになった
  • .dev.vars を環境ごとに使い分けできるようになった。 .dev.vars.test / .dev.vars.staging など
    • CI 上で単体テストを実行するために .dev.vars.test は Push する

TL;DR

  • ローカルで開発するときは .dev.vars を使う
  • Vitest で単体テストするときは .dev.vars.test 作って vitest.config.mts で環境名を書いて読み込み
  • GitHub Actions では公式の cloudflare/wrangler-action があるのでそれで設定する

サンプルリポジトリ

https://github.com/ryokryok/example-cloudflare-workers-secrets

Cloudflare Workers の Secret について

Cloudflare Workers / Pages で使える環境変数みたいなものです。

環境毎に設定を切り分け可能です。

https://developers.cloudflare.com/workers/wrangler/configuration/#secrets

Workers のサンプルコード

MY_VARIABLE という環境変数を返すだけです。型生成するまではエラーが出ますが気にしなくてOKです。

src/main.ts
export default {
	async fetch(request, env, ctx): Promise<Response> {
		return new Response(env.MY_VARIABLE);
	},
} satisfies ExportedHandler<Env>;

ローカル開発の場合

.dev.vars を作成します。

.dev.vars
MY_VARIABLE="development_value"

追記したら型を作成します。

pnpm wrangler types

成功すると型が生成されます。

worker-configuration.d.ts
declare namespace Cloudflare {
	interface Env {
		MY_VARIABLE: string; // 追加される
	}
}
interface Env extends Cloudflare.Env {}

これで env.MY_VARIABLE と入力する時点で型補完が効くようになります。

単体テストの場合

テスト用に.dev.vars.<environment-name> を作成して vitest.config.mts で読み込む必要があります。

テスト用に環境名 test として、 .dev.vars.test を作成します。

touch .dev.vars.test
.dev.vars.test
MY_VARIABLE="test_value"

VitestのConfigにて、テスト時は test 環境として実行するように明示します。

vitest.config.mts
import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config';

export default defineWorkersConfig({
	test: {
		poolOptions: {
			workers: {
				wrangler: {
					configPath: './wrangler.jsonc',
					environment: 'test', // これを指定する
				},
			},
		},
	},
});

テストコードに修正を加えます。

test/index.spec.ts
import { env, createExecutionContext, waitOnExecutionContext, SELF } from 'cloudflare:test';
import { describe, it, expect } from 'vitest';
import worker from '../src/index';

const IncomingRequest = Request<unknown, IncomingRequestCfProperties>;

describe('Hello World worker', () => {
	it('responds with env.MY_VARIABLE (unit style)', async () => {
		const request = new IncomingRequest('http://example.com');
		const ctx = createExecutionContext();
		const response = await worker.fetch(request, env, ctx);
		await waitOnExecutionContext(ctx);
+	        expect(await response.text()).toMatchInlineSnapshot(`"test_value"`); // This is the value of MY_VARIABLE in your .dev.vars.test file
	});

	it('responds with env.MY_VARIABLE (integration style)', async () => {
		const response = await SELF.fetch('https://example.com');
+ 	        expect(await response.text()).toMatchInlineSnapshot(`"test_value"`); // This is the value of MY_VARIABLE in your .dev.vars.test file
	});
});

これで実行はできるのですが、WARNINGが表示されます。

▲ [WARNING] Processing wrangler.jsonc configuration:

    - No environment found in configuration with name "test".
      Before using `--env=test` there should be an equivalent environment section in the
  configuration.
  
      Consider adding an environment configuration section to the wrangler.json file:
      ```
      [env.test]
      ```

これを回避するには wrangler.json に設定を追加します。

wrangler.json
+ "env": {
+   "test": {}
+ }

GitHub Actions でデプロイする場合

公式から提供される cloudflare/wrangler-action を使用します。

https://developers.cloudflare.com/workers/ci-cd/external-cicd/github-actions/#2-set-up-cicd

それぞれのsecrets を登録します。 gh repo secret set <KEY> で登録するのを推奨します。

Actionsを実行するのに最低限設定必要

  • CLOUDFLARE_ACCOUNT_ID
    • pnpm wrangler whoami でも確認できる
  • CLOUDFLARE_API_TOKEN
    • 発行が必要

https://developers.cloudflare.com/workers/ci-cd/external-cicd/github-actions/#api-token

例として MY_VARIABLE という Secrets を登録したいとします。

.github/workflows/ci.yml
name: CI

on:
  push:

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    timeout-minutes: 5
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      - name: Setup pnpm
        uses: pnpm/action-setup@v4
        with:
          version: 10
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: 'pnpm'
      - name: Install dependencies
        run: pnpm i --frozen-lockfile
      - name: Build & Deploy Worker
        id: deploy
        uses: cloudflare/wrangler-action@v3
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
          secrets: |
            MY_VARIABLE
        env:
          MY_VARIABLE: ${{ secrets.MY_VARIABLE }}

余談: 公式ドキュメントでの Secrets 設定への言及

公式のドキュメントにも記載がある通り、Cloudflare ダッシュボードからではなく、デプロイ環境、今回の場合はGitHub Actions側から設定するのを優先するのがベストプラクティスとのことです。

--keep-vars (default: false) optional
It is recommended best practice to treat your Wrangler developer environment as a source of truth for your Worker configuration, and avoid making changes via the Cloudflare dashboard.

https://developers.cloudflare.com/workers/wrangler/commands/#deploy

最後に

前回の記事を書いたときはこんなに反応をもらえると思っていませんでした。

Wrangler や Cloudflare Workers 周りも久々にキャッチアップしていると色々変わっていることを実感します。

上記もとありあえず書きましたが、 基本的に unstable なので迷ったら公式ドキュメント眺める必要があります。

Discussion