Skip to content

OAPE-836: V1.42.3 Rebase openshift/main with upstream v1.42.3#82

Open
mytreya-rh wants to merge 22 commits into
openshift:mainfrom
mytreya-rh:v1.42.3-rebase-main
Open

OAPE-836: V1.42.3 Rebase openshift/main with upstream v1.42.3#82
mytreya-rh wants to merge 22 commits into
openshift:mainfrom
mytreya-rh:v1.42.3-rebase-main

Conversation

@mytreya-rh

@mytreya-rh mytreya-rh commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Description of the change:*
Rebase this repo's main branch with upstream https://github.com/operator-framework/ansible-operator-plugins/releases/tag/v1.42.3 tag.
Changes done:

  1. Cherry-picked [WIP] UPSTREAM: <carry>: automate hermetic build requirements generation #79 (UPSTREAM: <carry>: automate hermetic build requirements generation) onto the rebase branch first, so make -f openshift/Makefile generate-requirements uses the new Python-based generator (openshift/hack/generate_requirements.py) against the v1.42.3 Pipfile/Pipfile.lock instead of the old manual bash pipeline in openshift/Dockerfile.requirements.
  2. Updated openshift/hack/rebase_upstream.sh to allow reusing a pre-existing <version>-rebase-<branch> branch, so the [WIP] UPSTREAM: <carry>: automate hermetic build requirements generation #79 cherry-pick could be staged before running the rest of the script.
  3. Triggered the rebase using openshift/hack/rebase_upstream.sh v1.42.3, which merged upstream tag v1.42.3 (no conflicts), ran go mod tidy && go mod vendor, regenerated openshift/release/ansible/ansible_collections (only benign galaxy metadata URL diffs), and regenerated openshift/requirements*.txt / openshift/Pipfile.lock via the new generator.
    Motivation for the change:
    Pick up upstream v1.42.3, which bumps the Go toolchain to 1.26.3 and updates several Go/Python dependencies for CVE fixes (cryptography, urllib3, idna, requests, grpc, pyasn1, pip/pipenv, ubi9-minimal, etc.), while also landing the automated hermetic build-requirements generation from [WIP] UPSTREAM: <carry>: automate hermetic build requirements generation #79 ahead of the dependency regeneration so the new requirements files are produced by the maintained script rather than the manual bash pipeline.

Summary by CodeRabbit

  • New Features
    • Improved automated generation of OpenShift build and runtime requirements, including vulnerability checks and conflict handling.
  • Updates
    • Released version v1.42.3.
    • Refreshed supported build environments and Python package versions.
    • Updated Galaxy collection metadata links.
  • Maintenance
    • Updated automated release and test workflows for improved reliability.
    • Rebase tooling now reuses existing versioned work branches.

dependabot Bot and others added 22 commits March 18, 2026 07:04
Bumps [pyasn1](https://github.com/pyasn1/pyasn1) from 0.6.2 to 0.6.3.
- [Release notes](https://github.com/pyasn1/pyasn1/releases)
- [Changelog](https://github.com/pyasn1/pyasn1/blob/main/CHANGES.rst)
- [Commits](pyasn1/pyasn1@v0.6.2...v0.6.3)

---
updated-dependencies:
- dependency-name: pyasn1
  dependency-version: 0.6.3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.75.1 to 1.79.3.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](grpc/grpc-go@v1.75.1...v1.79.3)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.79.3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Signed-off-by: Adam D. Cornett <adc@redhat.com>
Bumps [requests](https://github.com/psf/requests) from 2.32.5 to 2.33.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](psf/requests@v2.32.5...v2.33.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-version: 2.33.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…#215)

Bumps [cryptography](https://github.com/pyca/cryptography) from 46.0.5 to 46.0.6.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](pyca/cryptography@46.0.5...46.0.6)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-version: 46.0.6
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [go.opentelemetry.io/otel/sdk](https://github.com/open-telemetry/opentelemetry-go) from 1.40.0 to 1.43.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](open-telemetry/opentelemetry-go@v1.40.0...v1.43.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/otel/sdk
  dependency-version: 1.43.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…#217)

Bumps [cryptography](https://github.com/pyca/cryptography) from 46.0.6 to 46.0.7.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](pyca/cryptography@46.0.6...46.0.7)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-version: 46.0.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.6.3 to 2.7.0.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](urllib3/urllib3@2.6.3...2.7.0)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-version: 2.7.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [idna](https://github.com/kjd/idna) from 3.11 to 3.15.
- [Release notes](https://github.com/kjd/idna/releases)
- [Changelog](https://github.com/kjd/idna/blob/master/HISTORY.md)
- [Commits](kjd/idna@v3.11...v3.15)

---
updated-dependencies:
- dependency-name: idna
  dependency-version: '3.15'
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@v6...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…#225)

Bumps [cryptography](https://github.com/pyca/cryptography) from 46.0.7 to 48.0.1.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](pyca/cryptography@46.0.7...48.0.1)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-version: 48.0.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Signed-off-by: Adam D. Cornett <adc@redhat.com>
…e to reduce cve footprint (#227)

Signed-off-by: Adam D. Cornett <adc@redhat.com>
Bumps ubi9/ubi-minimal from 9.7 to 9.8.

---
updated-dependencies:
- dependency-name: ubi9/ubi-minimal
  dependency-version: '9.8'
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Update go.mod

need 1.26.1. version to fix CVE-2026-25679,CVE-2026-27139,CVE-2026-27142

Signed-off-by: Preethi-Ps <nannetpreethi@gmail.com>

* Update go.mod

Signed-off-by: Preethi-Ps <nannetpreethi@gmail.com>

* Update go.mod

Signed-off-by: Preethi-Ps <nannetpreethi@gmail.com>

---------

Signed-off-by: Preethi-Ps <nannetpreethi@gmail.com>
Co-authored-by: Preethi-Ps <nannetpreethi@gmail.com>
Signed-off-by: Adam D. Cornett <adc@redhat.com>
Replace the manually maintained ~100-line bash pipeline in
openshift/Dockerfile.requirements with a Python script that derives
all four requirements files entirely from the Pipfile, with no
hardcoded package names.

openshift/hack/generate_requirements.py implements five stages:

Stage 1 – pipenv install + CVE auto-fix via Safety/pipenv update,
  then pip freeze to capture all pinned runtime packages.

Stage 2 – Iterative pip-compile with dynamic conflict exclusion to
  produce requirements.txt.  Packages that make pip-compile fail due
  to incompatible declared metadata (e.g. conflicting setuptools
  version ranges) are detected from the error output, excluded from
  compilation, and appended manually.  RPM-installed packages
  (cryptography, cffi, pycparser, maturin) are commented out in
  post-processing.

Stage 3 – pip_find_builddeps.py is run once per runtime package so
  that every package's build-system requirements can be associated
  with it individually.

Stage 4 – Conflict detection and phase splitting.  Merging all
  build-dep constraints is attempted with pip-compile; when it fails
  the conflicting dependency is identified and packages split into an
  earlier phase (needing the older version) and a later phase
  (needing the newer version) using three fallback strategies in
  order: direct upper-bound heuristic, per-package compilation to
  detect transitive conflicts, and single-package bisection.
  N discovered phases are mapped to exactly three build files with a
  greedy merge that verifies compatibility before absorbing each
  middle phase into the main build group.
  Build-isolation exact-version pins (e.g. wheel==0.45.1 declared by
  ansible-core's pyproject.toml) are discovered automatically from
  pkg_constraints, injected into requirements-pre-build.txt so cachi2
  pre-fetches them, and stripped from later phases so those phases
  resolve newer CVE-fixed versions.  No version numbers are hardcoded.

Stage 5 – Safety scans each generated build requirements file for
  CVEs and attempts to fix them by adding minimum-version constraints
  and re-running pip-compile.  Conflicts that prevent the fix are
  reported with the name of the blocking constraint.

openshift/hack/generate_requirements.md documents the full algorithm.

openshift/Dockerfile.requirements is reduced to installing the
toolchain and invoking the script.  The generated requirements files
and Pipfile.lock (updated by any CVE auto-fixes) are exported to the
mounted volume by the ENTRYPOINT.

The regenerated requirements files reflect:
- pyasn1 0.6.2 → 0.6.3  (CVE-2026-30922)
- requests 2.32.5 → 2.33.1  (CVE-2026-25645)
- wheel 0.46.3 → 0.47.0 in requirements-build.txt (CVE-2026-24049;
  0.45.1 is retained in requirements-pre-build.txt for ansible-core
  build isolation as discovered from its build-system metadata)
- certifi, charset-normalizer, idna, packaging, pathspec,
  poetry-core, setuptools, trove-classifiers bumped to latest
- kubernetes 33.1.0 build deps skipped (internal setuptools-scm
  conflict in the package's own build-system declaration)

Co-authored-by: Cursor <cursoragent@cursor.com>
…ebase branch

Supports pre-creating the <version>-rebase-<branch> branch and staging
commits on it (e.g. cherry-picks) before running the script.

Co-authored-by: Cursor <cursoragent@cursor.com>
Ansible Operator Plugins v1.42.3

Merge executed via ./rebase-upstream.sh v1.42.3 upstream main

Overwritten conflicts:
<NONE>

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@openshift-ci-robot

openshift-ci-robot commented Jul 26, 2026

Copy link
Copy Markdown

@mytreya-rh: This pull request references OAPE-836 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Description of the change:*
Rebase this repo's main branch with upstream https://github.com/operator-framework/ansible-operator-plugins/releases/tag/v1.42.3 tag.
Changes done:

  1. Cherry-picked [WIP] UPSTREAM: <carry>: automate hermetic build requirements generation #79 (UPSTREAM: <carry>: automate hermetic build requirements generation) onto the rebase branch first, so make -f openshift/Makefile generate-requirements uses the new Python-based generator (openshift/hack/generate_requirements.py) against the v1.42.3 Pipfile/Pipfile.lock instead of the old manual bash pipeline in openshift/Dockerfile.requirements.
  2. Updated openshift/hack/rebase_upstream.sh to allow reusing a pre-existing <version>-rebase-<branch> branch, so the [WIP] UPSTREAM: <carry>: automate hermetic build requirements generation #79 cherry-pick could be staged before running the rest of the script.
  3. Triggered the rebase using openshift/hack/rebase_upstream.sh v1.42.3, which merged upstream tag v1.42.3 (no conflicts), ran go mod tidy && go mod vendor, regenerated openshift/release/ansible/ansible_collections (only benign galaxy metadata URL diffs), and regenerated openshift/requirements*.txt / openshift/Pipfile.lock via the new generator.
    Motivation for the change:
    Pick up upstream v1.42.3, which bumps the Go toolchain to 1.26.3 and updates several Go/Python dependencies for CVE fixes (cryptography, urllib3, idna, requests, grpc, pyasn1, pip/pipenv, ubi9-minimal, etc.), while also landing the automated hermetic build-requirements generation from [WIP] UPSTREAM: <carry>: automate hermetic build requirements generation #79 ahead of the dependency regeneration so the new requirements files are produced by the maintained script rather than the manual bash pipeline.

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 openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jul 26, 2026
@openshift-ci

openshift-ci Bot commented Jul 26, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: mytreya-rh

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

The pull request process is described 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

@openshift-ci
openshift-ci Bot requested review from anik120 and oceanc80 July 26, 2026 12:45
@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jul 26, 2026
@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Walkthrough

The change adds a five-stage OpenShift requirements generator and wires it into the Docker build. It also refreshes generated dependency files, Go and Python tooling, release versions, GitHub Actions checkout versions, Galaxy URLs, and rebase branch handling.

Changes

Hermetic requirements generation

Layer / File(s) Summary
Generator contract and documentation
openshift/hack/generate_requirements.py, openshift/hack/generate_requirements.md
Adds generator configuration, staged pipeline documentation, command usage, and extension guidance.
Resolution and phase-splitting logic
openshift/hack/generate_requirements.py
Implements command execution, parsing, CVE handling, build-dependency conflict detection, and recursive phase splitting.
Pipeline wiring and generated requirements
openshift/Dockerfile.requirements, openshift/requirements*.txt
Invokes the generator from the Docker build, exports Pipfile.lock, and refreshes runtime and build requirement artifacts.

Release and build maintenance

Layer / File(s) Summary
Release version alignment
Makefile, internal/version/version.go, testdata/memcached-molecule-operator/Makefile
Updates the image version and downloaded ansible-operator release to v1.42.3.
Go and Python toolchain refresh
go.mod, images/ansible-operator/*
Updates Go modules, UBI images, Python pins, pip tooling, and audit behavior.
Workflow checkout updates
.github/workflows/*
Changes workflow checkout actions from v6 to v7.
Rebase and Galaxy metadata updates
openshift/hack/rebase_upstream.sh, openshift/release/ansible/ansible_collections/*/GALAXY.yml
Reuses existing rebase branches and updates Galaxy API endpoint paths.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Dockerfile.requirements
  participant generate_requirements.py
  participant pipenv
  participant pip_compile
  participant pip_find_builddeps
  Dockerfile.requirements->>generate_requirements.py: invoke generator
  generate_requirements.py->>pipenv: resolve and freeze runtime dependencies
  generate_requirements.py->>pip_compile: compile runtime and build requirements
  generate_requirements.py->>pip_find_builddeps: collect build constraints
  generate_requirements.py-->>Dockerfile.requirements: write requirements files and Pipfile.lock
Loading

Important

Pre-merge checks failed

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

❌ Failed checks (2 errors)

Check name Status Explanation Resolution
Container-Privileges ❌ Error No privileged flags were added, but images/ansible-operator/pipfile.Dockerfile and openshift/Dockerfile.requirements still run as root by default with no justification. Run those helper images as a non-root user (or document the root requirement) and keep the main image’s non-root USER.
No-Sensitive-Data-In-Logs ❌ Error New logs echo raw pipenv/pip-compile stderr/stdout and git status, which can leak URLs, tokens, or other sensitive paths. Redact or summarize subprocess output, and avoid dumping full stderr/stdout or git status unless explicitly sanitized.
✅ 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 clearly reflects the main change: rebasing openshift/main onto upstream v1.42.3.
Docstring Coverage ✅ Passed Docstring coverage is 95.24% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed PR only changes requirement lockfiles; no test files or Ginkgo titles were added/edited, so there are no dynamic test names to flag.
Test Structure And Quality ✅ Passed PR changes don't touch any Ginkgo test files or cluster test logic; only workflows, vendored deps, and requirements were updated.
Microshift Test Compatibility ✅ Passed No new Ginkgo e2e specs were added; the non-vendor diff is workflows, scripts, docs, and dependency refreshes only.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No new *_test.go or Ginkgo DSL additions appear in the PR diff; only workflow, dependency, and generator files changed.
Topology-Aware Scheduling Compatibility ✅ Passed No deployment manifests, controllers, or scheduling logic were modified; the PR only updates requirements/workflow/rebase tooling files.
Ote Binary Stdout Contract ✅ Passed No changed OTE binary entrypoints; stdout prints are confined to the standalone requirements-generator script, not openshift-tests JSON producers.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No new Ginkgo e2e test specs were added; the diff is workflow, dependency, and generator updates only, with no Ginkgo constructs in non-vendor changes.
No-Weak-Crypto ✅ Passed No weak-crypto APIs or secret/token comparisons appear in the changed files; searches found only benign cryptography build references and workflow secrets.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 14

🧹 Nitpick comments (5)
images/ansible-operator/Pipfile (1)

8-11: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Pin the build-tool installs exactly

pip~=26.1.2 and the unpinned pip-audit in both Dockerfiles can drift; use exact versions there. The Pipfile entries already resolve to exact versions through Pipfile.lock, so they don’t need == pins.

🤖 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 `@images/ansible-operator/Pipfile` around lines 8 - 11, Pin the build-tool
dependencies exactly in both Dockerfiles: update pip to 26.1.2 and assign an
exact version to pip-audit in images/ansible-operator/Dockerfile lines 29-30 and
images/ansible-operator/pipfile.Dockerfile lines 23-24. No change is required in
images/ansible-operator/Pipfile lines 8-11 because its lockfile already resolves
those entries exactly.

Source: Path instructions

openshift/hack/generate_requirements.py (3)

452-468: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Gap heuristic splits on patch-only differences.

When every consecutive gap is 0 (e.g. resolved versions 8.1.0 and 8.1.2), max_gap never exceeds 0, split_after stays at unique[0], and the group is split even though no major/minor conflict exists. The recursion re-validates each sub-group, so the result is only extra phases rather than a wrong one — but requiring max_gap > 0 before splitting would avoid the spurious phase.

🤖 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 `@openshift/hack/generate_requirements.py` around lines 452 - 468, Update the
gap-splitting logic around split_after and max_gap so it returns no split when
the largest major/minor gap is zero, including patch-only differences. Only
compute and return the older group when max_gap is greater than zero; preserve
the existing split behavior for genuine major/minor gaps.

203-207: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

_min_safe_version picks the last upper bound, not the tightest.

For multi-clause specs (Safety often emits ranges joined by ||, e.g. <1.9 || >=2.0,<2.1), the last <X match is the newest bound, so the inferred "min safe version" can silently overshoot or undershoot. Selecting the maximum bound with packaging.version.Version makes the intent explicit and matches the docstring.

♻️ Proposed refactor
-    # Find the tightest upper bound: the version just after <X
-    best: str | None = None
-    for m in re.finditer(r"<([0-9][0-9a-zA-Z._-]*)", affected_spec):
-        best = m.group(1)   # last match wins (most restrictive)
-    return best
+    # Pick the highest upper bound across all clauses so the resulting
+    # ">=best" constraint clears every affected range.
+    from packaging.version import InvalidVersion, Version
+
+    best: str | None = None
+    for m in re.finditer(r"<([0-9][0-9a-zA-Z._-]*)", affected_spec):
+        cand = m.group(1)
+        if best is None:
+            best = cand
+            continue
+        try:
+            if Version(cand) > Version(best):
+                best = cand
+        except InvalidVersion:
+            best = cand
+    return best
🤖 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 `@openshift/hack/generate_requirements.py` around lines 203 - 207, Update
_min_safe_version to compare every matched upper-bound version using
packaging.version.Version and retain the maximum bound rather than relying on
the last regex match. Return the selected version in the existing string format,
preserving None when no upper bounds are found.

625-629: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Every committed lockfile header now records absolute /requirements*.in paths. stage2_runtime_txt writes the compile input into out_dir specifically to keep pip-compile's # via annotations relative-looking, but the container invokes the generator with the default --output-dir . at /, so all three regenerated files carry /requirements-*.in annotations instead of the previous relative form. Harmless for pip, but it inflates the diff on every regeneration.

  • openshift/hack/generate_requirements.py#L625-L629: either write the .in files relative to the process CWD, or update the comment to reflect that the annotation path follows --output-dir.
  • openshift/requirements-build.txt#L5-L6: regenerate once the output directory is a real subdirectory so annotations return to the relative form.
  • openshift/requirements-pre-build.txt#L5-L6: same regeneration applies to this header and its # via lines.
  • openshift/requirements.txt#L5-L6: same regeneration applies to this header and its # via lines.
🤖 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 `@openshift/hack/generate_requirements.py` around lines 625 - 629, The
stage2_runtime_txt path setup around compile_in and out_txt currently produces
absolute # via annotations when --output-dir is /. Make the compile input path
relative to the process CWD (or update the comment to accurately document
--output-dir-dependent behavior), then regenerate
openshift/requirements-build.txt:5-6, openshift/requirements-pre-build.txt:5-6,
and openshift/requirements.txt:5-6 using a real subdirectory so their headers
and # via lines use relative paths.
openshift/hack/generate_requirements.md (1)

27-32: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add languages to fenced code blocks (markdownlint MD040).

Seven fenced blocks (Lines 27, 60, 121, 183, 216, 242, 288) have no language specified. text is fine for the ASCII diagrams.

Also applies to: 60-80, 121-125

🤖 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 `@openshift/hack/generate_requirements.md` around lines 27 - 32, Add the `text`
language identifier to the seven unlabeled fenced code blocks in
generate_requirements.md, including the blocks around the listed sections, while
preserving their existing diagram and content text.

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 @.github/workflows/release.yml:
- Line 28: Pin every actions/checkout invocation to a full immutable commit SHA
instead of the mutable `@v7` tag: update .github/workflows/release.yml at lines
28-28 and 66-66, .github/workflows/test-ansible.yml at lines 10-10 and 23-23,
.github/workflows/test-sanity.yml at line 10, and .github/workflows/unit.yml at
line 10.

In @.github/workflows/test-ansible.yml:
- Around line 10-12: Add persist-credentials: false to every actions/checkout
step in .github/workflows/test-ansible.yml at lines 10-12 and 23-25,
.github/workflows/test-sanity.yml at lines 10-12, and .github/workflows/unit.yml
at lines 10-12; no other workflow behavior needs changing.

In `@go.mod`:
- Line 110: Update the google.golang.org/grpc dependency in go.mod from v1.79.3
to v1.82.1 or later, and synchronize related module checksums or dependency
metadata so the module build list no longer includes the vulnerable version.

In `@images/ansible-operator/pipfile.Dockerfile`:
- Line 1: Add a non-root user in the basebuilder image, grant that user write
access to /tmp/pip-airlock, and configure the image to run as that user so the
ENTRYPOINT cp operation does not create root-owned Pipfile.lock files.

In `@openshift/Dockerfile.requirements`:
- Around line 33-34: Update the documentation describing hardcoded package
assumptions: in openshift/Dockerfile.requirements lines 33-34, replace the
cachi2-specific wheel pin statement with a note that build-isolation pins are
auto-discovered from package metadata; in
openshift/hack/generate_requirements.py lines 5-7, remove “and cachi2-specific
pins” from the module docstring while leaving the script behavior unchanged.

In `@openshift/hack/generate_requirements.md`:
- Line 188: Update the step-count descriptions in the requirements-generation
documentation: change “five strategies” to “six strategies” near the
recursion-level list and “three-step process” to “four-step process” near the
later numbered list, without changing the steps themselves.

In `@openshift/hack/generate_requirements.py`:
- Around line 882-883: Remove the unnecessary f-string prefixes from the literal
string fragments in the requirement-generation output, including the fragments
near the auto-detected build-isolation pins and the corresponding locations
around lines 1001 and 1236. Preserve the existing concatenation and
interpolation for strings that still contain placeholders.
- Around line 230-239: Update the vulnerability parsing at this path and the
re-check around the second parse site to use the combined check.stdout and
check.stderr streams, matching Stage 5’s _strip_ansi handling. Preserve the
existing warning and auto-fix behavior while ensuring reports emitted on stderr
are parsed and processed.
- Around line 992-999: Change the deferred-package handling around the mapped
phase loop so `later_pkgs` constraints are accumulated when
`requirements-build.in` is not yet available, instead of being dropped. After
the loop has produced the build requirements, append all deferred specs and run
the same `_pip_compile`, `_normalize_quirks`, and `_comment_out` post-processing
used for the normal build output, ensuring RPM-installed packages remain
commented out.
- Around line 1062-1078: Update the Safety invocation loop around safety_cmd so
missing executables are caught as FileNotFoundError and the next command form is
attempted. Remove the premature stderr-based break and only stop when the
command executes successfully or produces a non-missing-command result, while
preserving the existing return-code handling and artifact generation flow.

In `@openshift/hack/rebase_upstream.sh`:
- Around line 49-52: Update the existing-branch path in the rebase_work_branch
reuse logic to ensure the checked-out branch contains the refreshed
rebase_branch before continuing. Merge the updated base into the reused branch,
or perform an ancestry check and abort with a clear message when it is not based
on the refreshed target.
- Around line 50-54: Update the existing-branch path around rebase_work_branch
so git checkout failure aborts the script immediately, matching the failure
handling in the branch-creation path. Preserve the current success behavior and
ensure no merge or commit proceeds when checkout fails.

In `@openshift/requirements-build.txt`:
- Around line 56-74: Update the pinned setuptools version in the requirements
file from 82.0.1 to a patched release that addresses the published advisory,
keeping the existing unsafe-package entry and formatting intact.

In `@openshift/requirements.txt`:
- Around line 33-36: Update the pinned runtime dependency set in
requirements.txt by restoring the rsa package required by google-auth==2.55.0,
using the compatible rsa>=3.1.4,<5 constraint and retaining the existing
generated dependency annotations for the google-auth dependency chain.

---

Nitpick comments:
In `@images/ansible-operator/Pipfile`:
- Around line 8-11: Pin the build-tool dependencies exactly in both Dockerfiles:
update pip to 26.1.2 and assign an exact version to pip-audit in
images/ansible-operator/Dockerfile lines 29-30 and
images/ansible-operator/pipfile.Dockerfile lines 23-24. No change is required in
images/ansible-operator/Pipfile lines 8-11 because its lockfile already resolves
those entries exactly.

In `@openshift/hack/generate_requirements.md`:
- Around line 27-32: Add the `text` language identifier to the seven unlabeled
fenced code blocks in generate_requirements.md, including the blocks around the
listed sections, while preserving their existing diagram and content text.

In `@openshift/hack/generate_requirements.py`:
- Around line 452-468: Update the gap-splitting logic around split_after and
max_gap so it returns no split when the largest major/minor gap is zero,
including patch-only differences. Only compute and return the older group when
max_gap is greater than zero; preserve the existing split behavior for genuine
major/minor gaps.
- Around line 203-207: Update _min_safe_version to compare every matched
upper-bound version using packaging.version.Version and retain the maximum bound
rather than relying on the last regex match. Return the selected version in the
existing string format, preserving None when no upper bounds are found.
- Around line 625-629: The stage2_runtime_txt path setup around compile_in and
out_txt currently produces absolute # via annotations when --output-dir is /.
Make the compile input path relative to the process CWD (or update the comment
to accurately document --output-dir-dependent behavior), then regenerate
openshift/requirements-build.txt:5-6, openshift/requirements-pre-build.txt:5-6,
and openshift/requirements.txt:5-6 using a real subdirectory so their headers
and # via lines use relative paths.
🪄 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: 29944b7a-ce45-4d4b-a48f-d75ab87228fb

📥 Commits

Reviewing files that changed from the base of the PR and between 0a0c4c2 and d822aff.

⛔ Files ignored due to path filters (255)
  • go.sum is excluded by !**/*.sum
  • images/ansible-operator/Pipfile.lock is excluded by !**/*.lock
  • openshift/Pipfile.lock is excluded by !**/*.lock
  • vendor/cel.dev/expr/BUILD.bazel is excluded by !**/vendor/**, !vendor/**
  • vendor/cel.dev/expr/MODULE.bazel is excluded by !**/vendor/**, !vendor/**
  • vendor/cel.dev/expr/checked.pb.go is excluded by !**/*.pb.go, !**/vendor/**, !vendor/**
  • vendor/cel.dev/expr/eval.pb.go is excluded by !**/*.pb.go, !**/vendor/**, !vendor/**
  • vendor/cel.dev/expr/explain.pb.go is excluded by !**/*.pb.go, !**/vendor/**, !vendor/**
  • vendor/cel.dev/expr/syntax.pb.go is excluded by !**/*.pb.go, !**/vendor/**, !vendor/**
  • vendor/cel.dev/expr/value.pb.go is excluded by !**/*.pb.go, !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/ginkgo/v2/.gitignore is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/ginkgo/v2/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/ginkgo/v2/core_dsl.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/ginkgo/v2/ginkgo/command/program.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/ginkgo/v2/ginkgo/main.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/ginkgo.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/outline.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/ginkgo/v2/ginkgo/run/run_command.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/ginkgo/v2/ginkgo/watch/watch_command.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/ginkgo/v2/ginkgo_t_dsl.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/ginkgo/v2/helpergo_dsl.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/ginkgo/v2/internal/global/init.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/ginkgo/v2/internal/suite.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/ginkgo/v2/internal/testingtproxy/testing_t_proxy.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/ginkgo/v2/reporters/default_reporter.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/ginkgo/v2/types/config.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/ginkgo/v2/types/errors.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/ginkgo/v2/types/flags.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/ginkgo/v2/types/version.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/gomega/CHANGELOG.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/gomega/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/gomega/format/format.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/gomega/gomega_dsl.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/gomega/matchers.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/gomega/matchers/be_a_slice_matcher.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/gomega/matchers/be_an_array_matcher.go is excluded by !**/vendor/**, !vendor/**
  • vendor/github.com/onsi/gomega/types/types.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/.golangci.yml is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/CHANGELOG.md is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/CONTRIBUTING.md is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/Makefile is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/RELEASING.md is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/attribute/encoder.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/attribute/hash.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/attribute/internal/attribute.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/attribute/kv.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/attribute/type_string.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/attribute/value.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/baggage/baggage.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/dependencies.Dockerfile is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/internal/errorhandler/errorhandler.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/internal/global/handler.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/internal/global/state.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/metric/asyncfloat64.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/metric/asyncint64.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/metric/meter.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/metric/syncfloat64.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/metric/syncint64.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/propagation/baggage.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/propagation/trace_context.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/requirements.txt is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/sdk/internal/x/features.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/sdk/resource/builtin.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/sdk/resource/config.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/sdk/resource/container.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/sdk/resource/env.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/sdk/resource/host_id.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/sdk/resource/host_id_readfile.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/sdk/resource/os.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/sdk/resource/process.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/sdk/resource/resource.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/sdk/trace/batch_span_processor.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/sdk/trace/internal/observ/batch_span_processor.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/sdk/trace/internal/observ/simple_span_processor.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/sdk/trace/internal/observ/tracer.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/sdk/trace/provider.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/sdk/trace/sampling.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/sdk/trace/span.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/sdk/version.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/semconv/v1.39.0/MIGRATION.md is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/semconv/v1.39.0/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/semconv/v1.40.0/MIGRATION.md is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/semconv/v1.40.0/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/semconv/v1.40.0/attribute_group.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/semconv/v1.40.0/doc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/semconv/v1.40.0/error_type.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/semconv/v1.40.0/exception.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/semconv/v1.40.0/otelconv/metric.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/semconv/v1.40.0/schema.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/trace/auto.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/trace/trace.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/trace/tracestate.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/version.go is excluded by !**/vendor/**, !vendor/**
  • vendor/go.opentelemetry.io/otel/versions.yaml is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/html/iter.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/html/node.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/html/nodetype_string.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/http2/README.md is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/http2/client_conn_pool.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/http2/client_priority_go126.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/http2/client_priority_go127.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/http2/clientconn.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/http2/config.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/http2/frame.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/http2/http2.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/http2/server.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/http2/server_common.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/http2/server_wrap.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/http2/transport.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/http2/transport_common.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/http2/transport_wrap.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/http2/writesched.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/http2/writesched_common.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/http2/writesched_priority_rfc7540.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/http2/writesched_priority_rfc9218.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/http2/writesched_random.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/http2/writesched_roundrobin.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/idna/go118.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/idna/idna.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/idna/idna9.0.0.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/idna/pre_go118.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/idna/punycode.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/idna/tables10.0.0.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/idna/tables11.0.0.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/idna/tables12.0.0.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/idna/tables13.0.0.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/idna/tables15.0.0.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/idna/tables17.0.0.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/idna/tables9.0.0.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/idna/trie12.0.0.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/idna/trie13.0.0.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/internal/httpcommon/request.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/net/internal/httpsfv/httpsfv.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/oauth2/deviceauth.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/oauth2/oauth2.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/oauth2/pkce.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/oauth2/token.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/oauth2/transport.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sync/errgroup/errgroup.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sync/singleflight/singleflight.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sys/plan9/syscall_plan9.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sys/unix/affinity_linux.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sys/unix/ioctl_signed.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sys/unix/ioctl_unsigned.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sys/unix/mkall.sh is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sys/unix/syscall_linux.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sys/unix/syscall_linux_arm.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sys/unix/syscall_linux_arm64.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sys/unix/syscall_linux_loong64.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sys/unix/syscall_solaris.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sys/unix/syscall_unix.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sys/unix/zsyscall_linux.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sys/unix/ztypes_linux.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sys/windows/aliases.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sys/windows/dll_windows.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sys/windows/registry/key.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sys/windows/security_windows.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sys/windows/syscall_windows.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sys/windows/types_windows.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/sys/windows/zsyscall_windows.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/go/ast/edge/edge.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/go/ast/inspector/cursor.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/go/ast/inspector/inspector.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/go/ast/inspector/iter.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/go/packages/golist.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/go/packages/packages.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/go/types/objectpath/objectpath.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/aliases/aliases.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/aliases/aliases_go122.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/event/core/event.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/event/keys/keys.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/event/label/label.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/gcimporter/iexport.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/gcimporter/iimport.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/gcimporter/ureader.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/gocommand/version.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/imports/fix.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/imports/mod.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/imports/source_modindex.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/modindex/directories.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/modindex/index.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/modindex/lookup.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/modindex/modindex.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/modindex/symbols.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/pkgbits/version.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/stdlib/deps.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/typeparams/coretype.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/typeparams/free.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/typesinternal/types.go is excluded by !**/vendor/**, !vendor/**
  • vendor/golang.org/x/tools/internal/versions/features.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/CONTRIBUTING.md is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/balancer/balancer.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/balancer/pickfirst/internal/internal.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/balancer/pickfirst/pickfirst.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/balancer/subconn.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/balancer_wrapper.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go is excluded by !**/*.pb.go, !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/clientconn.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/credentials/credentials.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/credentials/tls.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/encoding/encoding.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/encoding/gzip/gzip.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/encoding/internal/internal.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/encoding/proto/proto.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/experimental/stats/metricregistry.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/experimental/stats/metrics.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/health/grpc_health_v1/health.pb.go is excluded by !**/*.pb.go, !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go is excluded by !**/*.pb.go, !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/interceptor.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/balancer/weight/weight.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/buffer/unbounded.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/channelz/trace.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/envconfig/envconfig.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/envconfig/xds.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/experimental.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/idle/idle.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/internal.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/resolver/delegatingresolver/delegatingresolver.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/stats/metrics_recorder_list.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/stats/stats.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/transport/client_stream.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/transport/controlbuf.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/transport/flowcontrol.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/transport/handler_server.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/transport/http2_client.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/transport/http2_server.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/transport/http_util.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/transport/server_stream.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/internal/transport/transport.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/mem/buffer_pool.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/mem/buffer_slice.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/mem/buffers.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/preloader.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/resolver/resolver.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/resolver_wrapper.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/rpc_util.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/server.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/stream.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/grpc/version.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/filedesc/desc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/internal/version/version.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/reflect/protodesc/desc.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go is excluded by !**/vendor/**, !vendor/**
  • vendor/google.golang.org/protobuf/reflect/protodesc/proto.go is excluded by !**/vendor/**, !vendor/**
  • vendor/modules.txt is excluded by !**/vendor/**, !vendor/**
📒 Files selected for processing (24)
  • .github/workflows/release.yml
  • .github/workflows/test-ansible.yml
  • .github/workflows/test-sanity.yml
  • .github/workflows/unit.yml
  • Makefile
  • go.mod
  • images/ansible-operator/Dockerfile
  • images/ansible-operator/Pipfile
  • images/ansible-operator/pipfile.Dockerfile
  • internal/version/version.go
  • openshift/Dockerfile.requirements
  • openshift/hack/generate_requirements.md
  • openshift/hack/generate_requirements.py
  • openshift/hack/rebase_upstream.sh
  • openshift/release/ansible/ansible_collections/cloud.common-3.0.0.info/GALAXY.yml
  • openshift/release/ansible/ansible_collections/community.docker-3.12.1.info/GALAXY.yml
  • openshift/release/ansible/ansible_collections/community.library_inventory_filtering_v1-1.1.5.info/GALAXY.yml
  • openshift/release/ansible/ansible_collections/kubernetes.core-3.2.0.info/GALAXY.yml
  • openshift/release/ansible/ansible_collections/operator_sdk.util-0.5.0.info/GALAXY.yml
  • openshift/requirements-build.txt
  • openshift/requirements-build1.txt
  • openshift/requirements-pre-build.txt
  • openshift/requirements.txt
  • testdata/memcached-molecule-operator/Makefile

steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v6
uses: actions/checkout@v7

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Occurrences of actions/checkout in workflow files:\n'
rg -n "actions/checkout@" .github/workflows

printf '\nRelevant file excerpts:\n'
for f in .github/workflows/release.yml .github/workflows/test-ansible.yml .github/workflows/test-sanity.yml .github/workflows/unit.yml; do
  echo "==== $f ===="
  nl -ba "$f" | sed -n '1,120p'
  echo
done

Repository: openshift/ansible-operator-plugins

Length of output: 736


Pin actions/checkout to full commit SHAs. @v7 is a mutable tag and leaves the workflow supply chain unpinned.

  • .github/workflows/release.yml (lines 28, 66)
  • .github/workflows/test-ansible.yml (lines 10, 23)
  • .github/workflows/test-sanity.yml (line 10)
  • .github/workflows/unit.yml (line 10)
📍 Affects 4 files
  • .github/workflows/release.yml#L28-L28 (this comment)
  • .github/workflows/release.yml#L66-L66
  • .github/workflows/test-ansible.yml#L10-L10
  • .github/workflows/test-ansible.yml#L23-L23
  • .github/workflows/test-sanity.yml#L10-L10
  • .github/workflows/unit.yml#L10-L10
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml at line 28, Pin every actions/checkout
invocation to a full immutable commit SHA instead of the mutable `@v7` tag: update
.github/workflows/release.yml at lines 28-28 and 66-66,
.github/workflows/test-ansible.yml at lines 10-10 and 23-23,
.github/workflows/test-sanity.yml at line 10, and .github/workflows/unit.yml at
line 10.

Source: Path instructions

Comment on lines +10 to 12
- uses: actions/checkout@v7
with:
fetch-depth: 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== Workflow files ==\n'
git ls-files .github/workflows/*.yml .github/workflows/*.yaml

printf '\n== Relevant checkout steps ==\n'
for f in .github/workflows/test-ansible.yml .github/workflows/test-sanity.yml .github/workflows/unit.yml; do
  echo "--- $f ---"
  nl -ba "$f" | sed -n '1,220p' | rg -n 'checkout|persist-credentials|fetch-depth|uses: actions/checkout'
done

Repository: openshift/ansible-operator-plugins

Length of output: 431


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for f in .github/workflows/test-ansible.yml .github/workflows/test-sanity.yml .github/workflows/unit.yml; do
  echo "--- $f ---"
  awk 'NR>=1 && NR<=220 { printf "%4d  %s\n", NR, $0 }' "$f" | sed -n '/actions\/checkout/,+6p'
done

Repository: openshift/ansible-operator-plugins

Length of output: 1217


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for f in .github/workflows/test-ansible.yml .github/workflows/test-sanity.yml .github/workflows/unit.yml; do
  echo "--- $f ---"
  awk 'NR>=1 && NR<=120 { printf "%4d  %s\n", NR, $0 }' "$f" | sed -n '1,80p'
done

Repository: openshift/ansible-operator-plugins

Length of output: 2284


Disable persisted checkout credentials in these test jobs.

Add persist-credentials: false to each actions/checkout step in .github/workflows/test-ansible.yml (both jobs), .github/workflows/test-sanity.yml, and .github/workflows/unit.yml; they only run tests after checkout, so keeping GITHUB_TOKEN in .git/config is unnecessary exposure.

🧰 Tools
🪛 zizmor (1.26.1)

[warning] 10-12: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

📍 Affects 3 files
  • .github/workflows/test-ansible.yml#L10-L12 (this comment)
  • .github/workflows/test-ansible.yml#L23-L25
  • .github/workflows/test-sanity.yml#L10-L12
  • .github/workflows/unit.yml#L10-L12
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/test-ansible.yml around lines 10 - 12, Add
persist-credentials: false to every actions/checkout step in
.github/workflows/test-ansible.yml at lines 10-12 and 23-25,
.github/workflows/test-sanity.yml at lines 10-12, and .github/workflows/unit.yml
at lines 10-12; no other workflow behavior needs changing.

Source: Linters/SAST tools

Comment thread go.mod
google.golang.org/protobuf v1.36.9 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect
google.golang.org/grpc v1.79.3 // indirect

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

GHSA-hrxh-6v49-42gf google.golang.org/grpc v1.79.3 advisory fixed version

💡 Result:

The security advisory GHSA-hrxh-6v49-42gf affects the google.golang.org/grpc package and identifies the fixed version as v1.82.1 [1][2][3]. The package version v1.79.3 is considered affected by this advisory, as the vulnerability impacts all versions of gRPC-Go prior to v1.82.1 [1][3][4]. Users are advised to upgrade their dependency to v1.82.1 or later to remediate the identified xDS RBAC and HTTP/2 transport vulnerabilities [1][3].

Citations:


Upgrade google.golang.org/grpc to v1.82.1 or later. v1.79.3 is affected by GHSA-hrxh-6v49-42gf and should not remain in the module build list.

🧰 Tools
🪛 OSV Scanner (2.4.0)

[HIGH] 110-110: google.golang.org/grpc 1.79.3: gRPC-Go: xDS RBAC and HTTP/2 Vulnerabilities

(GHSA-hrxh-6v49-42gf)

🤖 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 `@go.mod` at line 110, Update the google.golang.org/grpc dependency in go.mod
from v1.79.3 to v1.82.1 or later, and synchronize related module checksums or
dependency metadata so the module build list no longer includes the vulnerable
version.

Source: Linters/SAST tools

@@ -1,4 +1,4 @@
FROM registry.access.redhat.com/ubi9/ubi-minimal:9.7 AS basebuilder
FROM registry.access.redhat.com/ubi9/ubi-minimal:9.8 AS basebuilder

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== file listing =="
git ls-files images/ansible-operator/pipfile.Dockerfile images/ansible-operator | sed 's#^`#-` #'

echo
echo "== Dockerfile lines =="
cat -n images/ansible-operator/pipfile.Dockerfile

echo
echo "== related image/container files =="
fd -a -t f 'Dockerfile' images/ansible-operator || true
rg -n --hidden --glob '!**/.git/**' 'pip-airlock|pip-audit|USER |ENTRYPOINT|pip install|pip wheel|lockfile' images/ansible-operator || true

Repository: openshift/ansible-operator-plugins

Length of output: 3492


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== README =="
cat -n images/ansible-operator/README.md

echo
echo "== main Dockerfile USER/runtime bits =="
sed -n '1,120p' images/ansible-operator/Dockerfile | cat -n

echo
echo "== non-root / DS-0002 references =="
rg -n 'non-root|DS-0002|USER_UID|USER |root' images/ansible-operator

Repository: openshift/ansible-operator-plugins

Length of output: 5471


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
p = Path('images/ansible-operator/pipfile.Dockerfile')
text = p.read_text()
print("has USER instruction:", any(line.strip().startswith("USER ") for line in text.splitlines()))
print("has install pin for pip-audit:", 'pip-audit' in text and 'pip-audit==' in text)
print("has exact pip pin:", 'pip3 install --upgrade pip~=26.1.2' in text)
print("entrypoint:", [line for line in text.splitlines() if line.strip().startswith('ENTRYPOINT')][0])
PY

Repository: openshift/ansible-operator-plugins

Length of output: 330


Run the helper image as non-root. The ENTRYPOINT still executes cp as root; add a non-root user and keep /tmp/pip-airlock writable so the generated Pipfile.lock isn’t written back to the bind mount as root-owned.

🧰 Tools
🪛 Trivy (0.72.0)

[error] 1-1: Image user should not be 'root'

Specify at least 1 USER command in Dockerfile with non-root user as argument

Rule: DS-0002

Learn more

(IaC/Dockerfile)

🤖 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 `@images/ansible-operator/pipfile.Dockerfile` at line 1, Add a non-root user in
the basebuilder image, grant that user write access to /tmp/pip-airlock, and
configure the image to run as that user so the ENTRYPOINT cp operation does not
create root-owned Pipfile.lock files.

Sources: Path instructions, Linters/SAST tools

Comment on lines +33 to +34
# No package names are hardcoded in the script beyond the RPM exclusion list
# and the cachi2-specific wheel==0.45.1 pin in the pre-build phase.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Stale "hardcoded wheel pin" claim in two places. Build-isolation exact pins are now auto-discovered and probed against the pre-build constraint set (script Lines 824-884), so no wheel version is hardcoded; both descriptions still say otherwise.

  • openshift/Dockerfile.requirements#L33-L34: replace the "cachi2-specific wheel==0.45.1 pin" sentence with a note that isolation pins are auto-discovered from package metadata.
  • openshift/hack/generate_requirements.py#L5-L7: drop "and cachi2-specific pins" from the module docstring's list of hardcoded assumptions.
📍 Affects 2 files
  • openshift/Dockerfile.requirements#L33-L34 (this comment)
  • openshift/hack/generate_requirements.py#L5-L7
🤖 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 `@openshift/Dockerfile.requirements` around lines 33 - 34, Update the
documentation describing hardcoded package assumptions: in
openshift/Dockerfile.requirements lines 33-34, replace the cachi2-specific wheel
pin statement with a note that build-isolation pins are auto-discovered from
package metadata; in openshift/hack/generate_requirements.py lines 5-7, remove
“and cachi2-specific pins” from the module docstring while leaving the script
behavior unchanged.

Comment on lines +1062 to +1078
# safety lives inside the pipenv virtualenv; try several invocation forms
for safety_cmd in (
["pipenv", "run", "safety", "check", "-r", str(txt_path)],
["python3", "-m", "safety", "check", "-r", str(txt_path)],
["safety", "check", "-r", str(txt_path)],
):
check = subprocess.run(safety_cmd, capture_output=True, text=True)
if check.returncode != 1 or check.stderr.strip():
# returncode==1 with no stderr → not a "command not found"
break
if "No such file" in check.stderr or "not found" in check.stderr.lower():
continue # try next form
break

if check.returncode == 0:
print(f" No CVEs in {txt_path.name}")
continue

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

The Safety fallback chain is unreachable and can crash on a missing binary.

Two defects:

  • subprocess.run raises FileNotFoundError when the executable does not exist; it never returns a "command not found" return code. So python3 -m safety / bare safety forms will abort the script rather than fall through to the next form.
  • The break on Line 1071 fires whenever check.stderr is non-empty, which is exactly the case for a not-found error, so the "No such file" check on Line 1072 is dead code and the later forms are never tried.

Since Stage 5 runs after all requirement files are written, an unhandled exception here fails the Docker build and discards the generated artifacts.

🐛 Proposed fix
+        check = None
         for safety_cmd in (
             ["pipenv", "run", "safety", "check", "-r", str(txt_path)],
             ["python3", "-m", "safety", "check", "-r", str(txt_path)],
             ["safety", "check", "-r", str(txt_path)],
         ):
-            check = subprocess.run(safety_cmd, capture_output=True, text=True)
-            if check.returncode != 1 or check.stderr.strip():
-                # returncode==1 with no stderr → not a "command not found"
-                break
-            if "No such file" in check.stderr or "not found" in check.stderr.lower():
-                continue   # try next form
-            break
+            try:
+                check = subprocess.run(safety_cmd, capture_output=True, text=True)
+            except FileNotFoundError:
+                continue   # executable missing — try next form
+            if "No such file" in check.stderr or "not found" in check.stderr.lower():
+                continue   # try next form
+            break
+
+        if check is None:
+            print(
+                f"  WARNING: safety is not available; skipping CVE scan of {txt_path.name}.",
+                file=sys.stderr,
+            )
+            continue
📝 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.

Suggested change
# safety lives inside the pipenv virtualenv; try several invocation forms
for safety_cmd in (
["pipenv", "run", "safety", "check", "-r", str(txt_path)],
["python3", "-m", "safety", "check", "-r", str(txt_path)],
["safety", "check", "-r", str(txt_path)],
):
check = subprocess.run(safety_cmd, capture_output=True, text=True)
if check.returncode != 1 or check.stderr.strip():
# returncode==1 with no stderr → not a "command not found"
break
if "No such file" in check.stderr or "not found" in check.stderr.lower():
continue # try next form
break
if check.returncode == 0:
print(f" No CVEs in {txt_path.name}")
continue
# safety lives inside the pipenv virtualenv; try several invocation forms
check = None
for safety_cmd in (
["pipenv", "run", "safety", "check", "-r", str(txt_path)],
["python3", "-m", "safety", "check", "-r", str(txt_path)],
["safety", "check", "-r", str(txt_path)],
):
try:
check = subprocess.run(safety_cmd, capture_output=True, text=True)
except FileNotFoundError:
continue # executable missing — try next form
if "No such file" in check.stderr or "not found" in check.stderr.lower():
continue # try next form
break
if check is None:
print(
f" WARNING: safety is not available; skipping CVE scan of {txt_path.name}.",
file=sys.stderr,
)
continue
if check.returncode == 0:
print(f" No CVEs in {txt_path.name}")
continue
🧰 Tools
🪛 ast-grep (0.44.1)

[error] 1067-1067: Use of unsanitized data to create processes
Context: subprocess.run(safety_cmd, capture_output=True, text=True)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(os-system-unsanitized-data)


[error] 1067-1067: Command coming from incoming request
Context: subprocess.run(safety_cmd, capture_output=True, text=True)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)

🪛 Ruff (0.15.21)

[error] 1068-1068: subprocess call: check for execution of untrusted input

(S603)

🤖 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 `@openshift/hack/generate_requirements.py` around lines 1062 - 1078, Update the
Safety invocation loop around safety_cmd so missing executables are caught as
FileNotFoundError and the next command form is attempted. Remove the premature
stderr-based break and only stop when the command executes successfully or
produces a non-missing-command result, while preserving the existing return-code
handling and artifact generation flow.

Comment on lines +49 to +52
rebase_work_branch="$version"-rebase-"$rebase_branch"
if git show-ref --verify --quiet refs/heads/"$rebase_work_branch"; then
echo "Branch $rebase_work_branch already exists, reusing it (assuming any pre-staged commits, e.g. cherry-picks, are intentional)."
git checkout "$rebase_work_branch"

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

Synchronize reused branches with the updated base.

"$rebase_branch" was updated immediately before this block, but an existing "$rebase_work_branch" is checked out without verifying that it contains the updated base. On reruns after upstream changes, the resulting merge can omit commits from the target branch. Either merge the refreshed base into the reused branch or abort with a clear ancestry check.

🤖 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 `@openshift/hack/rebase_upstream.sh` around lines 49 - 52, Update the
existing-branch path in the rebase_work_branch reuse logic to ensure the
checked-out branch contains the refreshed rebase_branch before continuing. Merge
the updated base into the reused branch, or perform an ancestry check and abort
with a clear message when it is not based on the refreshed target.

Comment on lines +50 to +54
if git show-ref --verify --quiet refs/heads/"$rebase_work_branch"; then
echo "Branch $rebase_work_branch already exists, reusing it (assuming any pre-staged commits, e.g. cherry-picks, are intentional)."
git checkout "$rebase_work_branch"
else
git checkout -b "$rebase_work_branch" || { echo "Failed to create branch $rebase_work_branch."; popd ; exit 1; }

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

Abort when reusing the branch fails.

Unlike the branch-creation path, the existing-branch git checkout is unchecked. If checkout fails—for example because the branch is active in another worktree—the script continues and may merge and commit on the current branch.

🧰 Tools
🪛 Shellcheck (0.11.0)

[warning] 54-54: Use 'popd ... || exit' or 'popd ... || return' in case popd fails.

(SC2164)

🤖 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 `@openshift/hack/rebase_upstream.sh` around lines 50 - 54, Update the
existing-branch path around rebase_work_branch so git checkout failure aborts
the script immediately, matching the failure handling in the branch-creation
path. Preserve the current success behavior and ensure no merge or commit
proceeds when checkout fails.

Comment on lines +56 to +74
setuptools-rust==1.13.0
# via -r /requirements-build.in
setuptools-scm==10.2.1
# via
# -r /requirements-build.in
# hatch-vcs
trove-classifiers==2026.6.1.19
# via
# -r requirements-build.in
# -r /requirements-build.in
# hatchling
wheel==0.46.3
# via -r requirements-build.in
vcs-versioning==2.2.2
# via
# -r /requirements-build.in
# setuptools-scm
wheel==0.47.0
# via -r /requirements-build.in

# The following packages are considered to be unsafe in a requirements file:
setuptools==81.0.0
setuptools==82.0.1

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
for p in setuptools-rust:1.13.0 vcs-versioning:2.2.2 setuptools:82.0.1 wheel:0.47.0 setuptools-scm:10.2.1; do
  name="${p%%:*}"; ver="${p##*:}"
  echo "=== $name $ver"
  curl -s -X POST https://api.osv.dev/v1/query \
    -d "{\"package\":{\"name\":\"$name\",\"ecosystem\":\"PyPI\"},\"version\":\"$ver\"}" \
    | jq -r '.vulns[]?  | "\(.id): \(.summary // "-")"'
done

Repository: openshift/ansible-operator-plugins

Length of output: 444


🏁 Script executed:

python3 - <<'PY'
import json, urllib.request

advisories = ["GHSA-h35f-9h28-mq5c", "PYSEC-2026-3447"]
for adv in advisories:
    url = f"https://api.osv.dev/v1/vulns/{adv}"
    print(f"=== {adv}")
    try:
        data = json.load(urllib.request.urlopen(url))
    except Exception as e:
        print("ERR", e)
        continue
    print("summary:", data.get("summary"))
    for aff in data.get("affected", []):
        pkg = aff.get("package", {})
        print("package:", pkg.get("name"), pkg.get("ecosystem"))
        for r in aff.get("ranges", []):
            print("type:", r.get("type"))
            for ev in r.get("events", []):
                print(" event:", ev)
        print("versions:", aff.get("versions"))
    print("references:")
    for ref in data.get("references", []):
        print(" ", ref.get("type"), ref.get("url"))
PY

Repository: openshift/ansible-operator-plugins

Length of output: 492


Bump setuptools off 82.0.1 setuptools==82.0.1 has a published advisory; move to a patched release.

🤖 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 `@openshift/requirements-build.txt` around lines 56 - 74, Update the pinned
setuptools version in the requirements file from 82.0.1 to a patched release
that addresses the published advisory, keeping the existing unsafe-package entry
and formatting intact.

Source: Path instructions

Comment on lines +33 to 36
google-auth==2.55.0
# via
# -r requirements.in
# -r /requirements.in
# kubernetes

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

🧩 Analysis chain

🌐 Web query:

google-auth 2.55.0 Python dependencies rsa requirement

💡 Result:

In google-auth version 2.55.0, the rsa library is listed as a required dependency, with the version constraint defined as >=3.1.4 and <5 [1][2]. While google-auth has transitioned to using the cryptography library as its primary backend for RSA operations [3], rsa remained a required dependency in version 2.55.0 to maintain backward compatibility and support existing functionality [4][3][2]. The library uses internal wrapper classes (such as RSASigner and RSAVerifier) that can leverage either the cryptography library or the rsa library [5][3]. In subsequent development, the project has aimed to reduce and eventually remove this hard dependency on rsa, moving it toward optional status in newer versions of the library [3][6][2].

Citations:


🏁 Script executed:

set -euo pipefail

printf '\n[1] locate google-auth and rsa entries in openshift/requirements.txt\n'
rg -n '^(google-auth==|rsa==|pyasn1==|pyasn1-modules==)' openshift/requirements.txt || true

printf '\n[2] show the surrounding block around google-auth\n'
python3 - <<'PY'
from pathlib import Path
p = Path('openshift/requirements.txt')
lines = p.read_text().splitlines()
for i, line in enumerate(lines, 1):
    if line.startswith('google-auth==') or line.startswith('rsa=='):
        start = max(1, i-6)
        end = min(len(lines), i+8)
        print(f'\n--- lines {start}-{end} around line {i} ---')
        for j in range(start, end+1):
            print(f'{j:4}: {lines[j-1]}')
PY

printf '\n[3] check whether rsa appears anywhere in the file at all\n'
python3 - <<'PY'
from pathlib import Path
text = Path('openshift/requirements.txt').read_text()
print('rsa present:' , 'rsa==' in text or '\nrsa\n' in text or ' rsa' in text)
PY

Repository: openshift/ansible-operator-plugins

Length of output: 834


Restore rsa to the google-auth runtime set. google-auth==2.55.0 still requires rsa>=3.1.4,<5, but rsa is missing from openshift/requirements.txt while its sibling deps are still pinned. A hermetic install will fail when google-auth is imported.

🤖 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 `@openshift/requirements.txt` around lines 33 - 36, Update the pinned runtime
dependency set in requirements.txt by restoring the rsa package required by
google-auth==2.55.0, using the compatible rsa>=3.1.4,<5 constraint and retaining
the existing generated dependency annotations for the google-auth dependency
chain.

@openshift-ci

openshift-ci Bot commented Jul 26, 2026

Copy link
Copy Markdown

@mytreya-rh: 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.

@chiragkyal

Copy link
Copy Markdown
Member

/assign
/cc

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

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants