devops-cicd — Claude Code skill: CI/CD and infrastructure
A skill that hands your agent working templates for pipelines, infrastructure as code and deployment strategies. Useful when you need a real workflow file, not vague advice.
npx skills add miles990/claude-software-skills --skill devops-cicd -a claude-codeWhat devops-cicd does
The skill activates on devops, CI/CD, pipeline, GitHub Actions, deployment and Docker, plus secondary terms like kubernetes, terraform, ansible, helm and argocd. Context markers such as frontend, design and ux lower its priority, so it stays out of the way on UI work.
What you get: a pipeline broken into commit, build, test, staging and production stages; a GitHub Actions workflow with lint, type check, tests and artifact upload; matrix builds across several operating systems and Node versions. Deployment strategies come next — blue-green, canary through Argo Rollouts with traffic weights and pauses, and a rolling update with maxSurge and maxUnavailable. For infrastructure there is Terraform with an S3 backend, variables, resources and modules.
The examples assume Node.js, npm, Kubernetes and AWS. Swap in your own runtime or cloud and the templates need rewriting rather than copying. The skill file itself sits at ~/.claude/skills/devops-cicd/SKILL.md.
What it helps with
- write a GitHub Actions workflow with lint, types and tests
- split a pipeline into stages from commit to release
- define a VPC and instances in Terraform with modules
- pick between blue-green, canary and rolling updates
- set up a matrix build across OS versions and Node releases
Example prompts for the agent
- Write a GitHub Actions workflow with lint, type check, tests with coverage, build and artifact upload
- Describe a Kubernetes canary deploy with Argo Rollouts at 10, 30, 50 and 100 percent traffic
- Create a Terraform config with an S3 backend, an environment variable and a VPC module
How to install devops-cicd
1Skills CLI (Vercel)
npx skills add miles990/claude-software-skills --skill devops-cicd -a claude-code2Manually: put the files in place
~/.claude/skills/devops-cicd/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/devops-cicd/
1Skills CLI (Vercel)
npx skills add miles990/claude-software-skills --skill devops-cicd -a codex2Manually: put the files in place
.agents/skills/devops-cicd/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add miles990/claude-software-skills --skill devops-cicd -a cursor2Manually: put the files in place
.cursor/skills/devops-cicd/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install miles990/claude-software-skills devops-cicd2Manually: put the files in place
.github/skills/devops-cicd/SKILL.md1Skills CLI (Vercel)
npx skills add miles990/claude-software-skills --skill devops-cicd -a gemini-cli2Platform CLI
gemini skills install https://github.com/miles990/claude-software-skills --path software-engineering/devops-cicdManually: put the files in place
.devin/skills/devops-cicd/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add miles990/claude-software-skills --skill devops-cicd -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about devops-cicd
How do I install devops-cicd in Claude?
Run npx skills add miles990/claude-software-skills --skill devops-cicd -a claude-code. The skill file then lands at ~/.claude/skills/devops-cicd/SKILL.md.
What does the devops-cicd skill do?
It gives the agent templates for pipelines, deployment strategies and infrastructure as code. It triggers on keywords around CI/CD, Docker, Kubernetes and Terraform.
Which tools does devops-cicd cover?
The examples use GitHub Actions, Docker, Kubernetes, Argo Rollouts, Terraform and AWS. The pipeline is built around Node.js and npm, so another stack means editing the templates.
Source text
SKILL.md · MIT
---
name: devops-cicd
description: CI/CD pipelines, infrastructure as code, and deployment strategies
domain: software-engineering
version: 1.0.0
tags: [ci, cd, github-actions, kubernetes, docker, terraform, gitops]
triggers:
keywords:
primary: [devops, ci, cd, cicd, pipeline, github actions, deployment, docker]
secondary: [kubernetes, k8s, terraform, ansible, jenkins, gitlab ci, argocd, helm]
context_boost: [automation, infrastructure, deploy, release]
context_penalty: [frontend, design, ux]
priority: high
---
# DevOps & CI/CD
## Overview
Practices for automating build, test, and deployment pipelines.
---
## CI/CD Pipeline
### Pipeline Stages
```
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ Commit │ → │ Build │ → │ Test │ → │ Deploy │ → │ Release │
│ │ │ │ │ │ │ Staging │ │ Prod │
└──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘
│ │ │ │ │
│ ┌────┴────┐ ┌────┴────┐ │ │
│ │ Compile │ │ Unit │ │ │
│ │ Lint │ │ Integ │ │ │
│ │ Type │ │ E2E │ │ │
│ └─────────┘ └─────────┘ │ │
│ │ │
Trigger Manual? Approval?
```
### GitHub Actions
```yaml
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Lint
run: npm run lint
- name: Type check
run: npm run type-check
- name: Test
run: npm run test -- --coverage
- name: Upload coverage
uses: codecov/codecov-action@v3
- name: Build
run: npm run build
- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: build
path: dist/
deploy-staging:
needs: build
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: staging
steps:
- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: build
path: dist/
- name: Deploy to staging
run: |
# Deploy script here
echo "Deploying to staging..."
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment:
name: production
url: https://myapp.com
steps:
- name: Deploy to production
run: |
echo "Deploying to production..."
```
### Matrix Builds
```yaml
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node: [18, 20, 22]
exclude:
- os: windows-latest
node: 18
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- run: npm ci
- run: npm test
```
---
## Deployment Strategies
### Blue-Green Deployment
```
Before:
┌─────────────────────────────────────────┐
│ Load Balancer │
└─────────────────┬───────────────────────┘
│
┌───────┴───────┐
↓ ↓
┌───────────┐ ┌───────────┐
│ Blue │ │ Green │
│ (v1.0) │ │ (idle) │
│ ACTIVE │ │ │
└───────────┘ └───────────┘
Deploy v1.1 to Green:
┌───────────┐ ┌───────────┐
│ Blue │ │ Green │
│ (v1.0) │ │ (v1.1) │
│ ACTIVE │ │ testing │
└───────────┘ └───────────┘
Switch traffic:
┌───────────────┐
↓ ↓
┌───────────┐ ┌───────────┐
│ Blue │ │ Green │
│ (v1.0) │ │ (v1.1) │
│ standby │ │ ACTIVE │
└───────────┘ └───────────┘
```
### Canary Deployment
```yaml
# Kubernetes canary with Argo Rollouts
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: my-app
spec:
replicas: 10
strategy:
canary:
steps:
- setWeight: 10 # 10% traffic to new version
- pause: { duration: 5m }
- setWeight: 30
- pause: { duration: 5m }
- setWeight: 50
- pause: { duration: 10m }
- setWeight: 100
analysis:
templates:
- templateName: success-rate
startingStep: 2 # Start analysis at 30%
args:
- name: service-name
value: my-app
```
### Rolling Update
```yaml
# Kubernetes rolling update
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # Can exceed replicas by 1
maxUnavailable: 0 # All must be available during update
template:
spec:
containers:
- name: app
image: my-app:v1.1
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
```
---
## Infrastructure as Code
### Terraform
```hcl
# main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "us-east-1"
}
}
# Variables
variable "environment" {
type = string
default = "production"
}
variable "instance_count" {
type = number
default = 2
}
# Resources
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "main-vpc"
Environment = var.environment
}
}
resource "aws_instance" "web" {
count = var.instance_count
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
vpc_security_group_ids = [aws_security_group.web.id]
tags = {
Name = "web-${count.index}"
}
}
# Outputs
output "instance_ips" {
value = aws_instance.web[*].public_ip
}
```
### Terraform Modules
```hcl
# modules/vpc/main.tf
variable "cidr_block" {
type = string
}
variable "environment" {
type = string
}
resource "aws_vpc" "this" {
cidr_block = var.cidr_block
tags = {
Environment = var.environment
}
}
output "vpc_id" {
value = aws_vpc.this.id
}
# Using the module
module "vpc" {
source = "./modules/vpc"
cidr_block = "10.0.0.0/16"
environment = "production"
}
resource "aws_subnet" "main" {
vpc_id = module.vpc.vpc_id
# ...
}
```
---
## Docker
### Dockerfile Best Practices
```dockerfile
# Use specific version tags
FROM node:20-alpine AS builder
# Set working directory
WORKDIR /app
# Copy dependency files first (layer caching)
COPY package*.json ./
# Install dependencies
RUN npm ci --only=production
# Copy source code
COPY . .
# Build application
RUN npm run build
# Production stage - smaller final image
FROM node:20-alpine AS production
WORKDIR /app
# Create non-root user
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
# Copy from builder
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
# Use non-root user
USER nodejs
# Expose port
EXPOSE 3000
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s \
CMD wget --quiet --tries=1 --spider http://localhost:3000/health || exit 1
# Run application
CMD ["node", "dist/index.js"]
```
### Docker Compose
```yaml
# docker-compose.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://postgres:password@db:5432/myapp
- REDIS_URL=redis://cache:6379
depends_on:
db:
condition: service_healthy
cache:
condition: service_started
db:
image: postgres:15-alpine
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=password
- POSTGRES_DB=myapp
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
cache:
image: redis:7-alpine
volumes:
- redis_data:/data
volumes:
postgres_data:
redis_data:
```
---
## Kubernetes
### Basic Deployment
```yaml
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-app:v1.0.0
ports:
- containerPort: 3000
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 3000
initialDelaySeconds: 3
periodSeconds: 10
readinessProbe:
httpGet:
path: /health/ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: app-secrets
key: database-url
---
apiVersion: v1
kind: Service
metadata:
name: my-app
spec:
selector:
app: my-app
ports:
- port: 80
targetPort: 3000
type: ClusterIP
```
### ConfigMaps and Secrets
```yaml
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
LOG_LEVEL: "info"
MAX_CONNECTIONS: "100"
---
# secret.yaml (base64 encoded)
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
type: Opaque
data:
database-url: cG9zdGdyZXM6Ly91c2VyOnBhc3NAaG9zdDo1NDMyL2Ri
```
---
## GitOps
### ArgoCD Application
```yaml
# application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/org/k8s-manifests.git
targetRevision: HEAD
path: apps/my-app/production
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
```
---
## Feature Flags
```typescript
// Using LaunchDarkly / Unleash pattern
interface FeatureFlags {
newCheckoutFlow: boolean;
betaFeatures: boolean;
maxUploadSize: number;
}
class FeatureFlagService {
constructor(private client: FeatureFlagClient) {}
async isEnabled(flag: keyof FeatureFlags, user?: User): Promise<boolean> {
return this.client.getBooleanValue(flag, false, {
userId: user?.id,
email: user?.email,
groups: user?.groups
});
}
}
// Usage
if (await featureFlags.isEnabled('newCheckoutFlow', user)) {
return <NewCheckoutFlow />;
} else {
return <LegacyCheckout />;
}
```
---
## Related Skills
- [[testing-strategies]] - CI test integration
- [[reliability-engineering]] - Deployment reliability
- [[monitoring-observability]] - Deployment monitoring
© miles990 · MIT · miles990/claude-software-skills