Skip to content

ci: analyze-disruption: root-cause attribution rules, onset/suspect-PR step, existing-bug discovery - #655

Open
mkowalski wants to merge 1 commit into
openshift-eng:mainfrom
mkowalski:harden-analyze-disruption
Open

ci: analyze-disruption: root-cause attribution rules, onset/suspect-PR step, existing-bug discovery#655
mkowalski wants to merge 1 commit into
openshift-eng:mainfrom
mkowalski:harden-analyze-disruption

Conversation

@mkowalski

@mkowalski mkowalski commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Summary

Recent AI-assisted Component Readiness triage duty for 5.0-main surfaced several root-cause-attribution failure modes that cost real time (regressions attached to the wrong bug, a router change blamed for an etcd defect, a duplicate bug filed for an already-fixed issue). Most of them apply directly to disruption analysis, which is symptom-chain work by nature. This PR folds those lessons into analyze-disruption.

Related: #651 (same lessons applied to the prow-job-analysis / triage-adjacent skills); #635 (the bulk-triage skill where they were learned).

Changes

Step 5.6 (new) — Root-Cause Attribution Rules

  • Victim-vs-owner with corroboration: a disrupted/crash-looping component whose error names a missing upstream dependency is usually a victim — but check the provider's actual health (CO conditions, APIService, endpoints) before reassigning, because RBAC/config faults masquerade as dependency errors (real cases in both directions: router→apiserver→etcd, and a capi-installer crash-looping on its own configmaps is forbidden RBAC bug).
  • clusteroperators.json as the end-state oracle: pods Running proves nothing about whether cluster etcd/apiservers were serving.
  • Extract condition messages: ClusterVersion/ClusterOperator interval entries carry the controller error string that names the culprit — quote it, don't stop at the Available=False flip.
  • *_previous.log is mandatory reading for any container that restarted in the disruption window.
  • Count condition transitions: ~1s-interval flapping is a sync-loop bug (permafail class), not a transient.

Step 7.3 (new) — Onset Determination and Suspect PRs for new/worsening disruption: clean-vs-disrupted payload comparison (including initial/target skew on upgrade jobs — a real regression was pure skew between a pre-GA base and post-GA target), fetch-new-prs-in-payload vetting, and the revert-PR shortcut (a fresh Revert "..." citing a TRT/OCPBUGS key yields trigger PR + tracking ticket + recovery ETA in one query). Unanchored "unidentified payload change" claims are banned.

Step 7.4 (new) — Existing Bugs and Known Disruption Families: fetch-related-triages with verify-before-adopt (confidence is clustering, not root cause), component-scoped JIRA listing (owning teams write summaries in developer vocabulary that keyword search misses — the exact mechanism behind a real duplicate filing), and the recurring disruption families to rule out first (etcd/Azure disk pressure, OVN upgrade CNI gaps, single-node OVS stalls, cloud LB churn).

Report templates: both Root Cause Hypothesis sections now require the full causal chain, the 5.6 corroboration evidence, and existing-ticket references.

Also bumps the ci plugin version (0.0.74 → 0.0.75).


AI-generated content: This PR was created by AI based on lessons from AI-assisted triage duty. Please verify before acting on it.

Summary by CodeRabbit

  • Documentation

    • Improved disruption analysis guidance for identifying root causes, affected components, and the timing of incidents.
    • Added instructions for using condition messages, prior logs, change history, and existing known issues as supporting evidence.
    • Updated report templates to require clearer evidence and attribution.
  • Chores

    • Updated the CI plugin version to 0.0.75.

…R step, existing-bug discovery

Fold the lessons from recent Component Readiness triage duty into the
disruption analysis skill:

- Step 5.6 (new): attribution rules — victim-vs-owner with upstream
  corroboration (dependency-error crash-loopers are usually victims, but
  check the provider's health before reassigning; RBAC/config faults
  masquerade as dependency errors), clusteroperators.json as the
  end-state oracle (pod existence proves nothing about etcd/apiserver
  serving), extract ClusterVersion/ClusterOperator condition *messages*
  (they name the culprit controller), read *_previous.log for any
  container restarted in the window, and count condition transitions
  (sync-loop flap vs slow rollout).
- Step 7.3 (new): onset determination for new/worsening disruption —
  clean-vs-disrupted payload delta (incl. initial/target skew on upgrade
  jobs), fetch-new-prs-in-payload vetting, and the revert-PR shortcut
  (fresh reverts citing TRT/OCPBUGS keys yield trigger + ticket in one
  query); bans unanchored 'unidentified payload change' claims.
- Step 7.4 (new): existing-bug discovery — fetch-related-triages with
  verify-before-adopt, component-scoped JIRA listing (developer
  vocabulary defeats keyword search), and the known recurring disruption
  families to rule out first.
- Report templates: Root Cause Hypothesis sections now require the full
  causal chain, the Step 5.6 corroboration, and existing-ticket
  references.
@openshift-ci
openshift-ci Bot requested review from smg247 and stleerh July 28, 2026 19:13
@openshift-ci

openshift-ci Bot commented Jul 28, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: mkowalski
Once this PR has been reviewed and has the lgtm label, please assign prashanth684 for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

The CI plugin version was incremented, and the disruption-analysis skill gained expanded root-cause attribution, onset analysis, known-issue checks, and updated single-run and multi-run report requirements.

Changes

CI disruption guidance

Layer / File(s) Summary
Plugin manifest version
plugins/ci/.claude-plugin/plugin.json
The plugin version is updated from 0.0.74 to 0.0.75.
Disruption analysis workflow
plugins/ci/skills/analyze-disruption/SKILL.md
Root-cause attribution rules, onset and suspect-PR analysis, existing-bug checks, and related report-template requirements are added or revised.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested labels: ok-to-test

Suggested reviewers: stbenjam, bryan-cox

🚥 Pre-merge checks | ✅ 10
✅ Passed checks (10 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main analyze-disruption documentation update and plugin version bump.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
No Real People Names In Style References ✅ Passed The changed plugin manifest and analyze-disruption docs contain no real-person names used as style references or examples.
No Assumed Git Remote Names ✅ Passed No hardcoded git remote names appear in the changed files; origin/upstream are used only in non-git prose, not git fetch/push/remote commands.
Git Push Safety Rules ✅ Passed The PR only updates disruption-analysis docs and a version string; no git push, force-push, or branch-push instructions were added.
No Untrusted Mcp Servers ✅ Passed Only a version bump and documentation changes were introduced; no MCP server installs, dependencies, or npx-based server additions appear in the diff.
Ai-Helpers Overlap Detection ✅ Passed Open PR #651 is adjacent but targets different skills, and existing regression/triage docs are related guidance rather than duplicate disruption functionality.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@plugins/ci/skills/analyze-disruption/SKILL.md`:
- Around line 325-333: Revise the guidance in the provider-corroboration rule so
provider health is evidence rather than an ownership verdict. Require a
time-correlated provider failure and trace dependencies to the first independent
fault before assigning ownership; likewise, do not conclude the victim is
responsible solely because the provider appears healthy.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 0a773c56-0b45-4439-9e8d-e23376a17249

📥 Commits

Reviewing files that changed from the base of the PR and between 7e71338 and d92d4a9.

📒 Files selected for processing (2)
  • plugins/ci/.claude-plugin/plugin.json
  • plugins/ci/skills/analyze-disruption/SKILL.md

Comment on lines +325 to +333
1. **A component whose error names a missing upstream dependency is a victim, not an owner —
but corroborate before reassigning.** If a disrupted backend's serving pods log
"cannot list/watch/reach X" (e.g., a router crash-looping on
`failed to list *v1.Route: the server could not find the requested resource`), check X's
provider directly (ClusterOperator conditions, APIService availability, endpoints) before
blaming either side: provider unhealthy → the disruption belongs upstream (in one real case,
router disruption traced through openshift-apiserver to etcd never deploying its static
pods); provider healthy → the fault is inside the "victim" after all (RBAC — a real
crash-looper failed on `configmaps is forbidden` — client config, or network reachability).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep provider health as corroborating evidence, not an ownership verdict.

The provider unhealthy → disruption belongs upstream rule can misattribute shared lower-level failures or downstream symptoms. Require time-correlated provider failure and continue tracing to the first independent fault before assigning ownership; likewise, provider health alone should not prove the victim is at fault.

Proposed wording
- provider unhealthy → the disruption belongs upstream
+ provider unhealthy → supports an upstream hypothesis; continue tracing to the first independent fault
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
1. **A component whose error names a missing upstream dependency is a victim, not an owner —
but corroborate before reassigning.** If a disrupted backend's serving pods log
"cannot list/watch/reach X" (e.g., a router crash-looping on
`failed to list *v1.Route: the server could not find the requested resource`), check X's
provider directly (ClusterOperator conditions, APIService availability, endpoints) before
blaming either side: provider unhealthy → the disruption belongs upstream (in one real case,
router disruption traced through openshift-apiserver to etcd never deploying its static
pods); provider healthy → the fault is inside the "victim" after all (RBAC — a real
crash-looper failed on `configmaps is forbidden` — client config, or network reachability).
1. **A component whose error names a missing upstream dependency is a victim, not an owner —
but corroborate before reassigning.** If a disrupted backend's serving pods log
"cannot list/watch/reach X" (e.g., a router crash-looping on
`failed to list *v1.Route: the server could not find the requested resource`), check X's
provider directly (ClusterOperator conditions, APIService availability, endpoints) before
blaming either side: provider unhealthy → supports an upstream hypothesis; continue tracing to the first independent fault (in one real case, router disruption traced through openshift-apiserver to etcd never deploying its static
pods); provider healthy → the fault is inside the "victim" after all (RBAC — a real
crash-looper failed on `configmaps is forbidden` — client config, or network reachability).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/ci/skills/analyze-disruption/SKILL.md` around lines 325 - 333, Revise
the guidance in the provider-corroboration rule so provider health is evidence
rather than an ownership verdict. Require a time-correlated provider failure and
trace dependencies to the first independent fault before assigning ownership;
likewise, do not conclude the victim is responsible solely because the provider
appears healthy.

@openshift-ci openshift-ci Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jul 30, 2026
@openshift-ci

openshift-ci Bot commented Jul 30, 2026

Copy link
Copy Markdown

PR needs rebase.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant