Agent Skills Framework Extension
CI/CD Automation Patterns Skill
When to Use This Skill
Use this skill when implementing cicd automation patterns patterns in your codebase.
How to Use This Skill
- Review the patterns and examples below
- Apply the relevant patterns to your implementation
- Follow the best practices outlined in this skill
Pipeline automation, deployment strategies, and artifact management for production-grade continuous delivery.
Core Capabilities
- Multi-Stage Pipelines - Build, test, security scan, deploy
- Deployment Strategies - Blue-green, canary, rolling updates
- Artifact Management - Versioning, caching, distribution
- Test Automation - Unit, integration, E2E, load testing
- Security Scanning - SAST, DAST, dependency scanning
Pipeline Stage Requirements Matrix
| Stage | Purpose | Required Gates | Timeout | Retry |
|---|---|---|---|---|
| 1. Checkout | Get code | None | 2 min | 3x |
| 2. Install | Dependencies | Cache hit/miss | 5 min | 2x |
| 3. Lint | Code quality | 0 errors | 5 min | 0 |
| 4. Type Check | Type safety | 0 errors | 5 min | 0 |
| 5. Unit Test | Logic verification | 100% pass, >80% coverage | 10 min | 0 |
| 6. Build | Create artifacts | Successful compile | 10 min | 2x |
| 7. Integration Test | Service integration | 100% pass | 15 min | 1x |
| 8. Security Scan | Vulnerability check | No critical/high | 10 min | 1x |
| 9. E2E Test | User flow validation | 100% pass | 20 min | 1x |
| 10. Docker Build | Container image | Valid image pushed | 15 min | 2x |
| 11. Deploy Staging | Pre-prod validation | Health check pass | 10 min | 2x |
| 12. Smoke Test | Basic functionality | All pass | 5 min | 1x |
| 13. Deploy Production | Release | Health + canary pass | 15 min | 0 |
Stage Dependencies:
Checkout → Install → [Lint, Type Check, Unit Test] → Build
↓
Integration Test ← Build Artifacts
↓
Security Scan → E2E Test
↓
Docker Build → Deploy Staging
↓
Smoke Test → Deploy Production
Environment-Specific Requirements:
| Environment | Approval | Test Coverage | Security Gates | Rollback |
|---|---|---|---|---|
| Development | None | 60% minimum | Warnings only | N/A |
| Staging | Auto | 80% minimum | No high severity | Manual |
| Production | Manual | 80%+ enforced | No critical/high | Auto |
Deployment Strategy Selection:
| Strategy | Use When | Risk Level | Rollback Speed | Complexity |
|---|---|---|---|---|
| Rolling | Standard updates, low risk | Low | Minutes | Low |
| Blue-Green | Zero-downtime required | Medium | Seconds | Medium |
| Canary | High-risk changes, gradual rollout | Low | Seconds | High |
| Feature Flag | A/B testing, gradual exposure | Very Low | Instant | Medium |
| Recreate | Dev/test environments only | High | Minutes | Low |
Quick Decision: Pipeline Complexity
What's your deployment context?
├── Single developer, no prod → Basic (lint + test + deploy)
├── Small team, staging only → Standard (+ security scan + E2E)
├── Production with SLA → Full (+ canary + rollback + monitoring)
├── Regulated industry → Enterprise (+ compliance gates + audit logs)
└── Microservices → Per-service + integration tests + contract testing
Pipeline Health Checklist:
- All stages have explicit timeouts
- Failed tests block deployment (no
continue-on-error: true) - Security scans run before deployment
- Artifacts versioned with git SHA
- Secrets in GitHub Secrets (not in code)
- Production requires manual approval
- Rollback tested and documented
- Cache improves build time by >30%
Production GitHub Actions Pipeline
# .github/workflows/production-cicd.yml
name: Production CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
release:
types: [published]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
NODE_VERSION: '18'
PYTHON_VERSION: '3.11'
jobs:
# Stage 1: Code Quality & Security
quality:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for SonarQube
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Lint
run: npm run lint
- name: Type check
run: npm run type-check
- name: Run SonarQube scan
uses: SonarSource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- name: Run Snyk security scan
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --severity-threshold=high
- name: Upload SARIF results
uses: github/codeql-action/upload-sarif@v2
if: always()
with:
sarif_file: snyk.sarif
# Stage 2: Build & Test
build-and-test:
runs-on: ubuntu-latest
needs: quality
strategy:
matrix:
node-version: [16, 18, 20]
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'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Run unit tests
run: npm test -- --coverage
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage/lcov.info
flags: unittests-node-${{ matrix.node-version }}
- name: Archive build artifacts
uses: actions/upload-artifact@v4
with:
name: build-node-${{ matrix.node-version }}
path: dist/
retention-days: 5
# Stage 3: Integration Tests
integration-test:
runs-on: ubuntu-latest
needs: build-and-test
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: testpass
POSTGRES_DB: testdb
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
redis:
image: redis:7
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: build-node-${{ env.NODE_VERSION }}
path: dist/
- name: Install dependencies
run: npm ci
- name: Run database migrations
env:
DATABASE_URL: postgresql://postgres:testpass@localhost:5432/testdb
run: npm run migrate:test
- name: Run integration tests
env:
DATABASE_URL: postgresql://postgres:testpass@localhost:5432/testdb
REDIS_URL: redis://localhost:6379
run: npm run test:integration
# Stage 4: E2E Tests
e2e-test:
runs-on: ubuntu-latest
needs: integration-test
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install Playwright
run: npx playwright install --with-deps
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: build-node-${{ env.NODE_VERSION }}
path: dist/
- name: Run E2E tests
run: npm run test:e2e
- name: Upload E2E test results
uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
# Stage 5: Build Docker Image
docker-build:
runs-on: ubuntu-latest
needs: [integration-test, e2e-test]
if: github.event_name != 'pull_request'
permissions:
contents: read
packages: write
outputs:
image-digest: ${{ steps.build.outputs.digest }}
image-tag: ${{ steps.meta.outputs.tags }}
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix={{branch}}-
- name: Build and push Docker image
id: build
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
VERSION=${{ github.sha }}
BUILD_DATE=${{ github.event.head_commit.timestamp }}
- name: Generate SBOM
uses: anchore/sbom-action@v0
with:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
format: spdx-json
output-file: sbom.spdx.json
- name: Scan image with Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
format: sarif
output: trivy-results.sarif
- name: Upload Trivy results to GitHub Security
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: trivy-results.sarif
# Stage 6: Deploy to Staging
deploy-staging:
runs-on: ubuntu-latest
needs: docker-build
if: github.ref == 'refs/heads/main'
environment:
name: staging
url: https://staging.example.com
steps:
- uses: actions/checkout@v4
- name: Setup kubectl
uses: azure/setup-kubectl@v3
with:
version: 'v1.28.0'
- name: Configure kubectl context
run: |
echo "${{ secrets.KUBECONFIG_STAGING }}" | base64 -d > kubeconfig
export KUBECONFIG=kubeconfig
kubectl config use-context staging
- name: Update deployment
run: |
kubectl set image deployment/myapp \
myapp=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \
-n staging
- name: Wait for rollout
run: |
kubectl rollout status deployment/myapp -n staging --timeout=5m
- name: Run smoke tests
run: |
npm run test:smoke -- --env staging
# Stage 7: Deploy to Production
deploy-production:
runs-on: ubuntu-latest
needs: deploy-staging
if: github.event_name == 'release'
environment:
name: production
url: https://example.com
steps:
- uses: actions/checkout@v4
- name: Setup kubectl
uses: azure/setup-kubectl@v3
- name: Configure kubectl context
run: |
echo "${{ secrets.KUBECONFIG_PRODUCTION }}" | base64 -d > kubeconfig
export KUBECONFIG=kubeconfig
kubectl config use-context production
- name: Canary deployment (10%)
run: |
kubectl apply -f k8s/canary/deployment.yaml
kubectl set image deployment/myapp-canary \
myapp=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \
-n production
- name: Monitor canary metrics
run: |
# Wait 5 minutes and check error rates
sleep 300
./scripts/check-canary-health.sh
- name: Full production rollout
if: success()
run: |
kubectl set image deployment/myapp \
myapp=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \
-n production
kubectl rollout status deployment/myapp -n production --timeout=10m
- name: Rollback on failure
if: failure()
run: |
kubectl rollout undo deployment/myapp -n production
kubectl delete deployment myapp-canary -n production
- name: Create GitHub deployment
uses: actions/github-script@v7
with:
script: |
await github.rest.repos.createDeployment({
owner: context.repo.owner,
repo: context.repo.repo,
ref: context.sha,
environment: 'production',
auto_merge: false,
required_contexts: []
});
Artifact Versioning & Caching
# .github/workflows/artifact-management.yml
name: Artifact Management
on:
workflow_call:
inputs:
cache-key:
required: true
type: string
jobs:
cache-dependencies:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Cache Node modules
uses: actions/cache@v3
id: cache-node
with:
path: |
node_modules
~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Cache Python packages
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Cache Docker layers
uses: actions/cache@v3
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
version-artifacts:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.versioning.outputs.version }}
semver: ${{ steps.versioning.outputs.semver }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Calculate version
id: versioning
run: |
# Get latest tag
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
# Calculate next version based on commit messages
if git log $LATEST_TAG..HEAD --pretty=format:%s | grep -q "^feat"; then
# Minor version bump for features
NEXT_VERSION=$(echo $LATEST_TAG | awk -F. '{$2++; print $1"."$2".0"}')
elif git log $LATEST_TAG..HEAD --pretty=format:%s | grep -q "^fix"; then
# Patch version bump for fixes
NEXT_VERSION=$(echo $LATEST_TAG | awk -F. '{$3++; print}')
else
NEXT_VERSION=$LATEST_TAG
fi
# Add build metadata
BUILD_META="+build.${{ github.run_number }}.sha.${GITHUB_SHA:0:7}"
FULL_VERSION="${NEXT_VERSION}${BUILD_META}"
echo "version=$FULL_VERSION" >> $GITHUB_OUTPUT
echo "semver=$NEXT_VERSION" >> $GITHUB_OUTPUT
- name: Create version file
run: |
cat > version.json <<EOF
{
"version": "${{ steps.versioning.outputs.version }}",
"semver": "${{ steps.versioning.outputs.semver }}",
"commit": "${{ github.sha }}",
"build_number": "${{ github.run_number }}",
"build_date": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
"branch": "${{ github.ref_name }}"
}
EOF
- name: Upload version artifact
uses: actions/upload-artifact@v4
with:
name: version-metadata
path: version.json
Deployment Automation Script
# scripts/deploy_automation.py
"""
Production deployment automation with health checks and rollback
"""
import subprocess
import time
import sys
from dataclasses import dataclass
from typing import List, Optional
import requests
@dataclass
class DeploymentConfig:
"""Deployment configuration"""
environment: str
namespace: str
deployment_name: str
image: str
replicas: int
health_check_url: str
rollback_on_failure: bool = True
canary_percentage: Optional[int] = None
class DeploymentAutomation:
"""Kubernetes deployment automation"""
def __init__(self, config: DeploymentConfig):
self.config = config
def deploy(self) -> bool:
"""Execute deployment with health checks"""
print(f"Starting deployment to {self.config.environment}...")
try:
# 1. Apply configuration changes
self._apply_config_changes()
# 2. Update image
self._update_image()
# 3. Wait for rollout
if not self._wait_for_rollout():
raise Exception("Rollout timeout")
# 4. Run health checks
if not self._health_check():
raise Exception("Health check failed")
# 5. Verify traffic
if not self._verify_traffic():
raise Exception("Traffic verification failed")
print("Deployment successful!")
return True
except Exception as e:
print(f"Deployment failed: {e}")
if self.config.rollback_on_failure:
print("Rolling back...")
self._rollback()
return False
def _apply_config_changes(self):
"""Apply ConfigMaps and Secrets"""
manifests = [
f"k8s/{self.config.environment}/configmap.yaml",
f"k8s/{self.config.environment}/secrets.yaml"
]
for manifest in manifests:
subprocess.run(
["kubectl", "apply", "-f", manifest, "-n", self.config.namespace],
check=True
)
def _update_image(self):
"""Update deployment image"""
cmd = [
"kubectl", "set", "image",
f"deployment/{self.config.deployment_name}",
f"{self.config.deployment_name}={self.config.image}",
"-n", self.config.namespace
]
subprocess.run(cmd, check=True)
def _wait_for_rollout(self, timeout: int = 600) -> bool:
"""Wait for rollout to complete"""
cmd = [
"kubectl", "rollout", "status",
f"deployment/{self.config.deployment_name}",
"-n", self.config.namespace,
f"--timeout={timeout}s"
]
result = subprocess.run(cmd)
return result.returncode == 0
def _health_check(self, retries: int = 10, delay: int = 10) -> bool:
"""Verify application health"""
for attempt in range(retries):
try:
response = requests.get(
self.config.health_check_url,
timeout=5
)
if response.status_code == 200:
print("Health check passed")
return True
except requests.RequestException as e:
print(f"Health check attempt {attempt + 1}/{retries} failed: {e}")
time.sleep(delay)
return False
def _verify_traffic(self) -> bool:
"""Verify traffic is being served"""
# Get pod IPs
cmd = [
"kubectl", "get", "pods",
"-l", f"app={self.config.deployment_name}",
"-n", self.config.namespace,
"-o", "jsonpath='{.items[*].status.podIP}'"
]
result = subprocess.run(cmd, capture_output=True, text=True)
pod_ips = result.stdout.strip("'").split()
if not pod_ips:
print("No pods found!")
return False
# Verify each pod is responding
for ip in pod_ips:
try:
response = requests.get(f"http://{ip}:8080/health", timeout=5)
if response.status_code != 200:
return False
except requests.RequestException:
return False
return True
def _rollback(self):
"""Rollback to previous version"""
cmd = [
"kubectl", "rollout", "undo",
f"deployment/{self.config.deployment_name}",
"-n", self.config.namespace
]
subprocess.run(cmd, check=True)
print("Rollback initiated")
# Wait for rollback to complete
self._wait_for_rollout()
# Example usage
if __name__ == "__main__":
config = DeploymentConfig(
environment="production",
namespace="default",
deployment_name="myapp",
image=f"ghcr.io/org/myapp:{sys.argv[1] if len(sys.argv) > 1 else 'latest'}",
replicas=3,
health_check_url="https://myapp.example.com/health",
rollback_on_failure=True
)
automation = DeploymentAutomation(config)
success = automation.deploy()
sys.exit(0 if success else 1)
Usage Examples
Setup Multi-Stage Pipeline
Apply cicd-automation-patterns skill to create GitHub Actions pipeline with quality gates, testing, and deployment
Artifact Versioning
Apply cicd-automation-patterns skill to implement semantic versioning with build metadata
Deployment Automation
Apply cicd-automation-patterns skill to automate Kubernetes deployment with health checks and rollback
Integration Points
- cloud-infrastructure-patterns - Infrastructure provisioning
- deployment-strategy-patterns - Deployment strategies
- binary-distribution-patterns - Artifact distribution
Success Output
When this skill is successfully applied, output:
✅ SKILL COMPLETE: cicd-automation-patterns
Completed:
- [x] Multi-stage CI/CD pipeline configured (build/test/scan/deploy)
- [x] Test automation integrated (unit/integration/e2e)
- [x] Security scanning gates active (SAST/DAST/dependency)
- [x] Docker image build and push configured
- [x] Deployment automation with health checks
- [x] Artifact versioning with semantic versioning
- [x] Rollback capability tested
Outputs:
- .github/workflows/production-cicd.yml (main pipeline)
- .github/workflows/artifact-management.yml (versioning/caching)
- scripts/deploy_automation.py (deployment script)
- Docker image: <registry>/<image>:<version> (pushed to registry)
- Deployment: <environment> (staging/production)
- Build artifacts cached: Yes/No
Completion Checklist
Before marking this skill as complete, verify:
- All pipeline stages execute successfully
- Unit tests pass with coverage report uploaded
- Integration tests run against services (DB, Redis)
- E2E tests execute in clean environment
- Security scans complete (SAST, container, dependency)
- Docker image builds and pushes to registry
- SBOM generated for container image
- Deployment to staging successful with health checks
- Rollback mechanism tested and working
- Artifact versioning follows semantic versioning
- Pipeline caching reduces build time (target: 30%+ reduction)
- Deployment includes smoke tests validation
Failure Indicators
This skill has FAILED if:
- ❌ Pipeline stages fail with no retry mechanism
- ❌ Tests skipped or not enforced in CI/CD
- ❌ Security scans bypassed or ignored
- ❌ Docker build fails or image not pushed
- ❌ Deployment succeeds but application not healthy
- ❌ Rollback not possible or untested
- ❌ No artifact versioning (always "latest")
- ❌ Caching not working (rebuilds everything every time)
- ❌ Secrets exposed in logs or pipeline config
- ❌ Production deployment with no approval gate
When NOT to Use
Do NOT use this skill when:
- Simple script deployment sufficient (use deployment-scripts instead)
- No automated testing in place yet (set up tests first)
- Single-developer project with no team (CI/CD overhead not worth it)
- Prototyping phase (defer until pre-production)
- Legacy system with no containerization (modernize first)
- No version control (Git required for CI/CD)
- Infrastructure not ready (provision cloud resources first)
- No deployment environments (need staging/production separation)
Use alternatives:
- simple-deployment-scripts - Manual deployment for small projects
- monorepo-cicd - CI/CD for monorepo structures
- serverless-cicd - Lambda/Cloud Functions deployment
- mobile-cicd - iOS/Android app deployment
Anti-Patterns (Avoid)
| Anti-Pattern | Problem | Solution |
|---|---|---|
| No test gates | Broken code reaches production | Make tests required; fail pipeline on failure |
| Slow builds | Developer friction, delayed feedback | Implement caching, parallel jobs, incremental builds |
| Hardcoded secrets | Security vulnerability | Use GitHub Secrets, environment variables |
| No rollback plan | Broken deployments unrecoverable | Test rollback in staging, automate via kubectl undo |
| Direct to production | High risk deployments | Deploy to staging first, use canary/blue-green |
| Missing health checks | Deploy broken applications | Add readiness/liveness probes, smoke tests |
| Ignoring security scans | Vulnerabilities in production | Block merges on critical/high severity findings |
| Manual artifact versioning | Inconsistent versions | Automate with git tags, semver, build metadata |
| No monitoring integration | Blind deployments | Send deployment events to monitoring (Datadog, New Relic) |
| One-size-fits-all | All environments same config | Environment-specific configs (dev/staging/prod) |
Principles
This skill embodies CODITECT core principles:
#1 Recycle → Extend → Re-Use → Create
- Reuse GitHub Actions from marketplace
- Extend workflow templates for project needs
- Build upon proven CI/CD patterns
#3 Keep It Simple
- Start with essential stages (build/test/deploy)
- Add complexity only when needed (canary after basic works)
- Clear pipeline structure easy to debug
#4 Shift Left on Security
- Security scans in CI/CD before deployment
- Dependency scanning catches CVEs early
- SBOM generation for supply chain security
#5 Eliminate Ambiguity
- Explicit stage dependencies (needs: build-and-test)
- Clear environment specifications (staging vs production)
- Versioning includes build metadata for traceability
#7 Separation of Concerns
- Quality gate separate from build stage
- Security scanning isolated from functional tests
- Deployment automation decoupled from pipeline definition
#8 No Assumptions
- Verify tool installation (kubectl, docker)
- Validate deployment health before marking success
- Test rollback mechanism in staging
#9 Evidence-Based Decisions
- Cache effectiveness measured (build time reduction)
- Test coverage tracked over time
- Deployment success rate monitored
Full Standard: CODITECT-STANDARD-AUTOMATION.md