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.
git clone https://github.com/cwinvestments/memstack
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"
skills/deployment/ci-cd-pipeline/SKILL.md🔄 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...
| Context | Status |
|---|---|
| User says "CI/CD", "pipeline", "GitHub Actions" | ACTIVE |
| User wants automated testing and deployment | ACTIVE |
| User mentions branch strategy, deploy gates, or rollbacks | ACTIVE |
| 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 only | DORMANT — 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 Signal | Platform Recommendation | Reason |
|---|---|---|
exists | GitHub Actions | Already on GitHub, native integration |
or Next.js | Vercel (auto-deploy) + GitHub Actions (CI) | Vercel handles deploy, GHA handles testing |
| Railway (auto-deploy) + GitHub Actions (CI) | Railway handles deploy, GHA handles testing |
| Netlify (auto-deploy) + GitHub Actions (CI) | Netlify handles deploy, GHA handles testing |
| Dockerfile present | GitHub Actions → Docker registry → deploy | Full control pipeline |
Monorepo () | GitHub Actions with matrix/path filters | Need per-package CI |
| Self-hosted server | GitHub Actions → SSH deploy | Push-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:
| Stage | Trigger | Failure Action | Duration Target |
|---|---|---|---|
| Lint | Every push, every PR | Block merge | < 1 min |
| Test | Every push, every PR | Block merge | < 5 min |
| Build | PR merge to main/develop | Block deploy | < 3 min |
| Deploy | Build passes on target branch | Alert + rollback | < 2 min |
| Verify | After deploy completes | Auto-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)
| Branch | Deploys To | CI Runs | Auto-Deploy? |
|---|---|---|---|
| — | Lint + Test | No |
| Staging | Lint + Test + Build + Deploy | Yes |
| Production | Lint + Test + Build + Deploy | Yes (or manual gate) |
| — | Lint + Test | No (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
for GitHub operations (auto-provided)GITHUB_TOKEN - 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:
| Target | Rollback Method | Speed | Data Safety |
|---|---|---|---|
| Vercel | Instant rollback in dashboard or CLI | Instant | Safe — immutable deploys |
| Railway | or dashboard | Instant | Safe — previous deploy preserved |
| Netlify | Deploy previous build in dashboard | Instant | Safe — immutable deploys |
| Docker | Tag previous image as , restart | Seconds | Safe — images preserved |
| VPS/PM2 | + | Minutes | Check DB migrations first |
| Kubernetes | | Seconds | Check DB migrations first |
Database migration caution:
- If the deploy includes DB migrations, rollback is complex
- Always write reversible migrations (
+up
)down - Test
migration before deployingdownup - 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)