Skip to content

Ci monitor consolidation - #245

Draft
vimauro wants to merge 3 commits into
openshift-eng:mainfrom
vimauro:ci-monitor-consolidation
Draft

Ci monitor consolidation#245
vimauro wants to merge 3 commits into
openshift-eng:mainfrom
vimauro:ci-monitor-consolidation

Conversation

@vimauro

@vimauro vimauro commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Added optional MicroShift CI and LVMS CI Doctor tabs to the payload-monitor dashboard.
    • Doctor reports can now be embedded directly into dashboard data and rendered from imported JSON.
    • Added expandable report details, sub-tabs, issue tables, analysis sections, and specialized visual styling.
    • Doctor report generation now supports standalone HTML and embeddable fragment output.
  • Bug Fixes

    • Reports now remain available when release job files or structured summaries are missing.
    • Dashboard generation continues gracefully when individual analyses fail or time out.
  • Documentation

    • Updated architecture diagrams, CLI guidance, dashboard feature descriptions, and Doctor integration instructions.

@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jul 29, 2026
@openshift-ci

openshift-ci Bot commented Jul 29, 2026

Copy link
Copy Markdown

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@openshift-ci

openshift-ci Bot commented Jul 29, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: vimauro

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

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jul 29, 2026
@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

Changes

Doctor fragment dashboard integration

Layer / File(s) Summary
Fragment generation and report states
plugins/shared/scripts/create-report.py, plugins/shared/scripts/aggregate.py
Doctor reports support HTML, fragment, or combined output, with prefixed fragment identifiers and improved empty-data handling.
Doctor command output wiring
plugins/shared/scripts/doctor.sh
Finalize and refresh now generate both HTML reports and embeddable fragments.
Payload storage and dashboard rendering
payload-monitor/payload_monitor/...
Doctor fragments are serialized, loaded, rendered as dynamic tabs, styled, and given expandable and nested-tab interactions.
CI doctor orchestration
plugins/edge-ocp-ci/skills/generate-dashboard/SKILL.md
The dashboard workflow collects doctor data, runs analyses, injects generated fragments into JSON, and regenerates HTML.
Integration documentation
payload-monitor/README.md
Architecture, CLI, dashboard features, and doctor fragment workflow documentation are updated.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (1 error)

Check name Status Explanation Resolution
No-Injection-Vectors ❌ Error FAIL: dashboard.html renders doctor_fragments with | safe, and load_json()/generate_html() pass JSON-provided fragments through unchanged, enabling XSS if the JSON is untrusted. Escape or whitelist fragment HTML, or only render fragments from a trusted internal generator before inserting them into the dashboard.
✅ 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 is concise and broadly matches the PR’s main theme of consolidating CI monitor and doctor-report flows.
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-Weak-Crypto ✅ Passed Exact scan of files changed vs main found no MD5/SHA1/DES/RC4/3DES/Blowfish/ECB or secret-compare code; the only digest hit is image metadata.
Container-Privileges ✅ Passed No changed file is a container/K8s manifest, and no privilege-related settings appear in the PR diff.
No-Sensitive-Data-In-Logs ✅ Passed New/updated logs only print counts, release names, and temp output paths; no secrets, tokens, PII, hostnames, or customer data were introduced.
No-Hardcoded-Secrets ✅ Passed No hardcoded secrets were added; the only token mention is documentation, and the new literals are non-secret IDs/URLs.
Ai-Attribution ✅ Passed No Assisted-by/Generated-by or AI-tool trailers appear in branch commits; the only AI refs are product docs, not contributor attribution.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Fix failing CI checks
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 markdownlint-cli2 (0.23.1)
payload-monitor/README.md

markdownlint-cli2 v0.23.1 (markdownlint v0.41.1)
Finding: :payload-monitor/README.md :plugins/edge-ocp-ci/skills/generate-dashboard/SKILL.md !node_modules/** !two-node-toolbox/**
Linting: 2 files
Summary: 0 issues in 0 files
AggregateError: Unable to import module 'markdownlint-cli2-formatter-pretty'.
at importModule (file:///usr/local/lib/node_modules/markdownlint-cli2/markdownlint-cli2.mjs:95:11)
at async Promise.all (index 0)
at async outputResults (file:///usr/local/lib/node_modules/markdownlint-cli2/markdownlint-cli2.mjs:915:9)
at async main (file:///usr/local/lib/node_modules/markdownlint-cli2/markdownlint-cli2.mjs:1111:5)
at async file:///usr/local/lib/node_modules/markdownlint-cli2/markdownlint-cli2-bin.mjs:14:22 {
[errors]: [
Error: Cannot find module 'markdownlint-cli2-formatter-pretty'
Require stack:
- /usr/local/lib/node_modules/markdownlint-cli2/node_modules/markdownlint/lib/resolve-module.cjs
at Module._resolveFilename (node:inter

... [truncated 1137 characters] ...

node:internal/modules/esm/resolve:271:11)
at moduleResolve (node:internal/modules/esm/resolve:861:10)
at defaultResolve (node:internal/modules/esm/resolve:988:11)
at #cachedDefaultResolve (node:internal/modules/esm/loader:697:20)
at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:714:38)
at ModuleLoader.resolveSync (node:internal/modules/esm/loader:746:52)
at #resolve (node:internal/modules/esm/loader:679:17)
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:599:35)
at node:internal/modules/esm/loader:628:32
at TracingChannel.tracePromise (node:diagnostics_channel:362:14) {
code: 'ERR_MODULE_NOT_FOUND',
url: 'file:///markdownlint-cli2-formatter-pretty'
}
]
}

plugins/edge-ocp-ci/skills/generate-dashboard/SKILL.md

markdownlint-cli2 v0.23.1 (markdownlint v0.41.1)
Finding: :payload-monitor/README.md :plugins/edge-ocp-ci/skills/generate-dashboard/SKILL.md !node_modules/** !two-node-toolbox/**
Linting: 2 files
Summary: 0 issues in 0 files
AggregateError: Unable to import module 'markdownlint-cli2-formatter-pretty'.
at importModule (file:///usr/local/lib/node_modules/markdownlint-cli2/markdownlint-cli2.mjs:95:11)
at async Promise.all (index 0)
at async outputResults (file:///usr/local/lib/node_modules/markdownlint-cli2/markdownlint-cli2.mjs:915:9)
at async main (file:///usr/local/lib/node_modules/markdownlint-cli2/markdownlint-cli2.mjs:1111:5)
at async file:///usr/local/lib/node_modules/markdownlint-cli2/markdownlint-cli2-bin.mjs:14:22 {
[errors]: [
Error: Cannot find module 'markdownlint-cli2-formatter-pretty'
Require stack:
- /usr/local/lib/node_modules/markdownlint-cli2/node_modules/markdownlint/lib/resolve-module.cjs
at Module._resolveFilename (node:inter

... [truncated 1137 characters] ...

node:internal/modules/esm/resolve:271:11)
at moduleResolve (node:internal/modules/esm/resolve:861:10)
at defaultResolve (node:internal/modules/esm/resolve:988:11)
at #cachedDefaultResolve (node:internal/modules/esm/loader:697:20)
at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:714:38)
at ModuleLoader.resolveSync (node:internal/modules/esm/loader:746:52)
at #resolve (node:internal/modules/esm/loader:679:17)
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:599:35)
at node:internal/modules/esm/loader:628:32
at TracingChannel.tracePromise (node:diagnostics_channel:362:14) {
code: 'ERR_MODULE_NOT_FOUND',
url: 'file:///markdownlint-cli2-formatter-pretty'
}
]
}


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

🧹 Nitpick comments (1)
payload-monitor/payload_monitor/report/templates/styles.css (1)

1235-1285: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Deprecated word-break: break-word flagged by stylelint.

overflow-wrap: anywhere on the same rule already provides the intended wrapping; word-break: break-word is a deprecated value for this purpose.

♻️ Proposed fix
-.doctor-detail-row td { padding: 0 6px 12px 40px; overflow-wrap: anywhere; word-break: break-word; }
+.doctor-detail-row td { padding: 0 6px 12px 40px; overflow-wrap: anywhere; }
🤖 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 `@payload-monitor/payload_monitor/report/templates/styles.css` around lines
1235 - 1285, Remove the deprecated word-break: break-word declaration from
.doctor-detail-row td. Keep overflow-wrap: anywhere unchanged so long detail
content continues wrapping correctly.

Source: Linters/SAST tools

🤖 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/edge-ocp-ci/skills/generate-dashboard/SKILL.md`:
- Around line 271-277: The Error Handling section in the dashboard workflow
should not remain as a trailing consolidated block. Move the prepare failure
rule next to the 3b.1 prepare commands, remove the duplicate analysis failure
rule because 3b.5 already mandates continuation, move the finalize failure
behavior next to 3b.6’s FileNotFoundError handling, and place the doctor-tab
count behavior beside 3b.6’s closing note; then remove the obsolete trailing
section.

In `@plugins/shared/scripts/create-report.py`:
- Line 1098: Update the hyphen separators in the report-rendering paths around
the evidence output and the referenced TOC/status locations to include a
trailing space before the following text. Apply the same spacing consistently to
the code handling `item`, lines 1631-1634, 1809, and 1820-1826, while preserving
the existing HTML escaping and rendering behavior.
- Around line 1998-2011: Update _doctor_prefix_ids to also prefix PR anchor ids
and matching href targets beginning with “pr-” using the provided slug,
alongside the existing release and images handling. Ensure both base PR ids and
issue-specific PR ids emitted by render_pr_section are rewritten consistently so
internal anchor navigation remains valid.

---

Nitpick comments:
In `@payload-monitor/payload_monitor/report/templates/styles.css`:
- Around line 1235-1285: Remove the deprecated word-break: break-word
declaration from .doctor-detail-row td. Keep overflow-wrap: anywhere unchanged
so long detail content continues wrapping correctly.
🪄 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: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 11f1c37a-45b6-452a-9ac5-254e29013324

📥 Commits

Reviewing files that changed from the base of the PR and between 932e3ca and fcc75db.

📒 Files selected for processing (10)
  • payload-monitor/README.md
  • payload-monitor/payload_monitor/models.py
  • payload-monitor/payload_monitor/report/generator.py
  • payload-monitor/payload_monitor/report/templates/dashboard.html
  • payload-monitor/payload_monitor/report/templates/scripts.js
  • payload-monitor/payload_monitor/report/templates/styles.css
  • plugins/edge-ocp-ci/skills/generate-dashboard/SKILL.md
  • plugins/shared/scripts/aggregate.py
  • plugins/shared/scripts/create-report.py
  • plugins/shared/scripts/doctor.sh

Comment on lines +271 to +277
#### Error Handling

- If prepare fails for a component, skip all subsequent steps for that component
- If analysis agents fail or time out, proceed to finalize - reports will note missing analysis
- If finalize fails for a component, its fragment won't exist and is simply not injected
- The dashboard works with zero, one, or any number of doctor tabs

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.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Error Handling rules should be co-located with their steps, not trailing at the end of 3b.

This section bundles failure policy for three different steps (3b.1 prepare, 3b.3 analysis, 3b.5 finalize) into one block after 3b.6. Based on learnings, failure policies/edge-case rules should be placed inline right next to the step they apply to (using "CRITICAL" for hard stops and "Error Handling" bullets for partial failures directly in the step context), since an LLM agent executing linearly won't reliably re-consult a separate trailing section — this creates two sources of truth without improving compliance.

Suggested placement:

  • "If prepare fails for a component, skip all subsequent steps for that component" → move next to the 3b.1 doctor.sh prepare commands (near line 126, alongside the existing "If a release has error in its entry... skip it" note).
  • "If analysis agents fail or time out, proceed to finalize" → already effectively covered by the 3b.5 "IMPORTANT: MANDATORY" note; consider removing the duplicate here.
  • "If finalize fails for a component, its fragment won't exist and is simply not injected" → move near 3b.6's try/except FileNotFoundError block (line 254), which already implements this behavior.
  • "The dashboard works with zero, one, or any number of doctor tabs" → fits naturally next to the closing note in 3b.6 ("Doctor tabs appear automatically...").

Based on learnings, "co-locate failure policies and edge-case rules inline with the specific step that needs them... Do not move these rules to a separate top-level 'Edge Cases' (or similar) section."

🤖 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/edge-ocp-ci/skills/generate-dashboard/SKILL.md` around lines 271 -
277, The Error Handling section in the dashboard workflow should not remain as a
trailing consolidated block. Move the prepare failure rule next to the 3b.1
prepare commands, remove the duplicate analysis failure rule because 3b.5
already mandates continuation, move the finalize failure behavior next to 3b.6’s
FileNotFoundError handling, and place the doctor-tab count behavior beside
3b.6’s closing note; then remove the obsolete trailing section.

Source: Learnings

item = _e(link.get("cause"))
if link.get("evidence"):
item += f' <span class="evidence">{_e(link["evidence"])}</span>'
item += f' -<span class="evidence">{_e(link["evidence"])}</span>'

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 | 🟡 Minor | ⚡ Quick win

Missing space after hyphen produces squished TOC/evidence text.

Several &mdash;→hyphen replacements dropped the trailing space, so rendered text reads like "-collection error", "-3 failures", "-5 running" (hyphen mashed against the next word/number, easily misread as a negative number).

🐛 Proposed fix
-                item += f' -<span class="evidence">{_e(link["evidence"])}</span>'
+                item += f' - <span class="evidence">{_e(link["evidence"])}</span>'
-        suffix = f' -{pending} running' if pending else ''
+        suffix = f' - {pending} running' if pending else ''
         toc_lines.append(
             f'                <li><a href="`#pr-`{pr["number"]}">PR# {pr["number"]}</a>'
-            f' -{pr["failed"]} failures ({b.get("build", 0)} build, {b.get("test", 0)} test, {b.get("infrastructure", 0)} infra){suffix}</li>'
+            f' - {pr["failed"]} failures ({b.get("build", 0)} build, {b.get("test", 0)} test, {b.get("infrastructure", 0)} infra){suffix}</li>'
         )
             toc.append(
-                f'                <li><a href="`#release-`{_e(version)}">Release {_e(version)}</a> -collection error</li>'
+                f'                <li><a href="`#release-`{_e(version)}">Release {_e(version)}</a> - collection error</li>'
             )
             toc.append(
-                f'                <li><a href="`#release-`{_e(version)}">Release {_e(version)}</a> -'
+                f'                <li><a href="`#release-`{_e(version)}">Release {_e(version)}</a> - '
                 f'<span class="toc-counts" data-release="{_e(version)}">'
                 f'{rdata["total_failed"]} failures ({b["build"]} build, {b["test"]} test, {b["infrastructure"]} infra)'
                 f'{pass_info}</span></li>'
             )
         else:
-            toc.append(f'                <li><a href="`#release-`{_e(version)}">Release {_e(version)}</a> -no data</li>')
+            toc.append(f'                <li><a href="`#release-`{_e(version)}">Release {_e(version)}</a> - no data</li>')

Also applies to: 1631-1634, 1809-1809, 1820-1826

🤖 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/shared/scripts/create-report.py` at line 1098, Update the hyphen
separators in the report-rendering paths around the evidence output and the
referenced TOC/status locations to include a trailing space before the following
text. Apply the same spacing consistently to the code handling `item`, lines
1631-1634, 1809, and 1820-1826, while preserving the existing HTML escaping and
rendering behavior.

Comment on lines +1998 to +2011
def _doctor_prefix_ids(html, slug):
"""Prefix id attributes to avoid collisions with payload-monitor."""
html = re.sub(r'id="release-', f'id="doctor-{slug}-release-', html)
html = re.sub(r'href="#release-', f'href="#doctor-{slug}-release-', html)
html = re.sub(r'id="images-', f'id="doctor-{slug}-images-', html)
html = re.sub(r'href="#images-', f'href="#doctor-{slug}-images-', html)
return html


def _postprocess_fragment(html, slug):
"""Prefix CSS classes and HTML ids for embedding in the payload-monitor dashboard."""
html = _doctor_prefix_classes(html)
return _doctor_prefix_ids(html, slug)

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

_doctor_prefix_ids doesn't cover PR anchor ids, risking id collisions between embedded doctor fragments.

The function only rewrites id="release-…" and id="images-…" (plus their href="#…" counterparts), but render_pr_section (used by generate_fragment) emits unprefixed id="pr-{number}" and id="pr-{number}-{issue}"/href="#pr-…" anchors. When multiple doctor fragments (e.g. future components that both track rebase PRs) are injected into the same payload-monitor dashboard, these ids collide, breaking href="#pr-…" anchor navigation (the browser jumps to whichever element appears first in the DOM) and producing invalid duplicate-id HTML — undermining the function's own stated purpose of avoiding collisions.

🐛 Proposed fix
 def _doctor_prefix_ids(html, slug):
     """Prefix id attributes to avoid collisions with payload-monitor."""
     html = re.sub(r'id="release-', f'id="doctor-{slug}-release-', html)
     html = re.sub(r'href="`#release-`', f'href="`#doctor-`{slug}-release-', html)
     html = re.sub(r'id="images-', f'id="doctor-{slug}-images-', html)
     html = re.sub(r'href="`#images-`', f'href="`#doctor-`{slug}-images-', html)
+    html = re.sub(r'id="pr-', f'id="doctor-{slug}-pr-', html)
+    html = re.sub(r'href="`#pr-`', f'href="`#doctor-`{slug}-pr-', html)
     return html
📝 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
def _doctor_prefix_ids(html, slug):
"""Prefix id attributes to avoid collisions with payload-monitor."""
html = re.sub(r'id="release-', f'id="doctor-{slug}-release-', html)
html = re.sub(r'href="#release-', f'href="#doctor-{slug}-release-', html)
html = re.sub(r'id="images-', f'id="doctor-{slug}-images-', html)
html = re.sub(r'href="#images-', f'href="#doctor-{slug}-images-', html)
return html
def _postprocess_fragment(html, slug):
"""Prefix CSS classes and HTML ids for embedding in the payload-monitor dashboard."""
html = _doctor_prefix_classes(html)
return _doctor_prefix_ids(html, slug)
def _doctor_prefix_ids(html, slug):
"""Prefix id attributes to avoid collisions with payload-monitor."""
html = re.sub(r'id="release-', f'id="doctor-{slug}-release-', html)
html = re.sub(r'href="`#release-`', f'href="`#doctor-`{slug}-release-', html)
html = re.sub(r'id="images-', f'id="doctor-{slug}-images-', html)
html = re.sub(r'href="`#images-`', f'href="`#doctor-`{slug}-images-', html)
html = re.sub(r'id="pr-', f'id="doctor-{slug}-pr-', html)
html = re.sub(r'href="`#pr-`', f'href="`#doctor-`{slug}-pr-', html)
return html
def _postprocess_fragment(html, slug):
"""Prefix CSS classes and HTML ids for embedding in the payload-monitor dashboard."""
html = _doctor_prefix_classes(html)
return _doctor_prefix_ids(html, slug)
🤖 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/shared/scripts/create-report.py` around lines 1998 - 2011, Update
_doctor_prefix_ids to also prefix PR anchor ids and matching href targets
beginning with “pr-” using the provided slug, alongside the existing release and
images handling. Ensure both base PR ids and issue-specific PR ids emitted by
render_pr_section are rewritten consistently so internal anchor navigation
remains valid.

```bash
bash "$SHARED_SCRIPTS/doctor.sh" prepare \
--component microshift --workdir "$MICROSHIFT_WORKDIR" \
--rebase --repo openshift/microshift <VERSIONS>

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.

doctor.sh prepare doesn't accept --rebase (only --pull-requests/--repo, doctor.sh:49), so it hits the -*) catch-all and return 1s under set -euo pipefail, aborting the whole MicroShift prepare phase (reproduced live).

performance graphs when relevant.
3. After the analysis completes, save the FULL report output (including the
--- STRUCTURED SUMMARY --- block) to:
<MICROSHIFT_WORKDIR>/jobs/release-<RELEASE>-job-<N>-<BUILD_ID>.txt

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.

Per-job reports are saved as .txt but aggregate.py only globs *.json (lines 140/145), so all analysis is silently dropped — restore .json here (as the standalone skills do) on lines 170, 186, and 197.

print("No valid job reports found", file=sys.stderr)
sys.exit(1)
result = build_release_json(release, [], timestamp)
result["no_job_files"] = True

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.

no_job_files is set whenever zero per-job files exist and is rendered as green "all clear" (create-report.py:1417-1419), producing a false pass for any release that had failures but no analysis (guaranteed by the .txt/.json mismatch, or when agents time out).

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. do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants