Comprehensive Claude Code guidance system with: - 5 agents: tdd-guardian, code-reviewer, security-scanner, refactor-scan, dependency-audit - 18 skills covering languages (Python, TypeScript, Rust, Go, Java, C#), infrastructure (AWS, Azure, GCP, Terraform, Ansible, Docker/K8s, Database, CI/CD), testing (TDD, UI, Browser), and patterns (Monorepo, API Design, Observability) - 3 hooks: secret detection, auto-formatting, TDD git pre-commit - Strict TDD enforcement with 80%+ coverage requirements - Multi-model strategy: Opus for planning, Sonnet for execution (opusplan) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
15 KiB
15 KiB
name, description
| name | description |
|---|---|
| cicd-pipelines | CI/CD pipeline patterns for Jenkins, GitHub Actions, and GitLab CI. Use when setting up continuous integration or deployment pipelines. |
CI/CD Pipelines Skill
Jenkins
Declarative Pipeline
// Jenkinsfile
pipeline {
agent any
environment {
REGISTRY = 'myregistry.azurecr.io'
IMAGE_NAME = 'myapp'
COVERAGE_THRESHOLD = '80'
}
options {
timeout(time: 30, unit: 'MINUTES')
disableConcurrentBuilds()
buildDiscarder(logRotator(numToKeepStr: '10'))
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Install Dependencies') {
parallel {
stage('Python') {
when {
changeset "apps/backend/**"
}
steps {
sh 'uv sync'
}
}
stage('Node') {
when {
changeset "apps/frontend/**"
}
steps {
sh 'npm ci'
}
}
}
}
stage('Lint & Type Check') {
parallel {
stage('Python Lint') {
when {
changeset "apps/backend/**"
}
steps {
sh 'uv run ruff check apps/backend/'
sh 'uv run mypy apps/backend/'
}
}
stage('TypeScript Lint') {
when {
changeset "apps/frontend/**"
}
steps {
sh 'npm run lint --workspace=frontend'
sh 'npm run typecheck --workspace=frontend'
}
}
}
}
stage('Test') {
parallel {
stage('Backend Tests') {
when {
changeset "apps/backend/**"
}
steps {
sh """
uv run pytest apps/backend/ \
--cov=apps/backend/src \
--cov-report=xml \
--cov-fail-under=${COVERAGE_THRESHOLD} \
--junitxml=test-results/backend.xml
"""
}
post {
always {
junit 'test-results/backend.xml'
publishCoverage adapters: [coberturaAdapter('coverage.xml')]
}
}
}
stage('Frontend Tests') {
when {
changeset "apps/frontend/**"
}
steps {
sh """
npm run test --workspace=frontend -- \
--coverage \
--coverageThreshold='{"global":{"branches":${COVERAGE_THRESHOLD},"functions":${COVERAGE_THRESHOLD},"lines":${COVERAGE_THRESHOLD}}}' \
--reporter=junit \
--outputFile=test-results/frontend.xml
"""
}
post {
always {
junit 'test-results/frontend.xml'
}
}
}
}
}
stage('Security Scan') {
steps {
sh 'trivy fs --severity HIGH,CRITICAL --exit-code 1 .'
}
}
stage('Build') {
when {
anyOf {
branch 'main'
branch 'release/*'
}
}
steps {
script {
def version = sh(script: 'git describe --tags --always', returnStdout: true).trim()
sh """
docker build -t ${REGISTRY}/${IMAGE_NAME}:${version} .
docker tag ${REGISTRY}/${IMAGE_NAME}:${version} ${REGISTRY}/${IMAGE_NAME}:latest
"""
}
}
}
stage('Push') {
when {
branch 'main'
}
steps {
withCredentials([usernamePassword(
credentialsId: 'registry-credentials',
usernameVariable: 'REGISTRY_USER',
passwordVariable: 'REGISTRY_PASS'
)]) {
sh """
echo \$REGISTRY_PASS | docker login ${REGISTRY} -u \$REGISTRY_USER --password-stdin
docker push ${REGISTRY}/${IMAGE_NAME}:${version}
docker push ${REGISTRY}/${IMAGE_NAME}:latest
"""
}
}
}
stage('Deploy to Staging') {
when {
branch 'main'
}
steps {
sh 'kubectl apply -f k8s/staging/'
sh 'kubectl rollout status deployment/myapp -n staging'
}
}
stage('Deploy to Production') {
when {
branch 'release/*'
}
input {
message "Deploy to production?"
ok "Deploy"
}
steps {
sh 'kubectl apply -f k8s/production/'
sh 'kubectl rollout status deployment/myapp -n production'
}
}
}
post {
always {
cleanWs()
}
success {
slackSend(
channel: '#deployments',
color: 'good',
message: "Build ${env.BUILD_NUMBER} succeeded: ${env.BUILD_URL}"
)
}
failure {
slackSend(
channel: '#deployments',
color: 'danger',
message: "Build ${env.BUILD_NUMBER} failed: ${env.BUILD_URL}"
)
}
}
}
Shared Library
// vars/pythonPipeline.groovy
def call(Map config = [:]) {
pipeline {
agent any
stages {
stage('Test') {
steps {
sh "uv run pytest ${config.testPath ?: 'tests/'} --cov --cov-fail-under=${config.coverage ?: 80}"
}
}
stage('Lint') {
steps {
sh "uv run ruff check ${config.srcPath ?: 'src/'}"
}
}
}
}
}
// Usage in Jenkinsfile
@Library('my-shared-library') _
pythonPipeline(
testPath: 'apps/backend/tests/',
srcPath: 'apps/backend/src/',
coverage: 85
)
GitHub Actions
Complete Workflow
# .github/workflows/ci.yml
name: CI/CD
on:
push:
branches: [main, 'release/*']
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
detect-changes:
runs-on: ubuntu-latest
outputs:
backend: ${{ steps.changes.outputs.backend }}
frontend: ${{ steps.changes.outputs.frontend }}
infrastructure: ${{ steps.changes.outputs.infrastructure }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: changes
with:
filters: |
backend:
- 'apps/backend/**'
- 'packages/shared/**'
frontend:
- 'apps/frontend/**'
- 'packages/shared/**'
infrastructure:
- 'infrastructure/**'
backend-test:
needs: detect-changes
if: needs.detect-changes.outputs.backend == 'true'
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_DB: test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
- name: Install dependencies
run: uv sync
- name: Lint
run: |
uv run ruff check apps/backend/
uv run mypy apps/backend/
- name: Test
env:
DATABASE_URL: postgresql://test:test@localhost:5432/test
run: |
uv run pytest apps/backend/ \
--cov=apps/backend/src \
--cov-report=xml \
--cov-fail-under=80
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
files: coverage.xml
flags: backend
frontend-test:
needs: detect-changes
if: needs.detect-changes.outputs.frontend == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Lint & Type Check
run: |
npm run lint --workspace=frontend
npm run typecheck --workspace=frontend
- name: Test
run: npm run test --workspace=frontend -- --coverage
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
files: apps/frontend/coverage/lcov.info
flags: frontend
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
severity: 'CRITICAL,HIGH'
exit-code: '1'
- name: Run Gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
build-and-push:
needs: [backend-test, frontend-test, security-scan]
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- 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=sha
type=ref,event=branch
- name: Build and push
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
deploy-staging:
needs: build-and-push
runs-on: ubuntu-latest
environment: staging
steps:
- uses: actions/checkout@v4
- name: Deploy to staging
run: |
kubectl apply -f k8s/staging/
kubectl rollout status deployment/myapp -n staging
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- name: Deploy to production
run: |
kubectl apply -f k8s/production/
kubectl rollout status deployment/myapp -n production
Reusable Workflow
# .github/workflows/python-ci.yml
name: Python CI
on:
workflow_call:
inputs:
python-version:
required: false
type: string
default: '3.12'
working-directory:
required: true
type: string
coverage-threshold:
required: false
type: number
default: 80
jobs:
test:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ${{ inputs.working-directory }}
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v4
- run: uv sync
- run: uv run ruff check .
- run: uv run pytest --cov --cov-fail-under=${{ inputs.coverage-threshold }}
GitLab CI
# .gitlab-ci.yml
stages:
- test
- build
- deploy
variables:
REGISTRY: registry.gitlab.com
IMAGE_NAME: $CI_PROJECT_PATH
.python-base:
image: python:3.12
before_script:
- pip install uv
- uv sync
.node-base:
image: node:22
before_script:
- npm ci
test:backend:
extends: .python-base
stage: test
script:
- uv run ruff check apps/backend/
- uv run pytest apps/backend/ --cov --cov-fail-under=80
rules:
- changes:
- apps/backend/**
test:frontend:
extends: .node-base
stage: test
script:
- npm run lint --workspace=frontend
- npm run test --workspace=frontend -- --coverage
rules:
- changes:
- apps/frontend/**
build:
stage: build
image: docker:24
services:
- docker:24-dind
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA .
- docker push $REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA
rules:
- if: $CI_COMMIT_BRANCH == "main"
deploy:staging:
stage: deploy
script:
- kubectl apply -f k8s/staging/
environment:
name: staging
rules:
- if: $CI_COMMIT_BRANCH == "main"
deploy:production:
stage: deploy
script:
- kubectl apply -f k8s/production/
environment:
name: production
rules:
- if: $CI_COMMIT_BRANCH == "main"
when: manual
Best Practices
Pipeline Design Principles
- Fail Fast - Run quick checks (lint, type check) before slow ones (tests)
- Parallelize - Run independent jobs concurrently
- Cache - Cache dependencies between runs
- Change Detection - Only run what's affected
- Immutable Artifacts - Tag images with commit SHA
- Environment Parity - Same process for all environments
- Secrets Management - Never hardcode, use CI/CD secrets
Quality Gates
# Minimum checks before merge
- Lint passes
- Type check passes
- Unit tests pass
- Coverage threshold met (80%+)
- Security scan passes
- No secrets detected
Deployment Strategies
# Rolling update (default)
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
# Blue-green (via service switch)
# Deploy new version alongside old
# Switch service selector when ready
# Canary (gradual rollout)
# Route percentage of traffic to new version
# Monitor metrics before full rollout