This directory contains automated CI/CD workflows for the Cloudflare Heartbeat Monitor.
┌─────────────────────────────────────────────────────────┐
│ Push to main │
└──────────────────────┬──────────────────────────────────┘
│
▼
┌────────────────┐
│ deploy.yml │ ──► Deploy to Production
└────────────────┘
┌─────────────────────────────────────────────────────────┐
│ Open/Update Pull Request │
└──────────────────────┬──────────────────────────────────┘
│
▼
┌────────────────┐
│ preview.yml │ ──► Validate Configuration
└────────────────┘ Comment on PR
File: .github/workflows/deploy.yml
Triggers:
- Push to
mainbranch - Manual dispatch from Actions tab
Steps:
- Checkout code
- Setup Node.js 20 with npm cache
- Install dependencies (
npm ci) - Fetch Account ID (from secret or API)
- Check if KV namespace needs creation
- If needed: Setup Terraform
- If needed: Create KV namespace with Terraform
- If needed: Commit updated wrangler.toml
- Deploy to Cloudflare Workers
Smart Setup:
- ✨ Automatically creates KV namespace on first deployment
- ✨ Uses Terraform to provision infrastructure
- ✨ Commits updated
wrangler.tomlautomatically - ✨ Skips setup on subsequent deployments (already configured)
Required Secrets:
CLOUDFLARE_API_TOKEN✅ Required
Optional Secrets:
CLOUDFLARE_ACCOUNT_ID(fetched from API if not provided)
Duration:
- First deployment: ~3-4 minutes (includes Terraform setup)
- Subsequent deployments: ~1-2 minutes (skips Terraform)
File: .github/workflows/preview.yml
Triggers:
- Pull requests to
mainbranch
Steps:
- Checkout code
- Setup Node.js 20 with npm cache
- Install dependencies (
npm ci) - Validate
services.jsonsyntax - Validate
wrangler.toml(dry-run deploy) - Comment on PR with results
Required Secrets:
- None (uses built-in
GITHUB_TOKEN)
Required Permissions:
contents: read- Read repository codepull-requests: write- Comment on PRsissues: write- Comment on issues/PRs
Duration: ~1 minute
-
Get Cloudflare API Token:
- Go to: https://dash.cloudflare.com/profile/api-tokens
- Create Token → Use "Edit Cloudflare Workers" template
- Copy the token
-
Add to GitHub Secrets:
- Go to: Repository → Settings → Secrets and variables → Actions
- New secret:
CLOUDFLARE_API_TOKEN - Paste your token
-
Commit and Push:
git add . git commit -m "Add package-lock.json" git push origin main
-
Watch it deploy!
- Go to Actions tab to see progress
To speed up deployments (skip API lookup):
# Add CLOUDFLARE_ACCOUNT_ID secret with your account ID- Actions Tab: See all workflow runs
- Commit Page: See status checks on commits
- PR Page: See validation status on PRs
Add this to your README.md:
[](https://github.com/USERNAME/REPO/actions/workflows/deploy.yml)
[](https://github.com/USERNAME/REPO/actions/workflows/preview.yml)Problem: No package-lock.json file
Solution:
npm install
git add package-lock.json
git commit -m "Add package-lock.json"
git pushProblem: Workflow is using an older Node.js version
Solution: Already fixed! Workflows now use Node.js v20.
If you see this locally:
# Check your Node.js version
node --version
# If < v20, update Node.js:
# - Download from: https://nodejs.org/
# - Or use nvm: nvm install 20 && nvm use 20
# - Or use volta: volta install node@20Problem: API token is wrong or expired
Solution:
- Generate new token in Cloudflare Dashboard
- Update
CLOUDFLARE_API_TOKENsecret in GitHub - Re-run workflow
Problem: API token doesn't have proper permissions
Solution:
- Verify token has "Edit Cloudflare Workers" permission
- Or manually add
CLOUDFLARE_ACCOUNT_IDsecret
Problem: services.json or wrangler.toml has errors
Solution:
- Check workflow logs for specific error
- Test locally:
npx wrangler deploy --dry-run - Validate JSON:
jq empty services.json - Fix errors and push again
To manually trigger a deployment:
- Go to Actions tab
- Select Deploy to Cloudflare Workers
- Click Run workflow dropdown
- Select branch:
main - Click Run workflow button
Before pushing, test locally:
# Install dependencies
npm install
# Validate configuration
npx wrangler deploy --dry-run
# Validate JSON
jq empty services.json
# Test locally
npm run devnpm ci vs npm install:
npm ciusespackage-lock.json(faster, reproducible)npm installgeneratespackage-lock.json- Always use
npm ciin CI/CD
cache: 'npm':
- Caches
node_modulesbetween runs - Speeds up workflow execution
- Automatic cache invalidation on lock file change
--dry-run:
- Validates without actually deploying
- Perfect for PR validation
- Catches configuration errors early
-
Always commit
package-lock.json- Ensures reproducible builds
- Required for
npm ci
-
Test locally first
- Run
npm run devto test worker - Run
npx wrangler deploy --dry-runto validate
- Run
-
Use branch protection
- Require PR reviews
- Require status checks to pass
- Prevent direct pushes to
main
-
Keep secrets secure
- Never commit API tokens
- Rotate tokens periodically
- Use minimal required permissions
-
Monitor deployments
- Check Actions tab after push
- Review deployment logs
- Test deployed worker
All workflows run within GitHub Actions free tier:
- Public repos: Unlimited minutes
- Private repos: 2,000 minutes/month free
- Typical usage: ~5 minutes/day