A solid reference for setting up CI/CD pipelines that goes beyond the basics. You get practical YAML examples for multi-stage pipelines, concrete deployment strategies like blue-green and canary with actual implementation snippets, and security scanning integration. The testing pyramid breakdown and environment management patterns are genuinely useful if you're moving from "we have some tests" to "we have a real pipeline." What stands out is the coverage of metrics that matter, like lead time and change failure rate, and the infrastructure as code examples using Terraform. More of a best practices guide than a step-by-step tutorial, so you'll need to adapt the patterns to your specific platform, whether that's GitLab, GitHub Actions, or Jenkins.
npx -y skills add mindrally/skills --skill ci-cd-best-practices --agent claude-codeInstalls into .claude/skills of the current project.
You are an expert in Continuous Integration and Continuous Deployment, following industry best practices for automated pipelines, testing strategies, deployment patterns, and DevOps workflows.
A typical CI/CD pipeline includes these stages:
Build -> Test -> Security -> Deploy (Staging) -> Deploy (Production)
build:
stage: build
script:
- npm ci --prefer-offline
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 day
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
Best practices:
test:
stage: test
parallel:
matrix:
- TEST_TYPE: [unit, integration, e2e]
script:
- npm run test:${TEST_TYPE}
coverage: '/Coverage: \d+\.\d+%/'
artifacts:
reports:
junit: test-results.xml
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
Testing layers:
security:
stage: security
parallel:
matrix:
- SCAN_TYPE: [sast, dependency, secrets]
script:
- ./security-scan.sh ${SCAN_TYPE}
allow_failure: false
Security scanning types:
deploy:staging:
stage: deploy
environment:
name: staging
url: https://staging.example.com
script:
- ./deploy.sh staging
rules:
- if: $CI_COMMIT_BRANCH == "develop"
deploy:production:
stage: deploy
environment:
name: production
url: https://example.com
script:
- ./deploy.sh production
rules:
- if: $CI_COMMIT_BRANCH == "main"
when: manual
Maintain two identical environments:
deploy:blue-green:
script:
- ./deploy-to-inactive.sh
- ./run-smoke-tests.sh
- ./switch-traffic.sh
- ./cleanup-old-environment.sh
Benefits:
Gradually roll out to subset of users:
deploy:canary:
script:
- ./deploy-canary.sh --percentage=5
- ./monitor-metrics.sh --duration=30m
- ./deploy-canary.sh --percentage=25
- ./monitor-metrics.sh --duration=30m
- ./deploy-canary.sh --percentage=100
Canary stages:
Update instances incrementally:
deploy:rolling:
script:
- kubectl rollout restart deployment/app
- kubectl rollout status deployment/app --timeout=5m
Configuration:
maxUnavailable and maxSurgeDecouple deployment from release:
// Feature flag implementation
if (featureFlags.isEnabled('new-checkout')) {
return <NewCheckout />;
} else {
return <LegacyCheckout />;
}
Benefits:
Development -> Testing -> Staging -> Production
Each environment should:
variables:
# Global variables
APP_NAME: my-app
# Environment-specific
.staging:
variables:
ENV: staging
API_URL: https://api.staging.example.com
.production:
variables:
ENV: production
API_URL: https://api.example.com
Best practices:
# Terraform example
resource "aws_ecs_service" "app" {
name = var.app_name
cluster = aws_ecs_cluster.main.id
task_definition = aws_ecs_task_definition.app.arn
desired_count = var.environment == "production" ? 3 : 1
deployment_configuration {
maximum_percent = 200
minimum_healthy_percent = 100
}
}
/\
/ \ E2E Tests (Few)
/----\
/ \ Integration Tests (Some)
/--------\
/ \ Unit Tests (Many)
--------------
test:
parallel: 4
script:
- npm test -- --shard=$CI_NODE_INDEX/$CI_NODE_TOTAL
test:
retry:
max: 2
when:
- runner_system_failure
- stuck_or_timeout_failure
Strategies:
Track these metrics:
deploy:
script:
- ./deploy.sh
- ./wait-for-healthy.sh --timeout=300
- ./run-smoke-tests.sh
Implement:
notify:failure:
stage: notify
script:
- ./send-alert.sh --channel=deployments --status=failed
when: on_failure
notify:success:
stage: notify
script:
- ./send-notification.sh --channel=deployments --status=success
when: on_success
# Use CI/CD secret variables
deploy:
script:
- echo "$DEPLOY_KEY" | base64 -d > deploy_key
- chmod 600 deploy_key
- ./deploy.sh
after_script:
- rm -f deploy_key
Best practices:
# Restrict who can run production deploys
deploy:production:
rules:
- if: $CI_COMMIT_BRANCH == "main"
when: manual
allow_failure: false
environment:
name: production
deployment_tier: production
Controls:
dependency_check:
script:
- npm audit --audit-level=high
- ./check-licenses.sh
allow_failure: false
cache:
key:
files:
- package-lock.json
paths:
- node_modules/
policy: pull-push
Cache strategies:
stages:
- build
- test
- deploy
# Run tests in parallel
test:unit:
stage: test
script: npm run test:unit
test:integration:
stage: test
script: npm run test:integration
test:e2e:
stage: test
script: npm run test:e2e
build:
artifacts:
paths:
- dist/
expire_in: 1 week
when: on_success
Best practices:
deploy:
script:
- ./deploy.sh
- ./health-check.sh || ./rollback.sh
rollback:
stage: deploy
when: manual
script:
- ./get-previous-version.sh
- ./deploy.sh --version=$PREVIOUS_VERSION
Document in your repository:
Create runbooks for:
sickn33/antigravity-awesome-skills
kubesphere/kubesphere
supercent-io/skills-template