Memstack memstack-deployment-ci-cd-pipeline

Use this skill when the user says 'CI/CD', 'GitHub Actions', 'pipeline', 'continuous integration', 'continuous deployment', 'ci-cd-pipeline', 'automate deploys', or needs to set up automated build, test, and deployment pipelines. Do NOT use for one-time manual deployments.

install
source · Clone the upstream repo
git clone https://github.com/cwinvestments/memstack
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/cwinvestments/memstack "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/deployment/ci-cd-pipeline" ~/.claude/skills/cwinvestments-memstack-memstack-deployment-ci-cd-pipeline && rm -rf "$T"
manifest: skills/deployment/ci-cd-pipeline/SKILL.md
source content

🔄 CI/CD Pipeline — Continuous Integration & Deployment

Detect project type and generate a complete CI/CD pipeline with lint, test, build, deploy stages, rollback strategy, and environment management.

Activation

When this skill activates, output:

🔄 CI/CD Pipeline — Designing your pipeline...

ContextStatus
User says "CI/CD", "pipeline", "GitHub Actions"ACTIVE
User wants automated testing and deploymentACTIVE
User mentions branch strategy, deploy gates, or rollbacksACTIVE
User wants Docker setup (CI/CD is secondary)DORMANT — see docker-setup
User wants server provisioning (not pipeline)DORMANT — see hetzner-setup
User wants to deploy to a specific platform onlyDORMANT — see railway-deploy or netlify-deploy

Protocol

Step 1: Gather Inputs

Ask the user for:

  • Project type: Node.js, Python, Go, Rust, monorepo?
  • Testing framework: Jest, Vitest, Pytest, Go test?
  • Deployment target: Vercel, Railway, Netlify, Hetzner VPS, AWS, Docker registry?
  • Current CI/CD: Any existing pipeline, or starting from scratch?
  • Branch strategy: Trunk-based, GitFlow, or custom?
  • Team size: Solo dev, small team, or large team?

Step 2: Detect Project & Recommend Platform

Auto-detect from project files and recommend CI/CD platform:

Project SignalPlatform RecommendationReason
.github/
exists
GitHub ActionsAlready on GitHub, native integration
vercel.json
or Next.js
Vercel (auto-deploy) + GitHub Actions (CI)Vercel handles deploy, GHA handles testing
railway.json
Railway (auto-deploy) + GitHub Actions (CI)Railway handles deploy, GHA handles testing
netlify.toml
Netlify (auto-deploy) + GitHub Actions (CI)Netlify handles deploy, GHA handles testing
Dockerfile presentGitHub Actions → Docker registry → deployFull control pipeline
Monorepo (
packages/
)
GitHub Actions with matrix/path filtersNeed per-package CI
Self-hosted serverGitHub Actions → SSH deployPush-based deployment

Default recommendation: GitHub Actions — free for public repos, 2,000 min/month for private.

Step 3: Design Pipeline Stages

Define the stage sequence:

┌─────────┐   ┌─────────┐   ┌─────────┐   ┌─────────┐   ┌─────────┐
│  LINT   │──→│  TEST   │──→│  BUILD  │──→│ DEPLOY  │──→│ VERIFY  │
│         │   │         │   │         │   │         │   │         │
│ ESLint  │   │ Unit    │   │ Compile │   │ Push to │   │ Health  │
│ Prettier│   │ Integ.  │   │ Bundle  │   │ target  │   │ Smoke   │
│ Types   │   │ E2E     │   │ Docker  │   │ env     │   │ Rollback│
└─────────┘   └─────────┘   └─────────┘   └─────────┘   └─────────┘
     │              │              │              │              │
  Fail fast    Gate: block     Artifacts      Env-specific    Auto-rollback
  < 1 min      if < 80%       cached         secrets         on failure

Stage details:

StageTriggerFailure ActionDuration Target
LintEvery push, every PRBlock merge< 1 min
TestEvery push, every PRBlock merge< 5 min
BuildPR merge to main/developBlock deploy< 3 min
DeployBuild passes on target branchAlert + rollback< 2 min
VerifyAfter deploy completesAuto-rollback< 1 min

Step 4: Branch Strategy

Recommended: Simplified GitFlow

main (production)
  ├── develop (staging)
  │     ├── feature/add-auth
  │     ├── feature/dashboard
  │     └── fix/login-bug
  └── hotfix/critical-fix (→ main + develop)
BranchDeploys ToCI RunsAuto-Deploy?
feature/*
Lint + TestNo
develop
StagingLint + Test + Build + DeployYes
main
ProductionLint + Test + Build + DeployYes (or manual gate)
hotfix/*
Lint + TestNo (merge to main to deploy)

Branch protection rules:

main:
  - Require PR review (1+ approvals)
  - Require status checks (lint, test, build)
  - No force push
  - No direct push

develop:
  - Require status checks (lint, test)
  - Allow direct push (for solo devs)
  - No force push

Step 5: Environment Variable Management

── ENVIRONMENT VARIABLES ──────────────────

Three environments with escalating secrets:

LOCAL (.env.local — never committed):
  DATABASE_URL=postgresql://localhost:5432/app_dev
  API_KEY=dev_test_key
  NODE_ENV=development

STAGING (GitHub Secrets / platform env):
  DATABASE_URL=[staging DB connection string]
  API_KEY=[staging API key]
  NODE_ENV=staging

PRODUCTION (GitHub Secrets / platform env):
  DATABASE_URL=[production DB connection string]
  API_KEY=[production API key]
  NODE_ENV=production

Secret management rules:

  • Never hardcode secrets in pipeline config
  • Use GitHub Environments for per-branch secrets
  • Use
    GITHUB_TOKEN
    for GitHub operations (auto-provided)
  • Rotate secrets quarterly
  • Audit secret access in GitHub Settings → Secrets → Audit log

GitHub Environments setup:

Repository → Settings → Environments:
  staging:
    Secrets: DATABASE_URL, API_KEY
    Deployment branches: develop

  production:
    Secrets: DATABASE_URL, API_KEY
    Deployment branches: main
    Required reviewers: [team member] (optional gate)

Step 6: Generate Pipeline Config

GitHub Actions — Node.js project:

name: CI/CD Pipeline

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

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  lint:
    name: Lint
    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 lint
      - run: npm run typecheck  # If TypeScript

  test:
    name: Test
    runs-on: ubuntu-latest
    needs: lint
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      - run: npm ci
      - run: npm test -- --coverage
      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: coverage-report
          path: coverage/

  build:
    name: Build
    runs-on: ubuntu-latest
    needs: test
    if: github.event_name == 'push'
    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-output
          path: dist/

  deploy-staging:
    name: Deploy to Staging
    runs-on: ubuntu-latest
    needs: build
    if: github.ref == 'refs/heads/develop'
    environment: staging
    steps:
      - uses: actions/checkout@v4
      - uses: actions/download-artifact@v4
        with:
          name: build-output
          path: dist/
      # Platform-specific deploy step here
      # Option A: Railway
      # - uses: bervProject/railway-deploy@main
      #   with:
      #     railway_token: ${{ secrets.RAILWAY_TOKEN }}
      # Option B: SSH deploy to VPS
      # - uses: appleboy/ssh-action@v1
      #   with:
      #     host: ${{ secrets.SERVER_HOST }}
      #     username: deploy
      #     key: ${{ secrets.SSH_PRIVATE_KEY }}
      #     port: 2222
      #     script: |
      #       cd /opt/app && git pull && npm ci --production && pm2 restart all

  deploy-production:
    name: Deploy to Production
    runs-on: ubuntu-latest
    needs: build
    if: github.ref == 'refs/heads/main'
    environment: production
    steps:
      - uses: actions/checkout@v4
      - uses: actions/download-artifact@v4
        with:
          name: build-output
          path: dist/
      # Same deploy pattern as staging but with production env

  verify:
    name: Verify Deployment
    runs-on: ubuntu-latest
    needs: [deploy-staging, deploy-production]
    if: always() && (needs.deploy-staging.result == 'success' || needs.deploy-production.result == 'success')
    steps:
      - name: Health check
        run: |
          URL="${{ github.ref == 'refs/heads/main' && secrets.PRODUCTION_URL || secrets.STAGING_URL }}"
          for i in 1 2 3 4 5; do
            STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$URL/health")
            if [ "$STATUS" = "200" ]; then
              echo "Health check passed"
              exit 0
            fi
            echo "Attempt $i: HTTP $STATUS — retrying in 10s..."
            sleep 10
          done
          echo "Health check failed after 5 attempts"
          exit 1

GitHub Actions — Python project:

name: CI/CD Pipeline

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

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
          cache: 'pip'
      - run: pip install ruff mypy
      - run: ruff check .
      - run: mypy .

  test:
    runs-on: ubuntu-latest
    needs: lint
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_USER: test
          POSTGRES_PASSWORD: test
          POSTGRES_DB: testdb
        ports: ['5432:5432']
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
          cache: 'pip'
      - run: pip install -r requirements.txt
      - run: pytest --cov --cov-report=xml
        env:
          DATABASE_URL: postgresql://test:test@localhost:5432/testdb

  build-and-deploy:
    runs-on: ubuntu-latest
    needs: test
    if: github.event_name == 'push'
    steps:
      - uses: actions/checkout@v4
      # Docker build + push or direct deploy

Step 7: Deployment Rollback Strategy

Automated rollback on failed health check:

  rollback:
    name: Rollback on Failure
    runs-on: ubuntu-latest
    needs: verify
    if: failure()
    steps:
      - name: Rollback deployment
        run: |
          echo "Deployment verification failed — rolling back"
          # Option A: Revert to previous Docker image
          # docker pull $REGISTRY/app:previous && docker tag $REGISTRY/app:previous $REGISTRY/app:latest
          # Option B: Railway rollback
          # railway rollback
          # Option C: Git revert + redeploy
          # git revert HEAD --no-edit && git push
      - name: Notify team
        run: |
          curl -X POST "${{ secrets.SLACK_WEBHOOK }}" \
            -H 'Content-Type: application/json' \
            -d '{"text":"🔴 Deployment rolled back — health check failed on ${{ github.ref }}"}'

Rollback strategies by deployment target:

TargetRollback MethodSpeedData Safety
VercelInstant rollback in dashboard or CLIInstantSafe — immutable deploys
Railway
railway rollback
or dashboard
InstantSafe — previous deploy preserved
NetlifyDeploy previous build in dashboardInstantSafe — immutable deploys
DockerTag previous image as
latest
, restart
SecondsSafe — images preserved
VPS/PM2
git revert
+
pm2 restart
MinutesCheck DB migrations first
Kubernetes
kubectl rollout undo
SecondsCheck DB migrations first

Database migration caution:

  • If the deploy includes DB migrations, rollback is complex
  • Always write reversible migrations (
    up
    +
    down
    )
  • Test
    down
    migration before deploying
    up
  • Consider: deploy DB migration separately from code deploy

Step 8: Notifications

Slack notification on deploy:

  notify:
    name: Notify
    runs-on: ubuntu-latest
    needs: [deploy-staging, deploy-production, verify]
    if: always()
    steps:
      - name: Send Slack notification
        env:
          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
        run: |
          if [ "${{ needs.verify.result }}" = "success" ]; then
            EMOJI="✅"
            STATUS="succeeded"
          else
            EMOJI="🔴"
            STATUS="failed"
          fi
          curl -X POST "$SLACK_WEBHOOK" \
            -H 'Content-Type: application/json' \
            -d "{
              \"text\": \"${EMOJI} Deploy ${STATUS}\",
              \"blocks\": [
                {
                  \"type\": \"section\",
                  \"text\": {
                    \"type\": \"mrkdwn\",
                    \"text\": \"${EMOJI} *Deploy ${STATUS}*\nBranch: \`${{ github.ref_name }}\`\nCommit: \`${{ github.sha }}\`\nBy: ${{ github.actor }}\"
                  }
                }
              ]
            }"

Alternative notification channels:

  • GitHub Actions built-in: Email on failure (Settings → Notifications)
  • Discord webhook: Same curl pattern, different payload format
  • PagerDuty: For production failures that need on-call response

Step 9: Output

Present the complete CI/CD configuration:

━━━ CI/CD PIPELINE ━━━━━━━━━━━━━━━━━━━━━━━
Project: [name]
Platform: GitHub Actions
Deploy target: [platform]
Branch strategy: [strategy]

── PIPELINE STAGES ────────────────────────
Lint → Test → Build → Deploy → Verify
[stage diagram with timing]

── BRANCH STRATEGY ────────────────────────
[branch → environment mapping]
[protection rules]

── ENVIRONMENT VARIABLES ──────────────────
[per-environment secret setup]

── PIPELINE CONFIG ────────────────────────
[complete .github/workflows/ci-cd.yml]

── ROLLBACK STRATEGY ──────────────────────
[per-target rollback method]
[database migration caution]

── NOTIFICATIONS ──────────────────────────
[Slack/Discord/email setup]

── SETUP CHECKLIST ────────────────────────
[ ] Create .github/workflows/ directory
[ ] Add pipeline YAML file
[ ] Configure GitHub Environments (staging, production)
[ ] Add secrets to each environment
[ ] Set branch protection rules
[ ] Configure notification webhook
[ ] Test pipeline with a feature branch PR
[ ] Verify staging deploy on develop merge
[ ] Verify production deploy on main merge

Inputs

  • Project type and language
  • Testing framework
  • Deployment target
  • Branch strategy preference
  • Team size
  • Existing CI/CD (if any)

Outputs

  • Pipeline stage design with timing targets
  • Branch strategy with protection rules
  • Environment variable management per stage
  • Complete CI/CD config file (GitHub Actions YAML)
  • Deployment rollback strategy per target
  • Notification setup (Slack, Discord, email)
  • Setup checklist for first-time configuration

Level History

  • Lv.1 — Base: Auto-detect project type, 5-stage pipeline (lint/test/build/deploy/verify), GitHub Actions configs for Node.js and Python, simplified GitFlow branch strategy, environment variable management with GitHub Environments, automated rollback on health check failure, Slack notifications, setup checklist. (Origin: MemStack v3.2, Mar 2026)