[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6JQ8BECTR3JBQZ9XQQ16HMH":3,"skill-same:01M6JQ8BECTR3JBQZ9XQQ16HMH":87},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":26,"publishedAt":47,"linkOnly":48,"markdownContent":49,"markdownBody":50,"frontMatter":51,"refName":52,"commitSha":53,"skillDirectory":54,"forksCount":14,"repositoryHtmlUrl":55,"repositoryHomepageUrl":6,"ownerHtmlUrl":56,"ownerBlogUrl":6,"ownerDescription":57,"updatedAt":58,"install":59,"resources":72},"01M6JQ8BECTR3JBQZ9XQQ16HMH","gitops-delivery",null,"Design GitOps continuous delivery with ArgoCD or Flux — declarative reconciliation, cross-repo CI\u002FCD triggers, drift detection, progressive delivery. Triggers: ArgoCD, Flux, FluxCD, GitOps, git-based deployment, declarative delivery, auto-sync, drift detection, cross-repo trigger, reconciliation loop, pull-based deployment, canary GitOps.","SWEStash\u002Fswe-workflow-skills","SWEStash","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F272895713?v=4","01M6JNRQ84JN5WFK9S1V5H4G46","SWE Stash","01M6JNRQCM45X8WPNHY30TSAB0",1,"MIT","https:\u002F\u002Fgithub.com\u002FSWEStash\u002Fswe-workflow-skills\u002Fblob\u002Fmain\u002Fskills\u002Fgitops-delivery\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000015","视觉设计","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],"gitops delivery","gitops","delivery","drift","drift detection","fluxcd","CI\u002FCD","trigger","flux","reconciliation","design","auto","repo","loop","canary","ci","pull","git","deployment","sync","2026-11-10 10:12:30",false,"---\nname: gitops-delivery\ndescription: \"Design GitOps continuous delivery with ArgoCD or Flux — declarative reconciliation, cross-repo CI\u002FCD triggers, drift detection, progressive delivery. Triggers: ArgoCD, Flux, FluxCD, GitOps, git-based deployment, declarative delivery, auto-sync, drift detection, cross-repo trigger, reconciliation loop, pull-based deployment, canary GitOps.\"\n---\n\n# GitOps Delivery\n\nGitOps makes Git the single source of truth for deployment state. An operator watches a Git repository and continuously reconciles the cluster to match what's declared in Git. The deployment repo defines the desired state — the GitOps operator enforces it.\n\n## Step 1: Choose the GitOps Model\n\n**Pull-based (recommended):** An operator running in the cluster watches the deployment repo and applies changes. No CI system needs cluster credentials.\n- **ArgoCD**: Application-centric, strong UI, sync waves for ordering, multi-cluster support\n- **Flux**: Toolkit-based, composable, native Kustomize\u002FHelm support, image automation\n\n**Push-based (simpler but less robust):** CI pipeline runs `kubectl apply` or `helm upgrade` after building. Simpler to set up but has drawbacks: CI needs cluster credentials, no drift detection, no self-healing.\n\n**Decision guide:**\n\n| Factor | Push-based | Pull-based (GitOps) |\n|--------|-----------|-------------------|\n| **Setup complexity** | Lower | Higher initial setup |\n| **Cluster credentials** | CI needs them | Only operator needs them |\n| **Drift detection** | None | Automatic |\n| **Self-healing** | None | Operator reverts manual changes |\n| **Audit trail** | CI logs | Git history (stronger) |\n| **Multi-cluster** | Duplicated CI jobs | Native support |\n\n**When push-based is fine:** Single cluster, single environment, small team, no compliance requirements. See `cicd-pipeline` for push-based patterns.\n\n**When GitOps is worth it:** Multiple environments, compliance\u002Faudit needs, multi-cluster, or you want drift detection and self-healing.\n\n**Either way, say this:** version pinning and a declarative record of what is deployed are\nworth adopting **regardless of which side of this decision you land on** — they are what make\na deploy reproducible and a rollback a known-good revert, and none of that requires an\noperator. Point at `deployment-repo` even when you are recommending against ArgoCD; a team\nthat keeps pinned manifests in Git gets most of the auditability benefit now, and has already\ndone the setup work if they adopt GitOps later. Recommending push-based is not a reason to\nleave the handoff out.\n\n## Step 2: Design Cross-Repo Triggers\n\nThe critical bridge: when an app repo builds a new image, the deployment repo must be updated. This is the most common source of friction in GitOps setups.\n\n**Pattern A: Automated PR via GitHub Actions `repository_dispatch`**\n\nApp repo CI triggers a workflow in the deployment repo:\n\n```yaml\n# In app repo: .github\u002Fworkflows\u002Frelease.yml\n- name: Mint a short-lived token for the deployment repo\n  id: app-token\n  uses: actions\u002Fcreate-github-app-token@v1\n  with:\n    app-id: ${{ vars.DEPLOY_APP_ID }}\n    private-key: ${{ secrets.DEPLOY_APP_PRIVATE_KEY }}\n    repositories: deployment-repo\n- name: Trigger deployment repo update\n  uses: peter-evans\u002Frepository-dispatch@v3\n  with:\n    token: ${{ steps.app-token.outputs.token }}\n    repository: org\u002Fdeployment-repo\n    event-type: version-bump\n    client-payload: |\n      {\n        \"service\": \"user-service\",\n        \"version\": \"v1.8.0\",\n        \"image\": \"ghcr.io\u002Forg\u002Fuser-service:v1.8.0\"\n      }\n```\n\n```yaml\n# In deployment repo: .github\u002Fworkflows\u002Fversion-bump.yml\non:\n  repository_dispatch:\n    types: [version-bump]\n\njobs:\n  update-version:\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - name: Update versions.yaml\n        run: |\n          yq e \".services.${{ github.event.client_payload.service }}.version = \\\"${{ github.event.client_payload.version }}\\\"\" \\\n            -i environments\u002Fdev\u002Fversions.yaml\n      - name: Create PR\n        uses: peter-evans\u002Fcreate-pull-request@v6\n        with:\n          title: \"bump ${{ github.event.client_payload.service }} to ${{ github.event.client_payload.version }}\"\n          branch: \"bump\u002F${{ github.event.client_payload.service }}-${{ github.event.client_payload.version }}\"\n```\n\n**Pattern B: Renovate \u002F Dependabot for image tags**\n\nConfigure Renovate to watch container registries and create PRs when new tags appear:\n\n```json\n{\n  \"packageRules\": [\n    {\n      \"matchDatasources\": [\"docker\"],\n      \"matchPackagePatterns\": [\"ghcr.io\u002Forg\u002F*\"],\n      \"automerge\": false,\n      \"labels\": [\"version-bump\"]\n    }\n  ]\n}\n```\n\n**Pattern C: GitLab CI downstream pipeline**\n\n```yaml\n# In app repo: .gitlab-ci.yml\ntrigger-deployment:\n  stage: deploy\n  trigger:\n    project: org\u002Fdeployment-repo\n    branch: main\n    strategy: depend\n  variables:\n    SERVICE_NAME: user-service\n    SERVICE_VERSION: $CI_COMMIT_TAG\n```\n\n**Recommendation:** Pattern A (repository_dispatch + PR) for most teams. It creates an auditable PR, allows contract tests to run before merge, and doesn't require additional tooling. Use Pattern B (Renovate) if you want fully automated version tracking without custom workflows.\n\n## Step 3: Configure the GitOps Operator\n\n### ArgoCD Setup\n\n**Application per service per environment:**\n\n```yaml\n# argocd\u002Fstaging\u002Fuser-service.yaml\napiVersion: argoproj.io\u002Fv1alpha1\nkind: Application\nmetadata:\n  name: user-service-staging\n  namespace: argocd\n  labels:\n    environment: staging\n    service: user-service\nspec:\n  project: default\n  source:\n    repoURL: https:\u002F\u002Fgithub.com\u002Forg\u002Fdeployment-repo\n    targetRevision: main\n    path: helm\u002Fuser-service\n    helm:\n      valueFiles:\n        - ..\u002F..\u002Fenvironments\u002Fstaging\u002Fuser-service-values.yaml\n  destination:\n    server: https:\u002F\u002Fkubernetes.default.svc\n    namespace: staging\n  syncPolicy:\n    automated:              # Auto-sync for staging\n      prune: true           # Remove resources not in Git\n      selfHeal: true        # Revert manual changes\n    syncOptions:\n      - CreateNamespace=true\n    retry:\n      limit: 3\n      backoff:\n        duration: 5s\n        factor: 2\n```\n\n**Production — manual sync with approval:**\n\n```yaml\n# argocd\u002Fproduction\u002Fuser-service.yaml\nspec:\n  syncPolicy: {}            # No automated sync — requires manual sync or CI trigger\n  # Add sync windows to restrict when syncs can happen:\n  syncPolicy:\n    syncOptions:\n      - CreateNamespace=true\n    # Sync windows defined in the ArgoCD project\n```\n\n**App of Apps pattern (manage all Applications as a single unit):**\n\n```yaml\napiVersion: argoproj.io\u002Fv1alpha1\nkind: Application\nmetadata:\n  name: platform-staging\nspec:\n  source:\n    repoURL: https:\u002F\u002Fgithub.com\u002Forg\u002Fdeployment-repo\n    path: argocd\u002Fstaging       # Directory containing all Application YAMLs\n  destination:\n    server: https:\u002F\u002Fkubernetes.default.svc\n```\n\n**Sync waves (control deployment order):**\n\n```yaml\n# Database migration job runs first (wave 0), then services (wave 1), then ingress (wave 2)\nmetadata:\n  annotations:\n    argocd.argoproj.io\u002Fsync-wave: \"0\"   # Lower runs first\n```\n\n### Flux Setup\n\n```yaml\n# flux\u002Fstaging\u002Fkustomization.yaml\napiVersion: kustomize.toolkit.fluxcd.io\u002Fv1\nkind: Kustomization\nmetadata:\n  name: staging-apps\n  namespace: flux-system\nspec:\n  interval: 5m\n  sourceRef:\n    kind: GitRepository\n    name: deployment-repo\n  path: .\u002Foverlays\u002Fstaging\n  prune: true\n  healthChecks:\n    - apiVersion: apps\u002Fv1\n      kind: Deployment\n      name: user-service\n      namespace: staging\n  timeout: 3m\n```\n\n**Flux image automation (auto-update image tags):**\n\n```yaml\napiVersion: image.toolkit.fluxcd.io\u002Fv1beta2\nkind: ImagePolicy\nmetadata:\n  name: user-service\nspec:\n  imageRepositoryRef:\n    name: user-service\n  policy:\n    semver:\n      range: \">=1.0.0\"\n```\n\nSee [references\u002Fgitops-patterns.md](references\u002Fgitops-patterns.md) for complete manifests and [templates\u002Fgitops-config.md](templates\u002Fgitops-config.md) for ready-to-use templates.\n\n## Step 4: Implement Progressive Delivery\n\nLayer progressive delivery on top of GitOps for safer production rollouts. This step is optional for lightweight setups but critical at scale.\n\n**Argo Rollouts (works with ArgoCD):**\n\n```yaml\napiVersion: argoproj.io\u002Fv1alpha1\nkind: Rollout\nmetadata:\n  name: user-service\nspec:\n  strategy:\n    canary:\n      steps:\n        - setWeight: 10       # Send 10% of traffic to new version\n        - pause: { duration: 5m }\n        - analysis:\n            templates:\n              - templateName: success-rate\n        - setWeight: 50\n        - pause: { duration: 10m }\n        - analysis:\n            templates:\n              - templateName: success-rate\n      # Auto-rollback if analysis fails\n```\n\n**Analysis template (gate on metrics):**\n\n```yaml\napiVersion: argoproj.io\u002Fv1alpha1\nkind: AnalysisTemplate\nmetadata:\n  name: success-rate\nspec:\n  metrics:\n    - name: success-rate\n      interval: 1m\n      successCondition: result[0] >= 0.99\n      provider:\n        prometheus:\n          address: http:\u002F\u002Fprometheus:9090\n          query: |\n            sum(rate(http_requests_total{service=\"user-service\",status=~\"2..\"}[5m]))\n            \u002F\n            sum(rate(http_requests_total{service=\"user-service\"}[5m]))\n```\n\n**Flagger (works with Flux):** Similar concept — canary analysis using Prometheus, Datadog, or other metrics providers. Flagger automatically manages the canary\u002Fprimary services and traffic splitting.\n\n**When to skip progressive delivery:** Dev and staging environments (just deploy directly). Small teams with low traffic. Services with comprehensive E2E tests that catch issues before deploy.\n\n## Step 5: Validate End-to-End\n\nTest the full GitOps pipeline:\n\n- [ ] **Trigger flow**: Merge a change in an app repo -> verify a PR appears in the deployment repo\n- [ ] **Contract validation**: The deployment repo PR CI runs contract tests against the new version combination\n- [ ] **GitOps sync**: After merging the deployment repo PR, the operator detects the change and syncs\n- [ ] **Health checks**: The operator reports healthy status after sync\n- [ ] **Drift detection**: Manually modify a resource in the cluster -> verify the operator reverts it\n- [ ] **Rollback**: Revert a commit in the deployment repo -> verify the operator rolls back the cluster\n- [ ] **Sync windows** (if configured): Verify syncs are blocked outside allowed windows\n- [ ] **Progressive delivery** (if configured): Verify canary analysis runs and gates promotion\n\n**Monitoring the GitOps pipeline:**\n- ArgoCD: Built-in UI shows sync status, health, and history per Application\n- Flux: `flux get kustomizations` shows reconciliation status\n- Both: Export metrics to Prometheus for alerting on sync failures\n\n## Principles Applied\n\n- **Git is the source of truth**: If it's not in Git, it doesn't exist. No `kubectl edit` in production, no manual Helm upgrades.\n- **Pull over push**: The cluster pulls desired state from Git rather than CI pushing to the cluster. This inverts the security model — the cluster needs Git read access, not the other way around.\n- **KISS**: Start with a single ArgoCD Application per environment. Add App of Apps, sync waves, and progressive delivery as complexity demands.\n- **YAGNI**: Don't set up Argo Rollouts for a service with 10 requests per minute. Don't configure multi-cluster GitOps for a single cluster.\n- **Declarative over imperative**: Define the desired state, let the operator figure out how to get there. Avoid custom sync scripts.\n\n## Cross-Skill References\n\n- `deployment-repo` — pinned versions and declarative manifests in Git, **valuable with or without an operator**: it is what ArgoCD\u002FFlux watch if you adopt GitOps, and the reproducibility\u002Frollback substrate if you stay push-based. Design the repo structure first either way.\n- `cicd-pipeline` — cross-repo trigger pipelines that update the deployment repo on new builds\n- `rollback-strategy` — in GitOps, rollback = revert a Git commit; the operator handles the rest\n- `observability-design` — metrics and dashboards for monitoring sync status, drift, and progressive delivery analysis\n- `containerization` — Helm chart structure and Kustomize overlay patterns used by the operator\n- `infrastructure-as-code` — Terraform for cluster and infrastructure provisioning (separate from app deployment)\n","# GitOps Delivery\n\nGitOps makes Git the single source of truth for deployment state. An operator watches a Git repository and continuously reconciles the cluster to match what's declared in Git. The deployment repo defines the desired state — the GitOps operator enforces it.\n\n## Step 1: Choose the GitOps Model\n\n**Pull-based (recommended):** An operator running in the cluster watches the deployment repo and applies changes. No CI system needs cluster credentials.\n- **ArgoCD**: Application-centric, strong UI, sync waves for ordering, multi-cluster support\n- **Flux**: Toolkit-based, composable, native Kustomize\u002FHelm support, image automation\n\n**Push-based (simpler but less robust):** CI pipeline runs `kubectl apply` or `helm upgrade` after building. Simpler to set up but has drawbacks: CI needs cluster credentials, no drift detection, no self-healing.\n\n**Decision guide:**\n\n| Factor | Push-based | Pull-based (GitOps) |\n|--------|-----------|-------------------|\n| **Setup complexity** | Lower | Higher initial setup |\n| **Cluster credentials** | CI needs them | Only operator needs them |\n| **Drift detection** | None | Automatic |\n| **Self-healing** | None | Operator reverts manual changes |\n| **Audit trail** | CI logs | Git history (stronger) |\n| **Multi-cluster** | Duplicated CI jobs | Native support |\n\n**When push-based is fine:** Single cluster, single environment, small team, no compliance requirements. See `cicd-pipeline` for push-based patterns.\n\n**When GitOps is worth it:** Multiple environments, compliance\u002Faudit needs, multi-cluster, or you want drift detection and self-healing.\n\n**Either way, say this:** version pinning and a declarative record of what is deployed are\nworth adopting **regardless of which side of this decision you land on** — they are what make\na deploy reproducible and a rollback a known-good revert, and none of that requires an\noperator. Point at `deployment-repo` even when you are recommending against ArgoCD; a team\nthat keeps pinned manifests in Git gets most of the auditability benefit now, and has already\ndone the setup work if they adopt GitOps later. Recommending push-based is not a reason to\nleave the handoff out.\n\n## Step 2: Design Cross-Repo Triggers\n\nThe critical bridge: when an app repo builds a new image, the deployment repo must be updated. This is the most common source of friction in GitOps setups.\n\n**Pattern A: Automated PR via GitHub Actions `repository_dispatch`**\n\nApp repo CI triggers a workflow in the deployment repo:\n\n```yaml\n# In app repo: .github\u002Fworkflows\u002Frelease.yml\n- name: Mint a short-lived token for the deployment repo\n  id: app-token\n  uses: actions\u002Fcreate-github-app-token@v1\n  with:\n    app-id: ${{ vars.DEPLOY_APP_ID }}\n    private-key: ${{ secrets.DEPLOY_APP_PRIVATE_KEY }}\n    repositories: deployment-repo\n- name: Trigger deployment repo update\n  uses: peter-evans\u002Frepository-dispatch@v3\n  with:\n    token: ${{ steps.app-token.outputs.token }}\n    repository: org\u002Fdeployment-repo\n    event-type: version-bump\n    client-payload: |\n      {\n        \"service\": \"user-service\",\n        \"version\": \"v1.8.0\",\n        \"image\": \"ghcr.io\u002Forg\u002Fuser-service:v1.8.0\"\n      }\n```\n\n```yaml\n# In deployment repo: .github\u002Fworkflows\u002Fversion-bump.yml\non:\n  repository_dispatch:\n    types: [version-bump]\n\njobs:\n  update-version:\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - name: Update versions.yaml\n        run: |\n          yq e \".services.${{ github.event.client_payload.service }}.version = \\\"${{ github.event.client_payload.version }}\\\"\" \\\n            -i environments\u002Fdev\u002Fversions.yaml\n      - name: Create PR\n        uses: peter-evans\u002Fcreate-pull-request@v6\n        with:\n          title: \"bump ${{ github.event.client_payload.service }} to ${{ github.event.client_payload.version }}\"\n          branch: \"bump\u002F${{ github.event.client_payload.service }}-${{ github.event.client_payload.version }}\"\n```\n\n**Pattern B: Renovate \u002F Dependabot for image tags**\n\nConfigure Renovate to watch container registries and create PRs when new tags appear:\n\n```json\n{\n  \"packageRules\": [\n    {\n      \"matchDatasources\": [\"docker\"],\n      \"matchPackagePatterns\": [\"ghcr.io\u002Forg\u002F*\"],\n      \"automerge\": false,\n      \"labels\": [\"version-bump\"]\n    }\n  ]\n}\n```\n\n**Pattern C: GitLab CI downstream pipeline**\n\n```yaml\n# In app repo: .gitlab-ci.yml\ntrigger-deployment:\n  stage: deploy\n  trigger:\n    project: org\u002Fdeployment-repo\n    branch: main\n    strategy: depend\n  variables:\n    SERVICE_NAME: user-service\n    SERVICE_VERSION: $CI_COMMIT_TAG\n```\n\n**Recommendation:** Pattern A (repository_dispatch + PR) for most teams. It creates an auditable PR, allows contract tests to run before merge, and doesn't require additional tooling. Use Pattern B (Renovate) if you want fully automated version tracking without custom workflows.\n\n## Step 3: Configure the GitOps Operator\n\n### ArgoCD Setup\n\n**Application per service per environment:**\n\n```yaml\n# argocd\u002Fstaging\u002Fuser-service.yaml\napiVersion: argoproj.io\u002Fv1alpha1\nkind: Application\nmetadata:\n  name: user-service-staging\n  namespace: argocd\n  labels:\n    environment: staging\n    service: user-service\nspec:\n  project: default\n  source:\n    repoURL: https:\u002F\u002Fgithub.com\u002Forg\u002Fdeployment-repo\n    targetRevision: main\n    path: helm\u002Fuser-service\n    helm:\n      valueFiles:\n        - ..\u002F..\u002Fenvironments\u002Fstaging\u002Fuser-service-values.yaml\n  destination:\n    server: https:\u002F\u002Fkubernetes.default.svc\n    namespace: staging\n  syncPolicy:\n    automated:              # Auto-sync for staging\n      prune: true           # Remove resources not in Git\n      selfHeal: true        # Revert manual changes\n    syncOptions:\n      - CreateNamespace=true\n    retry:\n      limit: 3\n      backoff:\n        duration: 5s\n        factor: 2\n```\n\n**Production — manual sync with approval:**\n\n```yaml\n# argocd\u002Fproduction\u002Fuser-service.yaml\nspec:\n  syncPolicy: {}            # No automated sync — requires manual sync or CI trigger\n  # Add sync windows to restrict when syncs can happen:\n  syncPolicy:\n    syncOptions:\n      - CreateNamespace=true\n    # Sync windows defined in the ArgoCD project\n```\n\n**App of Apps pattern (manage all Applications as a single unit):**\n\n```yaml\napiVersion: argoproj.io\u002Fv1alpha1\nkind: Application\nmetadata:\n  name: platform-staging\nspec:\n  source:\n    repoURL: https:\u002F\u002Fgithub.com\u002Forg\u002Fdeployment-repo\n    path: argocd\u002Fstaging       # Directory containing all Application YAMLs\n  destination:\n    server: https:\u002F\u002Fkubernetes.default.svc\n```\n\n**Sync waves (control deployment order):**\n\n```yaml\n# Database migration job runs first (wave 0), then services (wave 1), then ingress (wave 2)\nmetadata:\n  annotations:\n    argocd.argoproj.io\u002Fsync-wave: \"0\"   # Lower runs first\n```\n\n### Flux Setup\n\n```yaml\n# flux\u002Fstaging\u002Fkustomization.yaml\napiVersion: kustomize.toolkit.fluxcd.io\u002Fv1\nkind: Kustomization\nmetadata:\n  name: staging-apps\n  namespace: flux-system\nspec:\n  interval: 5m\n  sourceRef:\n    kind: GitRepository\n    name: deployment-repo\n  path: .\u002Foverlays\u002Fstaging\n  prune: true\n  healthChecks:\n    - apiVersion: apps\u002Fv1\n      kind: Deployment\n      name: user-service\n      namespace: staging\n  timeout: 3m\n```\n\n**Flux image automation (auto-update image tags):**\n\n```yaml\napiVersion: image.toolkit.fluxcd.io\u002Fv1beta2\nkind: ImagePolicy\nmetadata:\n  name: user-service\nspec:\n  imageRepositoryRef:\n    name: user-service\n  policy:\n    semver:\n      range: \">=1.0.0\"\n```\n\nSee [references\u002Fgitops-patterns.md](references\u002Fgitops-patterns.md) for complete manifests and [templates\u002Fgitops-config.md](templates\u002Fgitops-config.md) for ready-to-use templates.\n\n## Step 4: Implement Progressive Delivery\n\nLayer progressive delivery on top of GitOps for safer production rollouts. This step is optional for lightweight setups but critical at scale.\n\n**Argo Rollouts (works with ArgoCD):**\n\n```yaml\napiVersion: argoproj.io\u002Fv1alpha1\nkind: Rollout\nmetadata:\n  name: user-service\nspec:\n  strategy:\n    canary:\n      steps:\n        - setWeight: 10       # Send 10% of traffic to new version\n        - pause: { duration: 5m }\n        - analysis:\n            templates:\n              - templateName: success-rate\n        - setWeight: 50\n        - pause: { duration: 10m }\n        - analysis:\n            templates:\n              - templateName: success-rate\n      # Auto-rollback if analysis fails\n```\n\n**Analysis template (gate on metrics):**\n\n```yaml\napiVersion: argoproj.io\u002Fv1alpha1\nkind: AnalysisTemplate\nmetadata:\n  name: success-rate\nspec:\n  metrics:\n    - name: success-rate\n      interval: 1m\n      successCondition: result[0] >= 0.99\n      provider:\n        prometheus:\n          address: http:\u002F\u002Fprometheus:9090\n          query: |\n            sum(rate(http_requests_total{service=\"user-service\",status=~\"2..\"}[5m]))\n            \u002F\n            sum(rate(http_requests_total{service=\"user-service\"}[5m]))\n```\n\n**Flagger (works with Flux):** Similar concept — canary analysis using Prometheus, Datadog, or other metrics providers. Flagger automatically manages the canary\u002Fprimary services and traffic splitting.\n\n**When to skip progressive delivery:** Dev and staging environments (just deploy directly). Small teams with low traffic. Services with comprehensive E2E tests that catch issues before deploy.\n\n## Step 5: Validate End-to-End\n\nTest the full GitOps pipeline:\n\n- [ ] **Trigger flow**: Merge a change in an app repo -> verify a PR appears in the deployment repo\n- [ ] **Contract validation**: The deployment repo PR CI runs contract tests against the new version combination\n- [ ] **GitOps sync**: After merging the deployment repo PR, the operator detects the change and syncs\n- [ ] **Health checks**: The operator reports healthy status after sync\n- [ ] **Drift detection**: Manually modify a resource in the cluster -> verify the operator reverts it\n- [ ] **Rollback**: Revert a commit in the deployment repo -> verify the operator rolls back the cluster\n- [ ] **Sync windows** (if configured): Verify syncs are blocked outside allowed windows\n- [ ] **Progressive delivery** (if configured): Verify canary analysis runs and gates promotion\n\n**Monitoring the GitOps pipeline:**\n- ArgoCD: Built-in UI shows sync status, health, and history per Application\n- Flux: `flux get kustomizations` shows reconciliation status\n- Both: Export metrics to Prometheus for alerting on sync failures\n\n## Principles Applied\n\n- **Git is the source of truth**: If it's not in Git, it doesn't exist. No `kubectl edit` in production, no manual Helm upgrades.\n- **Pull over push**: The cluster pulls desired state from Git rather than CI pushing to the cluster. This inverts the security model — the cluster needs Git read access, not the other way around.\n- **KISS**: Start with a single ArgoCD Application per environment. Add App of Apps, sync waves, and progressive delivery as complexity demands.\n- **YAGNI**: Don't set up Argo Rollouts for a service with 10 requests per minute. Don't configure multi-cluster GitOps for a single cluster.\n- **Declarative over imperative**: Define the desired state, let the operator figure out how to get there. Avoid custom sync scripts.\n\n## Cross-Skill References\n\n- `deployment-repo` — pinned versions and declarative manifests in Git, **valuable with or without an operator**: it is what ArgoCD\u002FFlux watch if you adopt GitOps, and the reproducibility\u002Frollback substrate if you stay push-based. Design the repo structure first either way.\n- `cicd-pipeline` — cross-repo trigger pipelines that update the deployment repo on new builds\n- `rollback-strategy` — in GitOps, rollback = revert a Git commit; the operator handles the rest\n- `observability-design` — metrics and dashboards for monitoring sync status, drift, and progressive delivery analysis\n- `containerization` — Helm chart structure and Kustomize overlay patterns used by the operator\n- `infrastructure-as-code` — Terraform for cluster and infrastructure provisioning (separate from app deployment)\n",{"name":5,"description":7},"main","800dc9ad0ca2914d6ad15b8c5159d9b57bb104c2","skills\u002Fgitops-delivery","https:\u002F\u002Fgithub.com\u002FSWEStash\u002Fswe-workflow-skills","https:\u002F\u002Fgithub.com\u002FSWEStash","A stash of things we felt like building","2026-11-12 00:14:33",{"source":8,"skillName":5,"commands":60,"prompt":70,"zipAvailable":71},[61,64,67],{"tool":62,"command":63},"npx","npx skills add SWEStash\u002Fswe-workflow-skills --skill gitops-delivery",{"tool":65,"command":66},"bunx","bunx skills add SWEStash\u002Fswe-workflow-skills --skill gitops-delivery",{"tool":68,"command":69},"pnpm","pnpm dlx skills add SWEStash\u002Fswe-workflow-skills --skill gitops-delivery","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FSWEStash\u002Fswe-workflow-skills\u002Fblob\u002Fmain\u002Fskills\u002Fgitops-delivery\u002FSKILL.md",true,[73,79,83],{"path":74,"resourceType":75,"resourceTypeDesc":76,"sizeBytes":77,"sourceHtmlUrl":78},"evals\u002Fevals.json","REFERENCE","参考文档",3072,"https:\u002F\u002Fgithub.com\u002FSWEStash\u002Fswe-workflow-skills\u002Fblob\u002Fmain\u002Fskills\u002Fgitops-delivery\u002Fevals\u002Fevals.json",{"path":80,"resourceType":75,"resourceTypeDesc":76,"sizeBytes":81,"sourceHtmlUrl":82},"references\u002Fgitops-patterns.md",12219,"https:\u002F\u002Fgithub.com\u002FSWEStash\u002Fswe-workflow-skills\u002Fblob\u002Fmain\u002Fskills\u002Fgitops-delivery\u002Freferences\u002Fgitops-patterns.md",{"path":84,"resourceType":75,"resourceTypeDesc":76,"sizeBytes":85,"sourceHtmlUrl":86},"templates\u002Fgitops-config.md",5305,"https:\u002F\u002Fgithub.com\u002FSWEStash\u002Fswe-workflow-skills\u002Fblob\u002Fmain\u002Fskills\u002Fgitops-delivery\u002Ftemplates\u002Fgitops-config.md",[88,130,156,179,209,239],{"skillNo":89,"name":90,"nameZh":6,"description":91,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":92,"categories":93,"keywords":109,"publishedAt":47},"01M6JQFADV3T1MS9V1BNZS1232","writing-skills","Use when authoring, editing, or reviewing a skill in this library — a new SKILL.md, one that under-triggers, or hardening an existing one. Covers description and listing-budget rules, frontmatter, progressive disclosure, the 3-eval rule, and pressure-testing against rationalizations.","https:\u002F\u002Fgithub.com\u002FSWEStash\u002Fswe-workflow-skills\u002Fblob\u002Fmain\u002Fskills\u002Fwriting-skills\u002FSKILL.md",[94,97,100,101,106],{"categoryNo":95,"categoryName":96,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":98,"categoryName":99,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000018","写作与文案",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":102,"categoryName":103,"taxonomyType":104,"taxonomyTypeDesc":105},"01JBSEEDCAT000000000000036","内容创作者","PROFESSION","适用职业",{"categoryNo":107,"categoryName":108,"taxonomyType":104,"taxonomyTypeDesc":105},"01JBSEEDCAT000000000000040","财务",[110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129],"writing","writing skills","testing","eval","write","edit","Budget","authoring","new skill","library","frontmatter","editing","triggers","use","Existing","Rules","write a skill","when","listing","progressive disclosure",{"skillNo":131,"name":132,"nameZh":6,"description":133,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":134,"categories":135,"keywords":137,"publishedAt":47},"01M6JQF5DGMXPMQQVZBP8DH9SY","working-agreement","Define and validate how a multi-session project is run — where plans, status and decisions live, session routines, new work, milestone close. README\u002FCONTRIBUTING → project-documentation.","https:\u002F\u002Fgithub.com\u002FSWEStash\u002Fswe-workflow-skills\u002Fblob\u002Fmain\u002Fskills\u002Fworking-agreement\u002FSKILL.md",[136],{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},[138,139,140,141,142,143,144,145,146,147,148,149,46,150,151,152,153,154,122,155],"working agreement","project","definition of done","done","milestone","documentation","work","progress","how","contributing","close","run","status","live","do","README","session","routines",{"skillNo":157,"name":158,"nameZh":6,"description":159,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":160,"categories":161,"keywords":163,"publishedAt":47},"01M6JQF0SMRHN82RBSWMABC4J0","verification-before-completion","Evidence gate before any claim that work is done, fixed, passing, or deployed. Route here when a message declares the work finished or asks to commit, push, merge, ship, or close it out, including a brief sign-off, and before git-workflow or release-management act on it. Writing the commit message or PR text itself → git-workflow.","https:\u002F\u002Fgithub.com\u002FSWEStash\u002Fswe-workflow-skills\u002Fblob\u002Fmain\u002Fskills\u002Fverification-before-completion\u002FSKILL.md",[162],{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},[164,165,166,167,168,169,110,170,141,171,172,173,144,174,148,175,176,44,177,178],"verification","verification before completion","brief","ready","fix","claim","workflow","commit","text","route","message","merge","release","act","ship",{"skillNo":180,"name":181,"nameZh":6,"description":182,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":183,"categories":184,"keywords":190,"publishedAt":47},"01M6JQEVGE9NJZ11DV60AE6VWC","ui-ux-design","Design user experiences from an engineer's perspective — user flows, wireframes, interaction patterns, responsive strategy, navigation, loading\u002Ferror\u002Fempty states. Triggers: design the UI, user flow, wireframe, how should this screen look, loading state, error state, empty state, responsive design, navigation, page layout, form design, mockup.","https:\u002F\u002Fgithub.com\u002FSWEStash\u002Fswe-workflow-skills\u002Fblob\u002Fmain\u002Fskills\u002Fui-ux-design\u002FSKILL.md",[185,186,187],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":188,"categoryName":189,"taxonomyType":104,"taxonomyTypeDesc":105},"01JBSEEDCAT000000000000032","设计师",[37,191,192,193,194,195,196,197,198,199,200,201,146,202,203,204,205,206,207,208],"ux","ui","ui ux design","error","states","loading","flows","engineer","interaction","layout","responsive design","screen","flow","patterns","mockup","responsive","form","page",{"skillNo":210,"name":211,"nameZh":6,"description":212,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":213,"categories":214,"keywords":219,"publishedAt":47},"01M6JQEN4HVFTZWQYWGTDS76K9","threat-modeling","Design-time security analysis of a system or feature before it's built — trust boundaries, attack surface, STRIDE per element, abuse cases, prioritized mitigations that become security requirements. Triggers: threat model, STRIDE, trust boundary, attack surface, what could go wrong security-wise, security design review, abuse case, secure this design, security requirements. Reviewing EXISTING code\u002Fconfig for vulnerabilities → security-audit; use this skill while the design is still on the whiteboard.","https:\u002F\u002Fgithub.com\u002FSWEStash\u002Fswe-workflow-skills\u002Fblob\u002Fmain\u002Fskills\u002Fthreat-modeling\u002FSKILL.md",[215,216],{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":217,"categoryName":218,"taxonomyType":104,"taxonomyTypeDesc":105},"01JBSEEDCAT000000000000030","开发工程师",[220,221,222,223,224,225,37,226,227,228,229,230,231,232,233,234,235,236,237,238],"modeling","threat modeling","threat","model","time","element","whiteboard","security analysis","analysis","code","review","threat model","audit","security-audit","secure","config","go","security","trust",{"skillNo":240,"name":241,"nameZh":6,"description":242,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":243,"categories":244,"keywords":250,"publishedAt":47},"01M6JQEFT7VT3FQM16170EG9FW","test-suite-design","Design comprehensive test suites for existing code — strategy across unit\u002Fintegration\u002Fe2e, fixtures, factories, helpers. Triggers: add tests, write tests for, increase coverage, test this module, testing strategy, test plan, what tests do I need, test infrastructure, test helpers, this has no tests. Not for TDD — use tdd-workflow.","https:\u002F\u002Fgithub.com\u002FSWEStash\u002Fswe-workflow-skills\u002Fblob\u002Fmain\u002Fskills\u002Ftest-suite-design\u002FSKILL.md",[245,246,247,248,249],{"categoryNo":95,"categoryName":96,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":217,"categoryName":218,"taxonomyType":104,"taxonomyTypeDesc":105},{"categoryNo":188,"categoryName":189,"taxonomyType":104,"taxonomyTypeDesc":105},[37,251,252,253,254,255,112,256,257,170,229,258,259,114,260,261,152,262,263,122],"test suite","test","test suite design","coverage","unit","write tests","testing strategy","across","plan","add","infrastructure","test plan","for"]