█
LastWrite
  • > Curriculum
  • > Pricing
  • > For Educators
  • > About
  • > Contact
Log InGet Started

Questions, concerns, bug reports, or suggestions? We read every message, write to us at [email protected].

More ways to reach us →
LastWrite

Structured computer science lessons for aspiring developers and security professionals.

[email protected]

(201) 785-7951

Mon–Fri, 9 AM–5 PM EST

Learn

  • Curriculum
  • Pricing

Company

  • About
  • For Educators & Schools
  • Contact Us

Legal

  • Terms of Service
  • Privacy Policy
© 2026 LastWrite. All rights reserved.
Curriculum/DevOps and Infrastructure/CI/CD Pipelines/A Complete CD Pipeline
55 minIntermediate

A Complete CD Pipeline

After this lesson, you will be able to: Build a CD pipeline that deploys to staging on PR merge and to production on release tag. Use Vercel for web apps + a VPS or Render for containers.

CD turns 'image pushed' into 'live at the URL'. This lesson wires the second half.

Prerequisites:A Complete CI Pipeline

The deploy event model

Different triggers for different envs: - Push to `main` → deploy staging automatically. - Create a git tag `v1.2.3` → deploy production. - GitHub Release (or workflow_dispatch with input) → deploy production with optional approval gate. Avoid: deploy to prod on every push to main. Too easy to ship a regression at 3am.

Deploy to Vercel (the simple path for web)

Most Next.js / static sites land here.

tsx
# .github/workflows/deploy-vercel.yml
name: Deploy (Vercel)
on:
push:
branches: [main]
workflow_dispatch:
inputs:
target:
type: choice
options: [staging, production]
default: staging
jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: ${{ inputs.target || 'staging' }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20, cache: npm }
- run: npm ci
- name: Install Vercel CLI
run: npm i -g vercel@latest
- name: Pull Vercel env
run: vercel pull --yes --environment=${{ inputs.target || 'preview' }} --token=${{ secrets.VERCEL_TOKEN }}
- name: Build
run: vercel build ${{ inputs.target == 'production' && '--prod' || '' }} --token=${{ secrets.VERCEL_TOKEN }}
- name: Deploy
run: vercel deploy ${{ inputs.target == 'production' && '--prod' || '' }} --prebuilt --token=${{ secrets.VERCEL_TOKEN }}

Deploy a Docker image to a VPS via SSH

When you control the host (do-linux-passion box). Simple, transparent, no vendor.

tsx
# .github/workflows/deploy-vps.yml
name: Deploy (VPS)
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- name: SSH deploy
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SSH_HOST }}
username: deploy
key: ${{ secrets.SSH_KEY }}
script: |
cd /srv/myapp
docker compose pull
docker compose up -d
# health check
sleep 5
curl -fsS http://localhost/health || exit 1

Deploy to Render (containers without VPS hassle)

Render auto-deploys from your repo or via API.

tsx
# Render Native auto-deploy: connect repo in Render dashboard; every push to main triggers deploy.
# For more control via workflow:
name: Deploy (Render)
on:
workflow_dispatch:
release:
types: [published]
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- name: Trigger Render deploy
run: |
curl -X POST "https://api.render.com/v1/services/${{ secrets.RENDER_SERVICE_ID }}/deploys" \
-H "Authorization: Bearer ${{ secrets.RENDER_API_KEY }}" \
-H "Content-Type: application/json"

Environments + approval gates

GitHub Environments add per-env protections: required reviewers, wait timers, env-scoped secrets. Settings → Environments → New environment → 'production'. Add 'Required reviewers' = 1. Workflows with `environment: production` pause for approval before running. Click 'Approve' in the Actions tab. Use this for production deploys; staging is auto.

Common mistakes only experienced engineers avoid

Deploying without a smoke test. The pipeline 'succeeds' but the site 404s. Always curl /health after deploy. Skipping the rollback story. If deploy fails, what's the one-liner to roll back? `git revert` + redeploy is a fine default. Deploying to prod without an approval gate. Single keystroke = global breakage. Storing deploy keys in plain repo files. Always GitHub Secrets. No deploy notifications. Slack / Discord webhook on success/failure is half the on-call story.

Quick Check

Your deploy completes successfully but the site is broken. What does your pipeline lack?

Pick the missing piece.

Sign in and purchase access to unlock this lesson.

Sign in to purchase
←A Complete CI Pipeline
Back to CI/CD Pipelines
Environment Management→