Continuous Deployment Example
Build and deploy automatically when a version tag is pushed.
Continuous Deployment (CD) takes CI one step further: after tests pass, it ships the code automatically. This workflow builds and deploys whenever a version tag like v1.2.0 is pushed.
Key ideas
- Trigger only on tags with
on.push.tags. - Store deploy credentials as secrets.
- Use an
environmentto require approvals or track deployments.
Example
name: Deploy
on:
push:
tags: ["v*"]
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npm run build
- name: Deploy to server
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
run: ./scripts/deploy.shWhen to use it
- A team deploys a Docker image to AWS ECS automatically when a PR merges into main, eliminating manual deployment steps.
- A developer uses GitHub Environments with required reviewers so every production deploy requires a human approval in the Actions UI.
- A Kubernetes team uses a CD workflow to update an image tag in a Helm values file and push it, triggering ArgoCD to sync the cluster.
More examples
Build and push Docker image to GHCR
Logs in to GitHub Container Registry using the built-in GITHUB_TOKEN and pushes a freshly built image on every merge to main.
name: CD
on:
push:
branches: [main]
jobs:
build-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v5
with:
push: true
tags: ghcr.io/${{ github.repository }}:latestDeploy to environment with approval gate
Referencing a GitHub Environment named 'production' pauses the job until a required reviewer approves in the Actions UI.
jobs:
deploy-prod:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- run: ./scripts/deploy.sh
env:
DEPLOY_KEY: ${{ secrets.PROD_DEPLOY_KEY }}SSH deploy to a VPS on merge
Uses a community SSH action to connect to a VPS, pull the latest code, and restart the process manager — a simple zero-downtime deploy.
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.VPS_HOST }}
username: deploy
key: ${{ secrets.VPS_SSH_KEY }}
script: |
cd /app
git pull origin main
npm ci --production
pm2 restart app
Discussion