Skip to content

fix(cicd): make the Core gate cover every Core job - #4655

Open
chet wants to merge 1 commit into
NVIDIA:mainfrom
chet:gh-issue-4649
Open

fix(cicd): make the Core gate cover every Core job#4655
chet wants to merge 1 commit into
NVIDIA:mainfrom
chet:gh-issue-4649

Conversation

@chet

@chet chet commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

core-ci-pass was only waiting on part of the workflow, which meant an unlisted build could fail while the protected check still reported green. This makes it wait on every current substantive Core job and checks that inventory before the expensive work starts.

  • Expected green-run effect: No speedup. The final gate may finish later because it now waits for every job it represents.
  • What it really buys us: core-ci-pass cannot report green while a known Core job is red, and a future top-level job cannot quietly sit outside the gate.

Intentional skips remain accepted, while failures, cancellations, malformed results, and unknown inventory entries stop the gate. The inventory check also requires if: always() on the gate, because otherwise a failing dependency could skip the protected check entirely. proto-breaking-changes now uses the Core classifier as well, so REST-only PRs do not pick up a Core-only check just because the final gate became complete.

Related issues

This supports #4649

Type of Change

  • Add - New feature or capability
  • Change - Changes in existing functionality
  • Fix - Bug fixes
  • Remove - Removed features or deprecated functionality
  • Internal - Internal changes (refactoring, tests, docs, etc.)

Breaking Changes

  • This PR contains breaking changes

Testing

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed
  • No testing required (docs, internal refactor, etc.)
python3 -B .github/ci/test_check_core_ci_gate.py
python3 -B .github/ci/check_core_ci_gate.py inventory .github/workflows/ci.yaml
cargo make format-nightly
cargo make clippy
cargo make carbide-lints

Additional Notes

The gate intentionally does not exempt a job because it has been flaky or depends on the network -- a red Core job needs to make the protected Core result red. Reliability work for those jobs can stay separate from the question of whether the gate reports them.

core-ci-pass inherits the workflow-wide contents: read token baseline from #4656. Merge #4656 first so the permission policy stays centralized and checked instead of being duplicated on this one job.

This does not change the repository ruleset itself. It makes the existing core-ci-pass check accurately represent the workflow the ruleset already relies on; #4586 still owns the later classifier-aware selected/full policy and timing report.

@chet
chet requested review from a team as code owners August 6, 2026 07:05
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b1d737ee-4f3f-4c41-a4a7-03f7b82b2ba1

📥 Commits

Reviewing files that changed from the base of the PR and between 9cc6a20 and af343ad.

📒 Files selected for processing (3)
  • .github/ci/check_core_ci_gate.py
  • .github/ci/test_check_core_ci_gate.py
  • .github/workflows/ci.yaml

Summary by CodeRabbit

  • Bug Fixes

    • Improved CI validation to ensure all required checks are included in the final pass status.
    • Updated conditional checks so protocol compatibility validation runs only when applicable.
    • CI now fails safely when required results are missing, malformed, cancelled, or unsuccessful.
  • Tests

    • Added comprehensive validation for workflow coverage, job classifications, and CI result handling.

Walkthrough

The change adds a Core CI gate checker, tests workflow inventory and result policies, expands core-ci-pass dependencies, and gates proto-breaking-changes on the changes job output.

Changes

Core CI gate

Layer / File(s) Summary
Checker implementation and validation
.github/ci/check_core_ci_gate.py, .github/ci/test_check_core_ci_gate.py
The checker validates workflow job classifications, exemptions, gate conditions, and serialized job results. Tests cover inventory errors, result policies, CLI behavior, and missing configuration.
Workflow gate integration
.github/workflows/ci.yaml
The workflow runs checker tests and inventory validation, expands core-ci-pass to the complete Core CI inventory, uses NEEDS_JSON for result evaluation, and gates proto-breaking-changes on changes.

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

Sequence Diagram(s)

sequenceDiagram
  participant ChangesJob
  participant GateChecker
  participant CoreCIPass
  participant ProtoBreakingChanges

  ChangesJob->>GateChecker: Validate workflow inventory
  GateChecker-->>ChangesJob: Return inventory status
  ChangesJob->>CoreCIPass: Set run_core_ci
  CoreCIPass->>GateChecker: Evaluate NEEDS_JSON results
  GateChecker-->>CoreCIPass: Return gate status
  CoreCIPass->>ProtoBreakingChanges: Provide gated dependency result
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: expanding the Core CI gate to cover every Core job.
Description check ✅ Passed The description directly explains the Core CI gate bug, inventory validation, classifier update, and associated testing.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@chet

chet commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full_review, thanks!

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

@chet I will perform a complete review of PR #4655.

✅ Action performed

Full review finished.

@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

🧹 Nitpick comments (3)
scripts/test_check_core_ci_gate.py (1)

136-194: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a passing-path assertion for _check_results and a malformed-entry case for result_errors.

Every _check_results case asserts return code 1. No test asserts that a healthy context returns 0. A regression that makes the gate always fail would still pass this suite, and the failure would surface only as a red required check on every pull request.

result_errors also has an untested branch. Line 208 of scripts/check_core_ci_gate.py reports did not provide a job result object for a non-mapping entry. No case exercises it.

Both gaps are one assertion each.

💚 Proposed tests for the uncovered branches
     def test_gate_result_policy(self) -> None:
         cases = (
             {
                 "name": "success",
                 "result": "success",
                 "expected": [],
             },
@@
         for case in cases:
             with self.subTest(case["name"]):
                 needs_context = {"fixture-job": {"result": case["result"]}}
                 self.assertEqual(result_errors(needs_context), case["expected"])
 
+    def test_non_mapping_entry_is_rejected(self) -> None:
+        self.assertEqual(
+            result_errors({"fixture-job": "success"}),
+            ["`fixture-job` did not provide a job result object"],
+        )
+
+    def test_result_command_accepts_healthy_context(self) -> None:
+        needs_json = '{"gated-job":{"result":"success"},"skipped-job":{"result":"skipped"}}'
+        output = io.StringIO()
+        with mock.patch.dict(os.environ, {"NEEDS_JSON": needs_json}):
+            with contextlib.redirect_stdout(output):
+                return_code = _check_results()
+
+        self.assertEqual(return_code, 0)
+        self.assertNotIn("::error::", output.getvalue())
+
     def test_result_command_rejects_invalid_context(self) -> None:
🤖 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 `@scripts/test_check_core_ci_gate.py` around lines 136 - 194, Add a
healthy-context case to test_result_command_rejects_invalid_context or a
dedicated _check_results test, asserting _check_results returns 0 for valid
successful NEEDS_JSON. Add a malformed non-mapping entry case to
test_gate_result_policy, such as a job value that is not an object, and assert
result_errors returns the expected “did not provide a job result object”
message.
scripts/check_core_ci_gate.py (2)

235-244: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Parse the workflow once in _check_inventory.

inventory_errors already parses the workflow at line 151. Line 240 parses the same text again only to count jobs. This duplicates work and leaves a WorkflowFormatError raise outside any handler. The second call cannot currently fail, because inventory_errors returns early for the same input, but the coupling is implicit and fragile.

Expose the parsed inventory from a single call instead.

♻️ Proposed refactor to parse once
-    errors = inventory_errors(workflow_text)
-    if errors:
-        _print_annotations(errors)
-        return 1
-
-    inventory = parse_workflow(workflow_text)
+    try:
+        inventory = parse_workflow(workflow_text)
+    except WorkflowFormatError as error:
+        _print_annotations([str(error)])
+        return 1
+
+    errors = inventory_errors(workflow_text)
+    if errors:
+        _print_annotations(errors)
+        return 1
+
     print(
🤖 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 `@scripts/check_core_ci_gate.py` around lines 235 - 244, Update
_check_inventory to obtain the parsed inventory from the single workflow-parsing
operation used by inventory_errors, then reuse that inventory for validation and
job-count reporting instead of calling parse_workflow again. Preserve the
existing error annotations and return behavior while ensuring any
WorkflowFormatError remains handled through the established path.

160-164: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Count gate dependencies once instead of per unique job.

duplicate_needs calls tuple.count for every unique dependency. That is a quadratic scan over gate_needs. The list is small today, so this is a clarity improvement more than a performance fix. collections.Counter states the intent directly.

♻️ Proposed refactor using collections.Counter
+from collections import Counter
-    duplicate_needs = sorted(
-        job
-        for job in gated_jobs
-        if inventory.gate_needs.count(job) > 1
-    )
+    duplicate_needs = sorted(
+        job for job, count in Counter(inventory.gate_needs).items() if count > 1
+    )
🤖 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 `@scripts/check_core_ci_gate.py` around lines 160 - 164, Update the duplicate
dependency detection around duplicate_needs to build a collections.Counter from
inventory.gate_needs once, then identify gated_jobs whose counted dependency
total exceeds one. Preserve the sorted duplicate_needs result and add the
required Counter import.
🤖 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 @.github/workflows/ci.yaml:
- Around line 2222-2231: Add a job-level permissions block to the job containing
the “Decide pass/fail” step, granting only contents: read. Keep the existing
checkout and check_core_ci_gate.py execution unchanged.

---

Nitpick comments:
In `@scripts/check_core_ci_gate.py`:
- Around line 235-244: Update _check_inventory to obtain the parsed inventory
from the single workflow-parsing operation used by inventory_errors, then reuse
that inventory for validation and job-count reporting instead of calling
parse_workflow again. Preserve the existing error annotations and return
behavior while ensuring any WorkflowFormatError remains handled through the
established path.
- Around line 160-164: Update the duplicate dependency detection around
duplicate_needs to build a collections.Counter from inventory.gate_needs once,
then identify gated_jobs whose counted dependency total exceeds one. Preserve
the sorted duplicate_needs result and add the required Counter import.

In `@scripts/test_check_core_ci_gate.py`:
- Around line 136-194: Add a healthy-context case to
test_result_command_rejects_invalid_context or a dedicated _check_results test,
asserting _check_results returns 0 for valid successful NEEDS_JSON. Add a
malformed non-mapping entry case to test_gate_result_policy, such as a job value
that is not an object, and assert result_errors returns the expected “did not
provide a job result object” message.
🪄 Autofix

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: 9642482f-295b-47ad-aabe-f84cfea7904f

📥 Commits

Reviewing files that changed from the base of the PR and between 4f0e11f and 4d376ae.

📒 Files selected for processing (3)
  • .github/workflows/ci.yaml
  • scripts/check_core_ci_gate.py
  • scripts/test_check_core_ci_gate.py

Comment thread .github/workflows/ci.yaml Outdated
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

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

🧹 Nitpick comments (1)
scripts/test_check_core_ci_gate.py (1)

188-207: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test the missing and malformed NEEDS_JSON paths.

_check_results() has separate failure branches when NEEDS_JSON is unset or contains invalid JSON. The test cases do not execute either branch. Add cases for an unset variable with mock.patch.dict(os.environ, {}, clear=True) and malformed JSON. This keeps the CI gate error contract covered.

🤖 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 `@scripts/test_check_core_ci_gate.py` around lines 188 - 207, The
test_result_command_rejects_invalid_context cases do not cover unset or
malformed NEEDS_JSON. Add an unset-variable case using
mock.patch.dict(os.environ, {}, clear=True) and a malformed-JSON case, asserting
each branch’s expected CI gate error output while preserving the existing
invalid-context cases.
🤖 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.

Nitpick comments:
In `@scripts/test_check_core_ci_gate.py`:
- Around line 188-207: The test_result_command_rejects_invalid_context cases do
not cover unset or malformed NEEDS_JSON. Add an unset-variable case using
mock.patch.dict(os.environ, {}, clear=True) and a malformed-JSON case, asserting
each branch’s expected CI gate error output while preserving the existing
invalid-context cases.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b4648b70-3b0c-41dc-b7b0-5e67c2260019

📥 Commits

Reviewing files that changed from the base of the PR and between 4f0e11f and 4050f74.

📒 Files selected for processing (3)
  • .github/workflows/ci.yaml
  • scripts/check_core_ci_gate.py
  • scripts/test_check_core_ci_gate.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • .github/workflows/ci.yaml
  • scripts/check_core_ci_gate.py

@chet

chet commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full_review, thanks!

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

@chet I will perform a complete review of PR #4655.

🐇🔎

⚠️ Action not completed

Review rate limited.


Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 5 minutes.

@chet

chet commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full_review, thanks!

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

@chet I will perform a complete review of PR #4655.

🐇🔎

✅ Action performed

Full review finished.

@chet chet changed the title fix: make the Core gate cover every Core job fix(cicd): make the Core gate cover every Core job Aug 6, 2026
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@nv-dmendoza nv-dmendoza left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, aligns the jobs needed for CI passing, some of which were probably not added to this list as time went on

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@chet

chet commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full_review, thanks!

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

@chet I will perform a complete review of PR #4655.

🐇🔎

✅ Action performed

Full review finished.

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

🧹 Nitpick comments (1)
.github/ci/test_check_core_ci_gate.py (1)

296-303: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for the inventory command.

_check_results is covered end to end, but _check_inventory is not tested. That function owns the exit codes and annotations the workflow relies on, including the unreadable-file branch and the success summary. Add a short test with a temporary workflow file.

💚 Proposed tests for `_check_inventory`
import tempfile
from pathlib import Path

from check_core_ci_gate import _check_inventory


class InventoryCommandTests(unittest.TestCase):
    """Verify the exit codes and annotations of the `inventory` command."""

    def _run(self, workflow_text: str) -> tuple[int, str]:
        output = io.StringIO()
        with tempfile.TemporaryDirectory() as directory:
            path = Path(directory, "ci.yaml")
            path.write_text(workflow_text, encoding="utf-8")
            with contextlib.redirect_stdout(output):
                return_code = _check_inventory(path)
        return return_code, output.getvalue()

    def test_command_accepts_complete_inventory(self) -> None:
        return_code, output = self._run(COMPLETE_WORKFLOW)
        self.assertEqual(return_code, 0)
        self.assertNotIn("::error::", output)

    def test_command_rejects_ungated_job(self) -> None:
        workflow = COMPLETE_WORKFLOW.replace("      - build\n", "")
        return_code, output = self._run(workflow)
        self.assertEqual(return_code, 1)
        self.assertIn("::error::top-level jobs are not gated or exempt: build", output)

    def test_command_rejects_unreadable_workflow(self) -> None:
        output = io.StringIO()
        with contextlib.redirect_stdout(output):
            return_code = _check_inventory(Path("does-not-exist.yaml"))
        self.assertEqual(return_code, 1)
        self.assertIn("::error::could not read", output.getvalue())

Note: test_command_accepts_complete_inventory passes only when the fixture's exempt jobs match the production EXEMPT_JOBS, because _check_inventory uses the module constant. The current fixture satisfies that.

🤖 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 @.github/ci/test_check_core_ci_gate.py around lines 296 - 303, Add focused
tests for _check_inventory using a temporary workflow file: cover a complete
inventory returning 0 without errors, an ungated job returning 1 with the
expected annotation, and an unreadable path returning 1 with a “could not read”
annotation. Reuse the existing fixture and production EXEMPT_JOBS expectations,
and place the tests alongside the current command tests.
🤖 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.

Nitpick comments:
In @.github/ci/test_check_core_ci_gate.py:
- Around line 296-303: Add focused tests for _check_inventory using a temporary
workflow file: cover a complete inventory returning 0 without errors, an ungated
job returning 1 with the expected annotation, and an unreadable path returning 1
with a “could not read” annotation. Reuse the existing fixture and production
EXEMPT_JOBS expectations, and place the tests alongside the current command
tests.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: df2dbaa5-94dc-43fa-9f68-638eda600d6d

📥 Commits

Reviewing files that changed from the base of the PR and between c529f58 and 529db80.

📒 Files selected for processing (3)
  • .github/ci/check_core_ci_gate.py
  • .github/ci/test_check_core_ci_gate.py
  • .github/workflows/ci.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/ci.yaml

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

🧹 Nitpick comments (2)
.github/ci/test_check_core_ci_gate.py (1)

112-202: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider covering _check_inventory end to end.

The suite exercises inventory_errors and _check_results thoroughly. _check_inventory remains untested, so the annotation output, the unreadable-file branch, and the summary line have no regression guard. A single test that writes the fixture to a temporary path and asserts the return code and the summary text would close the gap.

🤖 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 @.github/ci/test_check_core_ci_gate.py around lines 112 - 202, Add an
end-to-end test for `_check_inventory` that writes a representative workflow
fixture to a temporary path, invokes the checker, and asserts its return code
and summary output. Cover annotation output and the unreadable-file branch so
these behaviors have regression protection, using the existing
`inventory_errors` and `_check_results` conventions where appropriate.
.github/ci/check_core_ci_gate.py (1)

303-309: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reuse inventory_errors to remove the duplicate parse path.

_check_inventory repeats the parse-and-classify sequence that inventory_errors already implements. The inventory count message needs the parsed object, so a small refactor keeps one code path: parse once, then report. The current form risks the two paths drifting apart.

♻️ Optional consolidation
-    try:
-        inventory = parse_workflow(workflow_text)
-    except WorkflowFormatError as error:
-        _print_annotations([str(error)])
-        return 1
-
-    errors = _inventory_errors(inventory, EXEMPT_JOBS)
-    if errors:
+    try:
+        inventory = parse_workflow(workflow_text)
+    except WorkflowFormatError as error:
+        _print_annotations([str(error)])
+        return 1
+
+    if errors := _inventory_errors(inventory, EXEMPT_JOBS):

The public inventory_errors helper remains the entry point for tests. Consider making it return the parsed inventory alongside the errors so both callers share one implementation.

🤖 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 @.github/ci/check_core_ci_gate.py around lines 303 - 309, Refactor
_check_inventory to reuse the parsing and classification performed by
inventory_errors instead of duplicating the parse path. Extend inventory_errors
to return both the parsed inventory and its errors while preserving its public
test-facing entry point, then use the returned inventory for the count message
and errors for reporting.
🤖 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.

Nitpick comments:
In @.github/ci/check_core_ci_gate.py:
- Around line 303-309: Refactor _check_inventory to reuse the parsing and
classification performed by inventory_errors instead of duplicating the parse
path. Extend inventory_errors to return both the parsed inventory and its errors
while preserving its public test-facing entry point, then use the returned
inventory for the count message and errors for reporting.

In @.github/ci/test_check_core_ci_gate.py:
- Around line 112-202: Add an end-to-end test for `_check_inventory` that writes
a representative workflow fixture to a temporary path, invokes the checker, and
asserts its return code and summary output. Cover annotation output and the
unreadable-file branch so these behaviors have regression protection, using the
existing `inventory_errors` and `_check_results` conventions where appropriate.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9048820f-61d7-4b7e-885b-e5c5e905f8d5

📥 Commits

Reviewing files that changed from the base of the PR and between c529f58 and 529db80.

📒 Files selected for processing (3)
  • .github/ci/check_core_ci_gate.py
  • .github/ci/test_check_core_ci_gate.py
  • .github/workflows/ci.yaml

@thossain-nv

Copy link
Copy Markdown
Contributor

Looks great @chet Seems like the Python script could be generic enough to apply to REST gate as well.

@thossain-nv

Copy link
Copy Markdown
Contributor

/ok to test 529db80

@@ -0,0 +1,381 @@
#!/usr/bin/env python3

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.

Should we add these files in .github/workflows/scripts?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@thossain-nv Yeah I actually put these in .github/ci/ intentionally! I think you can tell most of my PR(s) here are introducing some Python to bump us more into kind of an "advanced" mode away from pure workflows config, lol.

In this case, my thinking is .github/workflows/ is where we keep all of the declarative Actions YAML, while .github/ci/ is the common home for the code behind it.

And yeah, especially since the other CI PRs are adding helpers too, this would be where we'd build out tools/libs/etc.

Totally doesn't need to be, but that was my thinking!

@chet

chet commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full_review, thanks!

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

@chet I will perform a complete review of PR #4655.

🐇🔎

✅ Action performed

Full review finished.

@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

🧹 Nitpick comments (1)
.github/ci/test_check_core_ci_gate.py (1)

260-283: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover malformed per-job result objects.

The cases do not test a job object with a missing or non-string result field. Add cases such as {"fixture-job":{}} and {"fixture-job":{"result":null}}. Both must return a failure code.

This protects the stated fail-closed policy for malformed results.

🤖 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 @.github/ci/test_check_core_ci_gate.py around lines 260 - 283, Extend
test_result_command_rejects_invalid_context with cases for a per-job object
missing the result field and one whose result is non-string/null. Assert each
produces the expected malformed-result error and a nonzero failure code,
preserving the fail-closed behavior already covered by the command tests.
🤖 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 @.github/ci/check_core_ci_gate.py:
- Around line 91-100: Update the jobs scan around the loop following jobs_blocks
to track BLOCK_SCALAR headers and skip their bodies while indentation remains at
least indentation + 1; add the requested BLOCK_SCALAR pattern alongside the
other grammar patterns. When scalar tracking ends, reject unexpected column-0
content with the existing format-error path instead of silently breaking, while
preserving normal job-key handling and avoiding errors for valid scalar lines
indented two spaces. Add a fixture in test_check_core_ci_gate.py with a column-0
heredoc body between two job declarations and assert the later job remains
classified.

---

Nitpick comments:
In @.github/ci/test_check_core_ci_gate.py:
- Around line 260-283: Extend test_result_command_rejects_invalid_context with
cases for a per-job object missing the result field and one whose result is
non-string/null. Assert each produces the expected malformed-result error and a
nonzero failure code, preserving the fail-closed behavior already covered by the
command tests.
🪄 Autofix

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: 62e68d02-0460-4f14-b715-9238062d560e

📥 Commits

Reviewing files that changed from the base of the PR and between 9d296f6 and 89a14df.

📒 Files selected for processing (3)
  • .github/ci/check_core_ci_gate.py
  • .github/ci/test_check_core_ci_gate.py
  • .github/workflows/ci.yaml

Comment thread .github/ci/check_core_ci_gate.py
@chet

chet commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Looks great @chet Seems like the Python script could be generic enough to apply to REST gate as well.

@thossain-nv Oh yeah totally! I wanted to keep this scoped to Core, but I generalize and extend to REST in a follow-up PR if we like it.

`core-ci-pass` was only waiting on part of the workflow, which meant an unlisted build could fail while the protected check still reported green. This makes it wait on every current substantive Core job and checks that inventory before the expensive work starts.

- **Expected green-run effect:** No speedup. The final gate may finish later because it now waits for every job it represents.
- **What it really buys us:** `core-ci-pass` cannot report green while a known Core job is red, and a future top-level job cannot quietly sit outside the gate.

Intentional skips remain accepted, while failures, cancellations, malformed results, and unknown inventory entries stop the gate.

Tests added!

This supports NVIDIA#4649

Signed-off-by: Chet Nichols III <chetn@nvidia.com>
@chet

chet commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full_review, thanks!

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

@chet I will perform a complete review of PR #4655.

🐇🔎

✅ Action performed

Full review finished.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants