Receber por email
← Voltar para o catálogo

release-management

Provides release management strategies including deployment patterns, version control, and rollback procedures. Use when planning releases, managing deployments, or when user mentions 'release', 'canary', 'blue-green', 'rollback', 'feature flag', 'release train', 'semantic versioning', 'changelog', 'migration'.

65estrelas
Atualizado há 4 meses

Ver no GitHub ↗ Licença: NOASSERTION

Como adicionar

/plugin marketplace add Tibsfox/gsd-skill-creator

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/release-management/svg)](https://www.skillteca.com.br/skills/release-management)

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Release Management

Best practices for shipping software reliably through structured release processes, deployment strategies, and rollback automation.

Deployment Strategy Comparison

Choosing the right deployment strategy depends on risk tolerance, infrastructure budget, and rollback requirements.

| Strategy | Zero Downtime | Rollback Speed | Infrastructure Cost | Complexity | Best For | |----------|--------------|----------------|--------------------:|------------|----------| | Blue-Green | Yes | Instant (switch) | 2x | Medium | Critical services, compliance | | Canary | Yes | Fast (route away) | 1.05-1.5x | High | High-traffic user-facing apps | | Rolling | Yes | Slow (re-deploy) | 1x | Low | Stateless microservices | | Recreate | No (brief outage) | Slow (re-deploy) | 1x | Low | Dev/staging, batch jobs | | A/B Testing | Yes | Fast (route away) | 1.2-1.5x | High | Feature experimentation | | Shadow/Dark | Yes | N/A (no user impact) | 1.5-2x | Very High | ML models, data pipelines |

Decision Matrix

Is the service stateful?
  YES --> Can you afford 2x infrastructure?
            YES --> Blue-Green
            NO  --> Rolling (with drain + health checks)
  NO  --> Is it high-traffic (>1000 rps)?
            YES --> Canary (gradual rollout)
            NO  --> Rolling (simple, cost-effective)

Canary Deployment Configuration

Kubernetes Canary with Argo Rollouts

# argo-rollout.yaml -- Progressive canary with automated analysis
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: payment-service
  namespace: production
spec:
  replicas: 10
  revisionHistoryLimit: 3
  selector:
    matchLabels:
      app: payment-service
  strategy:
    canary:
      # Canary traffic steps with pause for analysis
      steps:
        - setWeight: 5
        - pause: { duration: 5m }    # 5% for 5 minutes
        - analysis:
            templates:
              - templateName: canary-success-rate
            args:
              - name: service-name
                value: payment-service
        - setWeight: 20
        - pause: { duration: 10m }   # 20% for 10 minutes
        - analysis:
            templates:
              - templateName: canary-success-rate
        - setWeight: 50
        - pause: { duration: 10m }   # 50% for 10 minutes
        - setWeight: 80
        - pause: { duration: 5m }    # 80% for 5 minutes
        # 100% happens automatically after final step

      # Auto-rollback on failure
      abortScaleDownDelaySeconds: 30
      dynamicStableScale: true

      # Traffic management via Istio
      trafficRouting:
        istio:
          virtualServices:
            - name: payment-service-vsvc
              routes:
                - primary
          destinationRule:
            name: payment-service-destrule
            canarySubsetName: canary
            stableSubsetName: stable

      # Analysis template for canary health
      analysis:
        templates:
          - templateName: canary-success-rate
        startingStep: 2
        args:
          - name: service-name
            value: payment-service

  template:
    metadata:
      labels:
        app: payment-service
    spec:
      containers:
        - name: payment-service
          image: registry.example.com/payment-service:v2.3.1
          ports:
            - containerPort: 8080
          readinessProbe:
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 10
          resources:
            requests:
              cpu: 250m
              memory: 256Mi
            limits:
              cpu: 500m
              memory: 512Mi

---
# Analysis template -- Prometheus-based success rate check
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
  name: canary-success-rate
spec:
  args:
    - name: service-name
  metrics:
    - name: success-rate
      interval: 60s
      count: 5
      successCondition: result[0] >= 0.99
      failureLimit: 2
      provider:
        prometheus:
          address: http://prometheus.monitoring:9090
          query: |
            sum(rate(http_requests_total{
              service="{{args.service-name}}",
              status=~"2..",
              canary="true"
            }[2m])) /
            sum(rate(http_requests_total{
              service="{{args.service-name}}",
              canary="true"
            }[2m]))
    - name: p99-latency
      interval: 60s
      count: 5
      successCondition: result[0] <= 500
      failureLimit: 2
      provider:
        prometheus:
          address: http://prometheus.monitoring:9090
          query: |
            histogram_quantile(0.99,
              sum(rate(http_request_duration_ms_bucket{
                service="{{args.service-name}}",
                canary="true"
              }[2m])) by (le)
            )

Feature Flag Implementation

LaunchDarkly Pattern with Gradual Rollout

// feature-flags.ts -- Structured feature flag management
import * as LaunchDarkly from "@launchdarkly/node-server-sdk";

// --- Flag Configuration Types ---

interface FlagConfig {
  key: string;
  description: string;
  type: "boolean" | "multivariate" | "percentage";
  owner: string;           // Team responsible
  createdAt: string;       // For cleanup tracking
  maxAge: string;          // Expected lifetime: "temporary" | "permanent"
  cleanupTicket?: string;  // JIRA ticket to remove flag
}

// Registry prevents flag sprawl -- all flags must be declared
const FLAG_REGISTRY: Record<string, FlagConfig> = {
  "new-checkout-flow": {
    key: "new-checkout-flow",
    description: "Redesigned checkout with one-page form",
    type: "percentage",
    owner: "checkout-team",
    createdAt: "2025-11-01",
    maxAge: "temporary",
    cleanupTicket: "CHECKOUT-1234",
  },
  "payment-v2-api": {
    key: "payment-v2-api",
    description: "Route payments through v2 processor",
    type: "boolean",
    owner: "payments-team",
    createdAt: "2025-10-15",
    maxAge: "temporary",
    cleanupTicket: "PAY-567",
  },
};

// --- Client Initialization ---

let ldClient: LaunchDarkly.LDClient;

export async function initFeatureFlags(): Promise<void> {
  ldClient = LaunchDarkly.init(process.env.LAUNCHDARKLY_SDK_KEY!);

  await ldClient.waitForInitialization({ timeout: 10 });
  console.log("LaunchDarkly client initialized");
}

// --- Flag Evaluation with Fallback ---

export async function isEnabled(
  flagKey: string,
  context: LaunchDarkly.LDContext,
  defaultValue = false
): Promise<boolean> {
  // Validate flag is registered
  if (!FLAG_REGISTRY[flagKey]) {
    console.warn(`Unknown flag: ${flagKey}. Returning default.`);
    return defaultValue;
  }

  try {
    const value = await ldClient.variation(flagKey, context, defaultValue);
    return Boolean(value);
  } catch (err) {
    // Flag evaluation failure should never break the app
    console.error(`Flag evaluation failed for ${flagKey}:`, err);
    return defaultValue;
  }
}

// --- Usage in Route Handler ---

export async function checkoutHandler(req: Request, res: Response) {
  const userContext: LaunchDarkly.LDContext = {
    kind: "user",
    key: req.user.id,
    email: req.user.email,
    custom: {
      plan: req.user.plan,       // Target by plan tier
      region: req.user.region,   // Target by geography
      company: req.user.orgId,   // Target by organization
    },
  };

  const useNewCheckout = await isEnabled("new-checkout-flow", userContext);

  if (useNewCheckout) {
    return renderNewCheckout(req, res);
  }
  return renderLegacyCheckout(req, res);
}

// --- Stale Flag Detection ---

export function getStaleFlags(maxAgeDays = 90): FlagConfig[] {
  const now = Date.now();
  return Object.values(FLAG_REGISTRY).filter((flag) => {
    if (flag.maxAge === "permanent") return false;
    const age = now - new Date(flag.createdAt).getTime();
    return age > maxAgeDays * 24 * 60 * 60 * 1000;
  });
}

Database Mi

Compartilhar X LinkedIn