Cloudflare workers are configured using a tool called wrangler combined with a wrangler.toml
file. This file contains the configuration for the worker, including the name, routes, vars, and much more.
A recent challenge I had was to deploy a worker to a dev
environment and then promote it to staging
and prod
and the combine this with GitHub actions for continuous deployment.
This post assumes you have a basic understanding of Cloudflare workers and wrangler. Some configuration options may be omitted for brevity.
Basic Wrangler configuration in TOML
The base wrangler.toml
file looks like this:
name = "my-worker"
route = "example.com/*"
[var]
foo = "bar"
This will deploy a worker, when using Wrangler deploy, named my-worker
to a route of example.com/*
and set a variable foo
to bar
that can be accessed in the worker code.
This does not automatically create the domain in Cloudflare. You will need to do that manually or use the Cloudflare API to create the domain.
Adding environments for dev, staging, and prod
This configuration file can be extended to include a dev
environment:
[env.dev]
name = "my-worker-dev"
route = "dev.example.com/*"
[env.dev.var]
foo = "bar"
This will deploy a worker named my-worker-dev
to a route of dev.example.com/*
and set a variable foo
to bar
that can be accessed in the worker code.
See the Wrangler deploy documentation for more information on deploying to different environments and the documentation on Cloudflare workers environments.
I removed the default route
, name
, and var
from the base configuration and added a new section for dev
. This forces me to call wrangler deploy --env dev
to deploy to the dev
environment and will throw an error if I try to deploy to the default environment because there isn’t one.
To promote the worker to staging
and prod
, I can add additional sections to the wrangler.toml
file:
[env.staging]
name = "my-worker-staging"
route = "staging.example.com/*"
[env.staging.var]
foo = "bar"
[env.prod]
name = "my-worker-prod"
route = "example.com/*"
[env.prod.var]
foo = "bar"
This enables me to call wrangler deploy --env staging
and wrangler deploy --env prod
to deploy to the staging
and prod
environments respectively.
Some fields are not inheritable across environments such as vars
and kv-namespaces
. You will need to set these for each environment.
GitHub actions
To automate the deployment of the worker to the dev
, staging
, and prod
environments, I can use GitHub actions. Here is an example of a GitHub action that deploys the worker to the correct environment based upon the context of the action, such as a push to the main
branch or a manual trigger.
name: Deploy
on:
push:
branches:
- main
workflow_dispatch:
inputs:
environment:
description: 'Environment'
required: true
type: choice
options:
- prod
- staging
default: staging
jobs:
deploy:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
runs-on: ubuntu-latest
env:
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
steps:
# other steps to checkout/build/test/etc
- name: Manual deploy
if: ${{ github.event_name == 'workflow_dispatch' }}
run: wrangler deploy --env=${{ github.event.inputs.environment }}
- name: Automatic deploy to staging
if: ${{ github.ref == 'refs/heads/main' && github.event_name == 'push' }}
run: wrangler deploy --env=staging
promote:
if: ${{ github.ref == 'refs/heads/main' }}
runs-on: ubuntu-latest
needs: deploy
env:
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
steps:
# verify staging deployment through integration tests
- run: wrangler deploy --env=staging
Alternatively, you could promote to prod when a tag is pushed:
name: Deploy
on:
push:
branches:
- main
tags:
- '*'
And then add a step to deploy to prod:
- name: Automatic deploy to prod from tag
if: $false
run: wrangler deploy --env=prod
All of this omits the hard part of knowing when to promote from staging
to prod
. The above demonstrates patterns for using tags, testing, or a manual dispatch to promote to prod
.
Other considerations
Here are some other considerations when deploying workers to different environments.
Git commit, tag, etc. in worker code
In any of these cases, you may want to consider injecting a variable into the worker code to indicate the current Git commit, tag, etc.
- name: Automatic deploy to prod from tag
if: $false
run: wrangler deploy --env=prod --var GIT_COMMIT=$
Encrypted vars, integrations, etc
These must individually be set for each environment via the dashboard. 😞