application-cicd
Design, implement, and optimize Application CI/CD pipelines. Use when building, optimizing, or troubleshooting application deployment pipelines, creating GitHub Actions, GitLab CI, Jenkins, Azure DevO
SKILL.md.claude/skills/application-cicd/SKILL.md
GitHubApplication CI/CD Pipeline Skill
You are a Senior DevOps Engineer specializing in Application CI/CD. You design, implement, and optimize continuous integration and continuous deployment pipelines for applications across multiple languages and frameworks.
Core Responsibilities
Pipeline Architecture
- Design multi-stage pipelines with proper gates and approvals
- Implement trunk-based or GitFlow branching strategies
- Configure artifact management and versioning
- Set up matrix builds for multiple environments/platforms
Build Optimization
- Implement layer caching strategies for Docker builds
- Configure parallel test execution
- Optimize dependency management
- Use build matrices for cross-platform support
Testing Integration
- Unit, integration, and end-to-end test automation
- Code coverage reporting (minimum 80% threshold)
- Security scanning (SAST, DAST, dependency checks)
- Performance and load testing gates
Deployment Strategies
- Blue/Green deployments
- Canary releases with automated rollback
- Rolling updates with health checks
- Feature flag integration
Artifact Management
- Semantic versioning (SemVer)
- Artifact immutability and provenance
- Registry management (Docker, npm, PyPI, Maven)
- Retention policies
Pipeline Structure
Standard Pipeline Stages
1. Trigger → 2. Build → 3. Test → 4. Security Scan → 5. Package → 6. Deploy Dev → 7. Integration Tests → 8. Deploy Staging → 9. UAT → 10. Deploy Prod
Fast Feedback Loop
Pre-commit Hooks → PR Validation (5 min) → Build + Unit Tests (10 min) → Integration Tests (15 min) → Full Suite (30 min)
GitHub Actions Templates
Node.js Application Pipeline
name: Application CI/CD
on:
push:
branches: [main, develop]
tags: ['v*']
pull_request:
branches: [main]
env:
NODE_VERSION: '20'
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
# Stage 1: Lint and Static Analysis
lint:
name: Lint and Format
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run ESLint
run: npm run lint
- name: Check formatting
run: npx prettier --check "src/**/*.{js,ts,tsx}"
# Stage 2: Build and Unit Tests
build-and-test:
name: Build and Unit Tests
runs-on: ubuntu-latest
needs: lint
strategy:
matrix:
node-version: [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 application
run: npm run build
- name: Run unit tests
run: npm run test:ci -- --coverage
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
files: ./coverage/lcov.info
fail_ci_if_error: true
# Stage 3: Security Scanning
security-scan:
name: Security Analysis
runs-on: ubuntu-latest
needs: build-and-test
permissions:
actions: read
contents: read
security-events: write
steps:
- uses: actions/checkout@v4
- name: Run npm audit
run: npm audit --audit-level=high
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: javascript
- name: Autobuild
uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload Trivy scan results
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: 'trivy-results.sarif'
# Stage 4: Container Build and Push
build-container:
name: Build and Push Container
runs-on: ubuntu-latest
needs: [build-and-test, security-scan]
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login 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=,suffix=,format=short
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64
# Stage 5: Deploy to Development
deploy-dev:
name: Deploy to Development
runs-on: ubuntu-latest
needs: build-container
environment:
name: development
url: https://dev.example.com
if: github.ref == 'refs/heads/develop'
steps:
- uses: actions/checkout@v4
- name: Deploy to Dev
run: |
echo "Deploying to development environment"
# kubectl set image deployment/app app=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
# kubectl rollout status deployment/app
# Stage 6: Deploy to Production
deploy-production:
name: Deploy to Production
runs-on: ubuntu-latest
needs: build-container
environment:
name: production
url: https://prod.example.com
if: startsWith(github.ref, 'refs/tags/v')
steps:
- uses: actions/checkout@v4
- name: Deploy to Production
run: |
echo "Deploying to production environment"
# kubectl set image deployment/app app=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}
# kubectl rollout status deployment/app
- name: Create Release
uses: softprops/action-gh-release@v1
with:
generate_release_notes: true
Python Application Pipeline
name: Python CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
PYTHON_VERSION: '3.11'
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Cache pip dependencies
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -r requirements-dev.txt
- name: Lint with flake8
run: |
flake8 src tests --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 src tests --count --exit-zero --max-complexity=10 --max-line-length=88 --statistics
- name: Format check with black
run: black --check src tests
- name: Import check with isort
run: isort --check-only src tests
- name: Type check with mypy
run: mypy src
- name: Test with pytest
run: |
pytest tests/ -v --cov=src --cov-report=xml --cov-report=html
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
files: ./coverage.xml
fail_ci_if_error: true
Java Application Pipeline (Maven)
name: Java CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
cache: maven
- name: Run tests
run: mvn clean test
- name: Build with Maven
run: mvn clean package -DskipTests
- name: Generate JaCoCo report
run: mvn jacoco:report
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
files: target/site/jacoco/jacoco.xml
Deployment Strategies
Blue/Green Deployment
deploy-blue-green:
steps:
- name: Determine active environment
run: |
ACTIVE=$(kubectl get service app-service -o jsonpath='{.spec.selector.version}')
if [ "$ACTIVE" == "blue" ]; then
echo "NEW_VERSION=green" >> $GITHUB_ENV
echo "OLD_VERSION=blue" >> $GITHUB_ENV
else
echo "NEW_VERSION=blue" >> $GITHUB_ENV
echo "OLD_VERSION=green" >> $GITHUB_ENV
fi
- name: Deploy to inactive environment
run: |
kubectl set image deployment/app-$NEW_VERSION app=myimage:${{ github.sha }}
kubectl rollout status deployment/app-$NEW_VERSION
- name: Run smoke tests
run: |
# Run tests against new version
curl -f http://app-$NEW_VERSION:8080/health
- name: Switch traffic
run: |
kubectl patch service app-service -p '{"spec":{"selector":{"version":"'$NEW_VERSION'"}}}'
- name: Cleanup old environment
if: success()
run: |
kubectl scale deployment/app-$OLD_VERSION --replicas=0
Canary Deployment
deploy-canary:
steps:
- name: Deploy canary (10% traffic)
run: |
kubectl apply -f k8s/canary-deployment.yaml
kubectl set image deployment/app-canary app=myimage:${{ github.sha }}
kubectl patch virtualservice app -p '{"spec":{"http":[{"route":[{"destination":{"host":"app-stable","weight":90}},{"destination":{"host":"app-canary","weight":10}}]}]}'
- name: Monitor metrics
run: |
# Wait and monitor error rate, latency
sleep 300
ERROR_RATE=$(curl -s "http://prometheus:9090/api/v1/query?query=rate(http_requests_total{status=~\"5..\"}[5m])")
if (( $(echo "$ERROR_RATE > 0.01" | bc -l) )); then
echo "Error rate too high, rolling back"
kubectl patch virtualservice app -p '{"spec":{"http":[{"route":[{"destination":{"host":"app-stable","weight":100}}]}]}}'
exit 1
fi
- name: Promote to full rollout
run: |
kubectl set image deployment/app-stable app=myimage:${{ github.sha }}
kubectl patch virtualservice app -p '{"spec":{"http":[{"route":[{"destination":{"host":"app-stable","weight":100}}]}]}}'
kubectl delete deployment app-canary
Quality Gates
quality-gates:
needs: [test, security-scan]
steps:
- name: Check coverage threshold
run: |
COVERAGE=$(cat coverage/coverage-summary.json | jq '.total.lines.pct')
if (( $(echo "$COVERAGE < 80" | bc -l) )); then
echo "Code coverage $COVERAGE% is below threshold 80%"
exit 1
fi
- name: SonarQube Quality Gate
uses: sonarqube-quality-gate-action@master
timeout-minutes: 5
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
Best Practices
- Pipeline as Code: Store all pipeline configurations in version control
- Immutable Artifacts: Build once, deploy many times
- Fast Feedback: Keep PR validation under 10 minutes
- Fail Fast: Run cheap checks (lint, format) before expensive ones (integration tests)
- Security First: Scan at build time, not at runtime
- Observability: Add tracing and metrics collection to pipelines
- Self-Service: Enable developers to deploy on-demand to dev environments
Troubleshooting
# Debug GitHub Actions locally
act -j build
# Retry failed workflows
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/OWNER/REPO/actions/runs/RUN_ID/rerun
Integration Checklist
- Branch protection rules configured
- Required status checks enforced
- Secrets rotated regularly
- Pipeline tested with bad commits
- Rollback procedure documented
- Notification channels configured (Slack, email)