devops-infra-scaffold
Generate CI/CD workflows, Dockerfiles, and deployment configs from tech.md — you can't ship what you can't deploy.
Context Files
$JAAN_CONTEXT_DIR/tech.md- Tech stack context (CRITICAL -- determines framework, services, deployment target)- Uses sections:
#current-stack,#frameworks,#constraints,#versioning
- Uses sections:
$JAAN_CONTEXT_DIR/config.md- Project configuration$JAAN_TEMPLATES_DIR/jaan-to-devops-infra-scaffold.template.md- Output template$JAAN_LEARN_DIR/jaan-to-devops-infra-scaffold.learn.md- Past lessons (loaded in Pre-Execution)${CLAUDE_PLUGIN_ROOT}/docs/extending/language-protocol.md- Language resolution protocol${CLAUDE_PLUGIN_ROOT}/docs/research/74-dev-cicd-infra-scaffold-generation.md- Research reference
Input
Upstream Artifacts: $ARGUMENTS
Accepts file paths or descriptions:
- tech.md -- Path to tech stack definition (from
$JAAN_CONTEXT_DIR/tech.md) - backend-scaffold output -- Path to backend scaffold output (from
/jaan-to:backend-scaffold) - frontend-scaffold output -- Path to frontend scaffold output (from
/jaan-to:frontend-scaffold) - detect-dev output -- Path to detect-dev output (optional, from
/jaan-to:detect-dev) - Empty -- Interactive wizard prompting for tech stack, CI/CD platform, and deployment target
Pre-Execution Protocol
MANDATORY — Read and execute ALL steps in: ${CLAUDE_PLUGIN_ROOT}/docs/extending/pre-execution-protocol.md
Skill name: devops-infra-scaffold
Execute: Step 0 (Init Guard) → A (Load Lessons) → B (Resolve Template) → C (Offer Template Seeding)
Also read context files if available:
$JAAN_CONTEXT_DIR/tech.md-- Know the tech stack for framework-specific infrastructure generation$JAAN_CONTEXT_DIR/config.md-- Project configuration
Language Settings
Read and apply language protocol: ${CLAUDE_PLUGIN_ROOT}/docs/extending/language-protocol.md
Override field for this skill: language_devops-infra-scaffold
Language exception: Generated code output (Dockerfiles, YAML workflows, shell scripts, .env files, deployment configs) is NOT affected by this setting and remains in English/code.
PHASE 1: Analysis (Read-Only)
Thinking Mode
ultrathink
Use extended reasoning for:
- Analyzing tech stack to determine optimal CI/CD pipeline stages
- Mapping framework + database + deployment target to infrastructure patterns
- Planning multi-stage Docker build strategy from detected stack
- Identifying environment variable hierarchy and secret management needs
- Evaluating existing CI/CD setup from detect-dev output (if available)
Step 1: Parse Tech Stack & Upstream Artifacts
Read and parse all available inputs:
-
tech.md -- Extract from
#current-stack:- Languages and frameworks (Node.js/Next.js, PHP/Laravel, Go, etc.)
- Databases (PostgreSQL, MySQL, Redis, etc.)
- Package manager (pnpm, npm, yarn, composer, go mod)
- Monorepo tool (Turborepo, Nx, none)
-
backend-scaffold output -- Extract:
- Entry points and build commands
- Dependencies and ORM
- Port configuration
- Environment variables referenced
-
frontend-scaffold output -- Extract:
- Framework and build config (Next.js standalone, Vite, etc.)
- Static vs SSR rendering
- Build output directory
- Environment variables (public + server)
-
detect-dev output (optional) -- Extract:
- Existing CI/CD workflows
- Current Dockerfiles
- Existing deployment configs
- Identified gaps and recommendations
Present input summary:
INPUT SUMMARY
-------------
Tech Stack: {framework} + {database} + {cache}
Package Manager: {package_manager}
Monorepo: {monorepo_tool or "no"}
Backend Entry: {entry_point}
Frontend Build: {build_tool / output_mode}
Existing CI/CD: {found / none}
Sources Found: {list}
Sources Missing: {list with fallback suggestions}
Step 2: Clarify Infrastructure Decisions
AskUserQuestion for items not derivable from inputs:
- CI/CD Platform: GitHub Actions (default) / GitLab CI / other
- Deployment Target: Vercel (frontend) + Railway (backend) / Fly.io / AWS ECS / Docker Compose only
- Container Registry: GitHub Container Registry (ghcr.io, default) / Docker Hub / AWS ECR / none
- Environment Strategy: How many environments? (dev / staging / production)
- Database Migrations: Which tool? (Prisma / Drizzle / Knex / golang-migrate / Laravel migrations)
- Security Scanning: Include Trivy container scanning? (recommended: yes)
Step 3: Plan Infrastructure Structure
Based on tech stack + decisions, plan the complete infrastructure scaffold:
INFRASTRUCTURE PLAN
===================
CI/CD PLATFORM: {platform}
DEPLOYMENT: {target}
REGISTRY: {registry}
ENVIRONMENTS: {list}
OUTPUT STRUCTURE
----------------
{id}-{slug}/
+-- {id}-{slug}.md # Infrastructure guide
+-- ci/
| +-- ci.yml # CI workflow (lint, type-check, test, build)
| +-- cd.yml # CD workflow (deploy to environments)
| +-- health-check.yml # Health monitoring (cron, 15-min interval)
| +-- secret-rotation-reminder.yml # Secret rotation reminder (quarterly)
+-- docker/
| +-- Dockerfile.backend # Multi-stage backend build
| +-- Dockerfile.frontend # Multi-stage frontend build
| +-- docker-compose.yml # Full-stack dev environment
| +-- docker-compose.prod.yml # Production overrides
| +-- .dockerignore # Build context exclusions
+-- config/
| +-- .env.example # All variables with safe defaults
| +-- .env.test # Test environment variables
| +-- .env.production.example # Production template (no secrets)
| +-- next.config.standalone.ts # Next.js standalone config (if Next.js detected)
+-- deploy/
| +-- {platform}.yml # Platform-specific config
| +-- migration.sh # Database migration script
+-- {id}-{slug}-readme.md # Setup + deployment instructions
PIPELINE STAGES
---------------
CI: {stage_list}
CD: {stage_list}
Docker Stages: {stage_list}
Services: {service_list}
Report any conflicts or missing information.
HARD STOP -- Review Infrastructure Plan
Use AskUserQuestion:
- Question: "Proceed with generating the infrastructure scaffold?"
- Header: "Generate"
- Options:
- "Yes" -- Generate all infrastructure files
- "No" -- Cancel
- "Edit" -- Let me revise the deployment target or CI/CD strategy first
Do NOT proceed to Phase 2 without explicit approval.
PHASE 2: Generation (Write Phase)
Phase 2 Output -- Folder with subfolders
All files in $JAAN_OUTPUTS_DIR/devops/infra-scaffold/{id}-{slug}/:
{id}-{slug}/
+-- {id}-{slug}.md # Main doc (infrastructure guide)
+-- ci/
| +-- ci.yml # GitHub Actions CI workflow
| +-- cd.yml # GitHub Actions CD workflow
| +-- health-check.yml # Health monitoring (cron, 15-min interval)
| +-- secret-rotation-reminder.yml # Secret rotation reminder (quarterly)
+-- docker/
| +-- Dockerfile.backend # Multi-stage backend Dockerfile
| +-- Dockerfile.frontend # Multi-stage frontend Dockerfile
| +-- docker-compose.yml # Development docker-compose
| +-- docker-compose.prod.yml # Production overrides (optional)
| +-- .dockerignore # Build context exclusions
+-- config/
| +-- .env.example # All env vars with safe defaults
| +-- .env.test # Test environment config
| +-- .env.production.example # Production template (no secrets)
| +-- next.config.standalone.ts # Next.js standalone config (if Next.js detected)
+-- deploy/
| +-- {platform}.yml # Deployment platform config
| +-- migration.sh # Database migration script
+-- {id}-{slug}-readme.md # Setup + deployment instructions
Step 5: Generate CI Workflow (ci.yml)
Generate GitHub Actions CI workflow with these stages:
- Detect Changes -- Use
dorny/paths-filter@v3for monorepo path filtering - Lint -- ESLint/Biome (Node.js), PHP-CS-Fixer (PHP), golangci-lint (Go)
- Type Check --
tsc --noEmit(TypeScript), PHPStan (PHP),go vet(Go) - Test -- With service containers (PostgreSQL, Redis) and healthchecks
- Build -- Framework-specific build with caching
- Security Scan -- Trivy filesystem scan +
pnpm audit/npm audit
Caching strategy:
- Package manager cache via
actions/setup-node@v4(or equivalent) - Build output cache via
actions/cache@v4(Next.js.next/cache, TypeScripttsbuildinfo) - Docker layer cache via
docker/build-push-action@v5withcache-from: type=gha
Key patterns from research:
fail-fast: falsefor matrix builds- Reusable workflow structure for DRY CI
retention-days: 1for ephemeral build artifacts- Pin actions by SHA for supply chain security
pnpm packageManager Conflict Prevention
When tech.md #current-stack indicates pnpm as package manager, check the project's package.json for a packageManager field:
- If
packageManagerfield exists (e.g.,"packageManager": "pnpm@9.x.x"): Usepnpm/action-setup@v4without theversionparameter — the action reads version frompackage.jsonautomatically. ExplicitversioncausesERR_PNPM_BAD_PM_VERSION. - If
packageManagerfield is absent: Usepnpm/action-setup@v4with explicitversionparameter.
Applies to both ci.yml and cd.yml.
Step 6: Generate CD Workflow (cd.yml)
Generate deployment workflow triggered on:
- Push to
main-- Deploy to production - Push to
develop-- Deploy to staging (if configured) - PR -- Deploy preview (if platform supports it)
Stages:
- Build Docker Images -- Multi-stage build, push to registry
- Run Migrations -- Separate job, before deployment
- Deploy -- Platform-specific (Vercel CLI / Railway CLI / Fly deploy / ECS update)
- Smoke Test -- Health check on deployed URL
- Notify -- Success/failure notification (optional)
Environment protection:
- Use GitHub Environments with required reviewers for production
- Use OIDC federation for cloud credentials (no stored secrets)
- Separate secrets per environment
Step 6a: Generate Optional Quality Pipeline Stages
Generate these stages ONLY if relevant config/spec is detected in the project. Each stage checks tool availability using npx --no-install (npm tools) or direct --version (binary tools). Never use bare npx (auto-installs). Never use which.
6a.1 Spectral Lint Stage (if OpenAPI spec detected)
Glob for *.yaml/*.json matching OpenAPI patterns (openapi:, swagger:). If found:
- name: API Spec Lint (Spectral)
run: npx --no-install @stoplight/spectral-cli lint api.yaml --ruleset .spectral.yaml
- Trigger: on every commit (CI workflow)
- Ruleset: built-in + OWASP if
.spectral.yamlexists
6a.2 Breaking Changes Detection Stage (if baseline spec exists)
If project has a baseline OpenAPI spec (e.g., api.yaml tracked in git):
- name: API Breaking Changes (oasdiff)
uses: oasdiff/oasdiff-action@{pinned-sha}
with:
base: api.yaml
revision: api.yaml
fail-on: ERR
- oasdiff is a Go binary, NOT npm. CI uses
oasdiff/oasdiff-actionpinned to immutable commit SHA (never@latest). - Local:
oasdiff breaking --fail-on ERR base.yaml head.yaml - Trigger: on PRs only
6a.3 Mutation Testing Stage (if mutation tool config detected)
Glob for mutation configs: stryker.config.*, infection.json5, .mutmut-cache. If found:
# PR: incremental (changed files only)
- name: Mutation Testing (Incremental)
if: github.event_name == 'pull_request'
run: npx stryker run --incremental
# Nightly: full run
- name: Mutation Testing (Full)
if: github.event_name == 'schedule'
run: npx stryker run
- Adapt command per stack (StrykerJS / Infection / go-mutesting / mutmut)
- PR runs: incremental, changed files only
- Nightly runs: full project scope
6a.4 API Fuzz Testing Stage (if OpenAPI spec + running API)
If OpenAPI spec detected AND deployment target configured:
- name: API Fuzz Testing (Schemathesis)
run: schemathesis run --url ${{ vars.API_URL }} api.yaml --stateful=links
- Trigger: nightly/on-demand only (resource-intensive)
- schemathesis is a Python pip package, NOT npm
6a.5 Preflight Availability Gate
Each stage above MUST include a preflight check before execution:
npx --no-install @stoplight/spectral-cli --versionfor Spectraloasdiff --versionfor oasdiff (binary, not npm)npx --no-install stryker --versionfor StrykerJS (adapt per stack)schemathesis --versionfor Schemathesis
If tool unavailable: skip stage with explicit comment in generated workflow, never silently omit.
Step 7: Generate Health Check Workflow (health-check.yml) — GitHub Actions Only
Platform conditional: Skip this step when CI platform is GitLab CI.
Generate a scheduled health monitoring workflow:
- Triggers: Cron every 15 min (
*/15 * * * *) +workflow_dispatchfor manual testing - Endpoint checks:
curlwith 30s timeout against configurable endpoints - Endpoint URLs: Stored as repository variables (
vars.API_URL,vars.WEB_URL) — not secrets - On failure:
actions/github-script(pinned by SHA) creates issue withincidentlabel - Deduplication: Search open issues with
incidentlabel before creating — skip if duplicate exists - On recovery: Auto-close open incident issue with resolution comment and timestamp
- Stack-agnostic: Works for any tech stack with HTTP endpoints (Node.js, PHP, Go, etc.)
Step 8: Generate Secret Rotation Reminder (secret-rotation-reminder.yml) — GitHub Actions Only
Platform conditional: Skip this step when CI platform is GitLab CI.
Generate a quarterly secret rotation reminder workflow:
- Trigger: Quarterly cron
0 9 1 1,4,7,10 *(Jan/Apr/Jul/Oct, 9 AM UTC) - Action:
actions/github-script(pinned by SHA) creates issue withsecurity+maintenancelabels - Checklist body: Generated from project's
.env.example/.env.production.example:- Rotate (credentials): Variables containing TOKEN, SECRET, KEY, PASSWORD, or URL-with-credentials
- Static (no rotation needed): Variables containing ID, NAME, REGION, ENV, PORT
- Stack-agnostic: Classification heuristic works for any project's environment variables
Step 9: Generate Dockerfiles
Reference: See
${CLAUDE_PLUGIN_ROOT}/docs/extending/devops-infra-scaffold-reference.mdsection "Dockerfile Generation Patterns" for per-stack Dockerfile patterns (backend, frontend, .dockerignore).
Next.js Standalone Output Consistency
When tech.md #current-stack indicates Next.js and generating Dockerfile.frontend with standalone COPY stage:
- Check if project's
next.config.ts(or.js/.mjs) already hasoutput: 'standalone' - If missing: generate
config/next.config.standalone.tsreference snippet showing the required config - Add README step: "Verify
output: 'standalone'innext.config.ts— required for Docker multi-stage build"
Step 10: Generate docker-compose.yml
Full-stack development environment with:
Services (based on tech.md):
- Backend app (build from Dockerfile.backend, target: development)
- Frontend app (build from Dockerfile.frontend, target: development)
- PostgreSQL (if detected) -- with healthcheck (
pg_isready) - MySQL (if detected) -- with healthcheck (
mysqladmin ping) - Redis (if detected) -- with healthcheck (
redis-cli ping) - Additional services from tech.md
Patterns from research:
condition: service_healthyfor alldepends_on- Named volumes for database persistence
- Bind mounts for hot-reload (source code only)
- Anonymous volumes to protect
node_modules - Network isolation (frontend / backend networks)
- Profiles for selective startup (
--profile backend,--profile full) - Environment variables from
.envfile
docker-compose.prod.yml (optional overlay):
- Production-optimized settings
- No bind mounts
- Resource limits
- Restart policies
Step 11: Generate Environment Config Files
Reference: See
${CLAUDE_PLUGIN_ROOT}/docs/extending/devops-infra-scaffold-reference.mdsection "Environment Config File Templates" for.env.example,.env.test, and.env.production.exampletemplates.
Generate three env config files based on the templates in the reference, customized to the detected tech stack and services from tech.md.
Step 12: Generate Deployment Config
Based on selected deployment target:
Reference: See
${CLAUDE_PLUGIN_ROOT}/docs/extending/devops-infra-scaffold-reference.mdsection "Deployment Platform Configurations" for Vercel, Railway, Fly.io, AWS ECS configs and migration.sh.
Step 13: Quality Check
Reference: See
${CLAUDE_PLUGIN_ROOT}/docs/extending/devops-infra-scaffold-reference.mdsection "Quality Checklist" for the full validation checklist.
Validate generated output against the quality checklist and output structure checklist in the reference. If any check fails, fix before preview.
Step 14: Preview & Approval
Present generated output summary showing:
- File count and structure
- CI stages and estimated pipeline time
- Docker image target sizes
- Environment variable count
- Deployment target summary
Use AskUserQuestion:
- Question: "Write infrastructure scaffold files to output?"
- Header: "Write Files"
- Options:
- "Yes" -- Write the files
- "No" -- Cancel
- "Refine" -- Make adjustments first
Step 15: Generate ID and Folder Structure
source "${CLAUDE_PLUGIN_ROOT}/scripts/lib/id-generator.sh"
SUBDOMAIN_DIR="$JAAN_OUTPUTS_DIR/devops/infra-scaffold"
mkdir -p "$SUBDOMAIN_DIR"
NEXT_ID=$(generate_next_id "$SUBDOMAIN_DIR")
slug="{project-name-slug}"
OUTPUT_FOLDER="${SUBDOMAIN_DIR}/${NEXT_ID}-${slug}"
Preview output configuration:
Output Configuration
- ID: {NEXT_ID}
- Folder:
$JAAN_OUTPUTS_DIR/devops/infra-scaffold/{NEXT_ID}-{slug}/- Main file:
{NEXT_ID}-{slug}.md
Step 16: Write Output
- Create output folder and subfolders:
mkdir -p "$OUTPUT_FOLDER"
mkdir -p "$OUTPUT_FOLDER/ci"
mkdir -p "$OUTPUT_FOLDER/docker"
mkdir -p "$OUTPUT_FOLDER/config"
mkdir -p "$OUTPUT_FOLDER/deploy"
-
Write all files to respective subfolders:
{id}-{slug}.md-- Main infrastructure guide (from template)ci/ci.yml-- CI workflowci/cd.yml-- CD workflowci/health-check.yml-- Health monitoring workflow (GitHub Actions only)ci/secret-rotation-reminder.yml-- Secret rotation reminder (GitHub Actions only)docker/Dockerfile.backend-- Backend Dockerfiledocker/Dockerfile.frontend-- Frontend Dockerfiledocker/docker-compose.yml-- Dev docker-composedocker/docker-compose.prod.yml-- Production overrides (if applicable)docker/.dockerignore-- Build context exclusionsconfig/.env.example-- All env varsconfig/.env.test-- Test env varsconfig/.env.production.example-- Production templateconfig/next.config.standalone.ts-- Next.js standalone config (if Next.js detected)deploy/{platform}.yml-- Deployment configdeploy/migration.sh-- Migration script{id}-{slug}-readme.md-- Setup + deployment instructions
-
Update subdomain index:
source "${CLAUDE_PLUGIN_ROOT}/scripts/lib/index-updater.sh"
add_to_index \
"$SUBDOMAIN_DIR/README.md" \
"$NEXT_ID" \
"${NEXT_ID}-${slug}" \
"{Project Title} Infrastructure" \
"{Executive summary -- 1-2 sentences}"
- Confirm completion:
Scaffold written to:
$JAAN_OUTPUTS_DIR/devops/infra-scaffold/{NEXT_ID}-{slug}/Index updated:$JAAN_OUTPUTS_DIR/devops/infra-scaffold/README.md
Step 17: Suggest Next Actions
Infrastructure scaffold generated successfully!
Next Steps:
- Copy CI/CD workflows to
.github/workflows/- Copy Dockerfiles and docker-compose to project root
- Copy
.env.exampleto project root and create.envfrom it- Copy deployment config to project root
- Run
docker compose upto verify local development environment- Push a branch to test CI workflow
- Configure endpoint repository variables (
API_URL,WEB_URL) for health monitoring workflow- Verify
output: 'standalone'innext.config.ts(if using Next.js Docker build)- Run
/jaan-to:sec-audit-remediateto audit security of generated configs- Run
/jaan-to:learn-add devops-infra-scaffold "{feedback}"to capture lessons
Step 18: Capture Feedback
Use AskUserQuestion:
- Question: "How did the infrastructure scaffold turn out?"
- Header: "Feedback"
- Options:
- "Perfect!" -- Done
- "Needs fixes" -- What should I improve?
- "Learn from this" -- Capture a lesson for future runs
If "Learn from this": Run /jaan-to:learn-add devops-infra-scaffold "{feedback}"
Multi-Stack Support (Research-Informed)
Reference: See
${CLAUDE_PLUGIN_ROOT}/docs/extending/devops-infra-scaffold-reference.mdsection "Multi-Stack Infrastructure Patterns" for detection table and per-stack key patterns (Node.js, PHP/Laravel, Go).
Security Best Practices (Applied to All Generated Files)
Reference: See
${CLAUDE_PLUGIN_ROOT}/docs/extending/devops-infra-scaffold-reference.mdsection "Security Best Practices" for full security checklist applied to all generated files.
DAG Position
tech.md + backend-scaffold + frontend-scaffold + detect-dev (optional)
|
v
devops-infra-scaffold
Skill Alignment
- Two-phase workflow with HARD STOP for human approval
- Multi-platform support (GitHub Actions, GitLab CI, etc.)
- Template-driven output structure
- Output to standardized
$JAAN_OUTPUTS_DIRpath
Definition of Done
Reference: See
${CLAUDE_PLUGIN_ROOT}/docs/extending/devops-infra-scaffold-reference.mdsection "Definition of Done" for the full checklist.