Skip to content

Downstream container-libs vendoring - #2066

Draft
bitoku wants to merge 3 commits into
openshift:masterfrom
bitoku:bitoku/downstream-container-libs-vendoring-for-cri-o
Draft

Downstream container-libs vendoring#2066
bitoku wants to merge 3 commits into
openshift:masterfrom
bitoku:bitoku/downstream-container-libs-vendoring-for-cri-o

Conversation

@bitoku

@bitoku bitoku commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Describe how downstream CRI-O will vendor a downstream fork of container-libs using Go module replace directives, ensuring alignment with the container-libs version shipped in the target RHEL release.

Assisted-by: Claude Code https://claude.com/claude-code

Summary by CodeRabbit

  • Documentation
    • Added a detailed enhancement proposal for downstream vendoring of container libraries in CRI-O.
    • Documented release, rebase, security-fix, backport, version-mapping, testing, upgrade, and support workflows.
    • Included guidance on compatibility, risks, alternatives, required infrastructure, and operational considerations.
    • Explained how downstream changes can be maintained while preserving alignment with upstream container-library updates.
    • No exported or public interfaces were changed.

…roposal

Describe how downstream CRI-O will vendor a downstream fork of
container-libs using Go module replace directives, ensuring alignment
with the container-libs version shipped in the target RHEL release.

Assisted-by: Claude Code <https://claude.com/claude-code>
@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jul 23, 2026
@openshift-ci

openshift-ci Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all


### Workflow Description

**CRI-O downstream maintainer** is a developer responsible for maintaining `openshift/cri-o`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Can we change the persona? Instead of "CRI-O downstream maintainer" can we say "OpenShift Node Team member". Then it cover a wider range of folks in the team and anyone can do it.

2. The `replace` directives in `openshift/cri-o`'s `go.mod` are updated to reference the new version. TODO: Evaluate automating this step (e.g., a bot that opens a PR when a new downstream container-libs release is tagged). In the interim, a CRI-O downstream maintainer performs this manually.
3. The maintainer runs `go mod tidy` and `go mod vendor`.
4. The maintainer submits a PR to `openshift/cri-o` with the updated vendor directory and `go.mod`/`go.sum`.
5. CI validates the build and runs tests.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Can we add a test in origin that will fail once RHEL updates the container-libs in podman? That will help to trigger the process of updating cri-o downstream?

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.

Thanks!
IMHO we should test semantic correctness (it behaves intentionally), rather than syntax correctness (it has the same version as podman), but it's worth mentioning here.

Comment thread enhancements/node/downstream-container-libs-vendoring-for-cri-o.md Outdated
…ment details

Fill in TODOs and resolve inconsistencies in the enhancement proposal:
- Add downstream container-libs repo link and concrete go.mod replace directives
- Expand user stories with specific personas, workflows, and rationale
- Add Dual Stream section covering RHEL 9/10 parity and future divergence handling
- Add Bug Fix / Feature Backport Workflow section
- Add RHEL Version Switch subsection to Upgrade/Downgrade Strategy
- Address version skew for dual-stream RHEL transitions
- Add container-libs version divergence detection test plan
- Fix Goal openshift#3 to not contradict dual-stream build tag/spec patching
- Clarify that MachineConfig-delivered custom configs may need updates on RHEL switch
- Correct upstream module paths to go.podman.io vanity imports
- Remove resolved open question about Go module proxy (already rejected in Alternatives)

Assisted-by: Claude Code <https://claude.com/claude-code>
@coderabbitai

coderabbitai Bot commented Jul 31, 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: 41662ff0-ddfa-4411-85ad-feaac14b30f7

📥 Commits

Reviewing files that changed from the base of the PR and between d38eeb8 and 6c52432.

📒 Files selected for processing (1)
  • enhancements/node/downstream-container-libs-vendoring-for-cri-o.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • enhancements/node/downstream-container-libs-vendoring-for-cri-o.md

Walkthrough

The enhancement proposes downstream CRI-O vendoring of a container-libs fork through Go module replace directives. It defines dependency workflows, version mapping, testing, upgrades, support procedures, risks, alternatives, and infrastructure requirements.

Changes

CRI-O container-libs vendoring

Layer / File(s) Summary
Proposal scope and objectives
enhancements/node/downstream-container-libs-vendoring-for-cri-o.md
Defines the downstream CRI-O context, container-libs alignment, user stories, goals, and non-goals.
Vendoring model and update workflows
enhancements/node/downstream-container-libs-vendoring-for-cri-o.md
Describes Go module replacements, version mapping, dependency updates, upstream rebases, security fixes, backports, implementation constraints, and CI access.
Validation and lifecycle support
enhancements/node/downstream-container-libs-vendoring-for-cri-o.md
Documents testing, divergence detection, upgrade and version-skew behavior, support procedures, alternatives, open questions, risks, and infrastructure requirements.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5 | ❌ 10

❌ Failed checks (10 inconclusive)

Check name Status Explanation Resolution
Stable And Deterministic Test Names ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Test Structure And Quality ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Microshift Test Compatibility ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Single Node Openshift (Sno) Test Compatibility ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Topology-Aware Scheduling Compatibility ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Ote Binary Stdout Contract ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Ipv6 And Disconnected Network Test Compatibility ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
No-Weak-Crypto ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Container-Privileges ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
No-Sensitive-Data-In-Logs ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: downstream vendoring of container-libs for CRI-O.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@openshift-ci

openshift-ci Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

[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 sdodson 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: 8

🤖 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 `@enhancements/node/downstream-container-libs-vendoring-for-cri-o.md`:
- Around line 78-85: Reconcile the “Non-Goals” statement with the
feature-backport workflow described near the fork scope and user story:
explicitly state whether feature backports are supported. If supported, update
the scope and non-goal to allow them; otherwise remove the feature-backport
workflow and its associated user story while retaining bug-fix-only
expectations.
- Around line 154-168: Narrow the “No impact” statements in the Hypershift /
Hosted Control Planes, Standalone Clusters, Single-node Deployments or
MicroShift, and OpenShift Kubernetes Engine sections to clarify that no
automatic cluster-level configuration edit is required. Explicitly note that
operators must review custom persisted storage.conf and containers.conf settings
when container-libs semantics change.
- Around line 127-137: Expand the “Security Fix Workflow” section to define the
embargoed-CVE release path before approval: identify the responsible owner,
turnaround target, private module/repository access, internal build and test
process, fast-track handling, and the post-embargo synchronization steps for the
public mirror and openshift/cri-o.
- Around line 88-104: Update the downstream CRI-O vendoring section to select
one dependency-source design instead of presenting an unresolved private-module
example. Document the exact replacement module paths and versions, whether
public CI resolves upstream dependencies or private forks, and how credentials
are supplied for private repositories; ensure the design is consistent with the
test plan and the RPM-patching alternative.
- Around line 60-64: Add an authoritative RHEL-stream version matrix to the
document, defining immutable downstream-container-libs versions or commits,
per-stream Go module replace inputs, and the expected vendored outputs. Specify
CI checks that validate the selected inputs and generated vendor contents; do
not imply build tags select go.mod replace directives. If stream-specific module
selection requires automation, document that separate step and update the
no-custom-tooling claim accordingly.
- Around line 368-372: Expand the “Version Skew Strategy” section to define the
storage migration contract for each supported RHEL/container-libs transition,
add mixed-version storage compatibility tests covering those transitions within
the same OCP release, and document explicit node recovery and rollback
procedures for migration failures, including the existing rollback TODO.
- Around line 5-15: Replace the TODO placeholder values in the reviewers,
approvers, and tracking-link fields with actual content before merging. For the
reviewers and approvers fields, substitute the TODO comments with a list of
actual GitHub usernames who should review and approve this enhancement. For the
tracking-link field, replace the TODO comment with a valid tracking ticket URL.
The api-approvers field is already correctly configured and does not require
changes.
- Around line 221-225: Define explicit replacement precedence rules for the
three Go modules (go.podman.io/common, go.podman.io/storage, and
go.podman.io/image/v5) in the document to establish which replacement directive
is authoritative. Add CI validation checks that verify the effective
replacements applied in go.mod match the intended precedence and that the
resulting vendor/modules.txt reflects the correct resolved replacements,
preventing text merge conflicts from introducing valid but incorrect module
versions.
🪄 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: 96eb04f2-3028-45f2-9a1f-86584b2e7eaf

📥 Commits

Reviewing files that changed from the base of the PR and between 23373e1 and d38eeb8.

📒 Files selected for processing (1)
  • enhancements/node/downstream-container-libs-vendoring-for-cri-o.md

Comment on lines +5 to +15
reviewers:
- TODO: Identify reviewers
approvers:
- TODO: Identify approvers
api-approvers:
- None
creation-date: 2026-07-23
last-updated: 2026-07-23
status: informational
tracking-link:
- TODO: Add tracking link

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

# Find and read the enhancement file
cd enhancements/node && head -20 downstream-container-libs-vendoring-for-cri-o.md

Repository: openshift/enhancements

Length of output: 509


🏁 Script executed:

# Find the enhancement schema definition in the repository
find . -name "*.yaml" -o -name "*.yml" | xargs grep -l "reviewers\|approvers" 2>/dev/null | head -5

Repository: openshift/enhancements

Length of output: 160


🏁 Script executed:

# Look for schema files that validate enhancements
find . -type f \( -name "*.md" -o -name "*.yaml" -o -name "*.yml" \) | xargs grep -l "enhancement.*schema\|kep.*template" 2>/dev/null | head -5

Repository: openshift/enhancements

Length of output: 404


🏁 Script executed:

# Test YAML parsing of the pattern in question
python3 - <<'PY'
import yaml

# Test 1: Current pattern with TODO: (space after colon)
yaml_with_todo_space = """
reviewers:
  - TODO: Identify reviewers
approvers:
  - TODO: Identify approvers
"""

# Test 2: Quoted version
yaml_quoted = """
reviewers:
  - "TODO: Identify reviewers"
approvers:
  - "TODO: Identify approvers"
"""

# Test 3: Plain TODO without colon
yaml_plain = """
reviewers:
  - TODO
approvers:
  - TODO
"""

try:
    result1 = yaml.safe_load(yaml_with_todo_space)
    print("Pattern 1 (TODO: with space) parsed as:")
    print(result1)
    print("\nType of reviewers list item:", type(result1['reviewers'][0]), repr(result1['reviewers'][0]))
except Exception as e:
    print(f"Pattern 1 failed: {e}")

print("\n" + "="*50 + "\n")

try:
    result2 = yaml.safe_load(yaml_quoted)
    print("Pattern 2 (quoted) parsed as:")
    print(result2)
    print("\nType of reviewers list item:", type(result2['reviewers'][0]), repr(result2['reviewers'][0]))
except Exception as e:
    print(f"Pattern 2 failed: {e}")

print("\n" + "="*50 + "\n")

try:
    result3 = yaml.safe_load(yaml_plain)
    print("Pattern 3 (plain TODO) parsed as:")
    print(result3)
    print("\nType of reviewers list item:", type(result3['reviewers'][0]), repr(result3['reviewers'][0]))
except Exception as e:
    print(f"Pattern 3 failed: {e}")
PY

Repository: openshift/enhancements

Length of output: 277


🏁 Script executed:

# Install PyYAML and test YAML parsing
pip install PyYAML -q && python3 - <<'PY'
import yaml

# Test 1: Current pattern with TODO: (space after colon)
yaml_with_todo_space = """
reviewers:
  - TODO: Identify reviewers
approvers:
  - TODO: Identify approvers
"""

# Test 2: Quoted version
yaml_quoted = """
reviewers:
  - "TODO: Identify reviewers"
approvers:
  - "TODO: Identify approvers"
"""

# Test 3: Plain TODO without colon
yaml_plain = """
reviewers:
  - TODO
approvers:
  - TODO
"""

try:
    result1 = yaml.safe_load(yaml_with_todo_space)
    print("Pattern 1 (TODO: with space) parsed as:")
    print(result1)
    print("Type of reviewers list item:", type(result1['reviewers'][0]), "Value:", repr(result1['reviewers'][0]))
except Exception as e:
    print(f"Pattern 1 failed: {e}")

print("\n" + "="*50 + "\n")

try:
    result2 = yaml.safe_load(yaml_quoted)
    print("Pattern 2 (quoted) parsed as:")
    print(result2)
    print("Type of reviewers list item:", type(result2['reviewers'][0]), "Value:", repr(result2['reviewers'][0]))
except Exception as e:
    print(f"Pattern 2 failed: {e}")

print("\n" + "="*50 + "\n")

try:
    result3 = yaml.safe_load(yaml_plain)
    print("Pattern 3 (plain TODO) parsed as:")
    print(result3)
    print("Type of reviewers list item:", type(result3['reviewers'][0]), "Value:", repr(result3['reviewers'][0]))
except Exception as e:
    print(f"Pattern 3 failed: {e}")
PY

Repository: openshift/enhancements

Length of output: 1001


🏁 Script executed:

# Search for validation scripts or CI checks that process enhancement files
find . -type f \( -name "*.sh" -o -name "*.py" -o -name "Makefile" \) | xargs grep -l "enhancement\|kep" 2>/dev/null | head -10

Repository: openshift/enhancements

Length of output: 284


🏁 Script executed:

# Look for any README or documentation about enhancement format
find . -maxdepth 2 -type f -name "README*" | xargs cat 2>/dev/null | head -100

Repository: openshift/enhancements

Length of output: 3439


🏁 Script executed:

# Find and read the enhancement template
find . -name "enhancement_template.md" -o -name "*template*" -type f | head -10

Repository: openshift/enhancements

Length of output: 221


🏁 Script executed:

# Look for the template file more broadly
find . -path ./tools -prune -o -type f -name "*.md" -print | xargs grep -l "template" | head -5

Repository: openshift/enhancements

Length of output: 321


🏁 Script executed:

# Check the template-lint.sh script to see how enhancements are validated
cat ./hack/template-lint.sh

Repository: openshift/enhancements

Length of output: 1640


🏁 Script executed:

# Use standard YAML knowledge to test the pattern
# In YAML: "TODO: Identify reviewers" at list item level is parsed as a string
# The colon syntax only creates a mapping if there's a key-value pair on the same/nested level
cat > /tmp/test_yaml.txt <<'EOF'
Test 1 - Current format (TODO: with space):
reviewers:
  - TODO: Identify reviewers

This is valid YAML and parses as:
- reviewers is a key
- Its value is a list with one string item: "TODO: Identify reviewers"
- The string is NOT a mapping; "TODO:" and "Identify reviewers" are part of one string value

Test 2 - If parsed as mapping (which it wouldn't be):
This would only happen if written as:
  - TODO: Identify reviewers
    (as a nested structure with proper indentation for a key-value pair)
But that's not the case here.

The YAML spec says: in a list item, "TODO: ..." is a string unless it's 
properly formatted as a mapping with indentation indicating a nested key-value.

Conclusion: The current pattern IS valid YAML and parses correctly as a string.
EOF
cat /tmp/test_yaml.txt

Repository: openshift/enhancements

Length of output: 924


🏁 Script executed:

# Read the enhancement template to see what the schema expects
head -50 ./guidelines/enhancement_template.md

Repository: openshift/enhancements

Length of output: 3549


🏁 Script executed:

# Check the full front matter section of the template
sed -n '1,40p' ./guidelines/enhancement_template.md

Repository: openshift/enhancements

Length of output: 2997


🏁 Script executed:

# Look for any YAML schema validation files
find . -type f \( -name "*.json" -o -name "*.schema" -o -name "*schema*" \) 2>/dev/null | head -10

Repository: openshift/enhancements

Length of output: 160


Replace incomplete placeholder values with actual reviewer and approver names.

The fields reviewers, approvers, and tracking-link use TODO: placeholders that must be filled before this enhancement is merged. Use the template convention: assign actual GitHub usernames for reviewers and approvers, and provide a tracking ticket URL for tracking-link. The api-approvers field is correctly set to None.

🤖 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 `@enhancements/node/downstream-container-libs-vendoring-for-cri-o.md` around
lines 5 - 15, Replace the TODO placeholder values in the reviewers, approvers,
and tracking-link fields with actual content before merging. For the reviewers
and approvers fields, substitute the TODO comments with a list of actual GitHub
usernames who should review and approve this enhancement. For the tracking-link
field, replace the TODO comment with a valid tracking ticket URL. The
api-approvers field is already correctly configured and does not require
changes.

Comment on lines +60 to +64
- As a Node team member, I want downstream CRI-O to vendor the downstream container-libs so that the container libraries match those shipped with the target RHEL release, avoiding incompatibilities between the container runtime and RHEL host configuration files (e.g., `storage.conf`, `containers.conf`, `registries.conf`, `policy.json`).

- As a Node team member or release engineer, I want the vendoring relationship managed via Go module `replace` directives so the build process is straightforward and reproducible, with no custom build tooling required beyond standard `go mod tidy` and `go mod vendor`.

- As a Node team member, I want a clear process for updating container-libs versions in downstream CRI-O so that when RHEL ships a new container-libs version, I know exactly which steps to follow — update `replace` directives, run `go mod tidy`/`go mod vendor`, submit a PR — and can do so without deep knowledge of the container-libs internals.

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
file="enhancements/node/downstream-container-libs-vendoring-for-cri-o.md"
printf '%s\n' '--- file outline ---'
ast-grep outline "$file" 2>/dev/null || true
printf '%s\n' '--- relevant sections ---'
sed -n '1,280p' "$file"
printf '%s\n' '--- repository references ---'
rg -n -S 'container-libs|RHEL 9\.8|RHEL 10\.2|go mod tidy|go mod vendor|replace directive|build tag|special handling' . --glob '!vendor/**' --glob '!node_modules/**' | head -300

Repository: openshift/enhancements

Length of output: 46431


🏁 Script executed:

#!/bin/bash
set -eu
file="enhancements/node/downstream-container-libs-vendoring-for-cri-o.md"
printf '%s\n' '--- CI, alternatives, and conclusions ---'
sed -n '280,410p' "$file"
printf '%s\n' '--- targeted structural checks ---'
python3 - "$file" <<'PY'
from pathlib import Path
import re, sys

text = Path(sys.argv[1]).read_text()
checks = {
    "explicit RHEL mapping TODO": r"TODO: Add an explicit downstream container-libs version to RHEL version mapping table",
    "second mapping TODO": r"TODO: Determine the RHEL version to container-libs version mapping",
    "dual-stream same-version assertion": r"OCP 5\.0–5\.2 targets both RHEL 9\.8 and RHEL 10\.2.*?same container-libs version",
    "go.mod patching option": r"\*\*`go\.mod` patching:\*\*.*?replace.*?patched and re-vendored",
    "build-tags option": r"\*\*Go build tags:\*\*.*?go build -tags el10",
    "standard commands claim": r"no custom build tooling required beyond standard `go mod tidy` and `go mod vendor`",
    "CI source-of-truth gap": r"Requires a reliable source of truth for Podman's container-libs version",
}
for name, pattern in checks.items():
    match = re.search(pattern, text, re.S)
    print(f"{name}: {'present' if match else 'absent'}")
PY

Repository: openshift/enhancements

Length of output: 8760


🌐 Web query:

Go command documentation: whether build tags select or alter go.mod module replace directives, and how module replacement is chosen during go mod operations

💡 Result:

Build tags (also known as build constraints) do not affect, select, or alter the replace directives in a go.mod file [1][2]. The go.mod file and its dependency graph, including all require, replace, and exclude directives, are resolved by the Go command before and independently of the build process that evaluates build tags [3][4]. Build tags are used during the compilation phase to determine which source files are included in a package for the target platform or configuration [5][6], but they do not influence which versions of modules are loaded into the build list or how module replacements are applied [2][3]. Regarding how module replacement is chosen during go mod operations: 1. Scope: replace directives are only honored when they appear in the main module's go.mod file or a go.work file [7][8]. They are explicitly ignored in the go.mod files of dependencies [7][8]. 2. Resolution: A replace directive does not independently add a module to the module graph; it only takes effect if the module path (and optionally the version) on the left side of the directive is already required by the build [7][8][9]. 3. Precedence: When go.work files are used, a replace directive in the go.work file will override any version-specific replace directive in a go.mod file [8]. 4. Mechanism: Go uses Minimal Version Selection (MVS) to build the dependency graph [3][4]. The go command resolves the required versions first, and if a module is flagged for replacement, the Go toolchain simply redirects the search for that module's source code to the specified local directory or alternative module path [7][10]. This substitution happens at the file system or module resolution level, not based on build-time tags [7][8]. Because build tags are not recorded in go.mod [2], the go command cannot automatically know which tags might be required to build a dependency correctly [1][11]. Consequently, build-specific configuration—such as requiring different dependencies based on build tags—cannot be managed through go.mod directives [2].

Citations:


Add an authoritative RHEL-stream version matrix and define the build inputs.

The document leaves the RHEL-to-downstream-container-libs mapping as TODO and provides no immutable version or commit source of truth. Add per-stream replace inputs, expected vendor outputs, and CI checks. Build tags select source files; they do not select go.mod replace directives. If streams diverge, document and automate a separate module-selection step, or remove the no-custom-tooling claim.

🧰 Tools
🪛 LanguageTool

[style] ~64-~64: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...d go mod tidy and go mod vendor. - As a Node team member, I want a clear proc...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~64-~64: Consider a different adjective to strengthen your wording.
Context: ...r`, submit a PR — and can do so without deep knowledge of the container-libs interna...

(DEEP_PROFOUND)

🤖 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 `@enhancements/node/downstream-container-libs-vendoring-for-cri-o.md` around
lines 60 - 64, Add an authoritative RHEL-stream version matrix to the document,
defining immutable downstream-container-libs versions or commits, per-stream Go
module replace inputs, and the expected vendored outputs. Specify CI checks that
validate the selected inputs and generated vendor contents; do not imply build
tags select go.mod replace directives. If stream-specific module selection
requires automation, document that separate step and update the
no-custom-tooling claim accordingly.

Comment thread enhancements/node/downstream-container-libs-vendoring-for-cri-o.md
Comment thread enhancements/node/downstream-container-libs-vendoring-for-cri-o.md
Comment on lines +127 to +137
#### Security Fix Workflow

When a CVE or security fix is needed in container-libs:

1. The fix is applied to the downstream container-libs fork (backported from upstream if applicable).
2. A new downstream container-libs version is tagged.
3. The container-libs version update workflow (above) is followed to pull the fix into downstream CRI-O.

For embargoed CVEs, the fix cannot be pushed to any public repository (including a GitHub mirror of container-libs, if used) until the embargo is lifted. During the embargo period, the fix is built and tested through internal processes only. Once the embargo is lifted, the public mirror and `openshift/cri-o` are updated following the standard workflow.

TODO: Clarify the expected turnaround time for security fixes and whether there is a fast-track process. Define the specific embargo workflow with the security response team.

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 | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
file="enhancements/node/downstream-container-libs-vendoring-for-cri-o.md"
printf '%s\n' '--- file outline ---'
ast-grep outline "$file" 2>/dev/null || true
printf '%s\n' '--- requested sections ---'
sed -n '100,155p' "$file"
sed -n '210,245p' "$file"
printf '%s\n' '--- related workflow and embargo references ---'
rg -n -i -C 3 'embargo|security fix|container-libs|vendoring|private module|fast.track|turnaround|disclosure' enhancements .github 2>/dev/null | head -n 300

Repository: openshift/enhancements

Length of output: 40184


🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- repository files related to the design ---'
git ls-files | rg -i 'container.libs|cri.o|security|vendoring|embargo|release'
printf '%s\n' '--- document headings and references ---'
rg -n '^#{1,6} |container-libs|CRI-O|CVE|embargo' enhancements/node/downstream-container-libs-vendoring-for-cri-o.md

Repository: openshift/enhancements

Length of output: 22138


Define the embargoed-CVE release path before approval.

Document the owner, turnaround target, private module access, internal build and test path, fast-track process, and post-embargo synchronization between the public mirror and openshift/cri-o.

🤖 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 `@enhancements/node/downstream-container-libs-vendoring-for-cri-o.md` around
lines 127 - 137, Expand the “Security Fix Workflow” section to define the
embargoed-CVE release path before approval: identify the responsible owner,
turnaround target, private module/repository access, internal build and test
process, fast-track handling, and the post-embargo synchronization steps for the
public mirror and openshift/cri-o.

Comment on lines +154 to +168
#### Hypershift / Hosted Control Planes

No impact. This is a build-time vendoring change. CRI-O runs on worker nodes regardless of control plane topology.

#### Standalone Clusters

No impact beyond the CRI-O binary shipping with updated container-libs.

#### Single-node Deployments or MicroShift

No impact. The change is limited to which container-libs version is compiled into the CRI-O binary.

#### OpenShift Kubernetes Engine

No impact. CRI-O is part of the base platform available to both OCP and OKE.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Narrow the “no impact” statements.

The document says that upgrades require no configuration changes, but it also states that persisted storage.conf and containers.conf may need updates when container-libs semantics change. State that no automatic cluster-level edit is required, while custom configuration still requires operator review.

Also applies to: 358-364

🤖 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 `@enhancements/node/downstream-container-libs-vendoring-for-cri-o.md` around
lines 154 - 168, Narrow the “No impact” statements in the Hypershift / Hosted
Control Planes, Standalone Clusters, Single-node Deployments or MicroShift, and
OpenShift Kubernetes Engine sections to clarify that no automatic cluster-level
configuration edit is required. Explicitly note that operators must review
custom persisted storage.conf and containers.conf settings when container-libs
semantics change.

Comment on lines +221 to +225
**Risk:** A container-libs update introduces a regression in downstream CRI-O.
**Mitigation:** Revert to the previous container-libs version via a rollback patch and release a new CRI-O build. TODO: Define the specific rollback process.

**Risk:** The `replace` directives conflict with other downstream patches in `openshift/cri-o` that also modify `go.mod`.
**Mitigation:** Go module `replace` directives are additive and well-understood. Conflicts are resolved through standard `go.mod` merge practices.

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

file="enhancements/node/downstream-container-libs-vendoring-for-cri-o.md"

printf '%s\n' '--- target file context ---'
sed -n '1,280p' "$file"

printf '%s\n' '--- container-libs and replacement references ---'
rg -n -i -C 3 'container-libs|replace|vendor|go\.mod|cri-o' --glob '!vendor/**' --glob '!node_modules/**' .

printf '%s\n' '--- repository files related to CI and vendoring ---'
git ls-files | rg -i '(^|/)(go\.mod|go\.sum|vendor/|\.github/|ci|test|container-libs|cri-o)' | head -300

Repository: openshift/enhancements

Length of output: 50381


🏁 Script executed:

#!/bin/bash
set -eu

file="enhancements/node/downstream-container-libs-vendoring-for-cri-o.md"

printf '%s\n' '--- target section ---'
sed -n '190,245p' "$file"

printf '%s\n' '--- exact references in target file ---'
rg -n -i -C 4 'container-libs|replace|vendor|go\.mod|module' "$file"

printf '%s\n' '--- repository-level exact references ---'
rg -n -i 'container-libs|github.com/.*/(containers|storage|image|ocicrypt)|go\.mod|vendor/modules\.txt' --glob '!enhancements/**' --glob '!vendor/**' --glob '!node_modules/**' . | head -300

printf '%s\n' '--- tracked CI and policy files ---'
git ls-files | rg '^(\.github/|hack/|Makefile|Makefile\.)' | head -300

Repository: openshift/enhancements

Length of output: 50380


🌐 Web query:

Official Go documentation for replace directives with duplicate/conflicting replacements, and for vendor/modules.txt consistency checks when using -mod=vendor

💡 Result:

In Go, the replace directive in a go.mod file is used to redirect module resolution, allowing you to substitute a module path and version with another module or a local filesystem path [1][2]. Duplicate or Conflicting Replace Directives When multiple replace directives target the same module, the Go toolchain does not strictly forbid them in the syntax, but it applies specific rules for resolution. - A replace directive with a version (e.g., example.com/mod v1.0.0 =>...) is more specific than one without a version (example.com/mod =>...). The specific, versioned replacement takes precedence when the corresponding version is selected by the module solver [3]. - If you have multiple conflicting directives (such as replacing the same version with different targets), the Go toolchain typically processes them sequentially, but rely on them being deterministic is not advised; generally, the most specific match for the required version is used [1][3]. - In a workspace context (go.work), a replace directive in the go.work file overrides any replace directive for the same module or version in the individual module's go.mod file [1][4]. Consistency Checks for vendor/modules.txt When using -mod=vendor, the Go command requires the vendor/modules.txt file to be strictly consistent with the go.mod (and go.work) files [5]. This consistency check ensures that the dependencies recorded in vendor/modules.txt accurately reflect the dependency graph, including all replacements [6][5]. The Go command will report an error if: - A module is required in go.mod but not marked as explicit in vendor/modules.txt [7]. - A replacement exists in go.mod but is missing from vendor/modules.txt [7]. - A replacement target in vendor/modules.txt differs from the replacement specified in go.mod [7]. - A replacement is recorded in vendor/modules.txt but does not exist in go.mod [7]. If inconsistencies are detected, the go command will fail the build with an error message indicating the discrepancy and suggesting that you run 'go mod vendor' (or 'go work vendor' in a workspace) to synchronize the vendor directory with the current module configuration [7][5].

Citations:


🏁 Script executed:

#!/bin/bash
set -eu

file="enhancements/node/downstream-container-libs-vendoring-for-cri-o.md"

printf '%s\n' '--- document invariants ---'
python3 - "$file" <<'PY'
import re, sys
from pathlib import Path

text = Path(sys.argv[1]).read_text()
expected = [
    "go.podman.io/common",
    "go.podman.io/storage",
    "go.podman.io/image/v5",
]
block = re.search(r"```go\nreplace \(\n(.*?)\n\)\n```", text, re.S)
assert block, "replace block not found"
found = re.findall(r"^\s*(go\.podman\.io/\S+)\s+=>", block.group(1), re.M)
print("replace module paths:", found)
print("all three present:", found == expected)
print("mitigation says additive:", "replace` directives are additive" in text)
print("CI/vendor metadata requirement present:",
      "vendor/modules.txt" in text and "effective replacement" in text)

printf '%s\n' '--- synthetic duplicate replacement parse ---'
if command -v go >/dev/null 2>&1; then
    d="$(mktemp -d)"
    trap 'rm -rf "$d"' EXIT
    cat >"$d/duplicate.mod" <<'EOF'
module example.com/main

go 1.20

require example.com/a v1.0.0

replace example.com/a => ../a
replace example.com/a => ../b
EOF
    if go mod edit -json -modfile="$d/duplicate.mod" >/tmp/duplicate-replace.json 2>/tmp/duplicate-replace.err; then
        echo "duplicate unversioned replacements: accepted"
        cat /tmp/duplicate-replace.json
    else
        echo "duplicate unversioned replacements: rejected"
        cat /tmp/duplicate-replace.err
    fi
else
    echo "go tool: unavailable"
fi

Repository: openshift/enhancements

Length of output: 408


🏁 Script executed:

#!/bin/bash
set -eu

file="enhancements/node/downstream-container-libs-vendoring-for-cri-o.md"

python3 - "$file" <<'PY'
import re
import shutil
import subprocess
import sys
import tempfile
from pathlib import Path

text = Path(sys.argv[1]).read_text()
expected = [
    "go.podman.io/common",
    "go.podman.io/storage",
    "go.podman.io/image/v5",
]
block = re.search(r"```go\nreplace \(\n(.*?)\n\)\n```", text, re.S)
assert block, "replace block not found"
found = re.findall(r"^\s*(go\.podman\.io/\S+)\s+=>", block.group(1), re.M)
print("replace module paths:", found)
print("all three present:", found == expected)
print("mitigation says additive:", "replace` directives are additive" in text)
print("CI/vendor metadata requirement present:",
      "vendor/modules.txt" in text and "effective replacement" in text)

go = shutil.which("go")
if not go:
    print("go tool: unavailable")
    raise SystemExit

with tempfile.TemporaryDirectory() as d:
    modfile = Path(d) / "duplicate.mod"
    modfile.write_text(
        "module example.com/main\n\n"
        "go 1.20\n\n"
        "require example.com/a v1.0.0\n\n"
        "replace example.com/a => ../a\n"
        "replace example.com/a => ../b\n"
    )
    result = subprocess.run(
        [go, "mod", "edit", "-json", f"-modfile={modfile}"],
        text=True,
        capture_output=True,
        check=False,
    )
    print("duplicate unversioned replacements accepted:", result.returncode == 0)
    if result.returncode:
        print(result.stderr.strip())
    else:
        print(result.stdout.strip())
PY

Repository: openshift/enhancements

Length of output: 517


🏁 Script executed:

#!/bin/bash
set -eu

python3 - <<'PY'
import shutil
import subprocess
import tempfile
from pathlib import Path

go = shutil.which("go")
if not go:
    print("go tool: unavailable")
    raise SystemExit

cases = {
    "duplicate unversioned replacements": (
        "replace example.com/a => ../a\n"
        "replace example.com/a => ../b\n"
    ),
    "version-scoped replacements": (
        "replace example.com/a v1.0.0 => ../a\n"
        "replace example.com/a v1.0.0 => ../b\n"
    ),
}
for name, replacements in cases.items():
    with tempfile.TemporaryDirectory() as d:
        root = Path(d)
        (root / "duplicate.mod").write_text(
            "module example.com/main\n\n"
            "go 1.20\n\n"
            "require example.com/a v1.0.0\n\n"
            + replacements
        )
        result = subprocess.run(
            [go, "mod", "edit", "-json", "-modfile=duplicate.mod"],
            cwd=d,
            text=True,
            capture_output=True,
            check=False,
        )
        print(f"{name} accepted:", result.returncode == 0)
        if result.returncode:
            print(result.stderr.strip())
        else:
            print(result.stdout.strip())
PY

Repository: openshift/enhancements

Length of output: 475


🏁 Script executed:

#!/bin/bash
set -eu

python3 - <<'PY'
import shutil
import subprocess
import tempfile
from pathlib import Path

go = shutil.which("go")
if not go:
    print("go tool: unavailable")
    raise SystemExit

cases = {
    "duplicate unversioned replacements": (
        "replace example.com/a => ../a\n"
        "replace example.com/a => ../b\n"
    ),
    "version-scoped replacements": (
        "replace example.com/a v1.0.0 => ../a\n"
        "replace example.com/a v1.0.0 => ../b\n"
    ),
}
for name, replacements in cases.items():
    with tempfile.TemporaryDirectory() as d:
        root = Path(d)
        (root / "go.mod").write_text("module example.com/main\n\ngo 1.20\n")
        (root / "duplicate.mod").write_text(
            "module example.com/main\n\n"
            "go 1.20\n\n"
            "require example.com/a v1.0.0\n\n"
            + replacements
        )
        result = subprocess.run(
            [go, "mod", "edit", "-json", "-modfile=duplicate.mod"],
            cwd=d,
            text=True,
            capture_output=True,
            check=False,
        )
        print(f"{name} accepted:", result.returncode == 0)
        if result.returncode:
            print(result.stderr.strip())
        else:
            print(result.stdout.strip())
PY

Repository: openshift/enhancements

Length of output: 912


🏁 Script executed:

#!/bin/bash
set -eu

python3 - <<'PY'
import shutil
import subprocess
import tempfile
from pathlib import Path

go = shutil.which("go")
if not go:
    print("go tool: unavailable")
    raise SystemExit

modules = {
    "go.podman.io/common": "common",
    "go.podman.io/storage": "storage",
    "go.podman.io/image/v5": "image",
}

with tempfile.TemporaryDirectory() as d:
    root = Path(d)
    replacements = []
    imports = []
    for index, (path, package) in enumerate(modules.items(), 1):
        source = root / f"source-{index}"
        source.mkdir()
        (source / "go.mod").write_text(f"module {path}\n\ngo 1.20\n")
        (source / f"{package}.go").write_text(
            f"package {package}\n\nfunc Value() string {{ return \"{package}\" }}\n"
        )
        replacements.append(f"    {path} => {source}\n")
        imports.append(f'    "{path}"\n')

    (root / "go.mod").write_text(
        "module example.com/main\n\n"
        "go 1.20\n\n"
        + "".join(f"require {path} v0.0.0\n" for path in modules)
        + "\nreplace (\n"
        + "".join(replacements)
        + ")\n"
    )
    (root / "main.go").write_text(
        "package main\n\nimport (\n"
        + "".join(imports)
        + ")\n\nfunc main() { _ = common.Value; _ = storage.Value; _ = image.Value }\n"
    )

    vendor = subprocess.run(
        [go, "mod", "vendor"],
        cwd=root,
        text=True,
        capture_output=True,
        check=False,
    )
    print("go mod vendor succeeded:", vendor.returncode == 0)
    if vendor.returncode:
        print(vendor.stderr.strip())
        raise SystemExit

    metadata = (root / "vendor" / "modules.txt").read_text()
    print("vendor/modules.txt records all three modules:",
          all(path in metadata for path in modules))
    print("--- vendor replacement metadata ---")
    print("\n".join(line for line in metadata.splitlines()
                    if any(path in line for path in modules) or line.startswith("# =>")))

    # Point one replacement at a different source without regenerating vendor/.
    altered = (root / "go.mod").read_text()
    altered = altered.replace(
        f"=> {root / 'source-1'}",
        f"=> {root / 'source-2'}",
        1,
    )
    (root / "go.mod").write_text(altered)
    check = subprocess.run(
        [go, "list", "-mod=vendor", "./..."],
        cwd=root,
        text=True,
        capture_output=True,
        check=False,
    )
    print("stale vendor metadata rejected:", check.returncode != 0)
    print(check.stderr.strip())
PY

Repository: openshift/enhancements

Length of output: 306


🏁 Script executed:

#!/bin/bash
set -eu

python3 - <<'PY'
import shutil
import subprocess
import tempfile
from pathlib import Path

go = shutil.which("go")
if not go:
    print("go tool: unavailable")
    raise SystemExit

modules = {
    "go.podman.io/common": ("common", "v0.0.0"),
    "go.podman.io/storage": ("storage", "v0.0.0"),
    "go.podman.io/image/v5": ("image", "v5.0.0"),
}

with tempfile.TemporaryDirectory() as d:
    root = Path(d)
    replacements = []
    imports = []
    for index, (path, (package, version)) in enumerate(modules.items(), 1):
        source = root / f"source-{index}"
        source.mkdir()
        (source / "go.mod").write_text(f"module {path}\n\ngo 1.20\n")
        (source / f"{package}.go").write_text(
            f"package {package}\n\nfunc Value() string {{ return \"{package}\" }}\n"
        )
        replacements.append(f"    {path} => {source}\n")
        imports.append(f'    "{path}"\n')

    (root / "go.mod").write_text(
        "module example.com/main\n\n"
        "go 1.20\n\n"
        + "".join(f"require {path} {version}\n" for path, (_, version) in modules.items())
        + "\nreplace (\n"
        + "".join(replacements)
        + ")\n"
    )
    (root / "main.go").write_text(
        "package main\n\nimport (\n"
        + "".join(imports)
        + ")\n\nfunc main() { _ = common.Value; _ = storage.Value; _ = image.Value }\n"
    )

    vendor = subprocess.run(
        [go, "mod", "vendor"],
        cwd=root,
        text=True,
        capture_output=True,
        check=False,
    )
    print("go mod vendor succeeded:", vendor.returncode == 0)
    if vendor.returncode:
        print(vendor.stderr.strip())
        raise SystemExit

    metadata = (root / "vendor" / "modules.txt").read_text()
    print("vendor/modules.txt records all three modules:",
          all(path in metadata for path in modules))
    print("--- vendor replacement metadata ---")
    print("\n".join(line for line in metadata.splitlines()
                    if any(path in line for path in modules) or line.startswith("# =>")))

    altered = (root / "go.mod").read_text()
    altered = altered.replace(
        f"=> {root / 'source-1'}",
        f"=> {root / 'source-2'}",
        1,
    )
    (root / "go.mod").write_text(altered)
    check = subprocess.run(
        [go, "list", "-mod=vendor", "./..."],
        cwd=root,
        text=True,
        capture_output=True,
        check=False,
    )
    print("stale vendor metadata rejected:", check.returncode != 0)
    print(check.stderr.strip())
PY

Repository: openshift/enhancements

Length of output: 1023


Define replacement precedence and enforce it in CI.

Specify the authoritative replacement for go.podman.io/common, go.podman.io/storage, and go.podman.io/image/v5. Add CI checks for the effective replacements and matching vendor/modules.txt; a text merge can retain a valid but incorrect replacement.

🤖 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 `@enhancements/node/downstream-container-libs-vendoring-for-cri-o.md` around
lines 221 - 225, Define explicit replacement precedence rules for the three Go
modules (go.podman.io/common, go.podman.io/storage, and go.podman.io/image/v5)
in the document to establish which replacement directive is authoritative. Add
CI validation checks that verify the effective replacements applied in go.mod
match the intended precedence and that the resulting vendor/modules.txt reflects
the correct resolved replacements, preventing text merge conflicts from
introducing valid but incorrect module versions.

Comment on lines +368 to +372
## Version Skew Strategy

CRI-O is a node-level component. During upgrades, nodes may temporarily run different CRI-O versions. This is unchanged by this proposal — container-libs vendoring is internal to the CRI-O binary and does not affect inter-component communication or APIs.

During dual-stream RHEL transitions, nodes may run CRI-O binaries built with different container-libs versions. This does not introduce inter-node version skew concerns because container-libs is statically linked into CRI-O and does not affect inter-component APIs. On-disk container storage formats managed by the `storage` library are local to each node; if a container-libs update changes the on-disk format, the impact is limited to the upgraded node and handled by CRI-O's existing storage migration logic.

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

🧩 Analysis chain

🏁 Script executed:

cat -n enhancements/node/downstream-container-libs-vendoring-for-cri-o.md | head -400 | tail -100

Repository: openshift/enhancements

Length of output: 8399


🏁 Script executed:

rg -n "storage|migration|test|rollback|recovery" enhancements/node/downstream-container-libs-vendoring-for-cri-o.md -i

Repository: openshift/enhancements

Length of output: 4660


🏁 Script executed:

sed -n '360,400p' enhancements/node/downstream-container-libs-vendoring-for-cri-o.md

Repository: openshift/enhancements

Length of output: 3230


Define storage migration contract and add mixed-version storage tests before declaring dual-stream upgrades safe.

The proposal delegates on-disk format changes to "CRI-O's existing storage migration logic" (line 372) but provides no definition of that migration contract, no test coverage for the dual-stream scenario (nodes running different container-libs versions simultaneously), and no explicit recovery procedure. The rollback process is already flagged as incomplete on line 222 (TODO: Define the specific rollback process).

Before merge, add:

  1. Documented storage migration contract specifying supported format transitions for each RHEL/container-libs pair.
  2. Mixed-version storage compatibility tests covering at least the supported RHEL transitions in the same OCP release.
  3. Explicit recovery and rollback procedures if migration fails on a node.
🤖 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 `@enhancements/node/downstream-container-libs-vendoring-for-cri-o.md` around
lines 368 - 372, Expand the “Version Skew Strategy” section to define the
storage migration contract for each supported RHEL/container-libs transition,
add mixed-version storage compatibility tests covering those transitions within
the same OCP release, and document explicit node recovery and rollback
procedures for migration failures, including the existing rollback TODO.

…ture details

- Add CI Access to gitlab.cee section describing the intranet capability
  and GOPRIVATE configuration for Prow jobs
- Replace manual workflow with automated Prow job for container-libs
  vendoring updates
- Add presubmit divergence check to test plan
- Resolve open questions on automation and gitlab.cee accessibility
- Simplify upstream rebase workflow to use carry patch model
- Simplify dual-stream RHEL mitigation
- Update Infrastructure Needed with specific Prow job requirements

Assisted-by: Claude Code <https://claude.com/claude-code>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants