Cloudflare Workers Deploys: Built-In Git vs. GitHub Actions

Close-up of a data center server rack, representing automated cloud infrastructure

Photo by panumas nikhomkhai

On this page

Running wrangler deploy from your own machine works fine for the first week of a project. It stops working the moment you want deploys to happen consistently: from a clean environment, without depending on whoever happens to be at their keyboard, and ideally gated on the build actually passing first. That’s what automated deploys solve, and for a static site on Cloudflare Workers there are two reasonable ways to set it up.

Option A: Cloudflare Workers Builds

Cloudflare can watch your GitHub repository directly and deploy on every push, with no YAML file of your own to maintain. In the dashboard: Workers & Pages → your Worker → Settings → Builds → Connect to Git, point it at the repo and branch, and set a build command (npm run build) and the directory the build outputs to.

From then on, every push to the connected branch triggers a build and deploy automatically, and the dashboard shows build logs and history per deploy, with no infrastructure to maintain on your side.

Scope the deploy, not the whole account

If you later add a GitHub Actions workflow alongside or instead of Workers Builds, generate a Cloudflare API token scoped to exactly Workers Scripts:Edit for the account/zone in question, not a broad, all-permissions token. A workflow only needs enough access to deploy the one Worker; if the token ever leaks, narrow scope limits the blast radius.

Option B: GitHub Actions

The tradeoff with Workers Builds is control: it runs your build command and deploys, full stop. If you want to run tests, linting, or accessibility checks first, and only deploy if they pass, you need a workflow you author yourself.

.github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5

      - uses: actions/setup-node@v5
        with:
          node-version: 24

      - run: npm ci
      - run: npm run lint
      - run: npm run build

      - name: Deploy to Cloudflare Workers
        uses: cloudflare/wrangler-action@v3
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          command: deploy

The deploy step only runs if every step above it succeeds: a broken build or a failing lint check never reaches production. The CLOUDFLARE_API_TOKEN secret is set once under the repo’s Settings → Secrets and variables → Actions, scoped the same way as described above.

Choosing between them

Workers BuildsGitHub Actions
Setup effortMinutes, no files to writeA YAML file to author and maintain
Pre-deploy checksBuild command onlyAny number of steps, deploy gated on all passing
Where logs liveCloudflare dashboardGitHub Actions tab
Best forSmall projects, fast iterationProjects with tests/lint you want enforced before deploy

A reasonable default: start with Workers Builds, since it costs nothing to set up and gets you automatic deploys immediately. Move to GitHub Actions once there’s a build step you genuinely don’t want to skip, such as tests, an accessibility check, or a broken-link scan, and you want a bad result to block the deploy rather than just show up in a log after the fact.

Both approaches deploy the exact same wrangler deploy command underneath; the difference is entirely about what runs before it.

Once deploys are automated, check the actual runtime behavior too, not just that the build succeeded: see fixing Cloudflare Workers’ empty 404 page for a config gap that a passing build won’t catch.

Frequently asked

What's the difference between Cloudflare Workers Builds and a GitHub Actions deploy workflow?

Workers Builds connects to your GitHub repo from the Cloudflare dashboard and deploys on every push with no YAML file to write, but it only runs your build command, nothing else. A GitHub Actions workflow needs a file you author yourself, but lets you run any number of steps (tests, lint, an accessibility check) and only deploy if every one of them passes.

How do I scope the Cloudflare API token for a GitHub Actions deploy?

Generate a token scoped to exactly Workers Scripts:Edit for the account/zone in question, not a broad, all-permissions token, then set it as the CLOUDFLARE_API_TOKEN secret under the repo's Settings -> Secrets and variables -> Actions. A workflow only needs enough access to deploy the one Worker; narrow scope limits the blast radius if the token ever leaks.

Does Cloudflare Workers Builds run tests or lint before deploying?

No. It runs your configured build command and deploys, full stop. If you want a broken test or a failing lint check to block the deploy rather than just show up in a log afterward, that requires a GitHub Actions workflow you write yourself.

Emitted as FAQPage JSON-LD from the same frontmatter — one source, no duplicated prose.

Recent posts

Full-text search via Pagefind · ↑↓ to navigate · ↵ to open