Skip to content

MCO-2294: promote OSStreams to GA in self-managed clusters#2849

Open
cheesesashimi wants to merge 1 commit into
openshift:masterfrom
cheesesashimi:zzlotnik/promote-osstream-to-ga
Open

MCO-2294: promote OSStreams to GA in self-managed clusters#2849
cheesesashimi wants to merge 1 commit into
openshift:masterfrom
cheesesashimi:zzlotnik/promote-osstream-to-ga

Conversation

@cheesesashimi
Copy link
Copy Markdown
Member

This promotes the OSStream feature to GA for self-managed clusters. The intent behind this is that we will be able to begin testing OCP on RHEL10 since OSStreams helps make that possible. This PR purposely avoids default enablement in Hypershift as there are some unknowns and must-have conversations around that.

@openshift-merge-bot
Copy link
Copy Markdown
Contributor

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: LGTM mode

@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 May 19, 2026
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 19, 2026

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

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 19, 2026

Hello @cheesesashimi! Some important instructions when contributing to openshift/api:
API design plays an important part in the user experience of OpenShift and as such API PRs are subject to a high level of scrutiny to ensure they follow our best practices. If you haven't already done so, please review the OpenShift API Conventions and ensure that your proposed changes are compliant. Following these conventions will help expedite the api review process for your PR.

@openshift-ci openshift-ci Bot added the size/S Denotes a PR that changes 10-29 lines, ignoring generated files. label May 19, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

📝 Walkthrough

Walkthrough

This PR enables the OSStreams feature for SelfManagedHA (Default and OKD) and for Hypershift preview channels by splitting and updating the feature-gate logic in features/features.go, updates the features.md matrix to mark SelfManagedHA/OKD as Enabled, moves OSStreams from disabled to enabled in the SelfManagedHA Default and OKD featureGate manifests, removes include.release.openshift.io/self-managed-high-availability annotations from several Hypershift CRD variants, and adds SelfManagedHA CRDs for MachineConfigPool and OSImageStream with full schemas.

Suggested reviewers

  • everettraven
🚥 Pre-merge checks | ✅ 12
✅ Passed checks (12 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: promoting OSStreams to GA status for self-managed clusters, which aligns with the changeset modifications across feature gates, CRDs, and feature gate configurations.
Description check ✅ Passed The description is directly related to the changeset, explaining the purpose of promoting OSStreams to GA for self-managed clusters to enable OCP testing on RHEL10, and noting the intentional avoidance of Hypershift default enablement.
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.
Stable And Deterministic Test Names ✅ Passed PR contains no Ginkgo tests or test files—only feature configuration, implementation code, and manifests. Check is not applicable.
Test Structure And Quality ✅ Passed Ginkgo tests use table-driven structure for single responsibility, proper BeforeEach/AfterEach for setup/cleanup, 5-second timeouts on all Eventually calls, and meaningful assertion messages.
Microshift Test Compatibility ✅ Passed No Ginkgo e2e tests are added in this PR. Changes are limited to feature gate definitions (features/features.go), documentation (features.md), and CRD manifests (YAML files). Check is not applicable.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No Ginkgo e2e tests are added in this PR. Changes are limited to feature gates, CRD definitions, and YAML manifests. SNO compatibility check does not apply.
Topology-Aware Scheduling Compatibility ✅ Passed This PR only modifies feature gate config and CRD schemas for machine/OS resources. It contains no deployment manifests, operator code, or Pod scheduling constraints.
Ote Binary Stdout Contract ✅ Passed PR only modifies API definitions, feature gate library, and Kubernetes manifests. No OTE binary or process-level test code present.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No new Ginkgo e2e tests added in this PR. Changes are feature gates, CRD manifests, and standard Go unit tests only.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

Error: build linters: unable to load custom analyzer "kubeapilinter": tools/_output/bin/kube-api-linter.so, plugin: not implemented
The command is terminated due to an error: build linters: unable to load custom analyzer "kubeapilinter": tools/_output/bin/kube-api-linter.so, plugin: not implemented


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 19, 2026

[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 deads2k 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

@sdodson
Copy link
Copy Markdown
Member

sdodson commented May 20, 2026

/test ci/prow/verify-feature-promotion

@sdodson
Copy link
Copy Markdown
Member

sdodson commented May 20, 2026

/test verify-feature-promotion

@cheesesashimi cheesesashimi changed the title promote OSStreams to GA in self-managed clusters MCO-2294: promote OSStreams to GA in self-managed clusters May 20, 2026
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label May 20, 2026
@openshift-ci-robot
Copy link
Copy Markdown

openshift-ci-robot commented May 20, 2026

@cheesesashimi: This pull request references MCO-2294 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:

This promotes the OSStream feature to GA for self-managed clusters. The intent behind this is that we will be able to begin testing OCP on RHEL10 since OSStreams helps make that possible. This PR purposely avoids default enablement in Hypershift as there are some unknowns and must-have conversations around that.

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.

@cheesesashimi
Copy link
Copy Markdown
Member Author

/jira-refresh

@cheesesashimi cheesesashimi marked this pull request as ready for review May 20, 2026 16:44
@openshift-ci openshift-ci Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label May 20, 2026
@openshift-ci openshift-ci Bot requested review from JoelSpeed and everettraven May 20, 2026 16:45
@cheesesashimi cheesesashimi force-pushed the zzlotnik/promote-osstream-to-ga branch from e00a624 to 2cbf3c8 Compare May 20, 2026 20:56
@openshift-ci openshift-ci Bot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/S Denotes a PR that changes 10-29 lines, ignoring generated files. labels May 20, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

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

Inline comments:
In
`@payload-manifests/crds/0000_80_machine-config_01_machineconfigpools-SelfManagedHA.crd.yaml`:
- Around line 350-360: The pinnedImageSets[].name schema and pattern allow
uppercase letters but must enforce RFC1123 lowercase; update the description to
state the name MUST be lowercase RFC1123 (a–z, 0–9, -) and replace all
[a-zA-Z0-9] occurrences in the pattern with [a-z0-9] so each segment and the
overall pattern only permit lowercase alphanumerics and hyphens (keep the
existing segment length rules and anchors intact); ensure the schema's pattern
string for name is the only change so validation rejects uppercase names that
cannot match Kubernetes object names.

In
`@payload-manifests/crds/0000_80_machine-config_01_osimagestreams-SelfManagedHA.crd.yaml`:
- Around line 20-29: The CRD currently exposes OSImageStream only as v1alpha1
with "Compatibility level 4", which hides the GA surface (notably
spec.defaultStream); promote this resource to a stable API by switching the CRD
version from v1alpha1 to a GA/stable version (e.g., v1) and update the
compatibility metadata (remove/replace "Compatibility level 4" with the
appropriate stable level) so spec.defaultStream is published with a stable
contract; ensure the OpenAPI schema under openAPIV3Schema for OSImageStream
remains intact and adjust any apiVersion/version fields and validation fields to
match the promoted CRD (target symbols: OSImageStream, spec.defaultStream,
v1alpha1).
- Around line 126-158: The repository/name part of the OCI pull-spec regex
allows an empty repository (e.g. "quay.io/@sha256:..."); update the two
x-kubernetes-validations rules (the rule for the OCI Image name under both the
earlier field and osImage) to require at least one character for the final
repository segment by changing the terminal quantifier from '*' to '+' (i.e.
ensure the final class [a-zA-Z0-9-_.] uses + so repository name is non-empty),
leaving the rest of the host[:port][/namespace]/name pattern intact and keeping
both validation locations in sync.
🪄 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 YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 7e2d5896-aa38-472f-a2e3-aecca24e341c

📥 Commits

Reviewing files that changed from the base of the PR and between e00a624 and 2cbf3c8.

⛔ Files ignored due to path filters (8)
  • machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_machineconfigpools-Hypershift-CustomNoUpgrade.crd.yaml is excluded by !**/zz_generated.crd-manifests/*
  • machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_machineconfigpools-Hypershift-Default.crd.yaml is excluded by !**/zz_generated.crd-manifests/*
  • machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_machineconfigpools-Hypershift-DevPreviewNoUpgrade.crd.yaml is excluded by !**/zz_generated.crd-manifests/*
  • machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_machineconfigpools-Hypershift-OKD.crd.yaml is excluded by !**/zz_generated.crd-manifests/*
  • machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_machineconfigpools-Hypershift-TechPreviewNoUpgrade.crd.yaml is excluded by !**/zz_generated.crd-manifests/*
  • machineconfiguration/v1/zz_generated.crd-manifests/0000_80_machine-config_01_machineconfigpools-SelfManagedHA.crd.yaml is excluded by !**/zz_generated.crd-manifests/*
  • machineconfiguration/v1alpha1/zz_generated.crd-manifests/0000_80_machine-config_01_osimagestreams-Hypershift.crd.yaml is excluded by !**/zz_generated.crd-manifests/*
  • machineconfiguration/v1alpha1/zz_generated.crd-manifests/0000_80_machine-config_01_osimagestreams-SelfManagedHA.crd.yaml is excluded by !**/zz_generated.crd-manifests/*
📒 Files selected for processing (12)
  • features.md
  • features/features.go
  • payload-manifests/crds/0000_80_machine-config_01_machineconfigpools-Hypershift-CustomNoUpgrade.crd.yaml
  • payload-manifests/crds/0000_80_machine-config_01_machineconfigpools-Hypershift-Default.crd.yaml
  • payload-manifests/crds/0000_80_machine-config_01_machineconfigpools-Hypershift-DevPreviewNoUpgrade.crd.yaml
  • payload-manifests/crds/0000_80_machine-config_01_machineconfigpools-Hypershift-OKD.crd.yaml
  • payload-manifests/crds/0000_80_machine-config_01_machineconfigpools-Hypershift-TechPreviewNoUpgrade.crd.yaml
  • payload-manifests/crds/0000_80_machine-config_01_machineconfigpools-SelfManagedHA.crd.yaml
  • payload-manifests/crds/0000_80_machine-config_01_osimagestreams-Hypershift.crd.yaml
  • payload-manifests/crds/0000_80_machine-config_01_osimagestreams-SelfManagedHA.crd.yaml
  • payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-Default.yaml
  • payload-manifests/featuregates/featureGate-4-10-SelfManagedHA-OKD.yaml
💤 Files with no reviewable changes (6)
  • payload-manifests/crds/0000_80_machine-config_01_machineconfigpools-Hypershift-OKD.crd.yaml
  • payload-manifests/crds/0000_80_machine-config_01_osimagestreams-Hypershift.crd.yaml
  • payload-manifests/crds/0000_80_machine-config_01_machineconfigpools-Hypershift-TechPreviewNoUpgrade.crd.yaml
  • payload-manifests/crds/0000_80_machine-config_01_machineconfigpools-Hypershift-CustomNoUpgrade.crd.yaml
  • payload-manifests/crds/0000_80_machine-config_01_machineconfigpools-Hypershift-DevPreviewNoUpgrade.crd.yaml
  • payload-manifests/crds/0000_80_machine-config_01_machineconfigpools-Hypershift-Default.crd.yaml

Comment on lines +350 to +360
name:
description: |-
name is a reference to the name of a PinnedImageSet. Must adhere to
RFC-1123 (https://tools.ietf.org/html/rfc1123).
Made up of one of more period-separated (.) segments, where each segment
consists of alphanumeric characters and hyphens (-), must begin and end
with an alphanumeric character, and is at most 63 characters in length.
The total length of the name must not exceed 253 characters.
maxLength: 253
minLength: 1
pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Make pinnedImageSets[].name actually enforce RFC1123 lowercase.

Line 360 currently allows uppercase characters even though the field is documented as RFC1123. That lets users submit PinnedImageSet refs that can never match a valid Kubernetes object name.

Suggested fix
-                      pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$
+                      pattern: ^([a-z0-9]|[a-z0-9][a-z0-9\-]{0,61}[a-z0-9])(\.([a-z0-9]|[a-z0-9][a-z0-9\-]{0,61}[a-z0-9]))*$
📝 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
name:
description: |-
name is a reference to the name of a PinnedImageSet. Must adhere to
RFC-1123 (https://tools.ietf.org/html/rfc1123).
Made up of one of more period-separated (.) segments, where each segment
consists of alphanumeric characters and hyphens (-), must begin and end
with an alphanumeric character, and is at most 63 characters in length.
The total length of the name must not exceed 253 characters.
maxLength: 253
minLength: 1
pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$
name:
description: |-
name is a reference to the name of a PinnedImageSet. Must adhere to
RFC-1123 (https://tools.ietf.org/html/rfc1123).
Made up of one of more period-separated (.) segments, where each segment
consists of alphanumeric characters and hyphens (-), must begin and end
with an alphanumeric character, and is at most 63 characters in length.
The total length of the name must not exceed 253 characters.
maxLength: 253
minLength: 1
pattern: ^([a-z0-9]|[a-z0-9][a-z0-9\-]{0,61}[a-z0-9])(\.([a-z0-9]|[a-z0-9][a-z0-9\-]{0,61}[a-z0-9]))*$
🤖 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
`@payload-manifests/crds/0000_80_machine-config_01_machineconfigpools-SelfManagedHA.crd.yaml`
around lines 350 - 360, The pinnedImageSets[].name schema and pattern allow
uppercase letters but must enforce RFC1123 lowercase; update the description to
state the name MUST be lowercase RFC1123 (a–z, 0–9, -) and replace all
[a-zA-Z0-9] occurrences in the pattern with [a-z0-9] so each segment and the
overall pattern only permit lowercase alphanumerics and hyphens (keep the
existing segment length rules and anchors intact); ensure the schema's pattern
string for name is the only change so validation rejects uppercase names that
cannot match Kubernetes object names.

Comment on lines +20 to +29
- name: v1alpha1
schema:
openAPIV3Schema:
description: |-
OSImageStream describes a set of streams and associated images available
for the MachineConfigPools to be used as base OS images.

The resource is a singleton named "cluster".

Compatibility level 4: No compatibility is provided, the API can change at any point for any reason. These capabilities should not be used by applications needing long term support.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Don’t ship the GA path behind a v1alpha1/compat-level-4 CRD.

This PR moves OSStreams into Default/OKD for self-managed clusters, but the only published OSImageStream API here is still v1alpha1 with “Compatibility level 4”. That leaves the user-editable spec.defaultStream surface without a stable contract while the feature is effectively GA.

🤖 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
`@payload-manifests/crds/0000_80_machine-config_01_osimagestreams-SelfManagedHA.crd.yaml`
around lines 20 - 29, The CRD currently exposes OSImageStream only as v1alpha1
with "Compatibility level 4", which hides the GA surface (notably
spec.defaultStream); promote this resource to a stable API by switching the CRD
version from v1alpha1 to a GA/stable version (e.g., v1) and update the
compatibility metadata (remove/replace "Compatibility level 4" with the
appropriate stable level) so spec.defaultStream is published with a stable
contract; ensure the OpenAPI schema under openAPIV3Schema for OSImageStream
remains intact and adjust any apiVersion/version fields and validation fields to
match the promoted CRD (target symbols: OSImageStream, spec.defaultStream,
v1alpha1).

Comment on lines +126 to +158
The format of the image pull spec is: host[:port][/namespace]/name@sha256:<digest>,
where the digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9.
The length of the whole spec must be between 1 to 447 characters.
maxLength: 447
minLength: 1
type: string
x-kubernetes-validations:
- message: the OCI Image reference must end with a valid '@sha256:<digest>'
suffix, where '<digest>' is 64 characters long
rule: (self.split('@').size() == 2 && self.split('@')[1].matches('^sha256:[a-f0-9]{64}$'))
- message: the OCI Image name should follow the host[:port][/namespace]/name
format, resembling a valid URL without the scheme
rule: (self.split('@')[0].matches('^([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9-]+(:[0-9]{2,5})?/([a-zA-Z0-9-_]{0,61}/)?[a-zA-Z0-9-_.]*?$'))
osImage:
description: |-
osImage is a required OS Image referenced by digest.

osImage contains the immutable, fundamental operating system components, including the kernel
and base utilities, that define the core environment for the node's host operating system.

The format of the image pull spec is: host[:port][/namespace]/name@sha256:<digest>,
where the digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9.
The length of the whole spec must be between 1 to 447 characters.
maxLength: 447
minLength: 1
type: string
x-kubernetes-validations:
- message: the OCI Image reference must end with a valid '@sha256:<digest>'
suffix, where '<digest>' is 64 characters long
rule: (self.split('@').size() == 2 && self.split('@')[1].matches('^sha256:[a-f0-9]{64}$'))
- message: the OCI Image name should follow the host[:port][/namespace]/name
format, resembling a valid URL without the scheme
rule: (self.split('@')[0].matches('^([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9-]+(:[0-9]{2,5})?/([a-zA-Z0-9-_]{0,61}/)?[a-zA-Z0-9-_.]*?$'))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Tighten the pull-spec regex so empty repository names stop validating.

The current rules accept invalid refs like quay.io/@sha256:... because the namespace part can be empty and the final repository component is *. That weakens validation for the image refs this CRD publishes.

Suggested fix
-                        rule: (self.split('@')[0].matches('^([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9-]+(:[0-9]{2,5})?/([a-zA-Z0-9-_]{0,61}/)?[a-zA-Z0-9-_.]*?$'))
+                        rule: (self.split('@')[0].matches('^([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9-]+(:[0-9]{2,5})?/([a-zA-Z0-9-_]{1,61}/)?[a-zA-Z0-9-_.]+$'))
...
-                        rule: (self.split('@')[0].matches('^([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9-]+(:[0-9]{2,5})?/([a-zA-Z0-9-_]{0,61}/)?[a-zA-Z0-9-_.]*?$'))
+                        rule: (self.split('@')[0].matches('^([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9-]+(:[0-9]{2,5})?/([a-zA-Z0-9-_]{1,61}/)?[a-zA-Z0-9-_.]+$'))
📝 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
The format of the image pull spec is: host[:port][/namespace]/name@sha256:<digest>,
where the digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9.
The length of the whole spec must be between 1 to 447 characters.
maxLength: 447
minLength: 1
type: string
x-kubernetes-validations:
- message: the OCI Image reference must end with a valid '@sha256:<digest>'
suffix, where '<digest>' is 64 characters long
rule: (self.split('@').size() == 2 && self.split('@')[1].matches('^sha256:[a-f0-9]{64}$'))
- message: the OCI Image name should follow the host[:port][/namespace]/name
format, resembling a valid URL without the scheme
rule: (self.split('@')[0].matches('^([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9-]+(:[0-9]{2,5})?/([a-zA-Z0-9-_]{0,61}/)?[a-zA-Z0-9-_.]*?$'))
osImage:
description: |-
osImage is a required OS Image referenced by digest.
osImage contains the immutable, fundamental operating system components, including the kernel
and base utilities, that define the core environment for the node's host operating system.
The format of the image pull spec is: host[:port][/namespace]/name@sha256:<digest>,
where the digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9.
The length of the whole spec must be between 1 to 447 characters.
maxLength: 447
minLength: 1
type: string
x-kubernetes-validations:
- message: the OCI Image reference must end with a valid '@sha256:<digest>'
suffix, where '<digest>' is 64 characters long
rule: (self.split('@').size() == 2 && self.split('@')[1].matches('^sha256:[a-f0-9]{64}$'))
- message: the OCI Image name should follow the host[:port][/namespace]/name
format, resembling a valid URL without the scheme
rule: (self.split('@')[0].matches('^([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9-]+(:[0-9]{2,5})?/([a-zA-Z0-9-_]{0,61}/)?[a-zA-Z0-9-_.]*?$'))
The format of the image pull spec is: host[:port][/namespace]/name@sha256:<digest>,
where the digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9.
The length of the whole spec must be between 1 to 447 characters.
maxLength: 447
minLength: 1
type: string
x-kubernetes-validations:
- message: the OCI Image reference must end with a valid '`@sha256`:<digest>'
suffix, where '<digest>' is 64 characters long
rule: (self.split('@').size() == 2 && self.split('@')[1].matches('^sha256:[a-f0-9]{64}$'))
- message: the OCI Image name should follow the host[:port][/namespace]/name
format, resembling a valid URL without the scheme
rule: (self.split('@')[0].matches('^([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9-]+(:[0-9]{2,5})?/([a-zA-Z0-9-_]{1,61}/)?[a-zA-Z0-9-_.]+$'))
osImage:
description: |-
osImage is a required OS Image referenced by digest.
osImage contains the immutable, fundamental operating system components, including the kernel
and base utilities, that define the core environment for the node's host operating system.
The format of the image pull spec is: host[:port][/namespace]/name@sha256:<digest>,
where the digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9.
The length of the whole spec must be between 1 to 447 characters.
maxLength: 447
minLength: 1
type: string
x-kubernetes-validations:
- message: the OCI Image reference must end with a valid '`@sha256`:<digest>'
suffix, where '<digest>' is 64 characters long
rule: (self.split('@').size() == 2 && self.split('@')[1].matches('^sha256:[a-f0-9]{64}$'))
- message: the OCI Image name should follow the host[:port][/namespace]/name
format, resembling a valid URL without the scheme
rule: (self.split('@')[0].matches('^([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9-]+(:[0-9]{2,5})?/([a-zA-Z0-9-_]{1,61}/)?[a-zA-Z0-9-_.]+$'))
🤖 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
`@payload-manifests/crds/0000_80_machine-config_01_osimagestreams-SelfManagedHA.crd.yaml`
around lines 126 - 158, The repository/name part of the OCI pull-spec regex
allows an empty repository (e.g. "quay.io/@sha256:..."); update the two
x-kubernetes-validations rules (the rule for the OCI Image name under both the
earlier field and osImage) to require at least one character for the final
repository segment by changing the terminal quantifier from '*' to '+' (i.e.
ensure the final class [a-zA-Z0-9-_.] uses + so repository name is non-empty),
leaving the rest of the host[:port][/namespace]/name pattern intact and keeping
both validation locations in sync.

@sdodson
Copy link
Copy Markdown
Member

sdodson commented May 23, 2026

/test verify-feature-promotion

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 23, 2026

@cheesesashimi: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/verify-feature-promotion 2cbf3c8 link true /test verify-feature-promotion

Full PR test history. Your PR dashboard.

Details

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

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

Labels

jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants