ci-cd

Automate testing, building, and deployment with GitHub Actions.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "ci-cd" with this command: npx skills add profpowell/vanilla-breeze/profpowell-vanilla-breeze-ci-cd

CI/CD Skill

Automate testing, building, and deployment with GitHub Actions.

Directory Structure

.github/ ├── workflows/ │ ├── ci.yml # Continuous integration │ ├── deploy.yml # Deployment │ └── release.yml # Release automation └── dependabot.yml # Dependency updates

Basic CI Workflow

.github/workflows/ci.yml

name: CI

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

jobs: test: runs-on: ubuntu-latest

steps:
  - name: Checkout
    uses: actions/checkout@v4

  - name: Setup Node.js
    uses: actions/setup-node@v4
    with:
      node-version: '20'
      cache: 'npm'

  - name: Install dependencies
    run: npm ci

  - name: Lint
    run: npm run lint

  - name: Test
    run: npm test

  - name: Build
    run: npm run build

Deploy to Cloudflare Pages

.github/workflows/deploy.yml

name: Deploy to Cloudflare Pages

on: push: branches: [main]

jobs: deploy: runs-on: ubuntu-latest

steps:
  - name: Checkout
    uses: actions/checkout@v4

  - name: Setup Node.js
    uses: actions/setup-node@v4
    with:
      node-version: '20'
      cache: 'npm'

  - name: Install dependencies
    run: npm ci

  - name: Build
    run: npm run build
    env:
      NODE_ENV: production

  - name: Deploy to Cloudflare Pages
    uses: cloudflare/pages-action@v1
    with:
      apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
      accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
      projectName: my-project
      directory: dist
      gitHubToken: ${{ secrets.GITHUB_TOKEN }}

Deploy to DigitalOcean App Platform

.github/workflows/deploy-do.yml

name: Deploy to DigitalOcean

on: push: branches: [main]

jobs: deploy: runs-on: ubuntu-latest

steps:
  - name: Checkout
    uses: actions/checkout@v4

  - name: Install doctl
    uses: digitalocean/action-doctl@v2
    with:
      token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}

  - name: Deploy to App Platform
    run: doctl apps create-deployment ${{ secrets.DO_APP_ID }}

Deploy to DigitalOcean Droplet (SSH)

.github/workflows/deploy-droplet.yml

name: Deploy to Droplet

on: push: branches: [main]

jobs: deploy: runs-on: ubuntu-latest

steps:
  - name: Checkout
    uses: actions/checkout@v4

  - name: Deploy via SSH
    uses: appleboy/ssh-action@v1.0.0
    with:
      host: ${{ secrets.DROPLET_HOST }}
      username: ${{ secrets.DROPLET_USER }}
      key: ${{ secrets.DROPLET_SSH_KEY }}
      script: |
        cd /var/www/my-app
        git pull origin main
        npm ci --only=production
        npm run build
        pm2 reload ecosystem.config.js

Matrix Testing

Test across multiple Node.js versions:

.github/workflows/ci.yml

jobs: test: runs-on: ubuntu-latest

strategy:
  matrix:
    node-version: [18, 20, 22]

steps:
  - uses: actions/checkout@v4

  - name: Setup Node.js ${{ matrix.node-version }}
    uses: actions/setup-node@v4
    with:
      node-version: ${{ matrix.node-version }}
      cache: 'npm'

  - run: npm ci
  - run: npm test

Caching

jobs: build: runs-on: ubuntu-latest

steps:
  - uses: actions/checkout@v4

  - name: Setup Node.js
    uses: actions/setup-node@v4
    with:
      node-version: '20'
      cache: 'npm'

  # Cache build output
  - name: Cache build
    uses: actions/cache@v4
    with:
      path: dist
      key: build-${{ hashFiles('src/**', 'package-lock.json') }}

  - run: npm ci

  - name: Build (if not cached)
    run: |
      if [ ! -d "dist" ]; then
        npm run build
      fi

Environment-Specific Deploys

.github/workflows/deploy.yml

name: Deploy

on: push: branches: - main # Production - staging # Staging

jobs: deploy: runs-on: ubuntu-latest

steps:
  - uses: actions/checkout@v4

  - name: Setup Node.js
    uses: actions/setup-node@v4
    with:
      node-version: '20'
      cache: 'npm'

  - run: npm ci

  - name: Build
    run: npm run build
    env:
      NODE_ENV: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}

  - name: Deploy to Production
    if: github.ref == 'refs/heads/main'
    run: npx wrangler pages deploy dist --project-name=my-app
    env:
      CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}

  - name: Deploy to Staging
    if: github.ref == 'refs/heads/staging'
    run: npx wrangler pages deploy dist --project-name=my-app-staging
    env:
      CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}

Secrets Management

Required Secrets

Set in repository Settings > Secrets and variables > Actions:

Secret Description

CLOUDFLARE_API_TOKEN

Cloudflare API token with Pages edit permission

CLOUDFLARE_ACCOUNT_ID

Cloudflare account ID

DIGITALOCEAN_ACCESS_TOKEN

DigitalOcean API token

DROPLET_HOST

Droplet IP or hostname

DROPLET_USER

SSH username

DROPLET_SSH_KEY

Private SSH key

Using Secrets

env: API_KEY: ${{ secrets.API_KEY }}

Or per-step

  • name: Deploy run: ./deploy.sh env: DATABASE_URL: ${{ secrets.DATABASE_URL }}

Pull Request Checks

.github/workflows/pr.yml

name: PR Checks

on: pull_request: branches: [main]

jobs: check: runs-on: ubuntu-latest

steps:
  - uses: actions/checkout@v4

  - name: Setup Node.js
    uses: actions/setup-node@v4
    with:
      node-version: '20'
      cache: 'npm'

  - run: npm ci
  - run: npm run lint
  - run: npm test
  - run: npm run build

  # Comment bundle size on PR
  - name: Report bundle size
    uses: preactjs/compressed-size-action@v2
    with:
      repo-token: ${{ secrets.GITHUB_TOKEN }}

Release Automation

.github/workflows/release.yml

name: Release

on: push: tags: - 'v*'

jobs: release: runs-on: ubuntu-latest

steps:
  - uses: actions/checkout@v4

  - name: Setup Node.js
    uses: actions/setup-node@v4
    with:
      node-version: '20'
      cache: 'npm'

  - run: npm ci
  - run: npm run build

  - name: Create Release
    uses: softprops/action-gh-release@v1
    with:
      files: dist/*
      generate_release_notes: true
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  - name: Deploy
    run: npx wrangler pages deploy dist --project-name=my-app
    env:
      CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}

Dependabot Configuration

.github/dependabot.yml

version: 2

updates:

NPM dependencies

  • package-ecosystem: "npm" directory: "/" schedule: interval: "weekly" open-pull-requests-limit: 10 groups:

    Group minor/patch updates

    dependencies: patterns: - "*" update-types: - "minor" - "patch"

GitHub Actions

  • package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly"

Workflow Templates

Reusable Workflow

.github/workflows/build.yml

name: Build

on: workflow_call: inputs: node-version: required: false type: string default: '20' outputs: artifact-name: value: ${{ jobs.build.outputs.artifact-name }}

jobs: build: runs-on: ubuntu-latest outputs: artifact-name: build-${{ github.sha }}

steps:
  - uses: actions/checkout@v4

  - name: Setup Node.js
    uses: actions/setup-node@v4
    with:
      node-version: ${{ inputs.node-version }}
      cache: 'npm'

  - run: npm ci
  - run: npm run build

  - name: Upload artifact
    uses: actions/upload-artifact@v4
    with:
      name: build-${{ github.sha }}
      path: dist/

Using Reusable Workflow

.github/workflows/deploy.yml

name: Deploy

on: push: branches: [main]

jobs: build: uses: ./.github/workflows/build.yml

deploy: needs: build runs-on: ubuntu-latest

steps:
  - name: Download artifact
    uses: actions/download-artifact@v4
    with:
      name: ${{ needs.build.outputs.artifact-name }}
      path: dist/

  - name: Deploy
    run: npx wrangler pages deploy dist
    env:
      CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}

Checklist

Before enabling CI/CD:

  • All required secrets are set

  • Workflows have correct triggers

  • Build command works locally

  • Tests pass locally

  • Deployment credentials are scoped appropriately

  • Branch protection rules configured

  • Dependabot enabled for security updates

Related Skills

  • deployment - Deployment target configuration

  • env-config - Environment variable management

  • unit-testing - Test configuration

  • security - Credential management

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

api-client

No summary provided by upstream source.

Repository SourceNeeds Review
General

validation

No summary provided by upstream source.

Repository SourceNeeds Review
General

fake-content

No summary provided by upstream source.

Repository SourceNeeds Review