π CI/CD Pipeline: Continuous Integration & Deployment
SkillCloud & infraUse 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.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the π CI/CD Pipeline: Continuous Integration & Deployment skill
What this skill tells your AI
The instructions your AI receives, as published by cwinvestments/memstack in skills/deployment/ci-cd-pipeline/SKILL.md and read by ahelβs review.
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 |
|---|---|---|
.github/ exists | GitHub Actions | Already 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 present | GitHub Actions β Docker registry β deploy | Full control pipeline |
Monorepo (packages/) | 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? |
|---|---|---|---|
feature/* | none | Lint + Test | No |
develop | Staging | Lint + Test + Build + Deploy | Yes |
main | Production | Lint + Test + Build + Deploy | Yes (or manual gate) |
hotfix/* | none | 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
GITHUB_TOKENfor 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:
| Target | Rollback Method | Speed | Data Safety |
|---|---|---|---|
| Vercel | Instant rollback in dashboard or CLI | Instant | Safe: immutable deploys |
| Railway | railway rollback or dashboard | Instant | Safe: previous deploy preserved |
| Netlify | Deploy previous build in dashboard | Instant | Safe: immutable deploys |
| Docker | Tag previous image as latest, restart | Seconds | Safe: images preserved |
| VPS/PM2 | git revert + pm2 restart | Minutes | Check DB migrations first |
| Kubernetes | kubectl rollout undo | Seconds | Check DB migrations first |
Database migration caution:
- If the deploy includes DB migrations, rollback is complex
- Always write reversible migrations (
up+down) - Test
downmigration before deployingup - 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)
Signals
- GitHub stars
- 421
- Forks
- 44
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
memstack-deployment-ci-cd-pipeline- Source
- github.com/cwinvestments/memstack