Skip to main content

production-deploy

Pre-deployment validation and release management — structured checklists for database migrations, environment variables, rollback plans, backward compatibility, and deployment strategies. Use this skill when the user mentions deploy, release, ship to prod, merge to main, CI/CD pipeline, or says /production deploy. Triggers on deployment-related discussions, release planning, or pre-release validation.

الانتقال إلى التثبيت

معلومات المصدر

المستودع
vstorm-co/production-stack-skills
آخر نشاط في المصدر
١٦ أبريل ٢٠٢٦ في ١٧:٥٤
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٢٥
التفرعات
٧

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
3 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
production-deploy
description
Pre-deployment validation and release management — structured checklists for database migrations, environment variables, rollback plans, backward compatibility, and deployment strategies. Use this skill when the user mentions deploy, release, ship to prod, merge to main, CI/CD pipeline, or says /production deploy. Triggers on deployment-related discussions, release planning, or pre-release validation.
# Production Deploy This skill encodes the pre-deployment discipline that separates teams who ship confidently from teams who ship and pray. Every checklist item here exists because someone skipped it and caused an outage. The patterns are opinionated and battle-tested — this is not a deployment tutorial, it is a deployment gate. If you cannot check every box, you are not ready to deploy. Partial deploys are how you get partial outages. --- ## 1. Pre-Deployment Checklist Run through this before every production deploy. No exceptions, no shortcuts, no "we'll check it in staging." Print this out and check the boxes with a pen if that is what it takes. ### Data Layer - [ ] All migrations reviewed and classified (see Section 2) - [ ] Rollback migration exists and has been tested against staging - [ ] Database backup taken (or continuous WAL archiving confirmed active) - [ ] Migrations tested against production-volume data on staging - [ ] No migrations hold locks longer than 2 seconds (`SET lock_timeout = '2s'`) - [ ] Migration order is correct (dependencies between migrations verified) ### Application Layer - [ ] All new environment variables documented and set in production (see Section 3) - [ ] Secrets rotated if required (API keys, tokens, certificates) - [ ] Feature flags configured for any gradual rollout - [ ] API changes are backward-compatible (see Section 6) - [ ] No breaking changes to event schemas, message formats, or shared contracts - [ ] Application starts successfully with production config on staging ### Infrastructure - [ ] Health check endpoints respond correctly (`/health/live`, `/health/ready`) - [ ] Graceful shutdown tested — in-flight requests complete before process exits - [ ] Resource limits set (CPU, memory) — no unbounded containers - [ ] Autoscaling configured and tested (min/max instances, scale-up triggers) - [ ] DNS/load balancer changes propagated (if applicable) - [ ] TLS certificates valid and not expiring within 30 days ### Observability - [ ] Logs reaching the aggregator (CloudWatch, Datadog, Grafana Loki) - [ ] Key metrics have alerts: error rate > threshold, latency p99 > SLA, pod restarts - [ ] Distributed traces enabled and sampling rate appropriate for production - [ ] Error budget reviewed — are we within SLO? If not, this deploy needs extra scrutiny - [ ] Dashboard updated with new metrics if the deploy adds new endpoints or features ### Rollback Readiness - [ ] Rollback plan written and reviewed (see Section 5) - [ ] Previous deployment artifact is available and verified (image tag, release SHA) - [ ] Team knows who has deploy access and who is on-call - [ ] Incident channel identified (Slack channel, PagerDuty service, phone tree) - [ ] Estimated time to rollback documented (should be under 5 minutes) **Detection — find deploys that skip the checklist:** ```bash # PRs merged to main without a deploy checklist comment gh pr list --state merged --base main --limit 20 --json title,body \ | jq '.[] | select(.body | test("deploy checklist|pre-deploy|rollback plan"; "i") | not) | .title' # Recent deploys without associated rollback tags git tag -l "rollback-*" --sort=-creatordate | head -5 ``` --- ## 2. Migration Safety Review Every migration must be classified before it ships. This is the single most important step in any deploy that touches the database. Get it wrong and you take the service down for every user, not just the ones using the new feature. ### Classification #### Additive (Safe) — Green Light These migrations are safe for zero-downtime rolling deploys. Old code ignores the new structures. - New tables - New nullable columns (without defaults on large tables) - New indexes (with `CONCURRENTLY`) - New views - New functions/procedures ```sql -- Safe: new table, no impact on existing code CREATE TABLE notifications ( id BIGSERIAL PRIMARY KEY, user_id BIGINT NOT NULL REFERENCES users(id), message TEXT NOT NULL, read_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); -- Safe: new nullable column, old code ignores it ALTER TABLE orders ADD COLUMN tracking_url TEXT; -- Safe: concurrent index, no write locks CREATE INDEX CONCURRENTLY ix_notifications_user_id ON notifications (user_id); ``` #### Transformative (Risky) — Yellow Light These require extra review, staging testing with production-volume data, and explicit sign-off. They can be done safely but the safe pattern is non-obvious. - Column type changes (expand-contract) - Data backfills on large tables (batch, not single UPDATE) - Adding NOT NULL constraints (use NOT VALID + VALIDATE) - Adding CHECK constraints on existing data - Adding foreign keys on existing data ```python # RISKY: backfill must be batched to avoid locking the table # and overwhelming the database with a single massive transaction # WRONG — single UPDATE locks the table and generates huge WAL # op.execute("UPDATE orders SET status = 'active' WHERE status IS NULL") # RIGHT — batch in chunks def upgrade(): conn = op.get_bind() batch_size = 1000 while True: result = conn.execute(text( "UPDATE orders SET status = 'active' " "WHERE id IN (" " SELECT id FROM orders WHERE status IS NULL LIMIT :batch" ")" ), {"batch": batch_size}) if result.rowcount == 0: break conn.execute(text("COMMIT")) ``` #### Destructive (Dangerous) — Red Light **REFUSE to deploy destructive migrations without explicit confirmation from the user.** These are irreversible. Suggest a zero-downtime alternative first. - Column drops - Table drops - Data deletion (DELETE/TRUNCATE) - Column renames (breaks old code during rolling deploy) - Type changes that narrow data (e.g., TEXT to VARCHAR(50)) ```python # DANGEROUS: dropping a column breaks old code during rolling deploy # Old instances still query this column. They crash. # Instead of: # op.drop_column('users', 'legacy_role') # Use expand-contract (3 deploys): # Deploy 1: Stop reading from legacy_role in code # Deploy 2: Stop writing to legacy_role in code # Deploy 3: Drop the column (only after ALL instances run new code) # Generate rollback script BEFORE executing: def downgrade(): op.add_column('users', sa.Column('legacy_role', sa.String(50))) # NOTE: data is gone. Restore from backup if needed. ``` **Detection — find risky migrations before they ship:** ```bash # Scan migration files for dangerous operations grep -rn "drop_column\|drop_table\|DROP TABLE\|DROP COLUMN\|TRUNCATE\|DELETE FROM" \ alembic/versions/ migrations/ # Scan for missing lock_timeout grep -rL "lock_timeout" alembic/versions/*.py # Use squawk for automated migration linting (PostgreSQL) # pip install squawk-cli squawk alembic/versions/latest_migration.sql ``` ### Migration Lint with squawk [squawk](https://squawkhq.com/) catches unsafe migration patterns automatically. Add it to CI: ```yaml # GitHub Actions - name: Lint migrations run: | pip install squawk-cli # Generate SQL from Alembic migrations alembic upgrade head --sql > migration.sql squawk migration.sql ``` squawk catches: missing `CONCURRENTLY` on indexes, `NOT NULL` additions without defaults, missing `lock_timeout`, and more. --- ## 3. Environment Variable Validation Missing environment variables are the #2 cause of deploy failures (after bad migrations). The fix is simple: validate everything at startup, fail fast with a clear error message. ### Python — Pydantic BaseSettings ```python from pydantic_settings import BaseSettings, SettingsConfigDict from pydantic import Field, field_validator from typing import Annotated class Settings(BaseSettings): model_config = SettingsConfigDict( env_file=".env", env_file_encoding="utf-8", case_sensitive=False, extra="ignore", ) # Required — app crashes at import time if missing database_url: str secret_key: str allowed_hosts: list[str] # Required with validation environment: str log_level: str = "INFO" # Optional with safe defaults redis_url: str = "redis://localhost:6379/0" cors_origins: list[str] = ["http://localhost:3000"] db_pool_size: int = 10 db_max_overflow: int = 5 sentry_dsn: str | None = None # Deploy metadata — set by CI/CD app_version: str = "dev" deploy_sha: str = "unknown" @field_validator("environment") @classmethod def validate_environment(cls, v: str) -> str: allowed = {"development", "staging", "production"} if v not in allowed: raise ValueError(f"environment must be one of {allowed}, got '{v}'") return v @field_validator("log_level") @classmethod def validate_log_level(cls, v: str) -> str: allowed = {"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"} if v.upper() not in allowed: raise ValueError(f"log_level must be one of {allowed}, got '{v}'") return v.upper() # Instantiate at module level — fails at import time, not at first request settings = Settings() ``` ### Node.js — envalid ```typescript import { cleanEnv, str, num, url, bool } from "envalid"; const env = cleanEnv(process.env, { // Required — process exits with clear error if missing DATABASE_URL: url(), SECRET_KEY: str({ desc: "JWT signing key" }), ALLOWED_HOSTS: str({ desc: "Comma-separated allowed hosts" }), // Required with validation NODE_ENV: str({ choices: ["development", "staging", "production"] }), LOG_LEVEL: str({ choices: ["debug", "info", "warn", "error"], default: "info", }), // Optional with safe defaults REDIS_URL: url({ default: "redis://localhost:6379/0" }), PORT: num({ default: 3000 }), SENTRY_DSN: str({ default: "" }), // Deploy metadata APP_VERSION: str({ default: "dev" }), DEPLOY_SHA: str({ default: "unknown" }), }); export default env; ``` ### Rules - Every required env var must be validated at startup, not on first use - Fail with a human-readable error: "Missing required environment variable: DATABASE_URL" — not a cryptic NoneType error 3 stack frames deep - Document every env var in a `.env.example` file committed to the repo - New env vars added in a PR MUST be set in production BEFORE the deploy, or have a safe default - Never use `os.getenv("SECRET")` without a fallback or validation — it silently returns None **Detection — find unvalidated env vars:** ```bash # Python: find raw os.getenv/os.environ without Settings class grep -rn "os\.getenv\|os\.environ\[" --include="*.py" src/ app/ \ | grep -v "settings\|config\|test" # Node.js: find raw process.env without envalid grep -rn "process\.env\." --include="*.ts" --include="*.js" src/ \ | grep -v "node_modules\|config\|env\.ts\|env\.js\|test" # Find env vars referenced in code but missing from .env.example comm -23 \ <(grep -rhoP '(?:os\.getenv|os\.environ\[|process\.env\.)["'"'"']?\K[A-Z_]+' src/ | sort -u) \ <(grep -oP '^[A-Z_]+' .env.example 2>/dev/null | sort -u) ``` --- ## 4. Deployment Strategies Choose the right strategy for the risk level. There is no universal best — each has tradeoffs. ### Rolling Update (Default for Stateless Services) New instances start, pass health checks, and begin receiving traffic. Old instances drain and shut down. At any point during the deploy, both old and new code are running simultaneously. ```yaml # Kubernetes Deployment apiVersion: apps/v1 kind: Deployment spec: replicas: 4 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 # At most 1 extra pod during rollout maxUnavailable: 0 # Never reduce below desired count template: spec: containers: - name: api readinessProbe: httpGet: path: /health/ready port: 8000 initialDelaySeconds: 5 periodSeconds: 10 livenessProbe: httpGet: path: /health/live port: 8000 initialDelaySeconds: 15 periodSeconds: 20 terminationGracePeriodSeconds: 30 ``` **When to use:** Standard deploys of stateless services with backward-compatible changes. Most deploys. **Risk:** Old and new code run simultaneously. Database schema and API contracts must be backward-compatible. ### Blue-Green (Zero-Downtime with Instant Rollback) Run two identical environments. Deploy to the inactive one ("green"), verify, then switch traffic. Rollback is instant — switch traffic back to "blue." ```bash # Cloud Run example — deploy to a new revision without serving traffic gcloud run deploy my-service \ --image gcr.io/my-project/my-service:${NEW_SHA} \ --no-traffic \ --tag canary # Smoke test the new revision curl -s https://canary---my-service-xxxxx.a.run.app/health/ready # If healthy, shift all traffic gcloud run services update-traffic my-service --to-latest # If broken, rollback to previous revision gcloud run services update-traffic my-service \ --to-revisions=my-service-00042-abc=100 ``` ```yaml # Docker Compose blue-green (simplified) # nginx.conf switches upstream between blue and green services: blue: image: myapp:current ports: ["8001:8000"] green: image: myapp:${NEW_TAG} ports: ["8002:8000"] nginx: volumes: - ./nginx.conf:/etc/nginx/nginx.conf ports: ["80:80"] ``` **When to use:** Critical services where rollback speed matters more than resource cost. Services with hard availability SLAs. **Cost:** Requires 2x infrastructure during deploy window. Both environments must be fully functional. ### Canary (High-Risk Changes) Route a small percentage of traffic to the new version. Monitor error rates and latency. Gradually increase traffic if metrics are healthy. ```yaml # Kubernetes canary with Istio VirtualService apiVersion: networking.istio.io/v1 kind: VirtualService spec: hosts: ["my-service"] http: - route: - destination: host: my-service subset: stable weight: 95 - destination: host: my-service subset: canary weight: 5 ``` ```bash # Cloud Run canary — send 5% of traffic to new revision gcloud run services update-traffic my-service \ --to-revisions=my-service-00043-def=5,my-service-00042-abc=95 # Monitor for 15 minutes, then promote or rollback # Check error rate: # - If canary error rate > 2x stable error rate, rollback immediately # - If canary latency p99 > 1.5x stable p99, rollback immediately ``` **When to use:** Large schema changes, major refactors, new integrations, anything where "it worked in staging" is not sufficient confidence. **Canary promotion criteria:** 1. Error rate within 1.5x of stable baseline for 15 minutes 2. Latency p99 within 1.5x of stable baseline 3. No new error types in logs 4. No increase in pod restarts ### Feature Flags (Gradual Rollout at Application Level) Decouple deploy from release. Ship the code, then enable the feature gradually. This is the safest approach for user-facing changes. ```python # Python — LaunchDarkly / Unleash / simple feature flag import structlog logger = structlog.get_logger() def get_recommendations(user_id: str, feature_flags: FeatureFlags) -> list: if feature_flags.is_enabled("new_recommendation_engine", user_id=user_id):
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub