Skip to content

Fix: Triage Y-stream CVEs when Z-stream clones are NOT_AFFECTED - #792

Open
majamassarini wants to merge 6 commits into
packit:mainfrom
majamassarini:fix/PACKIT-5281-ystream-not-affected-check
Open

Fix: Triage Y-stream CVEs when Z-stream clones are NOT_AFFECTED#792
majamassarini wants to merge 6 commits into
packit:mainfrom
majamassarini:fix/PACKIT-5281-ystream-not-affected-check

Conversation

@majamassarini

@majamassarini majamassarini commented Sep 1, 2026

Copy link
Copy Markdown
Member

Summary

Fixes PACKIT-5281: Y-stream CVEs were incorrectly skipped or postponed when Z-stream clones were NOT_AFFECTED.

Problem

When a Y-stream CVE (e.g., rhel-9.9) is checked for eligibility:

  • Low/Moderate severity + CentOS Stream first approach → told "fix is handled via Z-stream CentOS path"
  • Important/Critical severity → told "waiting for Z-stream to ship"

Both messages were incorrect when the CVE was actually NOT AFFECTED in the component. The Y-stream should have been triaged to confirm it's also not affected, instead of being skipped or postponed.

Impact: Maintainers had to manually close Y-stream issues that should have been automatically triaged.

Solution

Check Z-stream triage status before skipping or postponing Y-stream CVEs.

Changes

  1. Added _check_zstream_not_affected()

    • Searches for Z-stream clones with ymir_triaged_not_affected label
    • Includes fixVersion filter to prevent pagination issues
  2. Added _check_zstream_pending_triage()

    • Searches for Z-stream clones without terminal success labels (backported/rebased/rebuilt)
    • Treats failed/errored actions as still pending (Z-stream path is blocked)
    • Includes fixVersion filter to prevent pagination issues
  3. Modified _check_lowmod_ystream_eligibility()

    • For Low/Moderate Y-stream CVEs with CS_FIRST approach:
      • ✅ If Z-stream is NOT_AFFECTED → return IMMEDIATELY (triage Y-stream)
      • ⏳ If Z-stream pending triage → return PENDING_DEPENDENCIES (wait for results)
      • ❌ Otherwise → return NEVER (skip Y-stream - existing behavior)
  4. Modified _check_for_dependency_blocker()

    • For Important/Critical Y-stream CVEs:
      • ✅ If Z-stream is NOT_AFFECTED → return None with specific reason (proceed with triage)
      • ⏳ Otherwise → return PENDING_DEPENDENCIES (postpone - existing behavior)

Code Review Fixes

After code review by Claude, fixed seven additional issues:

  1. Pending-triage logic: Only exclude SUCCESS labels (ymir_backported/rebased/rebuilt) from pending search. Failed/errored labels are NOT excluded because the Z-stream path is blocked and Y-stream might be needed as fallback.

  2. Shell redirection fix: Quoted pip requirements with >= operators in three Containerfiles (supervisor, c10s, c9s) to prevent shell redirection interpretation. Unquoted pkg>=1.0 is parsed as "run pkg, redirect output to file =1.0".

  3. NOT_AFFECTED-specific reason: Return explicit message "Z-stream clone RHEL-XXX was NOT_AFFECTED, checking if Y-stream is also not affected" instead of generic message.

  4. Pagination limit fix: Added fixVersion filter directly to JQL queries. SearchJiraIssuesTool returns only first 50 results with no pagination. Without version filtering, broad CVE/component queries could hit the limit and miss applicable Z-stream clones.

  5. Duplicate preservation fix: The NOT_AFFECTED result path was dropping the duplicate_of field even though duplicate detection already ran. The triage workflow needs this field to notify maintainers about older rejected trackers. Fixed by passing duplicate_of through _check_for_dependency_blocker() and including it in the NOT_AFFECTED result. Added regression test combining rejected duplicate with NOT_AFFECTED Z-stream.

  6. Postponed labels fix: _check_zstream_pending_triage() excluded deprecated ymir_triaged_postponed but not the actual labels applied by current code (ymir_postponed_dependency, ymir_postponed_no_patch, ymir_postponed_pr_pending). These are terminal triage decisions (Z-stream was triaged and postponed with a reason), but without exclusion they match "pending triage" JQL. Y-stream then waits indefinitely for Z-stream results that already exist. Fixed by excluding the three active postponed labels. Added parameterized test verifying all three are excluded.

  7. Makefile consistency fix: The triage-issue and process targets used $(ISSUE) instead of $(JIRA_ISSUE), inconsistent with all other targets (process-issue, trigger-pipeline, trigger-reproducer). Users running make triage-issue JIRA_ISSUE=RHEL-123 got silent failures inside the container. Fixed by changing $(ISSUE) to $(JIRA_ISSUE) and adding guards to fail fast with usage message (like trigger-pipeline has).

Related

  • Implements the strategy suggested in PACKIT-5281: "triage all Z streams first. The Y-streams should then pick up findings from latest Z"

🤖 Generated with Claude Code

@qodo-for-packit

Copy link
Copy Markdown

PR Summary by Qodo

Triage Y-stream CVEs when Z-stream clones are not affected

🐞 Bug fix 🕐 20-40 Minutes

Grey Divider

AI Description

• Detect not-affected Z-stream clones before deferring Y-stream CVE triage.
• Hold low/moderate CS-first cases while Z-stream triage remains pending.
• Preserve skip and postponement outcomes for affected Z-stream clones.
Diagram

graph TD
  B{"Severity"} -->|Low Moderate| C["CS-first path"] --> E{"Z triage state"} -->|Not affected| G["Immediate triage"]
  B -->|Important Critical| D["Dependency gate"] --> F{"Z clone state"} -->|Unshipped| H["Pending dependencies"]
  E -->|Pending| H
  E -->|Affected| I["Skip Y-stream"]
  F -->|Shipped or not affected| G
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Single clone-state classifier
  • ➕ Queries Jira once for all relevant clone fields and labels
  • ➕ Uses one consistent snapshot for shipment and triage decisions
  • ➕ Centralizes stream filtering and terminal-label semantics
  • ➖ Requires a broader refactor of existing shipment and fix-approach helpers
  • ➖ Must preserve nuanced status, resolution, and Koji behavior
2. Extend existing eligibility helpers
  • ➕ Reuses clone results already fetched by each eligibility path
  • ➕ Avoids introducing two additional Jira searches
  • ➕ Keeps severity-specific behavior explicit
  • ➖ Expands helper return contracts and caller complexity
  • ➖ May continue duplicating classification rules between severity paths

Recommendation: The behavioral strategy is correct, but a shared clone-state classifier would be the strongest long-term design because it reduces Jira calls, duplicated stream filtering, and inconsistent snapshots. If minimizing scope is essential, the current focused implementation is acceptable, but its new not-affected and pending branches should be protected with unit tests.

Files changed (1) +212 / -0

Bug fix (1) +212 / -0
jira.pyAccount for Z-stream triage state in Y-stream eligibility +212/-0

Account for Z-stream triage state in Y-stream eligibility

• Adds Jira lookups for same-major Z-stream clones marked not affected or still awaiting terminal triage. Low/Moderate CS-first CVEs now proceed, wait, or skip based on that state, while Important/Critical CVEs proceed when a clone is not affected instead of waiting for shipment.

ymir/tools/privileged/jira.py

@qodo-for-packit

qodo-for-packit Bot commented Sep 1, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (1) 📜 Skill insights (0)

Grey Divider


Action required

1. Completed clones appear pending ✓ Resolved 🐞 Bug ≡ Correctness
Description
The pending-triage JQL omits terminal action labels such as ymir_backported, ymir_rebased,
ymir_rebuilt, and their failed/errored variants. Because action agents replace the
ymir_triaged_* label with these outcomes, completed Z-stream clones can be returned as pending and
postpone Y-stream triage indefinitely.
Code

ymir/tools/privileged/jira.py[R947-950]

+        f' AND labels != "ymir_triaged_not_affected"'
+        f' AND labels != "ymir_triaged"'
+        f' AND labels != "ymir_needs_attention"'
+        f' AND labels != "ymir_triage_errored"'
Relevance

●●● Strong

Recent PR #785 explicitly accepted enumerating successful, failed, and errored action labels as
terminal.

PR-#785

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new JQL excludes only triage decisions and triage-level blocked outcomes, while completed agents
remove those decision labels and add distinct terminal action labels. The post-query loop then
appends every version/module match without defensively checking its returned labels; prior PR #785
documents the same need to enumerate completion, failure, and error labels as terminal states.

ymir/tools/privileged/jira.py[934-991]
ymir/agents/backport_agent.py[1737-1775]
ymir/agents/rebase_agent.py[794-824]
ymir/agents/rebuild_agent.py[551-585]
ymir/common/constants.py[159-182]
PR-#785

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`_check_zstream_pending_triage()` classifies completed and failed Z-stream actions as pending because its JQL excludes triage-decision labels but not terminal action outcome labels.

## Issue Context
Backport, rebase, and rebuild agents remove their `ymir_triaged_*` labels when finishing and replace them with completion, failure, or error labels. These issues therefore satisfy the new pending JQL.

## Fix Focus Areas
- ymir/tools/privileged/jira.py[934-952]
- ymir/common/constants.py[159-182]
- ymir/tools/privileged/tests/unit/test_jira_zstream_status.py[233-310]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Module streams share clone status ✓ Resolved 🐞 Bug ≡ Correctness
Description
The new searches do not distinguish modular streams, so a NOT_AFFECTED or pending Z-stream tracker
for one module stream is treated as belonging to another tracker with the same CVE, component, and
fix version. This can incorrectly make the Y-stream immediately eligible or postpone it behind an
unrelated module stream.
Code

ymir/tools/privileged/jira.py[R793-796]

+    jql = (
+        f'summary ~ "{escaped_cve_id}" AND component = "{escaped_component}"'
+        f' AND labels = "SecurityTracking" AND labels = "ymir_triaged_not_affected"'
+        f' AND key != "{exclude_key}"'
Relevance

●●● Strong

Recent accepted precedent supports exact modular-summary matching to prevent cross-stream tracker
confusion.

PR-#743

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new JQL and local filters never inspect candidate summaries or module streams. Elsewhere,
tracker identity explicitly includes an exact parse_module_stream match, and regression tests
demonstrate that modular/non-modular trackers and different PostgreSQL streams may otherwise share
CVE, component, and fix-version values.

ymir/tools/privileged/jira.py[793-817]
ymir/tools/privileged/jira.py[524-562]
ymir/tools/privileged/tests/unit/test_jira.py[1951-1984]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new Z-stream status helpers match issues only by CVE, component, and fix version. Modular trackers can share those values while representing different module streams, causing unrelated NOT_AFFECTED or pending status to alter Y-stream eligibility.

## Issue Context
Use the current issue summary to derive its module stream with `parse_module_stream`, request candidate summaries from Jira, and retain only candidates whose parsed module stream exactly matches the current tracker, including the distinction between modular and non-modular trackers. Apply this consistently to both new helpers and their call sites, with regression tests for different module streams.

## Fix Focus Areas
- ymir/tools/privileged/jira.py[773-899]
- ymir/tools/privileged/jira.py[1097-1123]
- ymir/tools/privileged/jira.py[1292-1360]
- ymir/tools/privileged/tests/unit/test_jira_zstream_status.py[96-335]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. NOT_AFFECTED clone stays postponed ✓ Resolved 🐞 Bug ≡ Correctness
Description
For Low/Moderate CVEs, the new NOT_AFFECTED check only runs after _check_zstream_fix_approach
returns CS_FIRST, but an open clone triaged as NOT_AFFECTED normally has no Fixed in Build and
therefore returns PENDING first. The Y-stream is consequently postponed indefinitely instead of
becoming immediately eligible, leaving the core reported scenario unfixed.
Code

ymir/tools/privileged/jira.py[R1308-1311]

+            # Before skipping the Y-stream, check if Z-stream clones were NOT_AFFECTED
+            try:
+                not_affected_clones = await _check_zstream_not_affected(
+                    cve_id, component, issue_key, major_version
Relevance

●●● Strong

Clear control-flow bug prevents the PR’s stated NOT_AFFECTED scenario; similar Jira correctness
fixes were accepted recently.

PR-#729

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The pre-check classifies every relevant clone without Fixed in Build as pending and the caller
returns immediately for that result. The newly added lookup is nested only under the later
CS_FIRST branch, while the triage workflow records NOT_AFFECTED by adding a terminal label rather
than setting Fixed in Build or changing status, so a normally triaged open clone never reaches this
lookup.

ymir/tools/privileged/jira.py[689-693]
ymir/tools/privileged/jira.py[1292-1324]
ymir/agents/triage_agent.py[1496-1517]
ymir/agents/triage_agent.py[1524-1531]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The Low/Moderate Y-stream flow returns `PENDING_DEPENDENCIES` before checking whether the pending Z-stream clone has already been triaged as NOT_AFFECTED. Move or extend the NOT_AFFECTED decision so it executes before the `FixApproach.PENDING` return, and add a regression test using an open NOT_AFFECTED clone without Fixed in Build.

## Issue Context
`_check_zstream_fix_approach` classifies any relevant open clone lacking Fixed in Build as pending. Triage completion writes the `ymir_triaged_not_affected` terminal label without closing the issue or populating Fixed in Build, making this the normal shape of a NOT_AFFECTED result.

## Fix Focus Areas
- ymir/tools/privileged/jira.py[1277-1324]
- ymir/tools/privileged/tests/unit/test_jira.py[1232-1298]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View high (3)
4. Terminal clones remain pending ✓ Resolved 🐞 Bug ☼ Reliability
Description
The pending-triage JQL does not exclude ymir_needs_attention or exhausted ymir_triage_errored,
both of which are terminal triage outcomes elsewhere in the repository. A Y-stream can consequently
remain postponed waiting for a Z-stream clone that will not be automatically triaged again.
Code

ymir/tools/privileged/jira.py[R828-830]

+        f' AND labels != "ymir_triaged_postponed"'
+        f' AND labels != "ymir_triaged_not_affected"'
+        f' AND labels != "ymir_triaged"'
Relevance

●●● Strong

PR #785 recently accepted adding missing terminal triage labels to prevent reprocessing and
indefinite blocking.

PR-#785

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new query excludes six ymir_triaged* labels only. Triage maps clarification-needed to
ymir_needs_attention and errors to ymir_triage_errored, and the consolidation terminal-label
contract explicitly excludes both from further triage processing.

ymir/tools/privileged/jira.py[820-831]
ymir/agents/triage_agent.py[116-125]
ymir/agents/rebase_consolidation.py[98-115]
PR-#785

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The pending Z-stream query omits terminal clarification-needed and exhausted-error labels, causing completed or blocked clones to be reported as pending indefinitely.

## Issue Context
`Resolution.CLARIFICATION_NEEDED` maps to `ymir_needs_attention`, while exhausted triage errors use `ymir_triage_errored`. Existing consolidation logic treats both labels as terminal.

## Fix Focus Areas
- ymir/tools/privileged/jira.py[820-831]
- ymir/common/constants.py[159-191]
- ymir/agents/triage_agent.py[116-125]
- ymir/agents/rebase_consolidation.py[98-115]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Older clone overrides latest ✓ Resolved 🐞 Bug ≡ Correctness
Description
The helpers pool both current and upcoming Z-streams and treat any NOT_AFFECTED result as decisive,
even though the repository selects the upcoming stream as the applicable Z-stream when one exists.
An older current clone marked NOT_AFFECTED can therefore make the Y-stream immediately eligible
while the latest upcoming clone is affected or still pending.
Code

ymir/tools/privileged/jira.py[R779-784]

+    relevant_z_streams = {
+        variant.lower()
+        for streams in (current_z_streams, upcoming_z_streams)
+        for major, v in streams.items()
+        if major not in maintenance_majors and major == major_version
+        for variant in get_fix_version_variants(v)
Relevance

●● Moderate

Concrete version-selection risk, but no closely matching precedent confirms acceptance for this
repository-specific Z-stream behavior.

PR-#429

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Both helpers build relevant_z_streams from current and upcoming configurations and the caller
returns immediately when any matching clone is NOT_AFFECTED. The checked-in configuration can
contain both streams for one major, while VersionMapperTool explicitly chooses
upcoming_z_streams[major] before falling back to the current stream.

ymir/tools/privileged/jira.py[774-795]
ymir/tools/privileged/jira.py[845-866]
ymir/tools/privileged/jira.py[1286-1314]
templates/rhel-config.json[6-13]
ymir/tools/unprivileged/version_mapper.py[81-86]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new Z-stream status checks combine current and upcoming streams, allowing an older current-stream clone to override the applicable upcoming clone's triage result.

## Issue Context
The version mapper gives the upcoming Z-stream precedence over the current stream. The eligibility checks should inspect the applicable/latest stream rather than accepting any same-major result.

## Fix Focus Areas
- ymir/tools/privileged/jira.py[774-795]
- ymir/tools/privileged/jira.py[845-866]
- ymir/tools/privileged/jira.py[1286-1314]
- ymir/tools/unprivileged/version_mapper.py[81-86]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Lookup failure permanently skips ✓ Resolved 🐞 Bug ☼ Reliability
Description
The CS-first branch converts failures from either new Jira lookup into an empty result and then
returns NEVER, falsely asserting that the fix will be inherited. The triage workflow receives no
error field, so it records an open-ended terminal outcome instead of retrying the transient lookup
failure.
Code

ymir/tools/privileged/jira.py[R1282-1284]

+            except Exception as e:
+                logger.warning(f"Failed to check Z-stream NOT_AFFECTED status for {cve_id}: {e}")
+                not_affected_clones = []
Relevance

●● Moderate

Failure propagation is often accepted, but a closely related swallowed-fetch-failure finding was
rejected, leaving mixed precedent.

PR-#540
PR-#706

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Both added exception handlers assign an empty list, after which the branch can return NEVER with
no error. By contrast, the surrounding _check_zstream_fix_approach failure path sets error, and
check_cve_eligibility only routes operational failures to retry when that field is present;
otherwise it creates an open-ended analysis result.

ymir/tools/privileged/jira.py[1246-1258]
ymir/tools/privileged/jira.py[1277-1284]
ymir/tools/privileged/jira.py[1305-1343]
ymir/agents/triage_agent.py[592-648]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Failures in the new NOT_AFFECTED and pending-triage lookups are treated as negative results, causing a permanent eligibility skip instead of a retryable operational error.

## Issue Context
The surrounding fix-approach check returns an eligibility result containing `error` when its lookup fails. The triage workflow uses that field to select the retry path; without it, `NEVER` becomes an open-ended terminal result.

## Fix Focus Areas
- ymir/tools/privileged/jira.py[1277-1284]
- ymir/tools/privileged/jira.py[1305-1312]
- ymir/tools/privileged/jira.py[1333-1343]
- ymir/agents/triage_agent.py[592-648]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

7. Duplicate metadata gets dropped ✓ Resolved 🐞 Bug ≡ Correctness ⭐ New
Description
The Important/Critical NOT_AFFECTED branch returns an immediate eligibility result without
propagating the previously computed duplicate_of value. Consequently, triage proceeds without
posting the informational comment about an older rejected duplicate, unlike every other immediate
Y-stream path.
Code

ymir/tools/privileged/jira.py[R1253-1256]

+                        CVEEligibilityResult(
+                            is_cve=True,
+                            eligibility=TriageEligibility.IMMEDIATELY,
+                            reason=(
Relevance

●●● Strong

Clear metadata propagation bug; accepted precedents support preserving duplicate state and
preventing duplicate comment loss.

PR-#743
PR-#611

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Duplicate detection runs before Y-stream branching and passes duplicate_of into
_check_ystream_eligibility, but _check_for_dependency_blocker cannot receive it and its new
immediate return omits the field. The triage workflow only posts the rejected-duplicate notice when
an immediate result retains duplicate_of; sibling immediate Y-stream results explicitly preserve
it.

ymir/tools/privileged/jira.py[1097-1116]
ymir/tools/privileged/jira.py[1251-1262]
ymir/tools/privileged/jira.py[1366-1381]
ymir/agents/triage_agent.py[570-589]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new Important/Critical NOT_AFFECTED result drops `duplicate_of`, even though duplicate detection already ran and the triage workflow uses this field to notify maintainers about an older rejected tracker.

## Issue Context
Pass the duplicate key into `_check_for_dependency_blocker()` or otherwise preserve it when constructing the immediate NOT_AFFECTED result. Add a regression test combining a rejected duplicate with a NOT_AFFECTED Z-stream clone.

## Fix Focus Areas
- ymir/tools/privileged/jira.py[1251-1262]
- ymir/tools/privileged/jira.py[1359-1375]
- ymir/tools/privileged/tests/unit/test_jira.py[1578-1613]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Constraints become shell redirects ✓ Resolved 🐞 Bug ☼ Reliability
Description
The unquoted >= requirements are parsed by the Containerfile shell as output redirections, so pip
receives unconstrained sentry-sdk and GitPython package names and writes output into files named
after the version expressions. The supervisor image therefore does not enforce either required
minimum version.
Code

Containerfile.supervisor[R37-38]

+      sentry-sdk>=2.13.0 \
+      GitPython>=3.1.0 \
Relevance

●●● Strong

Unquoted shell redirections clearly break the intended minimum-version constraints.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Both newly added constrained requirements occur in a shell-form RUN command and are unquoted,
while the existing constrained litellm argument in that command is quoted.

Containerfile.supervisor[29-40]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The shell interprets the unquoted `>` characters in the two new pip requirements as redirection operators rather than parts of requirement specifiers.

## Issue Context
Other constrained requirements in the same command are quoted, such as the `litellm` requirement.

## Fix Focus Areas
- Containerfile.supervisor[29-38]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. Current fallback remains untested ✓ Resolved 📘 Rule violation ▣ Testability
Description
The test labeled as the current Z-stream fallback uses major version 10, but RHEL_CONFIG defines
rhel-10.3.z only in upcoming_z_streams, so the test exercises the upcoming-selection branch
rather than fallback to current_z_streams. A regression removing the fallback could therefore
still pass, leaving the changed privileged-tool behavior without effective unit coverage.
Code

ymir/tools/privileged/tests/unit/test_jira_zstream_status.py[R68-70]

+    variants = await _get_applicable_zstream_variants("10")
+    # get_fix_version_variants returns both Y and Z forms
+    assert variants == {"rhel-10.3", "rhel-10.3.z"}
Relevance

●●● Strong

The test clearly misses the fallback branch; adding a true current-stream-only configuration is a
deterministic coverage fix.

PR-#670
PR-#743

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 1589 requires tests that cover changed privileged-tool behavior and fail if that behavior is
reverted. The shared configuration maps RHEL 10 to rhel-10.3.z under upcoming_z_streams and has
no RHEL 10 entry under current_z_streams; because production selects upcoming streams before
falling back to current streams, calling the helper with "10" and asserting that value cannot
exercise or verify the fallback branch.

Rule 1589: Require unit tests for changes to privileged tools (ymir/tools/privileged/, esp. distgit.py)
ymir/tools/privileged/jira.py[761-763]
ymir/tools/privileged/tests/unit/test_jira_zstream_status.py[27-31]
ymir/tools/privileged/tests/unit/test_jira_zstream_status.py[62-70]
ymir/tools/privileged/tests/unit/test_jira_zstream_status.py[61-70]
ymir/tools/privileged/jira.py[761-768]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The current-fallback test uses major version 10, which is configured with an upcoming Z-stream, so it does not execute the fallback to `current_z_streams` that it claims to cover. Supply test configuration containing a current Z-stream for a non-maintenance major with no corresponding upcoming Z-stream, then assert that the current-stream variants are returned.

## Issue Context
Keep a matching current Y-stream so `get_maintenance_majors` does not classify the selected major as maintenance. The test configuration must omit an upcoming Z-stream for that major while retaining its current Z-stream.

## Fix Focus Areas
- ymir/tools/privileged/tests/unit/test_jira_zstream_status.py[27-31]
- ymir/tools/privileged/tests/unit/test_jira_zstream_status.py[61-70]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (5)
10. No-Z-stream tests hit Jira ✓ Resolved 📘 Rule violation ▣ Testability
Description
Both no-applicable-Z-stream tests invoke helpers without mocking SearchJiraIssuesTool.run, even
though each helper searches Jira before checking stream applicability. The tests can therefore make
real network requests to the fixture’s http://jira URL, making coverage of the privileged Jira
changes unreliable and susceptible to failures unrelated to the behavior under test.
Code

ymir/tools/privileged/tests/unit/test_jira_zstream_status.py[R195-196]

+    not_affected = await _check_zstream_not_affected("CVE-2026-12345", "curl", "RHEL-999", "7")
+    assert not_affected == []
Relevance

●●● Strong

Privileged Jira tests are expected to mock network calls; unmocked requests make regression coverage
unreliable.

PR-#729
PR-#410

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 1589 requires meaningful unit tests for changes under ymir/tools/privileged/. The tests mock
only load_rhel_config, while the production helpers first call the network-backed
SearchJiraIssuesTool.run, which performs an HTTP POST, and the autouse fixture merely configures
Jira as http://jira rather than replacing the request; this omission affects both the
no-applicable-Z-stream and pending-triage no-applicable-stream tests.

Rule 1589: Require unit tests for changes to privileged tools (ymir/tools/privileged/, esp. distgit.py)
ymir/tools/privileged/tests/unit/test_jira_zstream_status.py[189-196]
ymir/tools/privileged/tests/unit/test_jira_zstream_status.py[287-294]
ymir/tools/privileged/jira.py[794-806]
ymir/tools/privileged/jira.py[1699-1707]
ymir/tools/privileged/tests/unit/test_jira_zstream_status.py[188-196]
ymir/tools/privileged/tests/unit/test_jira_zstream_status.py[286-294]
ymir/tools/privileged/jira.py[862-874]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The no-applicable-Z-stream tests call helpers that search Jira before loading and evaluating stream applicability, but neither test mocks `SearchJiraIssuesTool.run`. Add an empty-result async mock to both tests so they cannot contact the configured Jira URL and reliably exercise the intended branch.

## Issue Context
The production helpers invoke `SearchJiraIssuesTool.run` before calling `_get_applicable_zstream_variants`. Mock the search to return an empty `JSONToolOutput` and assert that it is called once in each test, keeping these privileged-tool tests isolated and deterministic.

## Fix Focus Areas
- ymir/tools/privileged/tests/unit/test_jira_zstream_status.py[188-196]
- ymir/tools/privileged/tests/unit/test_jira_zstream_status.py[286-294]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


11. Maintenance branch remains untested ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
The maintenance test adds an unused maintenance_versions key and checks major 7, which has no
configured Z-stream, so the helper returns None through the no-stream branch instead of its
maintenance branch. A regression in maintenance-major detection would therefore still pass this
test.
Code

ymir/tools/privileged/tests/unit/test_jira_zstream_status.py[R85-88]

+    config_with_maintenance = {
+        **RHEL_CONFIG,
+        "maintenance_versions": ["7"],
+    }
Relevance

●●● Strong

Recent precedent accepts replacing tautological tests with behavioral coverage; this fixture never
exercises maintenance detection.

PR-#785
PR-#743

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The repository computes maintenance majors as current_z_streams.keys() - current_y_streams.keys()
and never reads maintenance_versions; with the supplied configuration, major 7 reaches the
separate not applicable_z_stream return instead.

ymir/tools/privileged/tests/unit/test_jira_zstream_status.py[82-94]
ymir/common/version_utils.py[229-233]
ymir/tools/privileged/jira.py[757-766]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Update the maintenance test so its configuration satisfies the repository's actual maintenance definition: a major present in `current_z_streams` but absent from `current_y_streams`. Assert behavior using that major rather than adding the unused `maintenance_versions` key.

## Issue Context
`get_maintenance_majors` derives maintenance majors from the difference between current Z-stream and current Y-stream keys. In the existing fixture, major `8` meets this condition while major `7` has no stream at all.

## Fix Focus Areas
- ymir/tools/privileged/tests/unit/test_jira_zstream_status.py[82-94]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


12. Z-stream checks lack tests 📘 Rule violation ▣ Testability
Description
New privileged Jira triage behavior was added without corresponding unit tests. The Z-stream status
queries and resulting eligibility decisions therefore violate the required test coverage for
privileged tools.
Code

ymir/tools/privileged/jira.py[R743-746]

+async def _check_zstream_not_affected(
+    cve_id: str, component: str, exclude_key: str, major_version: str
+) -> list[str]:
+    """Check if any Z-stream clone was triaged as NOT_AFFECTED.
Relevance

●●● Strong

Recent Jira changes were expected to include regression tests; this PR explicitly omits unit tests
despite the privileged-tools rule.

PR-#729
PR-#743

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Compliance rule 1589 requires new or updated unit tests whenever files under
ymir/tools/privileged/ change. The PR adds _check_zstream_not_affected and related eligibility
behavior in ymir/tools/privileged/jira.py, while the provided diff contains no test-file changes.

Rule 1589: Require unit tests for changes to privileged tools (ymir/tools/privileged/, esp. distgit.py)
ymir/tools/privileged/jira.py[743-875]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new Z-stream NOT_AFFECTED and pending-triage behavior in the privileged Jira tool has no corresponding unit tests.

## Issue Context
Tests should mock Jira search results and RHEL stream configuration, then assert the eligibility outcomes for NOT_AFFECTED, pending, affected, and Jira-query failure cases.

## Fix Focus Areas
- ymir/tools/privileged/jira.py[743-875]
- ymir/tools/privileged/jira.py[1073-1091]
- ymir/tools/privileged/jira.py[1277-1333]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


13. Not-affected reported as shipped ✓ Resolved 🐞 Bug ◔ Observability
Description
Returning the normal success tuple for a NOT_AFFECTED clone makes _check_ystream_eligibility()
emit the false reason that “at least one Z-stream clone shipped.” This hides the actual eligibility
basis from maintainers and audit output, reproducing the misleading-status problem this PR intends
to fix.
Code

ymir/tools/privileged/jira.py[R1234-1235]

+                # Return None to proceed with triage (same as if a clone had shipped)
+                return None, []
Relevance

●● Moderate

The misleading reason conflicts with the PR intent, but no close historical precedent confirms this
observability change.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The added branch returns None, [] when a clone is NOT_AFFECTED, and the caller handles every
None blocker by constructing a reason that explicitly claims a Z-stream clone shipped.

ymir/tools/privileged/jira.py[1229-1235]
ymir/tools/privileged/jira.py[1329-1351]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new NOT_AFFECTED success path is indistinguishable from the existing shipped-clone path, so the final eligibility reason incorrectly states that a clone shipped.

## Issue Context
The caller constructs one unconditional success reason whenever the blocker is `None`. Preserve the dependency outcome or return a result carrying a NOT_AFFECTED-specific reason.

## Fix Focus Areas
- ymir/tools/privileged/jira.py[1229-1235]
- ymir/tools/privileged/jira.py[1329-1351]
- ymir/tools/privileged/tests/unit/test_jira.py[1578-1610]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


14. Search truncates clone statuses ✓ Resolved 🐞 Bug ≡ Correctness
Description
Both status helpers inspect only the first 50 broad CVE/component matches and perform no pagination.
If the applicable Z-stream clone is outside that page, eligibility can incorrectly conclude that no
NOT_AFFECTED or pending clone exists.
Code

ymir/tools/privileged/jira.py[868]

+            "max_results": 50,
Relevance

●● Moderate

Pagination is a plausible correctness gap, but historical pagination feedback was rejected or
undetermined.

PR-#410

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The helpers request max_results: 50, then filter only output.result. The search tool passes that
limit directly to Jira and returns data['issues'] without requesting subsequent pages.

ymir/tools/privileged/jira.py[863-880]
ymir/tools/privileged/jira.py[958-977]
ymir/tools/privileged/jira.py[1809-1850]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new status searches silently stop after 50 Jira matches, potentially omitting the applicable Z-stream clone.

## Issue Context
`SearchJiraIssuesTool` sends one request with `maxResults` and returns only that response's `issues`; it has no pagination. Both new helpers use broad CVE/component queries and filter versions afterward.

## Fix Focus Areas
- ymir/tools/privileged/jira.py[863-880]
- ymir/tools/privileged/jira.py[958-977]
- ymir/tools/privileged/jira.py[1809-1850]
- ymir/tools/privileged/tests/unit/test_jira_zstream_status.py[96-361]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
⚠️ Tickets: not configured — ticket URL found in PR but could not be fetched — check ticket provider credentials
✅ Compliance rules (platform): 8 rules

Grey Divider

Tip of the day
💡 Did you know, you can add REVIEW.md to your repo root and Qodo follows it on every PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread ymir/tools/privileged/jira.py
Comment thread ymir/tools/privileged/jira.py Outdated
Comment thread ymir/tools/privileged/jira.py
Comment thread ymir/tools/privileged/jira.py Outdated
@majamassarini

Copy link
Copy Markdown
Member Author

/agentic_review

Comment thread ymir/tools/privileged/tests/unit/test_jira_zstream_status.py Outdated
Comment thread ymir/tools/privileged/tests/unit/test_jira_zstream_status.py Outdated
@qodo-for-packit

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 7cef65d

@majamassarini

Copy link
Copy Markdown
Member Author

/agentic_review

Comment thread ymir/tools/privileged/tests/unit/test_jira_zstream_status.py Outdated
@qodo-for-packit

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 8cd0470

@majamassarini
majamassarini force-pushed the fix/PACKIT-5281-ystream-not-affected-check branch from 432c327 to 094880c Compare September 1, 2026 12:44
@majamassarini

Copy link
Copy Markdown
Member Author

/agentic_review

Comment thread ymir/tools/privileged/jira.py Outdated
@qodo-for-packit

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 094880c

@majamassarini
majamassarini force-pushed the fix/PACKIT-5281-ystream-not-affected-check branch from 094880c to b594774 Compare September 1, 2026 13:27
@majamassarini

Copy link
Copy Markdown
Member Author

/agentic_review

@qodo-for-packit

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit e1d1866

@majamassarini
majamassarini force-pushed the fix/PACKIT-5281-ystream-not-affected-check branch from 834473b to a580a44 Compare September 2, 2026 07:38
@majamassarini

Copy link
Copy Markdown
Member Author

/agentic_review

Comment thread ymir/tools/privileged/jira.py
@qodo-for-packit

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit a580a44

@majamassarini

Copy link
Copy Markdown
Member Author

/agentic_review

@qodo-for-packit

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit ea5afea

@majamassarini
majamassarini force-pushed the fix/PACKIT-5281-ystream-not-affected-check branch 4 times, most recently from 65254ad to 2193bad Compare September 3, 2026 07:28
@majamassarini

Copy link
Copy Markdown
Member Author

/agentic_review

Comment thread ymir/tools/privileged/jira.py
Comment thread Containerfile.supervisor Outdated
Comment thread ymir/tools/privileged/jira.py Outdated
Comment thread ymir/tools/privileged/jira.py
@qodo-for-packit

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 2193bad

@majamassarini
majamassarini force-pushed the fix/PACKIT-5281-ystream-not-affected-check branch from 2193bad to 025f3bd Compare September 3, 2026 09:39
@majamassarini

Copy link
Copy Markdown
Member Author

/agentic_review

Comment thread ymir/tools/privileged/jira.py
@qodo-for-packit

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 025f3bd

@majamassarini
majamassarini force-pushed the fix/PACKIT-5281-ystream-not-affected-check branch 2 times, most recently from abd09c9 to 259f0ed Compare September 3, 2026 10:09
@nforro

nforro commented Sep 3, 2026

Copy link
Copy Markdown
Member

One general note that's been bothering me for some time. Could you please follow the contributing guidelines and, to quote, use common sense when creating commits, not too big, not too small? I think in this case 2 or 3 commits would be enough. It would make the PR(s) easier to review and the git history cleaner.

@nforro nforro left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

A couple of things Claude flagged:

Finding 1 (high confidence, real bug): _check_zstream_pending_triage misses the current postponed-triage labels

ymir/tools/privileged/jira.py, new function _check_zstream_pending_triage, excludes these labels as "terminal/already-triaged":

ymir_triaged_backport, ymir_triaged_rebase, ymir_triaged_rebuild,
ymir_triaged_postponed, ymir_triaged_not_affected, ymir_triaged,
ymir_backported, ymir_rebased, ymir_rebuilt,
ymir_needs_attention, ymir_triage_errored

ymir_triaged_postponed is the label the comment relies on for "postponed" — but per ymir/common/constants.py:202-204, that label is deprecated ("replaced by labels with reason for postponement") and is only ever referenced by label_postponed_issues in triage_agent.py for removal of legacy labels, never applied by current code. The actual labels a postponed triage decision gets today come from _RESOLUTION_TO_LABEL (triage_agent.py:141-152):

Resolution.POSTPONED_DEPENDENCY → ymir_postponed_dependency
Resolution.POSTPONED_NO_PATCH   → ymir_postponed_no_patch
Resolution.POSTPONED_PR_PENDING → ymir_postponed_pr_pending

None of these are excluded. So a Z-stream clone that has already been triaged and landed on "postponed — waiting on a dependency/patch/PR" (a real, terminal triage decision, just like backport/rebase/rebuild) still matches the "pending triage" JQL. The Y-stream CVE then gets PENDING_DEPENDENCIES, "waiting for Z-stream clone triage results" — results that already exist — and will wait indefinitely, since nothing in the normal sweep flow adds one of the excluded labels to resolve that state. This reproduces the same class of bug PACKIT-5281 was filed to fix, just via a different path.

Fix: also exclude ymir_postponed_dependency, ymir_postponed_no_patch, ymir_postponed_pr_pending (no need for ymir_postponed_y_stream — that's Y-stream-only).

Finding 2 (medium confidence): new Makefile targets break the JIRA_ISSUE convention

Makefile's new triage-issue and process targets read $(ISSUE):

triage-issue:
	$(COMPOSE_AGENTS) run --rm -e JIRA_ISSUE=$(ISSUE) ...
process:
	$(COMPOSE_AGENTS) run --rm -e JIRA_ISSUE=$(ISSUE) ...

Every other target in the file (8+ call sites, including the pre-existing process-issue, trigger-pipeline, trigger-reproducer) takes JIRA_ISSUE= from the invoker. A user running make triage-issue JIRA_ISSUE=RHEL-123 out of habit gets an empty $(ISSUE) with no error — trigger-pipeline/trigger-reproducer both guard with @if [ -z "$(JIRA_ISSUE)" ]; then ... exit 1; fi, but the two new targets have no such guard, so this fails silently inside the container instead of at the make invocation.

Finding 3 (lower confidence, pre-existing but adjacent): unquoted >= in Containerfile.c10s / Containerfile.c9s

This PR's own fix commit quotes sentry-sdk>=2.13.0 and GitPython>=3.1.0 in Containerfile.supervisor specifically because unquoted >= is parsed by the shell as output redirection (pkg>=1.0 → runs pkg, writes a file named =1.0). Verified empirically. The exact same pattern already exists two lines above the typer line this PR adds in Containerfile.c10s/Containerfile.c9s:

PyYAML>=5.1 \
sentry-sdk>=2.13.0 \
+typer \

These are pre-existing (not introduced by this PR), so lower priority, but since the PR is touching this exact list and just fixed the identical bug in a sibling file, it's worth a follow-up: both version pins are silently being dropped and a stray =5.1/=2.13.0 file is left in the build context.

@majamassarini

majamassarini commented Sep 3, 2026

Copy link
Copy Markdown
Member Author

not too big, not too small? I think in this case 2 or 3 commits would be enough.

I am always in doubt here, I used to squash commits in the past, because describing them "manually" was too much work and my english is not so good, however now that AI writes commit messages for me, I don't squash them any longer, because I think it is easier, in this way, to review things and decide if something completely wrong has been done. However I squashed them here.

Fixes PACKIT-5281: Y-stream CVEs were incorrectly skipped or postponed when
Z-stream clones were not affected. The CVE eligibility check would say "fix
is handled via Z-stream CentOS path" or "waiting for Z-stream to ship"
without checking if the Z-streams were actually triaged as NOT_AFFECTED.

This caused maintainers to manually close Y-stream issues that should have
been automatically triaged and marked as not affected.

Changes:
- Add _check_zstream_not_affected(): searches for Z-stream clones with
  ymir_triaged_not_affected label
- Add _check_zstream_pending_triage(): searches for Z-stream clones without
  any terminal ymir_triaged* labels
- Modify _check_lowmod_ystream_eligibility(): for Low/Moderate Y-stream CVEs
  with CS_FIRST approach detected:
  * First check if Z-stream was NOT_AFFECTED → return IMMEDIATELY (triage Y-stream)
  * Then check if Z-stream pending triage → return PENDING_DEPENDENCIES (wait)
  * Otherwise → return NEVER (existing behavior - skip Y-stream)
- Modify _check_for_dependency_blocker(): for Important/Critical Y-stream CVEs:
  * Check if Z-stream was NOT_AFFECTED before postponing
  * If yes → return None (proceed with triage, same as if clone had shipped)

Example scenarios fixed:
- RHEL-214038 (rhel-9.9, Moderate): was told "CentOS Stream path", now will
  be triaged when Z-stream is not affected
- RHEL-224798, RHEL-224847 (rhel-10.3/9.9, Important): were postponed waiting
  for Z-stream, now will be triaged when Z-stream is not affected

Assisted-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Adds comprehensive unit tests for the new Z-stream status check functions
introduced in PACKIT-5281.

Test coverage:
- _get_applicable_zstream_variants():
  * Upcoming Z-stream takes precedence over current
  * Falls back to current when no upcoming exists
  * Returns None for non-existent or maintenance versions

- _check_zstream_not_affected():
  * Finds Z-stream clones with ymir_triaged_not_affected label
  * Filters by applicable Z-stream version (upcoming > current)
  * Ignores old current Z-stream when upcoming exists
  * Returns empty list when no applicable clones found

- _check_zstream_pending_triage():
  * Finds Z-stream clones without terminal labels
  * Excludes clones with terminal labels (handled by JQL)
  * Filters by applicable Z-stream version
  * Ignores old current Z-stream when upcoming exists
  * Returns empty list when no applicable clones found

Test patterns follow existing conventions:
- Uses flexmock for mocking external dependencies
- Mocks SearchJiraIssuesTool.run() and load_rhel_config()
- Uses RHEL_CONFIG fixture matching production structure
- Tests both positive and edge cases

Assisted-by: Claude Sonnet 4.5 <noreply@anthropic.com>
…nation

Modular trackers can share CVE ID, component, and fix version while representing
different module streams. Without filtering, a NOT_AFFECTED or pending status in
one module stream (e.g., postgresql:16) could incorrectly affect eligibility for
another module stream (e.g., postgresql:15).

Changes:
- Updated _check_zstream_not_affected and _check_zstream_pending_triage to accept
  summary parameter
- Parse module stream from current issue using parse_module_stream
- Request summary field from Jira search results
- Filter clones to only match when:
  - Both are modular with the exact same (module, stream) tuple, OR
  - Both are non-modular (None module stream)
- Updated all 3 call sites to pass summary parameter
- Updated all existing tests to pass summary parameter
- Added 5 regression tests for modular tracker scenarios:
  - NOT_AFFECTED: modular match, modular mismatch, modular vs non-modular
  - Pending triage: modular match, modular mismatch

Example: postgresql:15/postgis and postgresql:16/postgis both in component postgis
now correctly tracked separately - NOT_AFFECTED in :16 doesn't affect :15 eligibility.

Related: PACKIT-5281

Assisted-by: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
Container fixes:
- Containerfile.supervisor:
  - Added git binary (fixes GitPython "Bad git executable" error)
  - Added sentry-sdk>=2.13.0 (fixes import error in ymir.agents.observability)
  - Added GitPython>=3.1.0 (fixes ModuleNotFoundError: No module named 'git')

- Containerfile.c10s (triage-agent):
  - Added typer (fixes import error in ymir.cli.main)

- Containerfile.c9s:
  - Added typer for consistency with c10s

Makefile targets:
- Added `triage-issue`: Run triage agent only (AUTO_CHAIN=false)
  Usage: make triage-issue ISSUE=RHEL-252788

- Added `process`: Run full pipeline without supervisor (AUTO_CHAIN=true)
  Usage: make process ISSUE=RHEL-252788
  Runs triage → backport/rebase/rebuild chain

- Kept `process-issue`: Run supervisor-managed pipeline
  Usage: make process-issue ISSUE=RHEL-252788

These changes fix ModuleNotFoundError and restore the old pipeline workflow.

Related: PACKIT-5281

Assisted-by: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
After rebasing onto upstream/main (commit 0276b38), the _check_zstream_clones_shipped
function signature changed from returning tuple[bool, list[str]] to returning
ZStreamDependencyResult object.

Updated test mocks to match the new API:
- test_eligibility_dependency_blocker_zstream_not_affected
- test_eligibility_dependency_blocker_zstream_not_affected_error

These tests were using the old tuple format (False, ["RHEL-777"]) which caused
TypeError when the code tried to access the ZStreamDependencyResult attributes.

Also fixed _check_dependency_blocker return statements to properly return tuples
matching the function signature tuple[JSONToolOutput | None, list[ShippedZStreamCandidate]]:
- Line 1217 (NOT_AFFECTED check exception): Now returns (JSONToolOutput(...), [])
- Line 1232 (NOT_AFFECTED clones found): Now returns (None, [])

These were returning single values, causing 'cannot unpack non-iterable' errors.

Related: PACKIT-5281

Assisted-by: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
1. _check_zstream_pending_triage(): Exclude SUCCESS labels only (backported/rebased/rebuilt).
   Failed/errored labels NOT excluded (Z-stream path blocked, Y-stream may be needed).

2. Containerfile shell redirection: Quote pip requirements with >= operators.
   Fixed: PyYAML>=5.1, sentry-sdk>=2.13.0, GitPython>=3.1.0
   (in Containerfile.supervisor, .c10s, .c9s)

3. NOT_AFFECTED reason: Return specific 'Z-stream clone RHEL-XXX was NOT_AFFECTED' message.

4. Pagination fix: Add fixVersion filter to JQL (SearchJiraIssuesTool max 50 results, no pagination).

5. Duplicate preservation: Pass duplicate_of through _check_for_dependency_blocker().

6. Postponed labels: Exclude ymir_postponed_{dependency,no_patch,pr_pending} from pending-triage JQL.

7. Makefile: Change $(ISSUE) to $(JIRA_ISSUE) in triage-issue/process targets, add guards.

Related: PACKIT-5281
Assisted-by: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
@majamassarini
majamassarini force-pushed the fix/PACKIT-5281-ystream-not-affected-check branch from 259f0ed to 9dc981a Compare September 3, 2026 13:19
@nforro

nforro commented Sep 3, 2026

Copy link
Copy Markdown
Member

However I squashed them here.

Thanks. Though the last two fixup commits should be squashed as well. I'm completely fine with doing that just before merging the PR though, if it makes reviews easier. Although that probably requires re-approvals.

@nforro nforro left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

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