[TERMINAL · SKILLS]
> mounting /skills...
> indexing skill manifests...
> linking agents: claude · codex · gemini · cursor
> ready.
[░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 0%
Use Cases/Build an Infrastructure-as-Code Testing Pipeline

Build an Infrastructure-as-Code Testing Pipeline

Test Terraform changes before they hit production — with unit tests for modules, integration tests with real cloud resources, cost estimation, and drift detection that caught 14 misconfigurations in the first month.

Development#typescript#tsconfig#type-checking#type-safety#javascript-migration
Works with:claude-codeopenai-codexgemini-clicursor

Skills stack · 6 skills

Avg quality 98/100·All SAFE
>

typescript

v1.0.0

Sets up and repairs TypeScript projects: picks tsconfig.json settings for a Node.js service, an npm library or a bundled web app, runs type-checking in CI, and replaces `any` and unsafe casts with types the compiler can verify. Use when someone asks to "set up TypeScript", "fix this tsconfig", "fix a TypeScript error", "upgrade to TypeScript 6 or 7", "migrate JavaScript to TypeScript", "publish types for a package", "run .ts files in Node" or "make this type-safe". Covers the changed defaults in TypeScript 6.0 and 7.0, module and moduleResolution, strict mode, project references, declaration output, narrowing, satisfies and common compiler errors.

93/100 quality
7.30× impact
SAFE· stale score
View skill
>

terraform-iac

v1.1.0

Manages cloud infrastructure using Terraform (and OpenTofu). Use when the user wants to write Terraform configurations, provision cloud resources, manage state, create modules, set up multi-environment deployments, import existing infrastructure, debug plan/apply errors, migrate between providers, or implement IaC best practices. Trigger words: terraform, opentofu, infrastructure as code, IaC, tf, hcl, terraform module, terraform state, terraform plan, terraform apply, terraform import, cloud provisioning, AWS terraform, GCP terraform, Azure terraform.

100/100 quality
2.21× impact
SAFE· stale score
View skill
>

github-actions

v1.1.0

GitHub Actions runs CI/CD pipelines defined as YAML workflows inside a GitHub repository. Use when someone asks to "set up CI", "add a GitHub Actions workflow", "run tests on every pull request", "cache dependencies", "build a matrix", "deploy from Actions", "push a Docker image to ghcr.io" or "reuse a workflow", or needs triggers, secrets, environments, artifacts and permissions explained.

100/100 quality
2.66× impact
SAFE· stale score
View skill
>

docker-helper

v1.1.0

Build, debug, and optimize Docker configurations. Use when a user asks to create a Dockerfile, fix Docker build errors, optimize image size, write docker-compose files, debug container issues, set up multi-stage builds, or troubleshoot networking between containers. Covers Dockerfile best practices and compose orchestration.

100/100 quality
1.44× impact
SAFE· stale score
View skill
>

vitest

v1.1.0

Vitest is a test runner for JavaScript and TypeScript built on Vite, with a Jest-compatible API, built-in mocking, snapshots and code coverage. Use when a user asks to set up or run unit tests in a Vite or Node project, write tests with describe/it/expect, mock modules with vi.mock, add coverage thresholds, configure vitest.config.ts or test projects, migrate from Jest, or upgrade to Vitest 5.

100/100 quality
1.50× impact
SAFE· stale score
View skill
>

zod

v1.1.0

Zod is a TypeScript-first schema library that validates data at runtime and infers static types from the same schema. Use when validating API request bodies, form input, environment variables or config files, parsing untrusted JSON, or migrating from Zod 3 to Zod 4. Covers z.object, safeParse, z.infer, coercion, discriminated unions, refinements, JSON Schema output and the v4 API changes.

93/100 quality
3.87× impact
SAFE· stale score
View skill
$

The Problem

A platform team manages 300+ Terraform resources across 5 AWS accounts. Every terraform apply is a prayer — no tests, no staging, no cost preview. Last month: an engineer changed an RDS instance class and accidentally wiped the production database (force replacement instead of in-place update). The month before: a security group change opened port 22 to the internet for 3 hours. Cost surprises are monthly — "why is the bill $8K more than last month?" Nobody knows until they investigate.

Step 1: Terraform Plan Analyzer

typescript
// src/analyzer/plan-parser.ts
import { z } from 'zod';

const ResourceChange = z.object({
  address: z.string(),
  type: z.string(),
  change: z.object({
    actions: z.array(z.enum(['create', 'read', 'update', 'delete', 'no-op'])),
    before: z.record(z.string(), z.unknown()).nullable(),
    after: z.record(z.string(), z.unknown()).nullable(),
  }),
});

export function analyzePlan(planJson: any): {
  creates: string[];
  updates: string[];
  destroys: string[];
  replaces: string[];  // delete + create = dangerous!
  risks: Array<{ resource: string; risk: string; severity: 'critical' | 'high' | 'medium' }>;
} {
  const changes = planJson.resource_changes ?? [];
  const creates: string[] = [];
  const updates: string[] = [];
  const destroys: string[] = [];
  const replaces: string[] = [];
  const risks: any[] = [];

  for (const change of changes) {
    const actions = change.change.actions;

    if (actions.includes('create') && actions.includes('delete')) {
      replaces.push(change.address);
      // Force replacement is always dangerous
      risks.push({
        resource: change.address,
        risk: 'Resource will be DESTROYED and recreated (data loss possible)',
        severity: 'critical',
      });
    } else if (actions.includes('delete')) {
      destroys.push(change.address);
      risks.push({
        resource: change.address,
        risk: 'Resource will be permanently deleted',
        severity: change.type.includes('db') || change.type.includes('rds') ? 'critical' : 'high',
      });
    } else if (actions.includes('create')) {
      creates.push(change.address);
    } else if (actions.includes('update')) {
      updates.push(change.address);

      // Check for risky updates
      if (change.type === 'aws_security_group_rule' || change.type === 'aws_security_group') {
        const after = change.change.after as any;
        if (after?.cidr_blocks?.includes('0.0.0.0/0') && after?.from_port !== 443) {
          risks.push({
            resource: change.address,
            risk: `Opens port ${after.from_port} to the internet (0.0.0.0/0)`,
            severity: 'critical',
          });
        }
      }
    }
  }

  return { creates, updates, destroys, replaces, risks };
}

Step 2: Cost Estimation

typescript
// src/cost/estimator.ts
// Estimates monthly cost delta from Terraform plan

const PRICING: Record<string, Record<string, number>> = {
  'aws_instance': {
    't3.micro': 7.59, 't3.small': 15.18, 't3.medium': 30.37,
    'm5.large': 69.12, 'm5.xlarge': 138.24, 'r6g.large': 72.27,
  },
  'aws_db_instance': {
    'db.t3.micro': 12.41, 'db.t3.small': 24.82, 'db.t3.medium': 49.64,
    'db.r6g.large': 131.40, 'db.r6g.xlarge': 262.80, 'db.r6g.2xlarge': 525.60,
  },
  'aws_elasticache_cluster': {
    'cache.t3.micro': 11.52, 'cache.t3.small': 23.04, 'cache.r6g.large': 118.08,
  },
};

export function estimateCostDelta(planJson: any): {
  monthlyCostBefore: number;
  monthlyCostAfter: number;
  delta: number;
  details: Array<{ resource: string; before: number; after: number; delta: number }>;
} {
  const changes = planJson.resource_changes ?? [];
  let before = 0, after = 0;
  const details: any[] = [];

  for (const change of changes) {
    const pricing = PRICING[change.type];
    if (!pricing) continue;

    const beforeInstance = change.change.before?.instance_class ?? change.change.before?.instance_type ?? change.change.before?.node_type;
    const afterInstance = change.change.after?.instance_class ?? change.change.after?.instance_type ?? change.change.after?.node_type;

    const beforeCost = pricing[beforeInstance as string] ?? 0;
    const afterCost = pricing[afterInstance as string] ?? 0;

    if (beforeCost !== afterCost) {
      before += beforeCost;
      after += afterCost;
      details.push({
        resource: change.address,
        before: beforeCost,
        after: afterCost,
        delta: afterCost - beforeCost,
      });
    }
  }

  return { monthlyCostBefore: before, monthlyCostAfter: after, delta: after - before, details };
}

Step 3: GitHub Actions Integration

yaml
# .github/workflows/terraform-test.yml
name: Terraform Test Pipeline
on:
  pull_request:
    paths: ['terraform/**']

jobs:
  plan-and-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3

      - name: Terraform Init & Plan
        working-directory: terraform/
        run: |
          terraform init -backend=false
          terraform plan -out=plan.bin -no-color
          terraform show -json plan.bin > plan.json

      - name: Analyze Plan
        id: analyze
        run: |
          node dist/analyze.js terraform/plan.json > analysis.json
          cat analysis.json

      - name: Estimate Cost
        run: node dist/estimate-cost.js terraform/plan.json > cost.json

      - name: Post PR Comment
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const analysis = JSON.parse(fs.readFileSync('analysis.json'));
            const cost = JSON.parse(fs.readFileSync('cost.json'));
            
            let body = '## 🏗️ Terraform Plan Analysis\n\n';
            body += `| Action | Count |\n|--------|-------|\n`;
            body += `| ✅ Create | ${analysis.creates.length} |\n`;
            body += `| 📝 Update | ${analysis.updates.length} |\n`;
            body += `| ❌ Destroy | ${analysis.destroys.length} |\n`;
            body += `| ⚠️ Replace | ${analysis.replaces.length} |\n\n`;
            
            if (analysis.risks.length > 0) {
              body += '### 🚨 Risks\n\n';
              for (const risk of analysis.risks) {
                body += `- **${risk.severity.toUpperCase()}**: ${risk.resource} — ${risk.risk}\n`;
              }
              body += '\n';
            }
            
            body += `### 💰 Cost Impact\n\n`;
            body += `Monthly delta: **$${cost.delta >= 0 ? '+' : ''}${cost.delta.toFixed(2)}/mo**\n`;
            
            await github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body,
            });

      - name: Block on Critical Risks
        run: |
          CRITICAL=$(cat analysis.json | node -e "
            const d=[];process.stdin.on('data',c=>d.push(c));
            process.stdin.on('end',()=>{
              const a=JSON.parse(d.join(''));
              console.log(a.risks.filter(r=>r.severity==='critical').length)
            })")
          if [ "$CRITICAL" -gt "0" ]; then
            echo "❌ Critical risks detected — requires manual approval"
            exit 1
          fi

Results

  • Production database wipe: would have been caught — replace detection blocks force-replacements
  • Open security group: caught in CI before merge (critical risk)
  • Cost surprises: zero — every PR shows monthly cost delta
  • 14 misconfigurations caught in first month (open ports, missing encryption, public buckets)
  • Deployment confidence: engineers merge Terraform PRs without fear
  • Cost visibility: team reduced monthly spend by $2.4K from cost-aware PR reviews

Related use cases