Complete CI/CD guide for Cloudflare Workers using GitHub Actions and GitLab CI. Use for automated testing, deployment pipelines, preview environments, secrets management, or encountering deployment failures, workflow errors, environment configuration issues.
Provides complete CI/CD guide for Cloudflare Workers using GitHub Actions and GitLab CI. Use when setting up automated testing, multi-environment deployments, preview environments, or resolving workflow errors and deployment failures.
/plugin marketplace add secondsky/claude-skills/plugin install workers-ci-cd@claude-skillsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/deployment-strategies.mdreferences/github-actions.mdreferences/gitlab-ci.mdreferences/secrets-management.mdscripts/verify-deployment.shtemplates/github-actions-full.ymltemplates/gitlab-ci-full.ymltemplates/preview-deployment.ymltemplates/rollback-workflow.ymlStatus: ✅ Production Ready | Last Verified: 2025-01-27 GitHub Actions: v4 | GitLab CI: Latest | Wrangler: 4.50.0
Automated testing and deployment of Cloudflare Workers using GitHub Actions or GitLab CI. Enables running tests on every commit, deploying to preview/staging/production environments automatically, managing secrets securely, and implementing deployment gates for safe releases.
Key capabilities: Automated testing, multi-environment deployments, preview URLs per PR, secrets management, deployment verification, automatic rollbacks.
GitHub Actions Updates (January 2025):
cloudflare/wrangler-action@v4 (improved caching, faster deployments)vars and secrets parametersapiToken renamed to api-token (kebab-case)Migration from v3:
# ❌ OLD (v3)
- uses: cloudflare/wrangler-action@3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
# ✅ NEW (v4)
- uses: cloudflare/wrangler-action@v4
with:
api-token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
Wrangler 4.50.0 (January 2025):
--dry-run flag for deployment validation--keep-vars to preserve environment variables1. Create Cloudflare API Token
Go to: https://dash.cloudflare.com/profile/api-tokens
Create token with permissions:
2. Add Secret to GitHub
Repository → Settings → Secrets → Actions → New repository secret:
CLOUDFLARE_API_TOKEN3. Create .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
name: Deploy to Cloudflare Workers
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- run: bun install
- run: bun test
- name: Deploy
uses: cloudflare/wrangler-action@v4
with:
api-token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
command: deploy
4. Push and Verify
git add .github/workflows/deploy.yml
git commit -m "Add CI/CD pipeline"
git push
Check Actions tab on GitHub to see deployment progress.
✅ CORRECT:
# Use GitHub Secrets
api-token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
❌ WRONG:
# ❌ NEVER hardcode tokens
api-token: "abc123def456..."
Why: Exposed tokens allow anyone to deploy to your account.
✅ CORRECT:
- run: bun test # ✅ Tests run first
- name: Deploy
uses: cloudflare/wrangler-action@v4
with:
api-token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
❌ WRONG:
# ❌ Skipping tests
- name: Deploy
uses: cloudflare/wrangler-action@v4
# No tests!
Why: Broken code shouldn't reach production.
✅ CORRECT:
# Production (main branch)
- name: Deploy to Production
if: github.ref == 'refs/heads/main'
run: bunx wrangler deploy --env production
# Staging (other branches)
- name: Deploy to Staging
if: github.ref != 'refs/heads/main'
run: bunx wrangler deploy --env staging
❌ WRONG:
# ❌ Always deploying to production
- run: bunx wrangler deploy
Why: Test changes in staging before production.
✅ CORRECT:
- name: Deploy
id: deploy
uses: cloudflare/wrangler-action@v4
- name: Verify Deployment
run: |
curl -f https://your-worker.workers.dev/health || exit 1
❌ WRONG:
# ❌ No verification
- name: Deploy
uses: cloudflare/wrangler-action@v4
# Assuming it worked...
Why: Deployments can fail silently (DNS issues, binding errors).
✅ CORRECT:
deploy-production:
environment:
name: production
url: https://your-worker.workers.dev
# Requires manual approval
❌ WRONG:
# ❌ Auto-deploy to production without review
deploy-production:
runs-on: ubuntu-latest
Why: Human review catches issues automation misses.
Recommended setup:
main branch → production environmentwrangler.jsonc:
{
"name": "my-worker",
"main": "src/index.ts",
"env": {
"production": {
"name": "my-worker-production",
"vars": {
"ENVIRONMENT": "production"
}
},
"staging": {
"name": "my-worker-staging",
"vars": {
"ENVIRONMENT": "staging"
}
}
}
}
Types of configuration:
Setting secrets:
# Local development
wrangler secret put DATABASE_URL
# CI/CD (via GitHub Actions)
bunx wrangler secret put DATABASE_URL --env production <<< "${{ secrets.DATABASE_URL }}"
Automatically deploy each PR to a unique URL for testing:
- name: Deploy Preview
uses: cloudflare/wrangler-action@v4
with:
api-token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
command: deploy --env preview-${{ github.event.number }}
Each PR gets URL like: my-worker-preview-42.workers.dev
name: Deploy Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bun install
- run: bun test
- run: bun run build
- name: Deploy to Production
uses: cloudflare/wrangler-action@v4
with:
api-token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
command: deploy --env production
name: Preview
on:
pull_request:
branches: [main]
jobs:
preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bun install
- run: bun test
- name: Deploy Preview
id: deploy
uses: cloudflare/wrangler-action@v4
with:
api-token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
command: deploy --env preview-${{ github.event.number }}
- name: Comment PR
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '✅ Preview deployed to: https://my-worker-preview-${{ github.event.number }}.workers.dev'
})
name: Test
on:
push:
branches: ['**']
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bun install
- run: bun test --coverage
- name: Upload Coverage
uses: codecov/codecov-action@v4
with:
files: ./coverage/lcov.info
name: Deploy Production (Manual Approval)
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: production
url: https://my-worker.workers.dev
# Requires manual approval in GitHub Settings
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bun install
- run: bun test
- name: Deploy
uses: cloudflare/wrangler-action@v4
with:
api-token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
command: deploy --env production
name: Canary Deployment
on:
workflow_dispatch:
inputs:
percentage:
description: 'Traffic percentage to new version'
required: true
default: '10'
jobs:
canary:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bun install
# Deploy to canary environment
- name: Deploy Canary
uses: cloudflare/wrangler-action@v4
with:
api-token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
command: deploy --env canary
# Configure traffic split via Cloudflare API
# (See references/deployment-strategies.md for full example)
Use semantic commit messages:
feat: add user authentication
fix: resolve rate limiting issue
chore: update dependencies
Run linting and type checking:
- run: bun run lint
- run: bun run type-check
- run: bun test
Cache dependencies:
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
# Bun automatically caches dependencies
Deploy different branches to different environments:
- name: Deploy
run: |
if [ "${{ github.ref }}" == "refs/heads/main" ]; then
bunx wrangler deploy --env production
else
bunx wrangler deploy --env staging
fi
Monitor deployments:
- name: Notify Slack
if: failure()
uses: slackapi/slack-github-action@v1
with:
payload: |
{"text": "Deployment failed: ${{ github.sha }}"}
Error: A valid Cloudflare API token is requiredCause: Missing or invalid CLOUDFLARE_API_TOKEN secret.
Fix:
api-token: ${{ secrets.CLOUDFLARE_API_TOKEN }}Error: Not enough permissions to deployCause: API token lacks required permissions.
Fix: Recreate token with:
Error: wrangler.toml not foundCause: Missing wrangler configuration.
Fix: Ensure wrangler.jsonc exists in repository root.
Cause: Missing secrets or environment variables.
Fix: Set secrets in CI:
- name: Set Secrets
run: |
echo "${{ secrets.DATABASE_URL }}" | bunx wrangler secret put DATABASE_URL --env production
Cause: Environment differences (Node version, missing dependencies).
Fix:
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest # Lock version
- run: bun install --frozen-lockfile # Use exact versions
Cause: Multiple PRs deploying to same preview environment.
Fix: Use PR number in environment name:
command: deploy --env preview-${{ github.event.number }}
Cause: Echoing secrets in workflow.
Fix:
# ❌ WRONG
- run: echo "Token: ${{ secrets.API_TOKEN }}"
# ✅ CORRECT
- run: echo "Deploying..." # No secrets in output
Load reference files for detailed, specialized content:
Load references/github-actions.md when:
Load references/gitlab-ci.md when:
Load references/deployment-strategies.md when:
Load references/secrets-management.md when:
Load templates/github-actions-full.yml for:
Load templates/gitlab-ci-full.yml for:
Load templates/preview-deployment.yml for:
Load templates/rollback-workflow.yml for:
Load scripts/verify-deployment.sh for:
For deployment testing, load:
This skill focuses on CI/CD automation for ALL Workers deployments regardless of bindings used.
Questions? Load references/secrets-management.md or use /workers-deploy command for guided deployment.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.