DevOps
GitHub Actions
CI/CD
Docker
Automation
Ask anything about this article
Hi! I've read this article.
What would you like to know?
@farhan
Every push to main should automatically test, build, and deploy your application. Here's how to build a production-grade CI/CD pipeline.
yaml# .github/workflows/deploy.yml
name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
# ====== STEP 1: TEST ======
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run type-check
- run: npm test -- --coverage
- uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage/
# ====== STEP 2: BUILD DOCKER ======
build:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- 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 }}:latest
ghcr.io/${{ github.repository }}:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
# ====== STEP 3: DEPLOY ======
deploy:
needs: build
runs-on: ubuntu-latest
environment: production
steps:
- name: Deploy to production
run: |
# SSH deploy, Kubernetes apply, or cloud CLI
echo "Deploying ${{ github.sha }} to production"
yaml preview:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy Preview
id: deploy
run: |
PREVIEW_URL="https://pr-${{ github.event.number }}.preview.myapp.com"
echo "url=$PREVIEW_URL" >> $GITHUB_OUTPUT
- 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: ${{ steps.deploy.outputs.url }}'
})
yaml migrate:
needs: build
runs-on: ubuntu-latest
steps:
- name: Run migrations
run: |
npx prisma migrate deploy
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
yaml rollback:
needs: deploy
if: failure()
runs-on: ubuntu-latest
steps:
- name: Rollback to previous version
run: |
# Deploy previous stable image
kubectl set image deployment/app \
app=ghcr.io/${{ github.repository }}:${{ env.PREVIOUS_SHA }}
A good CI/CD pipeline is the backbone of reliable software delivery. Build it once, benefit forever.