Skip to content

WIP: Bootstrap hypershift release controller#81750

Draft
JoelSpeed wants to merge 3 commits into
openshift:mainfrom
JoelSpeed:bootstrap-hypershift-release-controller
Draft

WIP: Bootstrap hypershift release controller#81750
JoelSpeed wants to merge 3 commits into
openshift:mainfrom
JoelSpeed:bootstrap-hypershift-release-controller

Conversation

@JoelSpeed

@JoelSpeed JoelSpeed commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

1st stage in an experiment to determine whether or not we could leverage https://github.com/openshift/release-controller to gate automated promotion of HyperShift Operator builds to the repositories that ARO/ROSA consume from.

This sets up a new release controller deployment (will gives us a separate dashboard for HyperShift) with a very minimal promotion config looking at the existing HyperShift ImageStream on the app.ci cluster (are we ok watching the existing image stream?)

I've been trying to work out how to validate whether this works or not and as far as I can tell the only way is to actually deploy it, would prefer some review before trying it on a live cluster so putting here to start that process

Summary by CodeRabbit

  • Adds a dedicated HyperShift release-controller deployment and API service in the app.ci cluster, including routing, probes, shared credentials, and Jira integration.
  • Introduces the initial hypershift stable release configuration to gate verified promotion of HyperShift Operator builds.
  • Extends generator logic and RBAC to support HyperShift release and release-payload controllers in the hypershift namespace.
  • Updates annotation automation so the existing HyperShift ImageStream uses the new release configuration.

@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 10, 2026
@openshift-ci

openshift-ci Bot commented Jul 10, 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

@openshift-merge-bot openshift-merge-bot Bot added the rehearsals-ack Signifies that rehearsal jobs have been acknowledged label Jul 10, 2026
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

[REHEARSALNOTIFIER]
@JoelSpeed: no rehearsable tests are affected by this change

Note: If this PR includes changes to step registry files (ci-operator/step-registry/) and you expected jobs to be found, try rebasing your PR onto the base branch. This helps pj-rehearse accurately detect changes when the base branch has moved forward.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

Adds HyperShift release configuration, annotation support, generated controller deployments and services, external routing, and namespace-scoped RBAC for release-controller and release-payload-controller.

Changes

HyperShift release controller

Layer / File(s) Summary
Release stream configuration
core-services/release-controller/_releases/release-hypershift.json, hack/annotate.sh
Defines the HyperShift continuous release stream and adds annotation support for the HyperShift operator configuration.
HyperShift RBAC resources
hack/generators/release-controllers/content/hypershift_admin_resources.py, hack/generators/release-controllers/content/release_payload_controller_resources.py, hack/generators/release-controllers/content/__init__.py, clusters/app.ci/release-controller/admin_deploy-hypershift-controller.yaml, clusters/app.ci/release-payload-controller/admin_rbac.yaml
Generates and adds namespace-scoped permissions and bindings for the HyperShift release controllers.
Controller services and deployments
hack/generators/release-controllers/content/hypershift_resources.py, clusters/app.ci/release-controller/deploy-hypershift-controller.yaml
Generates and adds HyperShift controller and API deployments, services, health probes, shared mounts, and an edge-terminated route.
Generator integration
hack/generators/release-controllers/generate-release-controllers.py
Invokes the HyperShift admin and deployment resource generators for the app.ci manifests.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Route as release-controller-hypershift Route
  participant Service as release-controller-api-hypershift Service
  participant API as release-controller-api-hypershift Deployment
  Client->>Route: HTTPS request
  Route->>Service: Edge-terminated request
  Service->>API: Port 80 to targetPort 8080
Loading

Suggested reviewers: bryan-cox, wking, stbenjam


Important

Pre-merge checks failed

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

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Container-Privileges ❌ Error New HyperShift Deployments lack securityContext/runAsNonRoot, so containers run as root by default; no anti-escalation settings are present. Add pod/container securityContext to every container: runAsNonRoot: true, allowPrivilegeEscalation: false, and drop ALL capabilities; set a non-root UID if needed.
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (13 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: bootstrapping a HyperShift release controller.
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 No _test.go files changed, and the modified files contain no Ginkgo title calls like It/Describe/When.
Test Structure And Quality ✅ Passed PR only changes hack/annotate.sh; no Ginkgo test files or test code are touched, so the test-structure check is not applicable.
Microshift Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the touched files are generators/manifests/scripts, with no It/Describe/Context/When declarations or MicroShift-specific checks.
Single Node Openshift (Sno) Test Compatibility ✅ Passed PR only adds manifests and generator scripts; no new Ginkgo e2e tests (.go) or It/Describe/When definitions were introduced.
Topology-Aware Scheduling Compatibility ✅ Passed No topology-sensitive scheduling constraints were added; the new HyperShift Deployments lack node selectors, anti-affinity, topology spread, and PDBs.
Ote Binary Stdout Contract ✅ Passed The PR adds manifests/generators only; no new main/init/TestMain stdout writes were introduced, and the shell script logs to stderr.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; changed files are manifests/generators and contain no It/Describe/Context/When or IPv4 test logic.
No-Weak-Crypto ✅ Passed Touched files only add manifests, RBAC, and annotation logic; no MD5/SHA1/DES/RC4/3DES/Blowfish/ECB, custom crypto, or secret/token comparisons found.
No-Sensitive-Data-In-Logs ✅ Passed PASS: No new log statements expose secrets/PII; added output is just a config path, and HyperShift mirrors existing Jira-flagged release-controller args.
✨ 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 10, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: JoelSpeed
Once this PR has been reviewed and has the lgtm label, please assign danilo-gemoli 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
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
hack/generators/release-controllers/content/hypershift_admin_resources.py (1)

46-50: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Hardcoded namespace: ci instead of using config value.

release_payload_controller_resources.py's _namespaced_rbac_resources uses config.rc_deployment_namespace for the equivalent subject namespace. Hardcoding 'ci' here risks drifting if that config value ever changes.

♻️ Suggested consistency fix
+def generate_hypershift_admin_resources(gendoc):
     """Generate RBAC for HyperShift release controller in existing hypershift namespace"""
+    config = gendoc.context.config
     # Create RBAC for release controller to manage imagestreams and releasepayloads
     ...
         'subjects': [{
             'kind': 'ServiceAccount',
             'name': 'release-controller',
-            'namespace': 'ci'
+            'namespace': config.rc_deployment_namespace
         }]
🤖 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 `@hack/generators/release-controllers/content/hypershift_admin_resources.py`
around lines 46 - 50, Replace the hardcoded 'ci' subject namespace in the
hypershift admin resource definitions with the configured namespace value,
matching _namespaced_rbac_resources in release_payload_controller_resources.py
by using config.rc_deployment_namespace.
🤖 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 `@hack/generators/release-controllers/content/hypershift_resources.py`:
- Around line 90-186: Add securityContext settings to every container in the pod
templates, including the init container and both regular containers under the
git-sync and release-controller definitions. Set runAsNonRoot: true,
allowPrivilegeEscalation: false, and capabilities.drop: ["ALL"] at container
level, and apply the same hardening to the corresponding deployment variant
referenced by the repeated section.
- Around line 116-146: Add resource specifications to every container in the
generated Kubernetes manifest: the git-sync sidecar’s resources must include
both requests and limits, and the git-sync-init and both controller containers
must define complete requests and limits. Update the container definitions
associated with the git-sync resources and the controller entries to use
appropriate CPU and memory values consistently.

---

Nitpick comments:
In `@hack/generators/release-controllers/content/hypershift_admin_resources.py`:
- Around line 46-50: Replace the hardcoded 'ci' subject namespace in the
hypershift admin resource definitions with the configured namespace value,
matching _namespaced_rbac_resources in release_payload_controller_resources.py
by using config.rc_deployment_namespace.
🪄 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: bd467bd7-2cfa-4bb8-b684-22a163f82d54

📥 Commits

Reviewing files that changed from the base of the PR and between 155a157 and 092c1c2.

📒 Files selected for processing (10)
  • clusters/app.ci/release-controller/admin_deploy-hypershift-controller.yaml
  • clusters/app.ci/release-controller/deploy-hypershift-controller.yaml
  • clusters/app.ci/release-payload-controller/admin_rbac.yaml
  • core-services/release-controller/_releases/release-hypershift.json
  • hack/annotate.sh
  • hack/generators/release-controllers/content/__init__.py
  • hack/generators/release-controllers/content/hypershift_admin_resources.py
  • hack/generators/release-controllers/content/hypershift_resources.py
  • hack/generators/release-controllers/content/release_payload_controller_resources.py
  • hack/generators/release-controllers/generate-release-controllers.py

Comment on lines +90 to +186
"initContainers": [
{
"name": "git-sync-init",
"command": ["/git-sync"],
"args": [
"--repo=https://github.com/openshift/release.git",
"--ref=main",
"--root=/tmp/git-sync",
"--one-time=true",
"--depth=1"
],
"env": [
{
"name": "GIT_SYNC_DEST",
"value": "release"
}
],
"image": "quay-proxy.ci.openshift.org/openshift/ci:ci_git-sync_v4.3.0",
"volumeMounts": [
{
"name": "release",
"mountPath": "/tmp/git-sync"
}
]
}
],
"containers": [
{
"name": "git-sync",
"command": ["/git-sync"],
"args": [
"--repo=https://github.com/openshift/release.git",
"--ref=main",
"--period=30s",
"--root=/tmp/git-sync",
"--max-failures=3"
],
"env": [
{
"name": "GIT_SYNC_DEST",
"value": "release"
}
],
"image": "quay-proxy.ci.openshift.org/openshift/ci:ci_git-sync_v4.3.0",
"volumeMounts": [
{
"name": "release",
"mountPath": "/tmp/git-sync"
}
],
"resources": {
"requests": {
"memory": "1Gi",
"cpu": "0.5",
}
}
},
{
"command": [
"/usr/bin/release-controller",
"--release-namespace=hypershift",
"--prow-config=/etc/config/config.yaml",
"--supplemental-prow-config-dir=/etc/config",
"--job-config=/var/repo/release/ci-operator/jobs",
"--prow-namespace=ci",
"--job-namespace=ci-release",
"--tools-image-stream-tag=release-controller-bootstrap:tools",
"--release-architecture=amd64",
"-v=4",
"--manifest-list-mode"
],
'image': 'quay-proxy.ci.openshift.org/openshift/ci:ci_release-controller_latest',
'imagePullPolicy': 'Always',
"name": "controller",
"volumeMounts": get_rc_volume_mounts(),
'livenessProbe': {
'httpGet': {
'path': '/healthz',
'port': 8081
},
'initialDelaySeconds': 3,
'periodSeconds': 3,
},
'readinessProbe': {
'httpGet': {
'path': '/healthz/ready',
'port': 8081
},
'initialDelaySeconds': 10,
'periodSeconds': 3,
'timeoutSeconds': 600,
},
}
],
"serviceAccountName": "release-controller",
"volumes": get_rc_volumes(context)
}

Copy link
Copy Markdown
Contributor

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

Missing securityContext on all containers (root + privilege escalation risk, per Checkov).

Neither Deployment sets a securityContext at pod or container level. Checkov flags allowPrivilegeEscalation and root-container risk on both. Per path instructions for Kubernetes manifests, containers should set runAsNonRoot, allowPrivilegeEscalation: false, and drop all capabilities.

🛡️ Suggested fix (apply to each container)
                             {
                                 "command": [
                                     "/usr/bin/release-controller",
                                     ...
                                 ],
                                 'image': 'quay-proxy.ci.openshift.org/openshift/ci:ci_release-controller_latest',
                                 'imagePullPolicy': 'Always',
                                 "name": "controller",
                                 "volumeMounts": get_rc_volume_mounts(),
+                                "securityContext": {
+                                    "allowPrivilegeEscalation": False,
+                                    "runAsNonRoot": True,
+                                    "capabilities": {"drop": ["ALL"]},
+                                },

Also applies to: 202-257

🧰 Tools
🪛 ast-grep (0.44.1)

[info] 110-110: Do not hardcode temporary file or directory names
Context: "/tmp/git-sync"
Note: [CWE-377] Insecure Temporary File.

(hardcoded-tmp-file)


[info] 136-136: Do not hardcode temporary file or directory names
Context: "/tmp/git-sync"
Note: [CWE-377] Insecure Temporary File.

(hardcoded-tmp-file)

🪛 Ruff (0.15.20)

[error] 111-111: Probable insecure usage of temporary file or directory: "/tmp/git-sync"

(S108)


[error] 137-137: Probable insecure usage of temporary file or directory: "/tmp/git-sync"

(S108)

🤖 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 `@hack/generators/release-controllers/content/hypershift_resources.py` around
lines 90 - 186, Add securityContext settings to every container in the pod
templates, including the init container and both regular containers under the
git-sync and release-controller definitions. Set runAsNonRoot: true,
allowPrivilegeEscalation: false, and capabilities.drop: ["ALL"] at container
level, and apply the same hardening to the corresponding deployment variant
referenced by the repeated section.

Sources: Path instructions, Linters/SAST tools

Comment on lines +116 to +146
"containers": [
{
"name": "git-sync",
"command": ["/git-sync"],
"args": [
"--repo=https://github.com/openshift/release.git",
"--ref=main",
"--period=30s",
"--root=/tmp/git-sync",
"--max-failures=3"
],
"env": [
{
"name": "GIT_SYNC_DEST",
"value": "release"
}
],
"image": "quay-proxy.ci.openshift.org/openshift/ci:ci_git-sync_v4.3.0",
"volumeMounts": [
{
"name": "release",
"mountPath": "/tmp/git-sync"
}
],
"resources": {
"requests": {
"memory": "1Gi",
"cpu": "0.5",
}
}
},

Copy link
Copy Markdown
Contributor

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

No resource limits/requests on most containers.

The git-sync-init initContainer and both controller containers have no resources block at all; the git-sync sidecar only sets requests without limits. Per path instructions, every container in a K8s manifest should have resource limits to avoid noisy-neighbor impact on the shared CI cluster.

♻️ Suggested fix
                                 "name": "controller",
                                 "volumeMounts": get_rc_volume_mounts(),
+                                "resources": {
+                                    "requests": {"cpu": "100m", "memory": "256Mi"},
+                                    "limits": {"cpu": "1", "memory": "1Gi"},
+                                },
                                 "volumeMounts": [
                                     {
                                         "name": "release",
                                         "mountPath": "/tmp/git-sync"
                                     }
-                                ]
+                                ],
+                                "resources": {
+                                    "requests": {"cpu": "50m", "memory": "128Mi"},
+                                    "limits": {"cpu": "200m", "memory": "256Mi"},
+                                }

Also applies to: 216-235

🧰 Tools
🪛 ast-grep (0.44.1)

[info] 136-136: Do not hardcode temporary file or directory names
Context: "/tmp/git-sync"
Note: [CWE-377] Insecure Temporary File.

(hardcoded-tmp-file)

🪛 Ruff (0.15.20)

[error] 137-137: Probable insecure usage of temporary file or directory: "/tmp/git-sync"

(S108)

🤖 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 `@hack/generators/release-controllers/content/hypershift_resources.py` around
lines 116 - 146, Add resource specifications to every container in the generated
Kubernetes manifest: the git-sync sidecar’s resources must include both requests
and limits, and the git-sync-init and both controller containers must define
complete requests and limits. Update the container definitions associated with
the git-sync resources and the controller entries to use appropriate CPU and
memory values consistently.

Source: Path instructions

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. rehearsals-ack Signifies that rehearsal jobs have been acknowledged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant