The impact is stated in one sentence: which pipelines are failing, which environments are blocked, which deploys are paused, for whom, since when. Everything else is secondary to this.
Scope is established across the CI/CD stack: source (git hosting), pipeline (runner, control plane), build (image, dependency, cache), artifact (registry, signature), deployment (controller, sync), or environment (cluster, runtime). The scope eliminates most hypotheses.
Recent changes are listed: pipeline definition, runner image, third-party action version, controller manifest, secret, registry policy, certificate. Most CI/CD incidents are a change, and the change is usually recent. git log --since="24 hours ago" -- .github/workflows/ .gitlab-ci.yml Jenkinsfile argocd/ flux/; kubectl rollout history deployment -n argocd; kubectl get events -n argocd --sort-by=.metadata.creationTimestampEvidence is captured before remediation: pipeline run logs (full, not truncated), controller logs (`kubectl logs -n argocd`), runner system logs, sync state, registry response, and the exact error string. A retry or queue drain destroys evidence. kubectl logs -n argocd -l app.kubernetes.io/name=argocd-application-controller --tail=500 --since=1h > /tmp/controller.log; gh run view <run-id> --log > /tmp/pipeline.logNo retry, no rebuild, no "let me just run it again" happens before the failure is captured. A second failure is not the same evidence as the first.
A determination is made: is the failure reproducible on a fresh pipeline run, or is it transient? Reproducible failures point at code, configuration, or environment; transient failures point at runners, network, or external dependencies.
For a "image won't deploy" or "image won't run" symptom, the artifact identity is verified: tag matches the expected one, digest matches the registry record, signature is valid, attestation is present. crane digest ghcr.io/<org>/<image>:<tag>; cosign verify --certificate-identity-regexp "https://github.com/<org>/<repo>" --certificate-oidc-issuer "https://token.actions.githubusercontent.com" ghcr.io/<org>/<image>@sha256:<digest>For a GitOps symptom, the controller state is checked: `argocd app get <app> --refresh` and `argocd app manifests <app>` show what the controller believes is the desired state and what it sees in the cluster. A diff between the two is the answer.
External dependencies (git hosting, registry, OIDC issuer, secret manager, KMS, container registry mirror, time server) are healthy and have not changed. A flaky third party often looks like a CI/CD bug.
A hypothesis is stated in one sentence that the evidence supports and that predicts something testable. The next action is chosen to confirm or refute the hypothesis, not to act on the first plausible story.
Mitigation precedes root-cause fix. A broken production deploy is mitigated (rollback, pause pipeline, freeze controller) before the team starts searching for why. Service and search are separate activities with different urgencies.
One thing is changed at a time. Parallel changes make the eventual post-mortem unresolvable. The change log is kept inline with the chat or ticket, not in someone's head.
Recovery is verified through the user-visible symptom (deploy succeeded, cluster reconciled, alert resolved) and not through the component that was changed. The pipeline being green does not mean the deploy ran.
A post-mortem is filed while detail is fresh (within 5 business days), with an owner, a date, contributing factors, root cause, and prevention actions. The post-mortem distinguishes what was known at the time from what was known afterwards.