Skip to main content

CI/CD with GitHub Actions

Manually running npx wrangler deploy from your laptop exposes your project to environmental drift (different local Node.js versions) and human error (deploying an unreviewed branch).

For production, deployments must be automated. Cloudflare provides an official GitHub Action that cleanly interfaces with Wrangler for secure, fast deployments.

Learning Focus

By the end of this module, you will understand how to securely provide Cloudflare API tokens to GitHub, configure split environments (staging vs production), and write the YAML workflow.


1. Secure Authentication Tokens

To allow GitHub Actions to deploy on your behalf, you need a scoped Cloudflare API Token.

  1. Go to your Cloudflare Dashboard -> My Profile -> API Tokens.
  2. Click Create Token -> Use the Edit Cloudflare Workers template.
  3. Select your Account and Zone.
  4. Generate the token. Copy it immediately; you cannot see it again.

Adding the Secret to GitHub

  1. In your GitHub repository, go to Settings -> Secrets and variables -> Actions.
  2. Click New repository secret.
  3. Name: CLOUDFLARE_API_TOKEN.
  4. Value: Paste your token.

2. Setting Up Environments in wrangler.toml

Before scripting the deployment, your Worker configuration needs to understand the concept of multiple environments so you don't accidentally overwrite your production API with your staging tests.

wrangler.toml
# Global defaults
name = "my-api"
main = "src/index.ts"
compatibility_date = "2024-03-01"

# Development / Staging override
[env.staging]
name = "my-api-staging"
# This assigns a different KV database to the staging environment!
[[env.staging.kv_namespaces]]
binding = "DB"
id = "staging_kv_uuid_1234"

# Production override
[env.production]
name = "my-api-production"
[[env.production.kv_namespaces]]
binding = "DB"
id = "prod_kv_uuid_9999"

3. The GitHub Actions Workflow

Create a new file in your repository at .github/workflows/deploy.yml.

This workflow will:

  1. Deploy to Staging automatically whenever code is pushed (or a PR is opened) to the main branch.
  2. Deploy to Production only when a release/tag is published.
.github/workflows/deploy.yml
name: Deploy Worker

on:
push:
branches:
- main
release:
types: [published]

jobs:
deploy-staging:
# Only run on pushes to main (not on releases)
if: github.event_name == 'push'
runs-on: ubuntu-latest
name: Deploy to Staging

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

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install Dependencies
run: npm ci

- name: Deploy to Cloudflare (Staging)
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
environment: 'staging'
# Alternatively: command: deploy --env staging

deploy-production:
# Only run when a GitHub release is cut
if: github.event_name == 'release'
runs-on: ubuntu-latest
name: Deploy to Production

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

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install Dependencies
run: npm ci

- name: Deploy to Cloudflare (Production)
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
environment: 'production'

Flow Breakdown

  • actions/checkout: Pulls your code into the runner.
  • npm ci: Clean install of your dependencies based strictly on your package-lock.json.
  • cloudflare/wrangler-action: The official action executes wrangler deploy. The environment parameter maps exactly to the [env.target] blocks defined in your wrangler.toml.

4. Managing Secrets in CI/CD

If your Worker relies on encrypted secrets (like a Stripe API Key), these secrets must be pre-loaded into the Cloudflare environment before the first deployment runs.

You can script secret injection within the GitHub Action, pulling from GitHub Secrets:

      - name: Deploy to Cloudflare (Production)
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
environment: 'production'
secrets: |
STRIPE_API_KEY
DATABASE_ENCRYPTION_KEY
env:
STRIPE_API_KEY: ${{ secrets.PROD_STRIPE_KEY }}
DATABASE_ENCRYPTION_KEY: ${{ secrets.PROD_DB_KEY }}

Note: This will securely inject the secrets mapped in the env block into the target Cloudflare Worker environment immediately prior to deploying the code.


What's Next

Now that we possess a rock-solid, automated deployment pipeline, let's explore some of the more advanced cutting-edge features Cloudflare provides, starting with AI.

Proceed to Module 10: AI and Advanced Patterns.