Skip to content

Add ci:fetch-payloads and ci:analyze-payload skills - #337

Merged
openshift-merge-bot[bot] merged 19 commits into
openshift-eng:mainfrom
stbenjam:analyze-payload
Feb 27, 2026
Merged

openshift-merge-bot[bot] merged 19 commits into
openshift-eng:mainfrom
stbenjam:analyze-payload

Conversation

@stbenjam

@stbenjam stbenjam commented Feb 26, 2026

Copy link
Copy Markdown
Member

Summary

  • Add ci:fetch-payloads skill for querying the OpenShift release controller API for recent payloads by architecture, version, and stream
  • Add ci:analyze-payload command that finds the latest rejected payload, investigates every failed blocking job in parallel, performs historical lookback through consecutive rejected payloads, correlates failures with newly introduced PRs, and generates a self-contained HTML report
  • The analyze-payload skill checks whether revert candidates have already been reverted before recommending a revert, reporting the revert PR's state (open/merged) and timing relative to the payload

New Commands

/ci:fetch-payloads [architecture] [version] [stream]

Lists recent payloads with their acceptance phase, failed blocking jobs, and Prow links.

/ci:analyze-payload [architecture] [version] [stream] [--lookback N]

Produces an HTML report with:

  • Executive summary of payload health
  • Historical lookback to identify when each failure first appeared
  • Per-job root cause analysis (install vs test failure, run in parallel)
  • PR correlation to identify suspect commits in originating payloads
  • Revert recommendations with confidence levels, with checks for already-existing reverts

@openshift-ci
openshift-ci Bot requested review from bryan-cox and zaneb February 26, 2026 13:26
@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Feb 26, 2026
@coderabbitai

coderabbitai Bot commented Feb 26, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a new CI plugin command and skill fetch-payloads with implementation, docs, and metadata; also adds comprehensive docs for analyze-payload skill/command and bumps plugin manifest versions.

Changes

Cohort / File(s) Summary
Command & Skill Docs
PLUGINS.md, plugins/ci/commands/fetch-payloads.md, plugins/ci/skills/fetch-payloads/SKILL.md, plugins/ci/commands/analyze-payload.md, plugins/ci/skills/analyze-payload/SKILL.md
Added documentation for fetch-payloads (usage, args, examples, output format, errors) and large new analyze-payload docs detailing end-to-end analysis workflow, outputs, and failure handling.
Skill Implementation
plugins/ci/skills/fetch-payloads/fetch_payloads.py
New Python implementation for fetch-payloads: builds stream names, queries release controller, optionally fetches latest version from Sippy API, supports CLI flags (architecture, version, stream, limit, phase), formats tab-separated output, and reports blocking-job details for Rejected payloads with error handling.
Metadata / Marketplace / Manifest
docs/data.json, .claude-plugin/marketplace.json, plugins/ci/.claude-plugin/plugin.json
Added fetch-payloads command and skill entries in docs/metadata and bumped plugin versions (docs/data.json and marketplace.json -> 0.0.8; plugins/ci/.claude-plugin/plugin.json -> 0.0.9).

Sequence Diagram

sequenceDiagram
    participant User
    participant CLI as "CLI Handler"
    participant Sippy as "Sippy API"
    participant RC as "Release Controller"
    participant Output

    User->>CLI: /ci:fetch-payloads [architecture] [version] [stream]
    CLI->>CLI: validate inputs & set defaults
    alt version not provided
        CLI->>Sippy: GET latest OCP version
        Sippy-->>CLI: return version
    end
    CLI->>RC: GET release tags (architecture, version, stream)
    RC-->>CLI: list of tags
    loop per tag
        alt tag phase is Rejected
            CLI->>RC: GET release details (blocking jobs)
            RC-->>CLI: release details
        end
        CLI->>CLI: format line (tag, phase, URL, optional blockers)
    end
    CLI->>Output: emit tab-separated results
    Output-->>User: display payloads
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

🚥 Pre-merge checks | ✅ 8
✅ Passed checks (8 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 90.00% which is sufficient. The required threshold is 80.00%.
No Real People Names In Style References ✅ Passed PR review confirms no real people's names used as style references or examples in documentation, Python implementation, or metadata updates.
No Assumed Git Remote Names ✅ Passed New PR files contain no hardcoded git remote name assumptions; code uses only HTTP API calls to OpenShift release controller and Sippy API.
Git Push Safety Rules ✅ Passed The PR does not violate Git push safety rules. New code only retrieves data via HTTP APIs with no git operations. The analyze-payload command recommends reverts but does not autonomously execute git push operations.
No Untrusted Mcp Servers ✅ Passed PR does not introduce untrusted MCP server installations. Changes are limited to documentation and Python implementation using only standard library imports.
Ai-Helpers Overlap Detection ✅ Passed PR adds entirely new ai-helpers files (fetch-payloads and analyze-payload commands/skills) with no overlapping functionality detected in existing repository content.
Title check ✅ Passed The title accurately summarizes the main changes: adding two new CI skills (fetch-payloads and analyze-payload) with corresponding commands and documentation.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

@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: 2

🧹 Nitpick comments (2)
plugins/ci/skills/fetch-payloads/fetch_payloads.py (1)

33-37: Remove extraneous f prefix from string literal.

The f-string on line 34 has no placeholders, so the f prefix is unnecessary.

🧹 Proposed fix
     if stream == "ci" and architecture != "amd64":
         print(
-            f"Error: The 'ci' stream is only available for amd64.",
+            "Error: The 'ci' stream is only available for amd64.",
             file=sys.stderr,
         )
         sys.exit(1)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/ci/skills/fetch-payloads/fetch_payloads.py` around lines 33 - 37, The
print statement in fetch_payloads.py is using an unnecessary f-string: remove
the leading "f" from the string literal inside the print call (the one printing
"Error: The 'ci' stream is only available for amd64.") so it becomes a normal
string; update the print(...) invocation (and keep the subsequent sys.exit(1))
accordingly.
plugins/ci/commands/fetch-payloads.md (1)

12-14: Consider adding language specifiers to fenced code blocks.

The markdownlint tool flags these code blocks as missing language specifiers (MD040). Adding text or leaving them empty with a trailing space can silence these warnings.

Also applies to: 43-45, 48-50

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/ci/commands/fetch-payloads.md` around lines 12 - 14, Update the
fenced code blocks in fetch-payloads.md (the snippets like "/ci:fetch-payloads
[architecture] [version] [stream]" and the other blocks flagged around the file)
to include a language specifier such as "text" (e.g., ```text) or add a trailing
space after the opening backticks (``` ) to satisfy markdownlint MD040; ensure
all similar fenced blocks (the ones flagged at the other locations) are updated
consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/ci/commands/fetch-payloads.md`:
- Around line 52-55: The "Only accepted payloads" example currently shows the
command '/ci:fetch-payloads amd64 4.23 nightly' but does not apply the described
filter; update the example to either change the title to match the shown command
or (preferably) add the filter flag so it reads '/ci:fetch-payloads amd64 4.23
nightly --phase Accepted' so the example matches the "Only accepted payloads"
behavior.

In `@plugins/ci/skills/fetch-payloads/fetch_payloads.py`:
- Around line 157-163: get_latest_version() currently filters releases into
ocp_releases then returns ocp_releases[0] without guaranteeing order; change it
to explicitly pick the highest semver by sorting or using max with a
semantic-version key (e.g., packaging.version.Version or tuple(map(int, ...)))
so you reliably return the newest release; update the code that builds
ocp_releases and replace the final return ocp_releases[0] with a semver-aware
selection (e.g., sorted(ocp_releases, key=semver_key, reverse=True)[0] or
max(ocp_releases, key=semver_key)).

---

Nitpick comments:
In `@plugins/ci/commands/fetch-payloads.md`:
- Around line 12-14: Update the fenced code blocks in fetch-payloads.md (the
snippets like "/ci:fetch-payloads [architecture] [version] [stream]" and the
other blocks flagged around the file) to include a language specifier such as
"text" (e.g., ```text) or add a trailing space after the opening backticks (```
) to satisfy markdownlint MD040; ensure all similar fenced blocks (the ones
flagged at the other locations) are updated consistently.

In `@plugins/ci/skills/fetch-payloads/fetch_payloads.py`:
- Around line 33-37: The print statement in fetch_payloads.py is using an
unnecessary f-string: remove the leading "f" from the string literal inside the
print call (the one printing "Error: The 'ci' stream is only available for
amd64.") so it becomes a normal string; update the print(...) invocation (and
keep the subsequent sys.exit(1)) accordingly.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 6524bea and 83f1105.

📒 Files selected for processing (5)
  • PLUGINS.md
  • docs/data.json
  • plugins/ci/commands/fetch-payloads.md
  • plugins/ci/skills/fetch-payloads/SKILL.md
  • plugins/ci/skills/fetch-payloads/fetch_payloads.py

Comment thread plugins/ci/commands/fetch-payloads.md
Comment thread plugins/ci/skills/fetch-payloads/fetch_payloads.py Outdated

@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.

♻️ Duplicate comments (1)
plugins/ci/skills/fetch-payloads/fetch_payloads.py (1)

157-163: ⚠️ Potential issue | 🟠 Major

Add explicit sorting to reliably return the latest version.

The function returns ocp_releases[0] assuming the Sippy API returns releases in descending order, but this ordering is not guaranteed by the API. Without explicit sorting, an older version could be returned.

Suggested fix
     releases = data.get("releases", [])
     ocp_releases = [r for r in releases if re.match(r"^\d+\.\d+$", r)]
     if not ocp_releases:
         print("Error: No OCP releases found in Sippy API.", file=sys.stderr)
         sys.exit(1)
 
-    return ocp_releases[0]
+    # Sort by version (major.minor) descending to get latest
+    ocp_releases.sort(key=lambda v: tuple(map(int, v.split("."))), reverse=True)
+    return ocp_releases[0]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/ci/skills/fetch-payloads/fetch_payloads.py` around lines 157 - 163,
The code currently returns ocp_releases[0] assuming API order; change this to
explicitly sort ocp_releases in descending semantic-version order before
returning the first element. Locate where releases and ocp_releases are
computed, then sort ocp_releases using a semver-aware comparator (e.g., parse
each "X.Y" into numeric parts or use packaging.version.Version) with
reverse=True so the highest/most recent release is at index 0, and return that
sorted[0] value instead of the unsorted ocp_releases[0].
🧹 Nitpick comments (3)
plugins/ci/skills/fetch-payloads/SKILL.md (1)

50-52: Add language specifier to fenced code block.

The code block showing the output format should have a language identifier to satisfy markdownlint (MD040).

Suggested fix
-```
+```text
 <payload_tag>\t<phase>\t<url>
 ```
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/ci/skills/fetch-payloads/SKILL.md` around lines 50 - 52, The fenced
code block showing the output format lacks a language specifier; update the
block in SKILL.md that contains "<payload_tag>\t<phase>\t<url>" to include a
language identifier (e.g., "text") after the opening backticks so markdownlint
MD040 is satisfied and the snippet is treated as plain text.
plugins/ci/skills/fetch-payloads/fetch_payloads.py (1)

32-37: Remove unnecessary f-string prefix.

Line 34 uses an f-string but has no placeholders. This is flagged by Ruff (F541).

Suggested fix
     if stream == "ci" and architecture != "amd64":
         print(
-            f"Error: The 'ci' stream is only available for amd64.",
+            "Error: The 'ci' stream is only available for amd64.",
             file=sys.stderr,
         )
         sys.exit(1)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/ci/skills/fetch-payloads/fetch_payloads.py` around lines 32 - 37, The
print call in fetch_payloads.py uses an unnecessary f-string in the error
message (inside the if block that checks stream == "ci" and architecture !=
"amd64"); update the print invocation in that block to use a plain string
literal (remove the leading f from the message) while keeping the same
file=sys.stderr and sys.exit(1) behavior so Ruff F541 is resolved.
plugins/ci/commands/fetch-payloads.md (1)

12-14: Consider adding language specifiers to code blocks.

Several fenced code blocks are missing language identifiers (markdownlint MD040). Adding bash for command examples would improve syntax highlighting.

Also applies to: 43-45, 48-50

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/ci/commands/fetch-payloads.md` around lines 12 - 14, Several fenced
code blocks in the document lack language specifiers (markdownlint MD040);
update each triple-backtick block that contains command examples (e.g., the
block showing "/ci:fetch-payloads [architecture] [version] [stream]" and the
other command examples referenced around the file) to include a language tag
such as bash (```bash) so command syntax is highlighted; locate the code fences
by searching for the literal command strings and add the language identifier to
their opening backticks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@plugins/ci/skills/fetch-payloads/fetch_payloads.py`:
- Around line 157-163: The code currently returns ocp_releases[0] assuming API
order; change this to explicitly sort ocp_releases in descending
semantic-version order before returning the first element. Locate where releases
and ocp_releases are computed, then sort ocp_releases using a semver-aware
comparator (e.g., parse each "X.Y" into numeric parts or use
packaging.version.Version) with reverse=True so the highest/most recent release
is at index 0, and return that sorted[0] value instead of the unsorted
ocp_releases[0].

---

Nitpick comments:
In `@plugins/ci/commands/fetch-payloads.md`:
- Around line 12-14: Several fenced code blocks in the document lack language
specifiers (markdownlint MD040); update each triple-backtick block that contains
command examples (e.g., the block showing "/ci:fetch-payloads [architecture]
[version] [stream]" and the other command examples referenced around the file)
to include a language tag such as bash (```bash) so command syntax is
highlighted; locate the code fences by searching for the literal command strings
and add the language identifier to their opening backticks.

In `@plugins/ci/skills/fetch-payloads/fetch_payloads.py`:
- Around line 32-37: The print call in fetch_payloads.py uses an unnecessary
f-string in the error message (inside the if block that checks stream == "ci"
and architecture != "amd64"); update the print invocation in that block to use a
plain string literal (remove the leading f from the message) while keeping the
same file=sys.stderr and sys.exit(1) behavior so Ruff F541 is resolved.

In `@plugins/ci/skills/fetch-payloads/SKILL.md`:
- Around line 50-52: The fenced code block showing the output format lacks a
language specifier; update the block in SKILL.md that contains
"<payload_tag>\t<phase>\t<url>" to include a language identifier (e.g., "text")
after the opening backticks so markdownlint MD040 is satisfied and the snippet
is treated as plain text.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 83f1105 and 1b53d12.

📒 Files selected for processing (8)
  • .claude-plugin/marketplace.json
  • PLUGINS.md
  • docs/data.json
  • plugins/ci/.claude-plugin/plugin.json
  • plugins/ci/commands/fetch-payloads.md
  • plugins/ci/skills/fetch-payloads/SKILL.md
  • plugins/ci/skills/fetch-payloads/fetch_payloads.py
  • plugins/testing/commands/mutation-test.md
✅ Files skipped from review due to trivial changes (1)
  • plugins/ci/.claude-plugin/plugin.json
🚧 Files skipped from review as they are similar to previous changes (2)
  • PLUGINS.md
  • docs/data.json

@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: 3

🧹 Nitpick comments (1)
plugins/ci/skills/fetch-payloads/fetch_payloads.py (1)

147-154: Reuse fetch_json() in get_latest_version() to avoid duplicated HTTP/error handling.

This keeps request behavior and error formatting consistent in one place.

Suggested refactor
 def get_latest_version() -> str:
     """Fetch the latest OCP version from the Sippy API."""
-    try:
-        with urllib.request.urlopen(SIPPY_API_URL, timeout=15) as resp:
-            data = json.loads(resp.read().decode("utf-8"))
-    except Exception as e:
-        print(f"Error: Could not fetch releases from Sippy: {e}", file=sys.stderr)
-        sys.exit(1)
+    data = fetch_json(SIPPY_API_URL, timeout=15)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/ci/skills/fetch-payloads/fetch_payloads.py` around lines 147 - 154,
get_latest_version() duplicates HTTP request and error handling that already
exists in fetch_json(); refactor get_latest_version() to call
fetch_json(SIPPY_API_URL) instead of using urllib.request.urlopen directly,
handle the return (parsed JSON) the same way current code expects, and preserve
the existing error behavior (printing to stderr and exiting) by allowing
fetch_json's exceptions/errors to propagate or by catching them and reusing the
same error message formatting; update references inside get_latest_version() to
use the parsed data from fetch_json rather than local resp decoding.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/ci/commands/fetch-payloads.md`:
- Around line 12-14: Add language identifiers (e.g., "text") to the fenced code
blocks that currently show invocations of /ci:fetch-payloads so they pass MD040;
locate each fenced block containing strings like "/ci:fetch-payloads
[architecture] [version] [stream]", "/ci:fetch-payloads", "/ci:fetch-payloads
arm64 4.18 nightly", and "/ci:fetch-payloads amd64 4.18 nightly --phase
Rejected" and change the opening backticks to include the language (for example
```text) for all occurrences noted in the comment (also apply the same change to
the additional blocks at lines referenced 45-47, 50-52, 55-57).
- Around line 65-68: The docs incorrectly state that `fetch-releases` is used
indirectly by the `fetch-payloads` skill; update the "Skills Used" section to
reflect reality: remove or correct the `fetch-releases (indirectly)` bullet and
state that `fetch-payloads` obtains the latest version directly from Sippy (see
`fetch_payloads.py`) rather than via `fetch-releases`. Ensure the entry
references `fetch-payloads` and `fetch_payloads.py` so readers know where the
logic lives.

In `@plugins/ci/skills/fetch-payloads/fetch_payloads.py`:
- Around line 181-186: The CLI currently allows invalid "stream", malformed
"version", and negative "--limit" values to pass through; update the argument
parsing to validate inputs at parse time by (1) adding choices=["nightly","ci"]
to the parser.add_argument call that registers "stream" (the existing
parser.add_argument for "stream"), (2) enforcing a non-negative integer for
"--limit" by providing a custom type or validator (e.g., a positive_int/type
function used in the parser.add_argument for "--limit"), and (3) validating
"version" format immediately after parser.parse_args() (or via a custom argparse
type function) and calling parser.error(...) when the version doesn't match the
expected pattern; implement these changes in the argument registration and the
function that calls parser.parse_args() (e.g., main or parse_args handler) so
invalid values fail fast.

---

Nitpick comments:
In `@plugins/ci/skills/fetch-payloads/fetch_payloads.py`:
- Around line 147-154: get_latest_version() duplicates HTTP request and error
handling that already exists in fetch_json(); refactor get_latest_version() to
call fetch_json(SIPPY_API_URL) instead of using urllib.request.urlopen directly,
handle the return (parsed JSON) the same way current code expects, and preserve
the existing error behavior (printing to stderr and exiting) by allowing
fetch_json's exceptions/errors to propagate or by catching them and reusing the
same error message formatting; update references inside get_latest_version() to
use the parsed data from fetch_json rather than local resp decoding.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 1b53d12 and 5013199.

📒 Files selected for processing (7)
  • .claude-plugin/marketplace.json
  • PLUGINS.md
  • docs/data.json
  • plugins/ci/.claude-plugin/plugin.json
  • plugins/ci/commands/fetch-payloads.md
  • plugins/ci/skills/fetch-payloads/SKILL.md
  • plugins/ci/skills/fetch-payloads/fetch_payloads.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • PLUGINS.md
  • plugins/ci/.claude-plugin/plugin.json
  • .claude-plugin/marketplace.json
  • plugins/ci/skills/fetch-payloads/SKILL.md

Comment thread plugins/ci/commands/fetch-payloads.md
Comment thread plugins/ci/commands/fetch-payloads.md Outdated
Comment thread plugins/ci/skills/fetch-payloads/fetch_payloads.py

@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.

♻️ Duplicate comments (1)
plugins/ci/commands/fetch-payloads.md (1)

12-14: ⚠️ Potential issue | 🟡 Minor

Add language identifiers to all remaining fenced command blocks.

MD040 is still triggered on the command examples (Line 12, Line 45, Line 50, Line 55). Add a language (e.g., text) to each opening fence.

Suggested fix
-```
+```text
 /ci:fetch-payloads [architecture] [version] [stream]

@@

  • /ci:fetch-payloads
    

@@

  • /ci:fetch-payloads arm64 4.18 nightly
    

@@

  • /ci:fetch-payloads amd64 4.23 nightly --phase Accepted
    
</details>


Also applies to: 45-47, 50-52, 55-57

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @plugins/ci/commands/fetch-payloads.md around lines 12 - 14, The fenced
command examples for the /ci:fetch-payloads usage blocks are missing a language
identifier and trigger MD040; update each opening fence for the command blocks
that contain the strings "/ci:fetch-payloads [architecture] [version] [stream]",
"/ci:fetch-payloads", "/ci:fetch-payloads arm64 4.18 nightly", and
"/ci:fetch-payloads amd64 4.23 nightly --phase Accepted" so the opening triple
backticks include a language token (e.g., change totext) for each of
those code fences.


</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>🤖 Prompt for all review comments with AI agents</summary>

Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In @plugins/ci/commands/fetch-payloads.md:

  • Around line 12-14: The fenced command examples for the /ci:fetch-payloads
    usage blocks are missing a language identifier and trigger MD040; update each
    opening fence for the command blocks that contain the strings
    "/ci:fetch-payloads [architecture] [version] [stream]", "/ci:fetch-payloads",
    "/ci:fetch-payloads arm64 4.18 nightly", and "/ci:fetch-payloads amd64 4.23
    nightly --phase Accepted" so the opening triple backticks include a language
    token (e.g., change totext) for each of those code fences.

</details>

---

<details>
<summary>ℹ️ Review info</summary>

**Configuration used**: Path: .coderabbit.yaml

**Review profile**: CHILL

**Plan**: Pro

**Cache: Disabled due to data retention organization setting**

**Knowledge base: Disabled due to data retention organization setting**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 50131994d1e15d8f5102c3413f28ddb1dbee8b3f and d30764f46e5590fd2206488c8a9d0e6b0fc9b093.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `plugins/ci/commands/fetch-payloads.md`

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Feb 26, 2026
@stbenjam stbenjam changed the title Add ci:fetch-payloads skill for querying release controller payloads Add ci:fetch-payloads and ci:analyze-payload skills Feb 26, 2026
stbenjam and others added 8 commits February 26, 2026 10:24
Add a primitive for fetching recent release payloads from the OpenShift
release controller API. This will serve as a building block for more
comprehensive payload analysis tools. The script takes architecture,
version, and stream arguments (defaulting to amd64/nightly/latest) and
returns payload tags with their acceptance phase and release controller
URLs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a new /ci:analyze-payload slash command that finds the latest
rejected nightly payload, investigates all failed blocking jobs in
parallel, and produces a self-contained HTML report. Key features:

- Historical lookback through consecutive rejected payloads to find
  when each job first started failing (originating payload)
- PR correlation via fetch-new-prs-in-payload to identify suspect PRs
- Parallel subagent investigation of each failed job
- Revert recommendations for PRs with >= 90% confidence of causing
  a regression, with rationale and /ci:revert-pr usage hints
- Attractive HTML report with executive summary, job table, collapsible
  details, and color-coded severity

Bumps CI plugin version to 0.0.9.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The analyze-payload skill now checks whether revert candidates have
already been reverted by searching for revert PRs in the same repo.
This prevents recommending reverts that are already in progress or
merged, and instead reports the revert PR's state and timing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Accept architecture, version, and stream arguments in the same order
as fetch-payloads instead of hardcoding nightly. This allows analyzing
CI stream payloads in addition to nightly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The filename must end with -summary.html for automatic rendering in
downstream tools.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@openshift-merge-robot openshift-merge-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Feb 26, 2026
stbenjam and others added 8 commits February 26, 2026 11:25
Update the analyze-payload skill to handle in-progress ("Ready")
payloads in addition to Rejected ones. This enables early analysis
of blocking jobs that have already failed, allowing determination
of whether a payload is on track for rejection before it reaches
terminal state.

Changes:
- fetch_payloads.py: Show failed job details for Ready payloads
- SKILL.md: Fetch payloads without phase filter, identify target
  as most recent Rejected or Ready-with-failures payload
- analyze-payload.md: Update description for Ready support

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The analyze-payload command now accepts a full payload tag
(e.g., 4.22.0-0.nightly-2026-02-25-152806) as the first argument,
in addition to just a version. When a tag is provided, version and
stream are parsed from it and that specific payload is targeted.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…payload

Subagents now determine failure type (install vs test) from JUnit results
rather than job name, and use the appropriate skill: install failure skill
for install failures (with metal-specific analysis for bare metal jobs),
test failure skill for test failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace hardcoded relative paths with ${CLAUDE_PLUGIN_ROOT} in
fetch-payloads and fetch-new-prs-in-payload skills so scripts
are found regardless of working directory.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The skill works for any stream (nightly, ci), not just nightlies.
Update description, usage text, and HTML template to be stream-agnostic.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@dgoodwin dgoodwin 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.

Future ideas:

  • Tell it to get really worked up if it's been more than 3-5 days since a nightly was accepted. Recommend enabling acknowledge-critical-fixes-only.
  • Anything it could do for crio/runc/kubelet updates someday? Just something we're having a lot of trouble with this week.

Just a couple thoughts added within, looks good to me so

/lgtm

We should get TRT involved in it's use and improvement as a stepping stone to getting QSE involved with payload monitoring. I'm also curious what we can do for patch managers here.

Comment thread plugins/ci/commands/analyze-payload.md Outdated

### Key Features

- **Automatic payload discovery**: Finds the latest rejected payload

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.

What does it do if the most recent payload is accepted? I would expect it to stop but this sounds like it will go analyze the last rejected?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is from an older version, I'll clean this up. analyze-payload takes a specific tag now

"""Fetch release tags from the release controller API."""
domain = rc_domain(architecture)
stream_name = release_stream_name(version, stream, architecture)
url = f"https://{domain}/api/v1/releasestream/{stream_name}/tags"

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.

Curious about the implications of using release controller vs sippy. The PRs in a payload is coming from sippy which will not have any compaction. (I think release controller is still removing failed payloads at some points, which could muddy the water a little in terms of how many failed payloads we've had, though not the time since last accepted.)

@stbenjam stbenjam Feb 27, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I want to do the analysis at the point of payload creation, Sippy takes too long to ingest the data. I may need to update fetch new PR's to consider the release controller data if sippy doesn't have it, right now this will only work for lookback PR's

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Feb 27, 2026
@openshift-ci

openshift-ci Bot commented Feb 27, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: dgoodwin, stbenjam

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

The pull request process is described 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

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

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants