[None][infra] Using agent to triage risks detected from PLC pipeline - #16510
[None][infra] Using agent to triage risks detected from PLC pipeline#16510yuanjingx87 wants to merge 10 commits into
Conversation
📝 WalkthroughWalkthroughChangesThe pipeline no longer loads previous scan results. Report submission now identifies untriaged risks, sends them to a triage agent, stores ticket records in Elasticsearch, and attaches ticket URLs to vulnerability and license documents. Triage-driven scan reporting
Sequence Diagram(s)sequenceDiagram
participant Pipeline
participant SubmitReport
participant Elasticsearch
participant TriageAgent
Pipeline->>SubmitReport: submit current scan reports
SubmitReport->>Elasticsearch: retrieve triaged dependencies
SubmitReport->>TriageAgent: send untriaged risk items
TriageAgent-->>SubmitReport: return ticket references
SubmitReport->>Elasticsearch: save triage records
SubmitReport->>Elasticsearch: bulk-post reports with ticket URLs
Elasticsearch-->>Pipeline: return submission results
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 11
🧹 Nitpick comments (2)
jenkins/scripts/pulse_in_pipeline_scanning/utils/triage.py (1)
49-50: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueDocument the changed public interfaces consistently.
Add Google-style
ArgsandReturnssections; also correctextract_ticket_refsbecause it returns a dictionary, not a list.
jenkins/scripts/pulse_in_pipeline_scanning/utils/triage.py#L49-L50: document both input document lists and returned agent items.jenkins/scripts/pulse_in_pipeline_scanning/utils/triage.py#L70-L71: document input items and response behavior.jenkins/scripts/pulse_in_pipeline_scanning/utils/triage.py#L90-L107: document response shape and dictionary return value.jenkins/scripts/pulse_in_pipeline_scanning/utils/es.py#L80-L81: document filters and returned mapping.jenkins/scripts/pulse_in_pipeline_scanning/utils/es.py#L112-L122: document persistence arguments and failure behavior.jenkins/scripts/pulse_in_pipeline_scanning/utils/es.py#L142-L152: add a docstring for the dashboard URL builder.As per coding guidelines, “Prefer docstrings for external interfaces, use Google-style docstrings, [and] 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/pulse_in_pipeline_scanning/utils/triage.py` around lines 49 - 50, Update the public function docstrings with Google-style Args and Returns sections: in jenkins/scripts/pulse_in_pipeline_scanning/utils/triage.py lines 49-50 document both document-list inputs and returned agent items; lines 70-71 document input items and response behavior; lines 90-107 document the response shape and dictionary return type, correcting extract_ticket_refs from list to dictionary. In jenkins/scripts/pulse_in_pipeline_scanning/utils/es.py lines 80-81 document filters and returned mapping, lines 112-122 document persistence arguments and failure behavior, and lines 142-152 add a docstring for the dashboard URL builder.Source: Coding guidelines
jenkins/scripts/pulse_in_pipeline_scanning/submit_report.py (1)
32-71: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRedundant debug artifacts in
_run_triage.Lines 36-41 call
format_risks_for_agent([], risk_docs)purely to print it, always misclassifyingrisk_docsas license docs regardless ofscan_type(wrong for vulnerability calls), then the real call on lines 43-48 redoes the formatting correctly. Line 49'sprint(agent_resp)is also a leftover debug statement. This duplicates formatting work and prints misleading data.🧹 Proposed cleanup
if not risk_docs: return {} - print( - format_risks_for_agent( - [], - risk_docs, - ) - ) is_vuln = "vulnerability" in scan_type agent_resp = call_triage_agent( format_risks_for_agent( risk_docs if is_vuln else [], risk_docs if not is_vuln else [], ) ) - print(agent_resp) if not agent_resp: return {}🤖 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/pulse_in_pipeline_scanning/submit_report.py` around lines 32 - 71, Remove the standalone format_risks_for_agent call and print before call_triage_agent in _run_triage, since it duplicates work and misclassifies vulnerability risks; retain the correctly constructed formatting passed to call_triage_agent. Also remove the print(agent_resp) debug output while preserving the existing response handling and ticket persistence logic.
🤖 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/pulse_in_pipeline_scanning/submit_report.py`:
- Line 117: Standardize the no-ticket fallback for s_ticket_url across
submit_source_code_vulns, submit_source_code_licenses, submit_container_vulns,
and submit_container_licenses. Choose one sentinel convention and apply it
consistently to all four document-building paths, including their triaged_deps
lookups, without changing ticketed values.
- Around line 111-118: Update the s_package_fix_version construction in the
report-building logic to coerce a null Upgrade-Guidance value to an empty
mapping before chaining Long-Term and Short-Term lookups. Preserve the existing
safe fallback order and “N/A” default.
- Around line 251-256: Update the container submission flow around
submit_container_* and save_triage_records so amd64 and arm64 passes reuse the
same triaged dependency data instead of calling get_triaged_deps independently.
Load triaged records once before both passes, pass that data into each
submit_container_* invocation, and ensure both architectures’ newly saved
records are considered before ticket creation.
- Around line 43-53: Guard the extract_ticket_refs(agent_resp) call in the
triage flow with exception handling for invalid or malformed responses,
including AttributeError, TypeError, and JSONDecodeError, and fall back to an
empty ticket-reference mapping on failure. Preserve the existing empty-response
return and continue processing so later es_post indexing still runs.
In `@jenkins/scripts/pulse_in_pipeline_scanning/utils/es.py`:
- Around line 137-139: Update the error branch after es_post in the
triage-record persistence flow to retry indexing or fail the operation instead
of returning normally. Ensure bulk indexing errors are propagated after retries
so callers do not treat persistence as successful; preserve the existing stderr
logging context for scan_type.
- Around line 83-98: Update the triaged-dependency lookup around
ES_CLIENT.search to paginate through all matching records instead of limiting
results to the first 10,000. Use Elasticsearch search_after or scroll with a
stable sort, repeatedly request subsequent pages, and aggregate each hit’s
s_package_name and s_ticket_url until no results remain while preserving the
existing filters.
- Around line 123-131: Use package name and version consistently for triage
cache identity: in jenkins/scripts/pulse_in_pipeline_scanning/utils/es.py lines
123-131, persist the version alongside s_package_name in saved triage records;
in lines 103-108, update lookup/filter key construction to include that version.
In jenkins/scripts/pulse_in_pipeline_scanning/utils/triage.py lines 53-58,
deduplicate items using the tuple (dependency_name, current_version,
action_type) rather than dependency name alone.
In `@jenkins/scripts/pulse_in_pipeline_scanning/utils/triage.py`:
- Line 1: Add the standard NVIDIA copyright header at the beginning of the new
triage.py module, before the existing module docstring. Preserve the current
docstring and implementation unchanged.
- Around line 26-27: Update the detail_parts construction near the triage agent
payload so it retains both severity and scan_type instead of overwriting the
severity entry. Ensure the resulting payload includes the existing severity
value and scan_type value.
- Around line 60-66: Update the license filtering condition in the triage loop
so known non-permissive license IDs, including GPL/LGPL values, reach
_license_doc_to_agent_item and are submitted for triage; do not restrict
processing to only “Unknown License” or empty IDs, while preserving the existing
seen-key deduplication and item append behavior.
- Around line 76-82: Narrow the exception handling in triage.py around the
request flow in the visible try block to catch only requests.RequestException
and the JSON decode exception raised by resp.json(), while preserving the
existing error logging and empty-dictionary fallback. In
jenkins/scripts/pulse_in_pipeline_scanning/utils/es.py lines 82-101, replace the
broad exception handler with only the Elasticsearch client’s transport/API
exception base; do not let programming errors be converted into empty results.
---
Nitpick comments:
In `@jenkins/scripts/pulse_in_pipeline_scanning/submit_report.py`:
- Around line 32-71: Remove the standalone format_risks_for_agent call and print
before call_triage_agent in _run_triage, since it duplicates work and
misclassifies vulnerability risks; retain the correctly constructed formatting
passed to call_triage_agent. Also remove the print(agent_resp) debug output
while preserving the existing response handling and ticket persistence logic.
In `@jenkins/scripts/pulse_in_pipeline_scanning/utils/triage.py`:
- Around line 49-50: Update the public function docstrings with Google-style
Args and Returns sections: in
jenkins/scripts/pulse_in_pipeline_scanning/utils/triage.py lines 49-50 document
both document-list inputs and returned agent items; lines 70-71 document input
items and response behavior; lines 90-107 document the response shape and
dictionary return type, correcting extract_ticket_refs from list to dictionary.
In jenkins/scripts/pulse_in_pipeline_scanning/utils/es.py lines 80-81 document
filters and returned mapping, lines 112-122 document persistence arguments and
failure behavior, and lines 142-152 add a docstring for the dashboard URL
builder.
🪄 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: 5846405b-6458-467d-925c-fae638421307
📒 Files selected for processing (4)
jenkins/scripts/pulse_in_pipeline_scanning/main.pyjenkins/scripts/pulse_in_pipeline_scanning/submit_report.pyjenkins/scripts/pulse_in_pipeline_scanning/utils/es.pyjenkins/scripts/pulse_in_pipeline_scanning/utils/triage.py
| agent_resp = call_triage_agent( | ||
| format_risks_for_agent( | ||
| risk_docs if is_vuln else [], | ||
| risk_docs if not is_vuln else [], | ||
| ) | ||
| ) | ||
| print(agent_resp) | ||
| if not agent_resp: | ||
| return {} | ||
| ticket_refs = extract_ticket_refs(agent_resp) | ||
| new_tickets = {} |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '--- submit_report.py ---\n'
sed -n '1,220p' jenkins/scripts/pulse_in_pipeline_scanning/submit_report.py
printf '\n--- triage utils ---\n'
sed -n '1,220p' jenkins/scripts/pulse_in_pipeline_scanning/utils/triage.pyRepository: NVIDIA/TensorRT-LLM
Length of output: 248
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '--- call sites and surrounding flow ---\n'
rg -n "call_triage_agent|extract_ticket_refs|es_post\(" jenkins/scripts/pulse_in_pipeline_scanning -n -A6 -B6
printf '\n--- file list in subtree ---\n'
git ls-files jenkins/scripts/pulse_in_pipeline_scanningRepository: NVIDIA/TensorRT-LLM
Length of output: 248
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
paths = [
Path("jenkins/scripts/pulse_in_pipeline_scanning/submit_report.py"),
Path("jenkins/scripts/pulse_in_pipeline_scanning/utils/triage.py"),
]
for path in paths:
print(f"\n### {path} ({sum(1 for _ in path.open())} lines)")
with path.open() as f:
for i, line in enumerate(f, 1):
if i <= 260:
print(f"{i:4d}: {line.rstrip()}")
PYRepository: NVIDIA/TensorRT-LLM
Length of output: 17164
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '## submit_report.py'
nl -ba jenkins/scripts/pulse_in_pipeline_scanning/submit_report.py | sed -n '1,220p'
echo
echo '## triage.py'
nl -ba jenkins/scripts/pulse_in_pipeline_scanning/utils/triage.py | sed -n '1,220p'
echo
echo '## call sites'
rg -n "call_triage_agent|extract_ticket_refs|es_post\\(" jenkins/scripts/pulse_in_pipeline_scanning -A6 -B6Repository: NVIDIA/TensorRT-LLM
Length of output: 217
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
for rel in [
"jenkins/scripts/pulse_in_pipeline_scanning/submit_report.py",
"jenkins/scripts/pulse_in_pipeline_scanning/utils/triage.py",
]:
p = Path(rel)
print(f"\n### {rel}")
text = p.read_text()
for i, line in enumerate(text.splitlines(), 1):
if 1 <= i <= 260:
print(f"{i:4d}: {line}")
PYRepository: NVIDIA/TensorRT-LLM
Length of output: 17140
Guard triage response parsing before ES indexing.
extract_ticket_refs(agent_resp) can raise AttributeError, TypeError, or JSONDecodeError on a non-dict response, missing value, or malformed JSON. Since _run_triage runs before es_post(...), that exception aborts the whole batch and skips indexing every collected document for the run. Wrap this parse step and fall back to {} on failure.
Proposed fix
- ticket_refs = extract_ticket_refs(agent_resp)
+ try:
+ ticket_refs = extract_ticket_refs(agent_resp)
+ except (TypeError, ValueError, AttributeError) as exc:
+ print(f"Failed to parse triage agent response: {exc}", file=sys.stderr)
+ return {}📝 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.
| agent_resp = call_triage_agent( | |
| format_risks_for_agent( | |
| risk_docs if is_vuln else [], | |
| risk_docs if not is_vuln else [], | |
| ) | |
| ) | |
| print(agent_resp) | |
| if not agent_resp: | |
| return {} | |
| ticket_refs = extract_ticket_refs(agent_resp) | |
| new_tickets = {} | |
| agent_resp = call_triage_agent( | |
| format_risks_for_agent( | |
| risk_docs if is_vuln else [], | |
| risk_docs if not is_vuln else [], | |
| ) | |
| ) | |
| print(agent_resp) | |
| if not agent_resp: | |
| return {} | |
| try: | |
| ticket_refs = extract_ticket_refs(agent_resp) | |
| except (TypeError, ValueError, AttributeError) as exc: | |
| print(f"Failed to parse triage agent response: {exc}", file=sys.stderr) | |
| return {} | |
| new_tickets = {} |
🤖 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/pulse_in_pipeline_scanning/submit_report.py` around lines 43
- 53, Guard the extract_ticket_refs(agent_resp) call in the triage flow with
exception handling for invalid or malformed responses, including AttributeError,
TypeError, and JSONDecodeError, and fall back to an empty ticket-reference
mapping on failure. Preserve the existing empty-response return and continue
processing so later es_post indexing still runs.
| "s_package_fix_version": ( | ||
| safe(v.get("Upgrade-Guidance", {}).get("Long-Term")) | ||
| or safe(v.get("Upgrade-Guidance", {}).get("Short-Term")) | ||
| or "N/A" | ||
| ), | ||
| "s_license_ids": "N/A", | ||
| "s_ticket_url": triaged_deps.get(package_name, "N/A"), | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
set -euo pipefail
echo '--- submit_report.py excerpt ---'
sed -n '80,140p' jenkins/scripts/pulse_in_pipeline_scanning/submit_report.py
echo
echo '--- search for Upgrade-Guidance usages ---'
rg -n '"Upgrade-Guidance"|Upgrade-Guidance' jenkins/scripts/pulse_in_pipeline_scanning -S
echo
echo '--- python semantics probe ---'
python3 - <<'PY'
v1 = {"Upgrade-Guidance": None}
try:
print((v1.get("Upgrade-Guidance", {}).get("Long-Term")))
except Exception as e:
print(type(e).__name__, e)
v2 = {}
try:
print((v2.get("Upgrade-Guidance", {}).get("Long-Term")))
except Exception as e:
print(type(e).__name__, e)
PYRepository: NVIDIA/TensorRT-LLM
Length of output: 3233
🏁 Script executed:
set -euo pipefail
echo '--- file stats ---'
wc -l jenkins/scripts/pulse_in_pipeline_scanning/submit_report.py
echo
echo '--- relevant region with line numbers ---'
nl -ba jenkins/scripts/pulse_in_pipeline_scanning/submit_report.py | sed -n '95,130p'Repository: NVIDIA/TensorRT-LLM
Length of output: 323
🏁 Script executed:
set -euo pipefail
python3 - <<'PY'
v = {"Upgrade-Guidance": None}
try:
x = v.get("Upgrade-Guidance", {}).get("Long-Term")
print("ok", x)
except Exception as e:
print(type(e).__name__, str(e))
PYRepository: NVIDIA/TensorRT-LLM
Length of output: 213
Guard Upgrade-Guidance before chaining .get() v.get("Upgrade-Guidance", {}) still raises when the scanner emits "Upgrade-Guidance": null; coerce it first with (v.get("Upgrade-Guidance") or {}).
🤖 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/pulse_in_pipeline_scanning/submit_report.py` around lines 111
- 118, Update the s_package_fix_version construction in the report-building
logic to coerce a null Upgrade-Guidance value to an empty mapping before
chaining Long-Term and Short-Term lookups. Preserve the existing safe fallback
order and “N/A” default.
| or "N/A" | ||
| ), | ||
| "s_license_ids": "N/A", | ||
| "s_ticket_url": triaged_deps.get(package_name, "N/A"), |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
Inconsistent "no ticket" sentinel across scan types ("N/A" vs "").
submit_source_code_vulns/submit_source_code_licenses default s_ticket_url to "N/A" (lines 117, 214) while submit_container_vulns/submit_container_licenses default to "" (lines 287, 371). Mixed sentinels for the same semantic "no ticket yet" state complicate downstream Kibana filtering/queries on s_ticket_url.
Pick one convention consistently across all four documents.
Also applies to: 214-214, 287-287, 371-371
🤖 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/pulse_in_pipeline_scanning/submit_report.py` at line 117,
Standardize the no-ticket fallback for s_ticket_url across
submit_source_code_vulns, submit_source_code_licenses, submit_container_vulns,
and submit_container_licenses. Choose one sentinel convention and apply it
consistently to all four document-building paths, including their triaged_deps
lookups, without changing ticketed values.
| ) -> list: | ||
| """Triage untriaged container vulnerabilities, save all docs to ES, return untriaged risks.""" | ||
| SCAN_TYPE = "container_vulnerability" | ||
| triaged_deps = get_triaged_deps(SCAN_TYPE, build_metadata["ref"]) | ||
| ts = int(start_datetime.timestamp() * 1000) | ||
|
|
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Map the relevant files and symbols first.
git ls-files 'jenkins/scripts/pulse_in_pipeline_scanning/*' | sed -n '1,120p'
echo '--- outline submit_report.py ---'
ast-grep outline jenkins/scripts/pulse_in_pipeline_scanning/submit_report.py --view expanded || true
echo '--- search triage helpers ---'
rg -n "def (get_triaged_deps|save_triage_records|submit_container_vulns|submit_container_licenses|_run_triage|main)" jenkins/scripts/pulse_in_pipeline_scanning -S || true
echo '--- outline main.py ---'
ast-grep outline jenkins/scripts/pulse_in_pipeline_scanning/main.py --view expanded || trueRepository: NVIDIA/TensorRT-LLM
Length of output: 2286
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the relevant sections with line numbers once files are identified.
sed -n '1,220p' jenkins/scripts/pulse_in_pipeline_scanning/submit_report.py | cat -n
echo '---'
sed -n '220,420p' jenkins/scripts/pulse_in_pipeline_scanning/submit_report.py | cat -n
echo '--- main.py ---'
sed -n '1,240p' jenkins/scripts/pulse_in_pipeline_scanning/main.py | cat -nRepository: NVIDIA/TensorRT-LLM
Length of output: 24378
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- submit_report.py 220-360 ---'
sed -n '220,360p' jenkins/scripts/pulse_in_pipeline_scanning/submit_report.py | cat -n
echo '--- main.py 1-220 ---'
sed -n '1,220p' jenkins/scripts/pulse_in_pipeline_scanning/main.py | cat -n
echo '--- helper definitions ---'
rg -n "def (get_triaged_deps|save_triage_records|_run_triage|submit_container_vulns|submit_container_licenses)" jenkins/scripts/pulse_in_pipeline_scanning -SRepository: NVIDIA/TensorRT-LLM
Length of output: 13424
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '1,220p' jenkins/scripts/pulse_in_pipeline_scanning/utils/es.py | cat -nRepository: NVIDIA/TensorRT-LLM
Length of output: 6312
Avoid re-reading ES between the amd64 and arm64 container passes. In main.py:98-127 and submit_report.py:245-256, 310-321, each submit_container_* call does a fresh get_triaged_deps(...), while save_triage_records(...) only bulk-indexes to ES with no refresh. The second pass can miss the first pass’s new triage records and open a duplicate ticket for the same package.
🤖 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/pulse_in_pipeline_scanning/submit_report.py` around lines 251
- 256, Update the container submission flow around submit_container_* and
save_triage_records so amd64 and arm64 passes reuse the same triaged dependency
data instead of calling get_triaged_deps independently. Load triaged records
once before both passes, pass that data into each submit_container_* invocation,
and ensure both architectures’ newly saved records are considered before ticket
creation.
| lics = doc.get("s_license_ids", "") | ||
| if lics == "Unknown License" or lics == "": | ||
| item = _license_doc_to_agent_item(doc) | ||
| key = (item["dependency_name"], item["current_version"], item["action_type"]) | ||
| if key not in seen: | ||
| seen.add(key) | ||
| items.append(item) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Submit known non-permissive licenses to triage.
The downstream license submitters construct risk documents with non-empty license IDs such as GPL/LGPL. This condition drops those risks, so no license ticket is created unless the license is unknown or absent.
Proposed fix
for doc in license_docs:
- lics = doc.get("s_license_ids", "")
- if lics == "Unknown License" or lics == "":
- item = _license_doc_to_agent_item(doc)
- key = (item["dependency_name"], item["current_version"], item["action_type"])
- if key not in seen:
- seen.add(key)
- items.append(item)
+ item = _license_doc_to_agent_item(doc)
+ key = (item["dependency_name"], item["current_version"], item["action_type"])
+ if key not in seen:
+ seen.add(key)
+ items.append(item)📝 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.
| lics = doc.get("s_license_ids", "") | |
| if lics == "Unknown License" or lics == "": | |
| item = _license_doc_to_agent_item(doc) | |
| key = (item["dependency_name"], item["current_version"], item["action_type"]) | |
| if key not in seen: | |
| seen.add(key) | |
| items.append(item) | |
| item = _license_doc_to_agent_item(doc) | |
| key = (item["dependency_name"], item["current_version"], item["action_type"]) | |
| if key not in seen: | |
| seen.add(key) | |
| items.append(item) |
🤖 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/pulse_in_pipeline_scanning/utils/triage.py` around lines 60 -
66, Update the license filtering condition in the triage loop so known
non-permissive license IDs, including GPL/LGPL values, reach
_license_doc_to_agent_item and are submitted for triage; do not restrict
processing to only “Unknown License” or empty IDs, while preserving the existing
seen-key deduplication and item append behavior.
| try: | ||
| resp = requests.post(TRIAGE_AGENT_URL, json=body, timeout=TRIAGE_AGENT_TIMEOUT) | ||
| resp.raise_for_status() | ||
| return resp.json() | ||
| except Exception as exc: | ||
| print(f"Triage agent call failed: {exc}", file=sys.stderr) | ||
| return {} |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== triage.py ==\n'
sed -n '1,220p' jenkins/scripts/pulse_in_pipeline_scanning/utils/triage.py
printf '\n== es.py ==\n'
sed -n '1,220p' jenkins/scripts/pulse_in_pipeline_scanning/utils/es.py
printf '\n== search for exception imports/usages ==\n'
rg -n "RequestException|JSONDecodeError|ElasticsearchException|TransportError|ApiError|ConnectionError|Exception as exc|except Exception" jenkins/scripts/pulse_in_pipeline_scanning/utils -SRepository: NVIDIA/TensorRT-LLM
Length of output: 10159
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
for path in [
Path("jenkins/scripts/pulse_in_pipeline_scanning/utils/triage.py"),
Path("jenkins/scripts/pulse_in_pipeline_scanning/utils/es.py"),
]:
print(f"\n== {path} ==")
for i, line in enumerate(path.read_text().splitlines(), 1):
if 1 <= i <= 220:
print(f"{i:4}: {line}")
PYRepository: NVIDIA/TensorRT-LLM
Length of output: 11770
🌐 Web query:
requests Response.json JSONDecodeError requests.exceptions.RequestException raise_for_status HTTPError and elasticsearch-py ApiError TransportError exception hierarchy
💡 Result:
The exception hierarchies for the Python requests library and the elasticsearch-py client serve distinct purposes, managing HTTP request errors and API-specific errors, respectively. Requests Exception Hierarchy In the requests library, RequestException is the base class for all exceptions [1][2]. Key components include: - RequestException: The root class for all exceptions raised by the library [1]. - HTTPError: A subclass of RequestException, raised when calling Response.raise_for_status if the response contains an unsuccessful HTTP status code (4xx or 5xx) [1][3]. - JSONDecodeError: A subclass of RequestException (and InvalidJSONError), raised when the Response.json method fails to parse the response body as valid JSON [4][1]. When handling these, it is best practice to catch specific exceptions first, followed by the more general RequestException [2]. Elasticsearch-py Exception Hierarchy The elasticsearch-py client uses a hierarchy centered on transport and API-level failures [5][6]: - TransportError: A generic exception for the underlying elastic-transport package, triggered by errors occurring before an HTTP response is received (e.g., connection issues, timeouts) [5][7]. - ApiError: A subclass used when the server returns an HTTP response that is not in the 2xx range [5][7]. The client maps specific HTTP status codes (like 400, 401, 409) to specialized subclasses of ApiError (e.g., BadRequestError, ConflictError) [8]. Unlike requests, where HTTPError is specifically triggered by an explicit call to raise_for_status, elasticsearch-py's ApiError is typically raised automatically by the client when it receives a non-successful response from the Elasticsearch cluster [5].
Citations:
- 1: https://requests.readthedocs.io/en/latest/api/index.html
- 2: https://stackoverflow.com/questions/49099313/how-to-get-the-exception-string-from-requests-exceptions-requestexception
- 3: https://requests.readthedocs.io/en/latest/api/?highlight=exception
- 4: https://github.com/psf/requests/blob/main/src/requests/exceptions.py
- 5: https://elasticsearch-py.readthedocs.io/en/v9.3.0/exceptions.html
- 6: https://elasticsearch-py.readthedocs.io/en/v8.16.0/exceptions.html
- 7: https://elasticsearch-py.readthedocs.io/en/v9.2.0/exceptions.html
- 8: https://github.com/elastic/elasticsearch-py/blob/main/elasticsearch/exceptions.py
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== dependency/version hints ==\n'
rg -n "elasticsearch|elastic-transport|requests==" -S requirements* pyproject.toml poetry.lock Pipfile* setup.cfg setup.py jenkins/scripts -g '!**/.git/**' || true
printf '\n== elasticsearch exception imports in repo ==\n'
rg -n "from elasticsearch import|import elasticsearch|TransportError|ApiError|ConnectionError|ElasticsearchException" -S . || trueRepository: NVIDIA/TensorRT-LLM
Length of output: 2076
Narrow these exception handlers
jenkins/scripts/pulse_in_pipeline_scanning/utils/triage.py: catchrequests.RequestExceptionplus the JSON decode error fromresp.json(), notException.jenkins/scripts/pulse_in_pipeline_scanning/utils/es.py: catch the Elasticsearch client’s transport/API exception base only.
return {} here can hide programming bugs as empty results.
🧰 Tools
🪛 ast-grep (0.44.1)
[warning] 76-76: Request-controlled URL passed to requests; validate against an allowlist to prevent SSRF.
Context: requests.post(TRIAGE_AGENT_URL, json=body, timeout=TRIAGE_AGENT_TIMEOUT)
Note: [CWE-918] Server-Side Request Forgery (SSRF).
(ssrf-requests)
🪛 Ruff (0.15.21)
[warning] 80-80: Do not catch blind exception: Exception
(BLE001)
📍 Affects 2 files
jenkins/scripts/pulse_in_pipeline_scanning/utils/triage.py#L76-L82(this comment)jenkins/scripts/pulse_in_pipeline_scanning/utils/es.py#L82-L101
🤖 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/pulse_in_pipeline_scanning/utils/triage.py` around lines 76 -
82, Narrow the exception handling in triage.py around the request flow in the
visible try block to catch only requests.RequestException and the JSON decode
exception raised by resp.json(), while preserving the existing error logging and
empty-dictionary fallback. In
jenkins/scripts/pulse_in_pipeline_scanning/utils/es.py lines 82-101, replace the
broad exception handler with only the Elasticsearch client’s transport/API
exception base; do not let programming errors be converted into empty results.
Sources: Coding guidelines, Linters/SAST tools
Signed-off-by: Yuanjing Xue <197832395+yuanjingx87@users.noreply.github.com>
Signed-off-by: Yuanjing Xue <197832395+yuanjingx87@users.noreply.github.com>
Signed-off-by: Yuanjing Xue <197832395+yuanjingx87@users.noreply.github.com>
Signed-off-by: Yuanjing Xue <197832395+yuanjingx87@users.noreply.github.com>
Signed-off-by: Yuanjing Xue <197832395+yuanjingx87@users.noreply.github.com>
6a7121c to
edfbc60
Compare
Signed-off-by: Yuanjing Xue <197832395+yuanjingx87@users.noreply.github.com>
856fa1b to
8d7e987
Compare
Signed-off-by: Yuanjing Xue <197832395+yuanjingx87@users.noreply.github.com>
8d7e987 to
91e2f45
Compare
Summary by CodeRabbit
New Features
Bug Fixes
Description
After PLC pipeline detected some new risks, send to PLC triage agent (https://gitlab-master.nvidia.com/ftp/infra/plc-risk-triage-agent) to create nvbug / jira task for it. And add ticket link to the report for later status tracking
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-compatibleorapi-breaking. Forapi-breaking, includeBREAKINGin 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.