Skip to content

[TRTLLM-12838][infra] CBTS: coverage-based test selection#16776

Open
crazydemo wants to merge 2 commits into
NVIDIA:mainfrom
crazydemo:cbts-coverage-selector
Open

[TRTLLM-12838][infra] CBTS: coverage-based test selection#16776
crazydemo wants to merge 2 commits into
NVIDIA:mainfrom
crazydemo:cbts-coverage-selector

Conversation

@crazydemo

@crazydemo crazydemo commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds Tier-2 coverage-based test selection (CBTS) for residual core-Python changes. The Jenkins pipeline now runs _cbtsCoverageAudit(pipeline) to discover an optional sqlite coverage DB path and, when present, threads it into jenkins/scripts/cbts/main.py as --coverage-db (omitted when empty or when audit failures are non-fatal), preserving existing CBTS behavior when coverage is unavailable.

Key new/updated coverage-tier behavior:

  • AST maps post-diff line numbers to function/class co_qualnames (jenkins/scripts/cbts/coverage_selection/qualname_map.py).
  • Coverage-driven residual selection computes impacted vs skippable tests via TouchDB queries with conservative fallbacks (jenkins/scripts/cbts/coverage_selection/selector.py).
  • Tier-2 narrowing removes only “SAFE” YAML entries while forcing must-run for impacted/untrusted/no-data cases, and can drop fully removable instrumented stages while explicitly excluding multi-GPU and post-merge stages from drop candidates (jenkins/scripts/cbts/coverage_tier.py).
  • CBTS outputs now support structured reasons (list of dicts) plus coverage-tier fields like enable_multi_gpu and coverage_dropped_stages (jenkins/scripts/cbts/main.py), with consistent rendering in dryrun.py and report_cbts_decision.py.
  • Adds coverage_explain.py to explain kept/removed coverage cases for a specific commit SHA, and extends dryrun.py with opt-in --coverage-db replay/formatting support.

Supporting infra tweaks:

  • _cbtsCoverageAudit is converted from best-effort “shadow audit” into a return-value helper that yields the sqlite path on success and "" otherwise; logs updated to reflect skipping Tier 2 when coverage artifacts can’t be found/processed (jenkins/L0_MergeRequest.groovy).
  • Multi-GPU stages are re-added to parallelJobsFiltered only when cbts.enable_multi_gpu is true and MULTI_GPU_FILE_CHANGED is set (jenkins/L0_Test.groovy).
  • Expands out-of-scope handling to include broader jenkins/ changes (jenkins/scripts/cbts/rules/out_of_scope_rule.py).
  • Adds a no-op CBTS touch marker comment in tensorrt_llm/_torch/pyexecutor/py_executor.py for coverage-based validation.

Dev Engineer Review

  • Correctness / behavior

    • jenkins/L0_MergeRequest.groovy: _cbtsCoverageAudit(pipeline) now returns the sqlite coverage artifact path on success and "" on non-fatal failures; --coverage-db is only appended to the Python invocation when the returned path is non-empty. Updated logging aligns with Tier 2 being skipped when the artifact is unavailable/unusable.
    • jenkins/scripts/cbts/main.py: implements optional coverage-tier execution behind --coverage-db, updates SelectionResult JSON with enable_multi_gpu and coverage_dropped_stages, and migrates reasons from list[str] to list[dict] with structured rendering/printing.
    • jenkins/scripts/cbts/coverage_selection/qualname_map.py: AST-based line→qualname attribution with scope selection rules; returns (set(), False) on SyntaxError and qualnames_for_lines(...)->(set[str], bool) to drive conservative downstream behavior.
    • jenkins/scripts/cbts/coverage_selection/selector.py: validates residual residual inputs, derives post-diff line numbers, maps them to qualnames, queries TouchDB for impacted tests, caches “untrusted” tests, and avoids marking untrusted tests skippable unless impacted; uses conservative “all touching-file tests impacted” fallback when mapping/reads fail.
    • jenkins/scripts/cbts/coverage_tier.py: narrows the test-db by removing only SAFE entries and accounting for must-run reasons (impacted/untrusted/no-data). Includes stage-dropping logic with explicit exclusions for multi-GPU and post-merge variants.
    • jenkins/scripts/cbts/tools/coverage_explain.py: diff+qualname mapping and TouchDB-based classification of KEPT vs REMOVED nodeids for a specific SHA; includes optional kept-case printing and safe fallbacks.
    • jenkins/scripts/cbts/tools/dryrun.py + jenkins/scripts/cbts/tools/report_cbts_decision.py: consistent formatting for structured reasons objects (dict-based reasons rendered as [source] k=v, ...).
  • Jenkins pipeline / scoping

    • jenkins/L0_Test.groovy: conditional re-add of multi-GPU stages into parallelJobsFiltered gated by cbts.enable_multi_gpu and MULTI_GPU_FILE_CHANGED.
    • jenkins/scripts/cbts/rules/out_of_scope_rule.py: treats jenkins/ as out-of-scope in addition to the existing more specific CBTS script prefix.
  • Schema / API consistency

    • jenkins/scripts/cbts/rules/base.py: adds RuleResult.detail: dict[str, object] defaulting to empty dict for structured rule payloads.
    • jenkins/scripts/cbts/rules/tests_def_rule.py and waives_rule.py: populates detail with narrowed-path counts and waived added/removed counts respectively.
    • jenkins/scripts/cbts/main.py + tooling: updates reason formatting/serialization to match the structured schema end-to-end.
  • Risk / areas to double-check

    • Optional coverage DB correctness: ensure Tier-2 selection logic is only activated when coverageDbPath is non-empty, and that empty/failed audit does not alter non-coverage CBTS semantics.
    • Safety of fallbacks: validate that AST mapping/source reads failing can’t lead to under-removal (i.e., should bias toward keeping tests).
    • Stage-drop guardrails: confirm the explicit exclusions (multi-GPU, post-merge) cover all expected stage naming variants so required work isn’t dropped.
    • YAML mutation consistency in coverage tier: verify removed-case deletion respects the block/index structure used by the YAML test DB.

QA Engineer Review

No test changes.

Description

Test Coverage

PR Checklist

Please review the following before submitting your PR:

  • PR description clearly explains what and why. If using CodeRabbit's summary, please make sure it makes sense.

  • PR Follows TRT-LLM CODING GUIDELINES to the best of your knowledge.

  • Test cases are provided for new code paths (see test instructions)

  • If PR introduces API changes, an appropriate PR label is added - either api-compatible or api-breaking. For api-breaking, include BREAKING in the PR title.

  • Any new dependencies have been scanned for license and vulnerabilities

  • CODEOWNERS updated if ownership changes

  • Documentation updated as needed

  • Update tava architecture diagram if there is a significant design change in PR.

  • The reviewers assigned automatically/manually are appropriate for the PR.

  • Please check this after reviewing the above items as appropriate for this PR.

GitHub Bot Help

To see a list of available CI bot commands, please comment /bot help.

@coderabbitai

coderabbitai Bot commented Jul 23, 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

Walkthrough

CBTS adds optional coverage-database test narrowing, maps changed Python lines to qualified names, preserves impacted and untrusted tests, removes safe YAML entries, exposes structured diagnostics, and propagates coverage settings through Jenkins and dry-run execution.

Changes

Coverage-tier CBTS selection

Layer / File(s) Summary
Changed-line coverage selection
jenkins/scripts/cbts/coverage_selection/*
Maps changed Python lines to qualified names and queries TouchDB for impacted, skippable, untrusted, and no-data test information.
Coverage-tier test narrowing
jenkins/scripts/cbts/coverage_tier.py, jenkins/scripts/cbts/rules/*
Classifies YAML entries, removes safe tests, filters droppable stages, writes narrowed YAML, and computes stage counts while preserving rule-kept and must-run entries.
CBTS result and reason integration
jenkins/scripts/cbts/main.py
Adds --coverage-db, applies coverage-tier results, serializes coverage fields, and changes diagnostics to structured reason objects.
Pipeline and replay wiring
jenkins/L0_MergeRequest.groovy, jenkins/L0_Test.groovy, jenkins/scripts/cbts/tools/dryrun.py, tensorrt_llm/_torch/pyexecutor/py_executor.py
Propagates coverage database paths, restores eligible multi-GPU stages, reports coverage-tier output, and adds a coverage touch marker.
Coverage decision explanation tool
jenkins/scripts/cbts/tools/coverage_explain.py
Reports kept and removed tests with file- and function-level touch details for a commit.
Jenkins path classification
jenkins/scripts/cbts/rules/out_of_scope_rule.py
Treats Jenkins paths as out of scope for pre-merge CI impact.

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

Sequence Diagram(s)

sequenceDiagram
  participant JenkinsPipeline
  participant main_py
  participant CoverageSelector
  participant TouchDB
  participant coverage_tier_py
  participant YAMLTestDB
  JenkinsPipeline->>main_py: pass coverage database path
  main_py->>CoverageSelector: run initial selection
  CoverageSelector-->>main_py: fallback result and selector state
  main_py->>TouchDB: open coverage database
  main_py->>coverage_tier_py: apply coverage tier
  coverage_tier_py->>TouchDB: query impacted and skippable tests
  coverage_tier_py-->>main_py: narrowed stages and diagnostics
  main_py->>YAMLTestDB: write narrowed test database
Loading

Suggested reviewers: yuxianq

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is still the template text and lacks the required issue summary, solution details, and test coverage. Replace the template placeholders with a brief problem/solution description and list the relevant tests or validation performed.
Docstring Coverage ⚠️ Warning Docstring coverage is 53.85% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and correctly summarizes the main change with the required ticket and type.
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.

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
jenkins/L0_MergeRequest.groovy (2)

809-815: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

reasons.join('; ') will now print raw Map toString() output.

result.reasons used to be a list of strings; main.py in this PR turns every entry into a structured Map ({source: ..., reason: ..., ...}). This log line still does a plain .join('; '), so the "CBTS: deferring" console message will render as Groovy Map literals (e.g. [source:fallback, reason:unhandled_files, files:[...]]) instead of readable text.

🩹 Suggested fix: format each structured reason before joining
-            pipeline.echo("CBTS: deferring — Python returned scope=null. " +
-                          "Reasons: ${result.reasons.join('; ')}")
+            def reasonStr = result.reasons.collect { r ->
+                if (r instanceof Map) {
+                    def src = r.source ?: "?"
+                    def rest = r.findAll { k, v -> k != "source" }.collect { k, v -> "${k}=${v}" }.join(", ")
+                    return rest ? "[${src}] ${rest}" : "[${src}]"
+                }
+                return r.toString()
+            }.join('; ')
+            pipeline.echo("CBTS: deferring — Python returned scope=null. Reasons: ${reasonStr}")
🤖 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 `@jenkins/L0_MergeRequest.groovy` around lines 809 - 815, Update the scope-null
handling in the pipeline flow around _cbtsParseSelectionResult and
_cbtsReportDecision so result.reasons maps are converted to readable reason text
before joining. Reuse the structured fields, including source and reason and any
relevant details, rather than calling join directly on the maps; preserve the
existing deferring message and fallback decision behavior.

954-968: 🗄️ Data Integrity & Integration | 🔴 Critical | ⚡ Quick win

Coverage-tier multi-GPU re-enable is broken: _cbtsParseSelectionResult never forwards enable_multi_gpu/coverage_dropped_stages to the Groovy consumer. main.py's SelectionResult.to_json() emits these two new fields, but the Groovy-side JSON parser explicitly whitelists a fixed set of keys that doesn't include them, so they never reach testFilter[(CBTS_RESULT)].

  • jenkins/L0_MergeRequest.groovy#L954-L968: add enable_multi_gpu: data.enable_multi_gpu ?: false and coverage_dropped_stages: data.coverage_dropped_stages ?: [] to the map literal returned by _cbtsParseSelectionResult.
  • jenkins/L0_Test.groovy#L5714-L5718: no code change needed here — this consumer is correct and will start working once cbts.enable_multi_gpu is actually populated by the fix above; currently it always evaluates falsy, so multi-GPU stages are never re-added under coverage-tier selection even when MULTI_GPU_FILE_CHANGED is true.
🤖 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 `@jenkins/L0_MergeRequest.groovy` around lines 954 - 968, The Groovy parser
_cbtsParseSelectionResult in jenkins/L0_MergeRequest.groovy:954-968 must forward
enable_multi_gpu with a false default and coverage_dropped_stages with an
empty-list default in its returned map. Make no code change to
jenkins/L0_Test.groovy:5714-5718; its consumer is already correct and will work
once the parser populates cbts.enable_multi_gpu.
🧹 Nitpick comments (2)
jenkins/scripts/cbts/coverage_selection/qualname_map.py (1)

79-86: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Complete the public API docstrings.

  • jenkins/scripts/cbts/coverage_selection/qualname_map.py#L79-L86: document source, lines, and the ok=False parse-failure result using Google-style Args and Returns.
  • jenkins/scripts/cbts/coverage_selection/selector.py#L108-L112: document residual_files, diffs, and all CoverageResult outcomes using Google-style sections.

As per coding guidelines, “Prefer docstrings for external interfaces, use Google-style docstrings, document public function arguments.”

🤖 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 `@jenkins/scripts/cbts/coverage_selection/qualname_map.py` around lines 79 -
86, The public API docstrings are missing parameter and result documentation. In
jenkins/scripts/cbts/coverage_selection/qualname_map.py lines 79-86, update
qualnames_for_lines with Google-style Args for source and lines and Returns
describing the qualname set and the ok=False result when parsing fails. In
jenkins/scripts/cbts/coverage_selection/selector.py lines 108-112, update the
affected public function’s docstring with Google-style Args for residual_files
and diffs and Returns covering every possible CoverageResult outcome.

Source: Coding guidelines

jenkins/scripts/cbts/coverage_tier.py (1)

175-251: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

must_run_reasons tally is computed but never surfaced.

_build_narrowing returns a Counter of why each entry was kept (rule_kept/impacted/untrusted/no_data/coarse), and apply_coverage_tier stores it on CoverageTierResult.must_run_reasons (Line 239). Nothing downstream reads it — main.py's coverage-tier block only consumes tier.detail, tier.affected_stages, tier.dropped, tier.removed. This diagnostic is silently discarded even though the PR explicitly aims to "emit structured selection reasons."

♻️ Suggested fix: fold the tally into `detail`
         detail={
             "source": "coverage",
             "files": len(residual),
             "impacted": n_impacted,
             "untrusted": cov.n_untrusted,
             "removed_cases": n_removed,
             "dropped_stages": len(dropped),
             "outcome": "narrowed" if narrowed else "nothing_removable",
+            **({"must_run_reasons": dict(must_run_reasons)} if must_run_reasons else {}),
             **({"no_data_funcs": list(cov.no_data_funcs)} if cov.no_data_funcs else {}),
         },
🤖 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 `@jenkins/scripts/cbts/coverage_tier.py` around lines 175 - 251, Expose the
must-run reason tally in the structured coverage-tier output by adding the
existing must_run_reasons value returned from _build_narrowing to
CoverageTierResult.detail in apply_coverage_tier. Preserve the existing
must_run_reasons field and include the tally under a clear stable detail key so
downstream main.py consumers receive it.
🤖 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 `@jenkins/scripts/cbts/coverage_selection/selector.py`:
- Around line 18-32: The Ruff auto-fixes must be applied and staged in both
affected files: rerun the configured pre-commit hook for
jenkins/scripts/cbts/coverage_selection/selector.py lines 18-32 and
jenkins/scripts/cbts/tools/coverage_explain.py lines 30-43, then stage the
resulting edits so the release check passes.

In `@jenkins/scripts/cbts/coverage_tier.py`:
- Around line 18-42: Re-run the ruff pre-commit hook for coverage_tier.py,
retain all four auto-fixes it applies, then stage the modified file and create a
new commit containing those changes so the hook completes successfully.

In `@jenkins/scripts/cbts/tools/coverage_explain.py`:
- Around line 86-103: The coverage explanation must mirror
CoverageSelector.decide() safety gates. In
jenkins/scripts/cbts/tools/coverage_explain.py lines 86-103, check
db.file_has_touch_rows(cf) before reporting file or function impact; when false,
stop and report the coverage decision as unsupported. In lines 124-143, remove
the selector’s untrusted tests from skip_s and report those tests as
forced-kept, preserving the selector’s actual behavior.

---

Outside diff comments:
In `@jenkins/L0_MergeRequest.groovy`:
- Around line 809-815: Update the scope-null handling in the pipeline flow
around _cbtsParseSelectionResult and _cbtsReportDecision so result.reasons maps
are converted to readable reason text before joining. Reuse the structured
fields, including source and reason and any relevant details, rather than
calling join directly on the maps; preserve the existing deferring message and
fallback decision behavior.
- Around line 954-968: The Groovy parser _cbtsParseSelectionResult in
jenkins/L0_MergeRequest.groovy:954-968 must forward enable_multi_gpu with a
false default and coverage_dropped_stages with an empty-list default in its
returned map. Make no code change to jenkins/L0_Test.groovy:5714-5718; its
consumer is already correct and will work once the parser populates
cbts.enable_multi_gpu.

---

Nitpick comments:
In `@jenkins/scripts/cbts/coverage_selection/qualname_map.py`:
- Around line 79-86: The public API docstrings are missing parameter and result
documentation. In jenkins/scripts/cbts/coverage_selection/qualname_map.py lines
79-86, update qualnames_for_lines with Google-style Args for source and lines
and Returns describing the qualname set and the ok=False result when parsing
fails. In jenkins/scripts/cbts/coverage_selection/selector.py lines 108-112,
update the affected public function’s docstring with Google-style Args for
residual_files and diffs and Returns covering every possible CoverageResult
outcome.

In `@jenkins/scripts/cbts/coverage_tier.py`:
- Around line 175-251: Expose the must-run reason tally in the structured
coverage-tier output by adding the existing must_run_reasons value returned from
_build_narrowing to CoverageTierResult.detail in apply_coverage_tier. Preserve
the existing must_run_reasons field and include the tally under a clear stable
detail key so downstream main.py consumers receive it.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: a4e8fe46-939f-4256-acec-6e03d0ed6157

📥 Commits

Reviewing files that changed from the base of the PR and between 0a401b4 and 1ed8175.

📒 Files selected for processing (11)
  • jenkins/L0_MergeRequest.groovy
  • jenkins/L0_Test.groovy
  • jenkins/scripts/cbts/coverage_selection/qualname_map.py
  • jenkins/scripts/cbts/coverage_selection/selector.py
  • jenkins/scripts/cbts/coverage_tier.py
  • jenkins/scripts/cbts/main.py
  • jenkins/scripts/cbts/rules/base.py
  • jenkins/scripts/cbts/rules/tests_def_rule.py
  • jenkins/scripts/cbts/rules/waives_rule.py
  • jenkins/scripts/cbts/tools/coverage_explain.py
  • jenkins/scripts/cbts/tools/dryrun.py

Comment thread jenkins/scripts/cbts/coverage_selection/selector.py Outdated
Comment on lines +18 to +42
import math
import re
import sys
from collections import Counter
from dataclasses import dataclass, field
from pathlib import Path

import yaml
from blocks import (
TARGET_SHARD_SECONDS,
Stage,
YAMLIndex,
_avg_duration,
_entry_applies_to_waive,
_entry_target,
_estimate_entries_seconds,
_target_in_filter_subtree,
block_matches_stage,
)

from rules.base import PRInputs, RuleResult

sys.path.insert(0, str(Path(__file__).resolve().parent / "coverage_selection"))
from selector import CoverageSelector # noqa: E402
from touch_db import TouchDB, db_key # noqa: E402

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

Re-stage ruff's auto-fixes and re-commit.

The attached pipeline logs show ruff (pre-commit) modified this file and fixed 4 errors, but the hook still exited non-zero. The current diff does not include those auto-fixes.

Based on learnings and pipeline failures, as per coding guidelines: "If pre-commit hooks modify files, re-stage the modified files and commit again."

🤖 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 `@jenkins/scripts/cbts/coverage_tier.py` around lines 18 - 42, Re-run the ruff
pre-commit hook for coverage_tier.py, retain all four auto-fixes it applies,
then stage the modified file and create a new commit containing those changes so
the hook completes successfully.

Sources: Coding guidelines, Pipeline failures

Comment on lines +86 to +103
for f in core:
cf = canon(f)
changed_files.add(cf)
diff = _git(repo, "diff", f"{args.sha}^", args.sha, "--", f, check=False)
lines = iter_diff_post_line_numbers(diff)
src = _src_at(repo, args.sha, f)
if not lines or src is None:
impact_files.add(cf)
impacted |= db.tests_touching_file(cf)
continue
qns, ok = qualnames_for_lines(src, lines)
if not ok:
impact_files.add(cf)
impacted |= db.tests_touching_file(cf)
continue
for q in qns:
impact_funcs.add((cf, q))
impacted |= db.tests_touching_func(cf, q)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep the explanation output aligned with selector safety gates. The tool can label cases as removed even when CoverageSelector.decide() refuses zero-touch files or forces untrusted tests to run.

  • jenkins/scripts/cbts/tools/coverage_explain.py#L86-L103: stop/report an unsupported coverage decision when db.file_has_touch_rows(cf) is false.
  • jenkins/scripts/cbts/tools/coverage_explain.py#L124-L143: exclude the selector’s untrusted tests from skip_s and report them as forced-kept.
📍 Affects 1 file
  • jenkins/scripts/cbts/tools/coverage_explain.py#L86-L103 (this comment)
  • jenkins/scripts/cbts/tools/coverage_explain.py#L124-L143
🤖 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 `@jenkins/scripts/cbts/tools/coverage_explain.py` around lines 86 - 103, The
coverage explanation must mirror CoverageSelector.decide() safety gates. In
jenkins/scripts/cbts/tools/coverage_explain.py lines 86-103, check
db.file_has_touch_rows(cf) before reporting file or function impact; when false,
stop and report the coverage decision as unsupported. In lines 124-143, remove
the selector’s untrusted tests from skip_s and report those tests as
forced-kept, preserving the selector’s actual behavior.

@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

🤖 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 `@jenkins/scripts/cbts/rules/out_of_scope_rule.py`:
- Line 59: Remove the broad "jenkins/" no-op prefix from the OutOfScopeRule
configuration before merging. If it is required for temporary validation, gate
it behind explicit test-only configuration so normal CBTS runs do not classify
every Jenkins change as out of scope.

In `@tensorrt_llm/_torch/pyexecutor/py_executor.py`:
- Line 106: Remove the temporary “[cbts-test] no-op touch to validate
coverage-based selection” comment from the production code, leaving the
surrounding implementation unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 23a719fe-5256-435e-8601-e5531343b7d7

📥 Commits

Reviewing files that changed from the base of the PR and between 1ed8175 and 8e99945.

📒 Files selected for processing (2)
  • jenkins/scripts/cbts/rules/out_of_scope_rule.py
  • tensorrt_llm/_torch/pyexecutor/py_executor.py

"tests/integration/defs/agg_unit_mem_df.csv",
"tests/microbenchmarks/",
"jenkins/scripts/cbts/",
"jenkins/",

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

Revert the broad jenkins/ no-op prefix before merging.

Because OutOfScopeRule is active in CBTS, this classifies every Jenkins change as out of scope and can suppress test-stage selection. Keep this only for the temporary validation run, or gate it behind explicit test-only configuration.

🤖 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 `@jenkins/scripts/cbts/rules/out_of_scope_rule.py` at line 59, Remove the broad
"jenkins/" no-op prefix from the OutOfScopeRule configuration before merging. If
it is required for temporary validation, gate it behind explicit test-only
configuration so normal CBTS runs do not classify every Jenkins change as out of
scope.


# Environment variable to specify iteration ranges for profiling start/stop.
# Format: "start1-stop1,start2-stop2,..." or single iterations "iter1,iter2,..."
# [cbts-test] no-op touch to validate coverage-based selection

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

Remove the temporary coverage marker before merging.

This comment only touches production code to trigger CBTS coverage selection and has no runtime purpose. Revert it after the validation run.

🤖 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 `@tensorrt_llm/_torch/pyexecutor/py_executor.py` at line 106, Remove the
temporary “[cbts-test] no-op touch to validate coverage-based selection” comment
from the production code, leaving the surrounding implementation unchanged.

@crazydemo
crazydemo force-pushed the cbts-coverage-selector branch from 8e99945 to 8ce112a Compare July 23, 2026 06:26
@crazydemo

Copy link
Copy Markdown
Collaborator Author

/bot run

@crazydemo
crazydemo force-pushed the cbts-coverage-selector branch from 8ce112a to 34ba032 Compare July 23, 2026 06:42
@crazydemo

Copy link
Copy Markdown
Collaborator Author

/bot run

@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)
jenkins/scripts/cbts/main.py (1)

390-392: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid swallowing every coverage-tier failure.

This converts programming defects in Tier 2 into an ordinary fallback, making coverage regressions hard to detect. Catch expected operational failures at this boundary (or a dedicated coverage-tier exception) and preserve unexpected-error diagnostics.

As per coding guidelines, “Avoid broad exception handling; catch specific exceptions instead of using bare except:.”

🤖 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 `@jenkins/scripts/cbts/main.py` around lines 390 - 392, Update the exception
handling around the coverage-tier invocation in the Tier 2 flow to catch only
expected operational failures or the dedicated coverage-tier exception, while
preserving the existing fallback note and tier=None behavior for those cases. Do
not convert unexpected programming errors into ordinary fallback; allow them to
propagate with their diagnostics, and update the handler near the existing note
and tier assignments rather than broadening error handling elsewhere.

Source: Coding guidelines

🤖 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 `@jenkins/scripts/cbts/main.py`:
- Around line 390-392: Update the exception handling around the coverage-tier
invocation in the Tier 2 flow to catch only expected operational failures or the
dedicated coverage-tier exception, while preserving the existing fallback note
and tier=None behavior for those cases. Do not convert unexpected programming
errors into ordinary fallback; allow them to propagate with their diagnostics,
and update the handler near the existing note and tier assignments rather than
broadening error handling elsewhere.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 39c1ca16-ae60-4c99-b8e9-b0e33d4122af

📥 Commits

Reviewing files that changed from the base of the PR and between 8ce112a and 34ba032.

📒 Files selected for processing (13)
  • jenkins/L0_MergeRequest.groovy
  • jenkins/L0_Test.groovy
  • jenkins/scripts/cbts/coverage_selection/qualname_map.py
  • jenkins/scripts/cbts/coverage_selection/selector.py
  • jenkins/scripts/cbts/coverage_tier.py
  • jenkins/scripts/cbts/main.py
  • jenkins/scripts/cbts/rules/base.py
  • jenkins/scripts/cbts/rules/out_of_scope_rule.py
  • jenkins/scripts/cbts/rules/tests_def_rule.py
  • jenkins/scripts/cbts/rules/waives_rule.py
  • jenkins/scripts/cbts/tools/coverage_explain.py
  • jenkins/scripts/cbts/tools/dryrun.py
  • tensorrt_llm/_torch/pyexecutor/py_executor.py
🚧 Files skipped from review as they are similar to previous changes (10)
  • jenkins/scripts/cbts/rules/tests_def_rule.py
  • jenkins/scripts/cbts/rules/base.py
  • jenkins/scripts/cbts/rules/out_of_scope_rule.py
  • tensorrt_llm/_torch/pyexecutor/py_executor.py
  • jenkins/scripts/cbts/rules/waives_rule.py
  • jenkins/L0_MergeRequest.groovy
  • jenkins/L0_Test.groovy
  • jenkins/scripts/cbts/coverage_tier.py
  • jenkins/scripts/cbts/coverage_selection/selector.py
  • jenkins/scripts/cbts/coverage_selection/qualname_map.py

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #61223 [ run ] triggered by Bot. Commit: 34ba032 Link to invocation

@crazydemo

Copy link
Copy Markdown
Collaborator Author

/bot kill

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #61226 [ kill ] triggered by Bot. Commit: 34ba032 Link to invocation

@crazydemo
crazydemo force-pushed the cbts-coverage-selector branch from 34ba032 to 28d14b0 Compare July 23, 2026 07:09
@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #61223 [ run ] completed with state ABORTED. Commit: 34ba032

Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #61226 [ kill ] completed with state SUCCESS. Commit: 34ba032
Successfully killed previous jobs for commit 34ba032

Link to invocation

@crazydemo

Copy link
Copy Markdown
Collaborator Author

/bot run

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
jenkins/scripts/cbts/main.py (1)

197-214: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

self.pairs/self.handled set only inside run(), never initialized in __init__.

They're read externally as selector.pairs/selector.handled in main() (lines 388), which makes them externally-visible class members. As per coding guidelines, "initialize externally visible class members in the constructor". Currently Selector.__init__ (lines 198-199) only sets self.stages, so pairs/handled are absent from the object until run() executes, and any future caller that inspects them before calling run() gets an AttributeError.

♻️ Proposed fix
 class Selector:
     def __init__(self, stages: dict[str, Stage]) -> None:
         self.stages = stages
+        self.pairs: list[tuple[Rule, RuleResult]] = []
+        self.handled: set[str] = set()
🤖 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 `@jenkins/scripts/cbts/main.py` around lines 197 - 214, Initialize the
externally visible Selector state in Selector.__init__ by setting pairs to an
empty list of rule/result tuples and handled to an empty set of file names. Keep
run() updating these members with the computed values before they are consumed
by main().

Source: Coding guidelines

🧹 Nitpick comments (1)
jenkins/scripts/cbts/tools/dryrun.py (1)

214-221: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicates _fmt_reason from main.py instead of reusing it.

This block re-implements the same dict-vs-non-dict reason formatting that main.py already defines as _fmt_reason(r). report_cbts_decision.py apparently imports/reuses that helper rather than reimplementing it; dryrun.py should do the same to avoid the two renderings drifting apart.

♻️ Proposed fix
+from main import _fmt_reason  # noqa: E402
+
 ...
-    lines.append("reasons:")
-    for r in result.get("reasons", []):
-        if isinstance(r, dict):
-            src = r.get("source", "?")
-            rest = ", ".join(f"{k}={v}" for k, v in r.items() if k != "source")
-            lines.append(f"  - [{src}] {rest}" if rest else f"  - [{src}]")
-        else:
-            lines.append(f"  - {r}")
+    lines.append("reasons:")
+    lines.extend(f"  - {_fmt_reason(r)}" for r in result.get("reasons", []))
🤖 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 `@jenkins/scripts/cbts/tools/dryrun.py` around lines 214 - 221, Replace the
inline reason-formatting logic in the report-generation block with the existing
_fmt_reason helper from main.py. Import or reuse that helper in dryrun.py and
pass each reason to it, preserving the current “reasons:” output structure while
ensuring formatting remains consistent.
🤖 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.

Outside diff comments:
In `@jenkins/scripts/cbts/main.py`:
- Around line 197-214: Initialize the externally visible Selector state in
Selector.__init__ by setting pairs to an empty list of rule/result tuples and
handled to an empty set of file names. Keep run() updating these members with
the computed values before they are consumed by main().

---

Nitpick comments:
In `@jenkins/scripts/cbts/tools/dryrun.py`:
- Around line 214-221: Replace the inline reason-formatting logic in the
report-generation block with the existing _fmt_reason helper from main.py.
Import or reuse that helper in dryrun.py and pass each reason to it, preserving
the current “reasons:” output structure while ensuring formatting remains
consistent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: c9b5ee70-2616-4357-9ad6-bde91f02cfce

📥 Commits

Reviewing files that changed from the base of the PR and between 34ba032 and 28d14b0.

📒 Files selected for processing (14)
  • jenkins/L0_MergeRequest.groovy
  • jenkins/L0_Test.groovy
  • jenkins/scripts/cbts/coverage_selection/qualname_map.py
  • jenkins/scripts/cbts/coverage_selection/selector.py
  • jenkins/scripts/cbts/coverage_tier.py
  • jenkins/scripts/cbts/main.py
  • jenkins/scripts/cbts/rules/base.py
  • jenkins/scripts/cbts/rules/out_of_scope_rule.py
  • jenkins/scripts/cbts/rules/tests_def_rule.py
  • jenkins/scripts/cbts/rules/waives_rule.py
  • jenkins/scripts/cbts/tools/coverage_explain.py
  • jenkins/scripts/cbts/tools/dryrun.py
  • jenkins/scripts/cbts/tools/report_cbts_decision.py
  • tensorrt_llm/_torch/pyexecutor/py_executor.py
🚧 Files skipped from review as they are similar to previous changes (9)
  • jenkins/scripts/cbts/rules/base.py
  • tensorrt_llm/_torch/pyexecutor/py_executor.py
  • jenkins/scripts/cbts/rules/tests_def_rule.py
  • jenkins/L0_Test.groovy
  • jenkins/L0_MergeRequest.groovy
  • jenkins/scripts/cbts/rules/waives_rule.py
  • jenkins/scripts/cbts/coverage_selection/qualname_map.py
  • jenkins/scripts/cbts/coverage_selection/selector.py
  • jenkins/scripts/cbts/coverage_tier.py

@crazydemo
crazydemo force-pushed the cbts-coverage-selector branch from 28d14b0 to c43b960 Compare July 23, 2026 07:23
@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #61233 [ run ] triggered by Bot. Commit: 28d14b0 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #61233 [ run ] completed with state FAILURE. Commit: 28d14b0
/LLM/main/L0_MergeRequest_PR pipeline #49472 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@crazydemo

Copy link
Copy Markdown
Collaborator Author

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #61261 [ run ] triggered by Bot. Commit: c43b960 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #61261 [ run ] completed with state FAILURE. Commit: c43b960
/LLM/main/L0_MergeRequest_PR pipeline #49497 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

…ector)

Add coverage-based test selection as Tier 2 in the CBTS decision pipeline.
When Tier 1 (flat rules) defers to a full run on a residual of core-Python
files, Tier 2 consults the merged touch DB to narrow per-stage test lists to
only the cases provably reached by the changed functions.

New files:
- coverage_selection/selector.py: CoverageSelector — maps changed lines to
  qualnames via AST, queries the DB for impacted tests, returns per-stage
  impacted/skippable sets.
- coverage_selection/qualname_map.py: AST-based line→qualname mapping with
  fallback to enclosing class/module importers for class-body changes.
- coverage_selection/fixture.py: pytest fixture that resolves the CBTS touch
  DB path for unit tests.
- coverage_tier.py: apply_coverage_tier() — orchestrates the selector, applies
  shared-block and rule-union correctness rules, sizes splits, emits structured
  reasons.
- rules/product_data_rule.py: ProductDataRule — scopes pure product-data PRs
  (configs, curated examples, golden manifests) to productdataonly.
- tools/coverage_explain.py: per-test explain tool showing which changed
  function triggered each must-run verdict.

Modified:
- main.py: wire Tier 2 (--coverage-db flag, CoverageTierResult → SelectionResult
  fields enable_multi_gpu / coverage_dropped_stages, structured reasons dict).
- L0_MergeRequest.groovy: _cbtsCoverageAudit() returns the sqlite path; pass
  --coverage-db to main.py when the DB is available (enforce step).
- L0_Test.groovy: re-add multiGpuJobs under baseline gate when enable_multi_gpu
  (coverage narrows single-GPU only; multi-GPU stays on MULTI_GPU_FILE_CHANGED).
- dryrun.py: --coverage-db option to replay Tier 2 over historical commits.
- rules/base.py, tests_def_rule.py, waives_rule.py: minor cleanups to expose
  block_filters and handled_files for Tier 2 consumption.

Signed-off-by: Ivy Zhang <25222398+crazydemo@users.noreply.github.com>
…py_executor

Test-only commit to exercise Tier 2 coverage selection in CI:
- out_of_scope_rule: expand noop prefix from jenkins/scripts/cbts/ to
  jenkins/ so L0_MergeRequest.groovy and L0_Test.groovy are claimed as
  noop instead of falling through as non-core-Python residual.
- py_executor.py: no-op comment touch to leave a core-Python file in
  the residual, triggering coverage tier. py_executor.py is also in
  getMultiGpuFileChanged, so MULTI_GPU_FILE_CHANGED=True → the
  enable_multi_gpu gate in L0_Test.groovy should re-add multi-GPU stages.

Expected CI outcome:
  scope=coverage, enable_multi_gpu=True, multi-GPU stages present.
Revert both changes before merging.

Signed-off-by: Ivy Zhang <25222398+crazydemo@users.noreply.github.com>
@crazydemo
crazydemo force-pushed the cbts-coverage-selector branch from c43b960 to f42c618 Compare July 23, 2026 12:25
@crazydemo

Copy link
Copy Markdown
Collaborator Author

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #61287 [ run ] triggered by Bot. Commit: f42c618 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #61287 [ run ] completed with state FAILURE. Commit: f42c618
/LLM/main/L0_MergeRequest_PR pipeline #49521 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

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.

2 participants