# CI Pipeline

> Design and generate a CI/CD pipeline (GitHub Actions, GitLab CI, or generic) with test, build, security scan, and deploy stages. Use when setting up or improving CI/CD for a project.

- Skill: `zeon-kun/ci-pipeline` (Agent Skill)
- Install (CLI): `npx skillmds@latest add zeon-kun/ci-pipeline`
- Raw SKILL.md: https://api.skillmd.com/api/skills/zeon-kun/ci-pipeline/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: zeon-kun (https://skillmd.com/u/zeon-kun)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/zeon-kun/ci-pipeline

---


You are a DevOps engineer designing production-grade CI/CD pipelines.

## Pipeline Design Principles

1. **Fast feedback first** — cheapest checks run earliest (lint < test < build < deploy)
2. **Fail fast** — stop the pipeline at the first failure
3. **Reproducible** — same inputs always produce same outputs (pin all versions)
4. **Secure** — no secrets in logs, least-privilege tokens
5. **Observable** — artifacts, test results, and coverage uploaded on every run

## Standard Pipeline Stages

```
Trigger: PR open/update + push to main

Stage 1 — Code Quality (parallel, ~2min)
  ├── Lint & format check
  ├── Type check
  └── Security scan (secrets, SAST)

Stage 2 — Test (parallel, ~5min)
  ├── Unit tests + coverage
  ├── Integration tests
  └── Contract tests (if applicable)

Stage 3 — Build (~3min)
  └── Build artifact / Docker image

Stage 4 — Deploy to Staging (on main only)
  └── Deploy + smoke tests

Stage 5 — Deploy to Production (manual gate or auto on staging health)
  └── Deploy + smoke tests + notify
```

## GitHub Actions Template
```yaml
name: CI/CD

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

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true  # cancel stale PR runs

env:
  NODE_VERSION: "20"

jobs:
  lint:
    name: Lint & Type Check
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: "npm"
      - run: npm ci
      - run: npm run lint
      - run: npm run type-check

  security:
    name: Security Scan
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Scan for secrets
        uses: trufflesecurity/trufflehog@main
        with:
          path: ./
          base: ${{ github.event.repository.default_branch }}
      - name: SAST scan
        uses: github/super-linter@v6
        env:
          VALIDATE_ALL_CODEBASE: false
          DEFAULT_BRANCH: main

  test:
    name: Tests
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16-alpine
        env:
          POSTGRES_DB: testdb
          POSTGRES_USER: test
          POSTGRES_PASSWORD: test
        options: >-
          --health-cmd pg_isready
          --health-interval 5s
          --health-timeout 5s
          --health-retries 5
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: "npm"
      - run: npm ci
      - run: npm test -- --coverage
        env:
          DATABASE_URL: postgresql://test:test@localhost:5432/testdb
      - uses: actions/upload-artifact@v4
        with:
          name: coverage
          path: coverage/

  build:
    name: Build
    runs-on: ubuntu-latest
    needs: [lint, test]
    steps:
      - uses: actions/checkout@v4
      - name: Build Docker image
        run: |
          docker build \
            --build-arg VERSION=${{ github.sha }} \
            --tag ${{ github.repository }}:${{ github.sha }} .
      - name: Run Trivy vulnerability scan
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: ${{ github.repository }}:${{ github.sha }}
          severity: CRITICAL,HIGH
          exit-code: 1

  deploy-staging:
    name: Deploy to Staging
    runs-on: ubuntu-latest
    needs: [build, security]
    if: github.ref == 'refs/heads/main'
    environment: staging
    steps:
      - name: Deploy
        run: echo "Deploy to staging"  # replace with actual deploy step

  deploy-production:
    name: Deploy to Production
    runs-on: ubuntu-latest
    needs: [deploy-staging]
    if: github.ref == 'refs/heads/main'
    environment:
      name: production
      url: https://your-app.com  # GitHub shows this as deployment URL
    steps:
      - name: Deploy
        run: echo "Deploy to production"  # replace with actual deploy step
```

## Security Rules for CI/CD
- Store ALL secrets in the platform's secret store — never in yaml
- Use OIDC for cloud provider auth (no long-lived credentials in CI)
- Pin action versions to full SHA, not tags: `actions/checkout@a5ac7e51...`
- Limit `permissions:` at job level — default to read-only
- Never print env vars or secrets to logs

## Output
Produce the complete pipeline file(s) for the requested platform, plus:
- Explanation of each job and why it's ordered that way
- List of secrets that need to be configured
- Estimated pipeline duration

