DEV Community

Atlas Whoff
Atlas Whoff

Posted on

GitHub Actions CI/CD: Testing, Docker Builds, Vercel Deploys, and Security Scanning

GitHub Actions can do a lot more than run your test suite. With the right workflow design, it becomes an autonomous deployment pipeline that tests, builds, scans for vulnerabilities, deploys, and notifies — without manual intervention.

The Complete CI/CD Workflow

# .github/workflows/ci.yml
name: CI/CD

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:15
        env:
          POSTGRES_DB: testdb
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
      - run: npm ci
      - run: npx prisma migrate deploy
        env:
          DATABASE_URL: postgresql://postgres:postgres@localhost:5432/testdb
      - run: npm test
        env:
          DATABASE_URL: postgresql://postgres:postgres@localhost:5432/testdb

  build:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
      - run: npm ci
      - run: npm run build
      - uses: actions/upload-artifact@v4
        with:
          name: build
          path: .next

  deploy:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4
      - uses: actions/download-artifact@v4
        with:
          name: build
          path: .next
      - name: Deploy to Vercel
        run: npx vercel --prod --token ${{ secrets.VERCEL_TOKEN }}
Enter fullscreen mode Exit fullscreen mode

Dependency Caching

The cache: npm option on setup-node caches ~/.npm based on package-lock.json. This cuts install time from 60s to ~5s on cache hits.

For Docker builds, cache layers explicitly:

- name: Build and push Docker image
  uses: docker/build-push-action@v5
  with:
    context: .
    push: true
    tags: ghcr.io/${{ github.repository }}:latest
    cache-from: type=gha
    cache-to: type=gha,mode=max
Enter fullscreen mode Exit fullscreen mode

Secrets Management

Store secrets in GitHub Settings > Secrets and Variables > Actions. Reference them in workflows:

env:
  DATABASE_URL: ${{ secrets.DATABASE_URL }}
  STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }}
  NEXTAUTH_SECRET: ${{ secrets.NEXTAUTH_SECRET }}
Enter fullscreen mode Exit fullscreen mode

Never hardcode secrets. Never echo them in logs (GitHub masks them, but be explicit).

Parallel Jobs

Run independent checks in parallel to reduce total CI time:

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm run lint

  typecheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npx tsc --noEmit

  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm test

  deploy:
    needs: [lint, typecheck, test]  # all three must pass
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - run: echo 'Deploying...'
Enter fullscreen mode Exit fullscreen mode

PR Preview Deployments

Deploy every PR to a unique preview URL:

on:
  pull_request:
    types: [opened, synchronize]

jobs:
  preview:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Deploy preview
        id: deploy
        run: |
          URL=$(npx vercel --token ${{ secrets.VERCEL_TOKEN }})
          echo "url=$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 }}'
            })
Enter fullscreen mode Exit fullscreen mode

Security Scanning

Add automated vulnerability scanning:

  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run npm audit
        run: npm audit --audit-level=high
      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: fs
          scan-ref: .
          severity: HIGH,CRITICAL
Enter fullscreen mode Exit fullscreen mode

The Ship Fast Skill Pack at whoffagents.com includes a /deploy skill that generates complete GitHub Actions workflows — test, build, Docker, Vercel, and security scanning — customized for your stack. $49 one-time.

Top comments (0)