Skip to content

[OCPERT-437] Port blocking sec-alerts check command to main for Konflux release flow - #1147

Open
jhuttana wants to merge 3 commits into
openshift:mainfrom
jhuttana:OCPERT-437
Open

[OCPERT-437] Port blocking sec-alerts check command to main for Konflux release flow#1147
jhuttana wants to merge 3 commits into
openshift:mainfrom
jhuttana:OCPERT-437

Conversation

@jhuttana

@jhuttana jhuttana commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

JIRA: https://redhat.atlassian.net/browse/OCPERT-437

Summary by CodeRabbit

  • New Features

    • Added a release workflow check to scan RHSA advisories for blocking security alerts.
    • When blocking alerts are found, reports the affected advisory details (with links), tracks a blocking issue, and sets the task status to Fail; otherwise sets Pass.
    • Updated workflow sequencing so CDN staging starts after this check.
    • Added CLI and MCP access to run the check.
  • Bug Fixes

    • Corrected blocking-alert detection to use the proper advisory alert-check method.
  • Tests

    • Expanded coverage for pass/fail behavior, RHSA-only filtering, StateBox rerun resolution logic, and error handling.

@jhuttana
jhuttana requested a review from tomasdavidorg July 23, 2026 09:45
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 560304b7-a794-4a68-acb2-e4f049c6d937

📥 Commits

Reviewing files that changed from the base of the PR and between f7fe1d5 and 9ca1b56.

📒 Files selected for processing (2)
  • oar/cli/cmd_check_blocking_sec_alerts.py
  • tests/test_advisory.py

Walkthrough

The release workflow replaces the prior RHCOS-only security-alert step with a blocking security-alert check. A new CLI command scans RHSA advisories, updates StateBox, creates blocker issues, and is exposed through an MCP tool.

Changes

Blocking security alert workflow

Layer / File(s) Summary
Task contract and advisory check
oar/core/const.py, oar/core/advisory.py
Registers check-blocking-sec-alerts and corrects the blocking-alert method name and call site.
CLI scanning and StateBox processing
oar/cli/cmd_check_blocking_sec_alerts.py, oar/cli/cmd_group.py, tests/test_advisory.py
Adds RHSA scanning, pass/fail handling, StateBox issue management, command registration, exception handling, and tests.
MCP and release workflow integration
mcp_server/server.py, .claude/skills/release-workflow/SKILL.md
Exposes the command through MCP and updates the task graph and task instructions before CDN staging.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ReleaseWorkflow
  participant MCPServer
  participant CheckBlockingSecAlerts
  participant AdvisoryManager
  participant StateBox
  ReleaseWorkflow->>MCPServer: oar_check_blocking_sec_alerts(release)
  MCPServer->>CheckBlockingSecAlerts: invoke check-blocking-sec-alerts
  CheckBlockingSecAlerts->>AdvisoryManager: load and inspect RHSA advisories
  AdvisoryManager-->>CheckBlockingSecAlerts: blocking alert results
  CheckBlockingSecAlerts->>StateBox: update task status and blocker issues
Loading

Suggested reviewers: tomasdavidorg, barboras7, cardelearht


Important

Pre-merge checks failed

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

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
No-Sensitive-Data-In-Logs ❌ Error New logs print advisory URLs and raw alert JSON; the URL includes internal hostname errata.devel.redhat.com. Remove or redact advisory links and raw alert payloads from logs; log only advisory IDs/counts or sanitized summaries.
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (13 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: porting the blocking sec-alerts check command to main for the Konflux release flow.
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.
Stable And Deterministic Test Names ✅ Passed New test names are static descriptive unittest methods; no dynamic pod/UUID/timestamp/node/namespace/IP values appear in any test title.
Test Structure And Quality ✅ Passed PASS: These are Python unittest cases, not Ginkgo; the new tests use setUp and mocks only, with no cluster resources, waits, or cleanup issues.
Microshift Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the changes are Python unit tests and CLI code, so MicroShift-specific API compatibility is not applicable.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No Ginkgo e2e tests were added; the PR only changes Python CLI/unit tests, so SNO multi-node assumptions are not applicable.
Topology-Aware Scheduling Compatibility ✅ Passed Modified files are CLI/MCP/constants/tests only; no deployment manifests, controllers, node selectors, anti-affinity, or topology-aware scheduling logic added.
Ote Binary Stdout Contract ✅ Passed PR only changes Python CLI/tests; no Go/OTE process-level entrypoints or stdout writes were added.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No new Ginkgo/e2e tests were added; the new tests are unittest/CliRunner mocks with no IPv4-only or external connectivity assumptions.
No-Weak-Crypto ✅ Passed Touched files add advisory/checking logic only; no MD5/SHA1/DES/RC4/3DES/Blowfish/ECB, custom crypto, or secret/token comparisons found.
Container-Privileges ✅ Passed No container/K8s manifest files were changed; the PR only touches Python CLI/tests and contains no privileged, hostPID/network/IPC, SYS_ADMIN, or allowPrivilegeEscalation settings.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@openshift-ci
openshift-ci Bot requested review from barboras7 and cardelearht July 23, 2026 09:45
@openshift-ci

openshift-ci Bot commented Jul 23, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign luboterifaj for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 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 @.claude/skills/release-workflow/SKILL.md:
- Around line 351-369: Add the `text` language annotation to all three fenced
code blocks in the security alert detection section, including the two behavior
examples and the Success/Failure Detection blocks, without changing their
contents.

In `@oar/cli/cmd_check_blocking_sec_alerts.py`:
- Line 6: Replace the wildcard import in
oar/cli/cmd_check_blocking_sec_alerts.py at lines 6-6 with explicit imports for
the task and status constants used by the module. Also replace the wildcard
import in tests/test_advisory.py at lines 9-9 with only the constants referenced
by that test module; preserve all existing behavior while eliminating Ruff F403.
- Around line 50-54: Update the RHSA result handling in the
check-blocking-alerts command so any non-empty check_errors causes
TASK_STATUS_FAIL, including mixed successful and failed checks, instead of only
failing when rhsa_checked == 0. Preserve known-blocker issue creation where
applicable, and add a regression test covering mixed success and failure.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 8e500334-2ae3-436f-b158-8881fb0400d4

📥 Commits

Reviewing files that changed from the base of the PR and between 3ee6a62 and 0131bf3.

📒 Files selected for processing (7)
  • .claude/skills/release-workflow/SKILL.md
  • mcp_server/server.py
  • oar/cli/cmd_check_blocking_sec_alerts.py
  • oar/cli/cmd_group.py
  • oar/core/advisory.py
  • oar/core/const.py
  • tests/test_advisory.py

Comment thread .claude/skills/release-workflow/SKILL.md Outdated
Comment thread oar/cli/cmd_check_blocking_sec_alerts.py Outdated
Comment thread oar/cli/cmd_check_blocking_sec_alerts.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (1)
.claude/skills/release-workflow/SKILL.md (1)

59-59: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Gate all downstream release actions on check-blocking-sec-alerts passing.

The workflow currently allows downstream actions after a task that can report Fail and create a StateBox blocker, undermining the intended blocking behavior.

  • .claude/skills/release-workflow/SKILL.md#L59-L59: make the task-graph transition conditional on Pass.
  • .claude/skills/release-workflow/SKILL.md#L89-L89: state that CDN staging starts only after a passing security-alert check.
  • .claude/skills/release-workflow/SKILL.md#L374-L376: trigger downstream actions only on Pass; otherwise stop and await blocker resolution.
🤖 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 @.claude/skills/release-workflow/SKILL.md at line 59, Gate all downstream
release actions on a Pass result from check-blocking-sec-alerts: update the
task-graph transition at .claude/skills/release-workflow/SKILL.md lines 59-59,
document at lines 89-89 that CDN staging begins only after the check passes, and
revise lines 374-376 so non-Pass results stop downstream actions and await
StateBox blocker resolution.
🧹 Nitpick comments (1)
oar/cli/cmd_check_blocking_sec_alerts.py (1)

51-53: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Narrow the per-advisory exception handler. Catch only the API/parsing errors expected from has_blocking_security_alert() here; unexpected exceptions should reach the outer logger.exception(...) path so tracebacks are preserved and programming bugs don’t look like ordinary advisory failures.

🤖 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 `@oar/cli/cmd_check_blocking_sec_alerts.py` around lines 51 - 53, In the
per-advisory handling around has_blocking_security_alert(), replace the broad
Exception handler with the specific API/parsing exception types that method is
expected to raise. Keep recording expected advisory failures in check_errors and
logger.error, while allowing unexpected exceptions to propagate to the outer
logger.exception(...) path with their tracebacks.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@oar/cli/cmd_check_blocking_sec_alerts.py`:
- Around line 55-60: Update the blocking-security-alert check flow around
TASK_CHECK_BLOCKING_SEC_ALERTS so the existing blocker is not resolved before
advisory checks and replacement add_issue persistence succeed. Resolve the prior
blocker only after a clean pass or confirmed replacement creation, and retain it
when checks fail or StateBoxException occurs during persistence.
- Around line 35-39: Update the no-RHSA early-return path in the blocking
security alert check to resolve any existing StateBox blocker before marking
TASK_CHECK_BLOCKING_SEC_ALERTS as PASS and returning. Reuse the existing
blocker-resolution mechanism, or centralize that cleanup so it runs whenever the
check succeeds after advisories disappear.

---

Outside diff comments:
In @.claude/skills/release-workflow/SKILL.md:
- Line 59: Gate all downstream release actions on a Pass result from
check-blocking-sec-alerts: update the task-graph transition at
.claude/skills/release-workflow/SKILL.md lines 59-59, document at lines 89-89
that CDN staging begins only after the check passes, and revise lines 374-376 so
non-Pass results stop downstream actions and await StateBox blocker resolution.

---

Nitpick comments:
In `@oar/cli/cmd_check_blocking_sec_alerts.py`:
- Around line 51-53: In the per-advisory handling around
has_blocking_security_alert(), replace the broad Exception handler with the
specific API/parsing exception types that method is expected to raise. Keep
recording expected advisory failures in check_errors and logger.error, while
allowing unexpected exceptions to propagate to the outer logger.exception(...)
path with their tracebacks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 00bfbd0d-49ea-40a8-9bc0-2934cb724dac

📥 Commits

Reviewing files that changed from the base of the PR and between 0131bf3 and f7fe1d5.

📒 Files selected for processing (3)
  • .claude/skills/release-workflow/SKILL.md
  • oar/cli/cmd_check_blocking_sec_alerts.py
  • tests/test_advisory.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/test_advisory.py

Comment thread oar/cli/cmd_check_blocking_sec_alerts.py
Comment on lines +55 to +60
existing_blocker = statebox.get_task_blocker(TASK_CHECK_BLOCKING_SEC_ALERTS)
if existing_blocker:
statebox.resolve_issue(
issue=existing_blocker["issue"],
resolution="Re-checked blocking security alerts",
)

@coderabbitai coderabbitai Bot Jul 24, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Retain the previous blocker until replacement state is durable.

The existing blocker is resolved before check completion. If any advisory check fails, or add_issue() raises StateBoxException, the old blocker can be gone without a replacement even though the task remains failed. Resolve it only after a clean pass or successful replacement creation; retain it on partial or persistence failures.

Also applies to: 74-83

🤖 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 `@oar/cli/cmd_check_blocking_sec_alerts.py` around lines 55 - 60, Update the
blocking-security-alert check flow around TASK_CHECK_BLOCKING_SEC_ALERTS so the
existing blocker is not resolved before advisory checks and replacement
add_issue persistence succeed. Resolve the prior blocker only after a clean pass
or confirmed replacement creation, and retain it when checks fail or
StateBoxException occurs during persistence.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed this issue by re-ordering that logic:
Re-run -> Check the issue -> Resolved/Update.

Also, made some more enhancements:
In cmd_check_blocking_sec_alerts.py -- using get_issues(unresolved_only=True, task_name=...) is better than get_task_blocker() because:

  • It returns all unresolved issues (blockers + non-blockers) for the task
  • The pass path (lines 100-105) resolves every unresolved issue in a loop, not just the first blocker
  • The fail path (lines 72-73) extracts the blocker from the list with next(...) for the dedup comparison

In test_advisory.py -- all tests properly updated:

  • Existing tests mock get_issues returning [] for the no-prior-issues case
  • test_rerun_pass_resolves_existing_blocker -- single blocker resolved on pass
  • test_rerun_same_blocker_skips_update -- duplicate blocker left alone
  • test_rerun_pass_resolves_all_issues -- both a blocker and a non-blocker resolved, asserts resolve_issue.call_count == 2

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

ast-grep outline oar/cli/cmd_check_blocking_sec_alerts.py --items all
ast-grep outline tests/test_advisory.py --match 'TestCheckBlockingSecAlerts' --view expanded

printf '\n--- command implementation ---\n'
sed -n '1,180p' oar/cli/cmd_check_blocking_sec_alerts.py

printf '\n--- relevant rerun tests ---\n'
rg -n -A45 -B8 \
  'def test_rerun_(pass_resolves_existing_blocker|same_blocker_skips_update|pass_resolves_all_issues)\b' \
  tests/test_advisory.py

Length of output: 10910


@jhuttana, thanks for the broader get_issues() cleanup—resolving all unresolved task issues on the clean-pass path is an improvement. However, the original issue remains in the current implementation.

In oar/cli/cmd_check_blocking_sec_alerts.py, the changed-blocker path still calls resolve_issue() before add_issue(). If add_issue() raises StateBoxException, its exception is caught and the task is marked failed, but the prior blocker has already been removed without a durable replacement.

Please create the replacement first, then resolve the previous blocker only after add_issue() succeeds. A regression test should cover an existing different blocker plus add_issue.side_effect = StateBoxException(...), asserting that resolve_issue() is not called.

@openshift-ci

openshift-ci Bot commented Jul 27, 2026

Copy link
Copy Markdown

@jhuttana: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

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.

1 participant