Skip to content

fix: remove Helm charts and standardize on operator-based deployment#448

Open
raballew wants to merge 18 commits intojumpstarter-dev:mainfrom
raballew:042-remove-helm-charts
Open

fix: remove Helm charts and standardize on operator-based deployment#448
raballew wants to merge 18 commits intojumpstarter-dev:mainfrom
raballew:042-remove-helm-charts

Conversation

@raballew
Copy link
Copy Markdown
Member

@raballew raballew commented Apr 9, 2026

Summary

  • Remove all Helm chart files and Helm-based deployment infrastructure from the repository
  • Update CLI admin commands, Kubernetes cluster operations, and e2e test scripts to use operator-only deployment
  • Clean up stale references to Helm in Makefiles, CI workflows, and Python packages

Closes #445

Test plan

  • Verify make pkg-test-jumpstarter_cli_admin passes
  • Verify make pkg-test-jumpstarter_kubernetes passes
  • Verify no remaining references to Helm charts in codebase (excluding vendor/docs)
  • Verify e2e setup scripts work with operator-only deployment
  • Verify CI workflows no longer reference removed Helm files

🤖 Generated with Claude Code

@netlify
Copy link
Copy Markdown

netlify bot commented Apr 9, 2026

Deploy Preview for jumpstarter-docs failed. Why did it fail? →

Name Link
🔨 Latest commit 635f4f7
🔍 Latest deploy log https://app.netlify.com/projects/jumpstarter-docs/deploys/69da00bcb9842a00081817c9

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 9, 2026

Warning

Rate limit exceeded

@raballew has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 11 minutes and 57 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 11 minutes and 57 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 97301f1a-3575-4dcb-9186-c8436570a4f2

📥 Commits

Reviewing files that changed from the base of the PR and between 1863f3f and 635f4f7.

📒 Files selected for processing (3)
  • .github/workflows/e2e.yaml
  • Makefile
  • e2e/compat/setup.sh
📝 Walkthrough

Walkthrough

This PR removes Helm-based deployment artifacts and support across the repository and consolidates deployments to operator-only flows using the Jumpstarter CR. Changes include deletion of Helm charts, Helm helpers, Helm-related Python APIs/CLI commands, CI lint/publish jobs, and e2e/Makefile Helm branching and flags.

Changes

Cohort / File(s) Summary
Helm chart removal
controller/deploy/helm/jumpstarter/*, controller/deploy/helm/jumpstarter/charts/...
Deleted entire Helm chart tree: Chart.yaml, values(.yaml/.kind/.schema), .helmignore, Pydantic model/schema generators, and all chart templates (CRDs, Deployments, Services, Ingress/Route, RBAC, Jobs, metrics).
Controller build & deploy scripts
controller/Makefile, controller/hack/deploy_with_helm.sh, controller/hack/install_helm.sh, controller/hack/utils, controller/hack/deploy_with_operator.sh, controller/Makefile
Removed METHOD variable and Helm branching; deleted Helm install helpers; made deploy operator-only; simplified print_deployment_success call site.
CI/CD workflows
.github/workflows/build-images.yaml, .github/workflows/controller-kind.yaml, .github/workflows/lint.yaml, .github/workflows/e2e.yaml
Removed Helm publish job, removed helm/operator matrix, dropped Helm lint job and Helm change detection, removed METHOD env vars, and bumped compat tags in e2e workflows.
E2E & compat test scripts
e2e/setup-e2e.sh, e2e/compat/setup.sh, e2e/compat/setup.sh
Removed METHOD handling and Helm-based install paths; compatibility tests now install operator from installer YAML; endpoint discovery now reads Jumpstarter CR spec.baseDomain via kubectl.
Python: CLI/admin & kubernetes packages
python/packages/jumpstarter-cli-admin/..., python/packages/jumpstarter-kubernetes/...
Removed Helm-related CLI commands/options (install, uninstall, ip, --helm, --chart, --values-file), deleted Helm install helpers/tests, removed InstallMethod type and Helm-related exports, switched detection to CRD-based checks, and updated signatures to drop helm/chart/values parameters.
Controller tests / envtest paths
controller/internal/*/suite_test.go
Updated envtest CRD lookup paths to use deploy/operator/config/crd/bases instead of Helm chart CRD templates.
Docs / rules / README
.cursor/rules/working-with-operator.mdc, controller/deploy/operator/README.md, controller/deploy/operator/internal/controller/...jumpstarter_controller.go
Removed Helm distribution docs/mentions, removed Helm directory entry from cursor rules, and adjusted inline comments referencing stable secret names (no behavior changes).

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Suggested labels

administration, operator

Suggested reviewers

  • bennyz

Poem

🐰
Helm charts shelved, templates gone with the breeze,
CRDs now flourish and operators seize,
No more chart.yaml, no values to comb,
Kubectl and CRs make the cluster my home,
Hoppy deploys now — a carrot of ease!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 58.62% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title 'fix: remove Helm charts and standardize on operator-based deployment' is clear, concise, and accurately summarizes the primary objective of removing Helm infrastructure.
Description check ✅ Passed The pull request description provides a comprehensive summary of changes, including removal of Helm charts, updates to CLI/Kubernetes operations, and cleanup of stale references, which directly relates to the changeset.
Linked Issues check ✅ Passed The PR comprehensively implements the requirements from issue #445: removes ~38 Helm files across controller/deploy/helm/, helper scripts, Python packages (jumpstarter-kubernetes, jumpstarter-cli-admin), CI workflows (.github/workflows), e2e scripts, and internal references. All major objectives listed in the issue are addressed.
Out of Scope Changes check ✅ Passed All changes are directly related to the Helm removal objective: deleted Helm charts/templates, removed Helm CLI commands from Python packages, updated deployment scripts to operator-only, modified CI workflows, and updated tests. Minor comment clarifications in jumpstarter_controller.go are documentation-only. No unrelated changes detected.

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

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

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.

# $1: deployment method (e.g., "Helm", "operator") - optional
# $1: deployment method (e.g., "operator") - optional
print_deployment_success() {
local method=${1:-""}
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

what other methods exist?

# Environment variables:
# COMPAT_SCENARIO - "old-controller" or "old-client" (required)
# COMPAT_CONTROLLER_TAG - Controller image tag for old-controller scenario (default: v0.7.1)
# COMPAT_CONTROLLER_TAG - Controller image tag for old-controller scenario (default: v0.7.0)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

why is it 0.7.0 and not 0.7.1?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

now it should be 0.8.1 to be right :)


# Always use helm for compat tests (simpler, direct control)
export METHOD="helm"
export METHOD="operator"
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

is method really needed after all? dont we only have operator now or do other methods exist too?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

not really needed anymore

e2e/setup-e2e.sh Outdated

# Deployment method: operator (default) or helm
# Deployment method
export METHOD="${METHOD:-operator}"
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

same question here - why is there still a method?

@raballew raballew force-pushed the 042-remove-helm-charts branch from 6884226 to fa102b3 Compare April 9, 2026 14:00
@raballew raballew marked this pull request as ready for review April 9, 2026 14:48
Copy link
Copy Markdown
Contributor

@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: 4

🧹 Nitpick comments (1)
python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl_test.py (1)

220-228: Cover the non-zero kubectl failure path too.

run_command() failures are often reported via a non-zero return code, not only by raising. This test only exercises the exception path, so the current regression in check_jumpstarter_installation() can slip through unnoticed.

💡 Suggested test addition
     `@pytest.mark.asyncio`
     `@patch`("jumpstarter_kubernetes.cluster.kubectl.run_command")
     async def test_check_jumpstarter_installation_command_failure(self, mock_run_command):
         mock_run_command.side_effect = RuntimeError("kubectl not found")

         result = await check_jumpstarter_installation("test-context")

         assert result.installed is False
         assert result.has_crds is False
         assert result.error is not None
         assert "kubectl not found" in result.error
+
+    `@pytest.mark.asyncio`
+    `@patch`("jumpstarter_kubernetes.cluster.kubectl.run_command")
+    async def test_check_jumpstarter_installation_nonzero_exit(self, mock_run_command):
+        mock_run_command.return_value = (1, "", "forbidden")
+
+        result = await check_jumpstarter_installation("test-context")
+
+        assert result.installed is False
+        assert result.has_crds is False
+        assert result.error is not None
+        assert "forbidden" in result.error
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl_test.py`
around lines 220 - 228, The test
test_check_jumpstarter_installation_command_failure only simulates run_command
raising an exception, but check_jumpstarter_installation must also handle
non-zero exit codes; add a test case that makes mock_run_command return a
completed-result with a non-zero return code (and stderr containing "kubectl not
found") instead of raising, then call
check_jumpstarter_installation("test-context") and assert result.installed is
False, result.has_crds is False, and the error message contains the stderr text;
reference the same test function name and mock_run_command to locate where to
add this non-exception path test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@controller/Makefile`:
- Around line 67-68: The Makefile's manifests target now emits CRDs/RBAC to
deploy/operator/config/... (see output:crd:artifacts and output:rbac:artifacts),
but the consuming targets install, uninstall and build-installer still reference
config/crd and config/default; update the consuming targets to read from
deploy/operator/config/... (or revert manifests to write to the canonical
config/... tree) so generated artifacts and consumers are aligned. Specifically,
modify the install and uninstall targets (currently building config/crd) and the
build-installer target (currently building config/default) to point to
deploy/operator/config/crd and deploy/operator/config/default respectively, or
change the manifests output back to the original config/... paths so nothing
else needs changing.

In `@e2e/setup-e2e.sh`:
- Around line 296-299: The script currently hardcodes ports when building
ENDPOINT and LOGIN_ENDPOINT; instead query the Jumpstarter CR for the actual
endpoints/ports and use those values. Replace the kubectl JSONPath that sets
BASEDOMAIN/ENDPOINT/LOGIN_ENDPOINT with commands that read the controller and
login endpoint values from the CR spec (e.g., fields like
.spec.controllerEndpoint or .spec.endpoints.controller and .spec.loginEndpoint
or .spec.endpoints.login) and assign them to ENDPOINT and LOGIN_ENDPOINT (fall
back to the previous host:port construction only if those spec fields are
empty); update any references to BASEDOMAIN if you must derive host/port
separately so ENDPOINT and LOGIN_ENDPOINT reflect the CR configuration rather
than hardcoded ports.

In `@e2e/tests.bats`:
- Around line 65-69: The teardown log dump redirection is wrong: the kubectl log
commands using `kubectl -n "${JS_NAMESPACE}" logs -l component=controller
--tail=250 2>&1 >&2` and the similar router line send both streams to stdout
instead of stderr; update those two commands (`kubectl -n "${JS_NAMESPACE}" logs
-l component=controller --tail=250 ...` and `kubectl -n "${JS_NAMESPACE}" logs
-l component=router --tail=250 ...`) to redirect their output directly to stderr
(use `>&2`) so kubectl errors are shown in Bats failure output.

In
`@python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl.py`:
- Around line 92-117: The current logic calls run_command(crd_cmd) and if
returncode != 0 it silently leaves result_data without an error and reports
installed=False; change this so non-zero return codes set result_data["error"]
(include the returncode and stdout/stderr text) and do not flip "installed" to
True/False based on absent output; specifically update the code around
run_command/crd_cmd and the handling of returncode to populate
result_data["error"] on failures (and avoid treating lack of jumpstarter_crds as
a clean "not installed" success), using the existing result_data and
jumpstarter_crds variables so callers can distinguish real errors from a genuine
"no CRDs" state.

---

Nitpick comments:
In
`@python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl_test.py`:
- Around line 220-228: The test
test_check_jumpstarter_installation_command_failure only simulates run_command
raising an exception, but check_jumpstarter_installation must also handle
non-zero exit codes; add a test case that makes mock_run_command return a
completed-result with a non-zero return code (and stderr containing "kubectl not
found") instead of raising, then call
check_jumpstarter_installation("test-context") and assert result.installed is
False, result.has_crds is False, and the error message contains the stderr text;
reference the same test function name and mock_run_command to locate where to
add this non-exception path test.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1c194525-ebff-4562-9606-789010160bb2

📥 Commits

Reviewing files that changed from the base of the PR and between 8896671 and fa102b3.

📒 Files selected for processing (86)
  • .cursor/rules/working-with-operator.mdc
  • .github/workflows/build-images.yaml
  • .github/workflows/controller-kind.yaml
  • .github/workflows/e2e.yaml
  • .github/workflows/lint.yaml
  • Makefile
  • controller/Makefile
  • controller/deploy/helm/jumpstarter/.helmignore
  • controller/deploy/helm/jumpstarter/Chart.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/Chart.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/model.py
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/_endpoints.tpl
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-deployment.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-ingress.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-route.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-service.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-deployment.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-ingress.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-route.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-service.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_clients.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_exporteraccesspolicies.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_exporters.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_leases.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-ingress.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-route.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-service.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/metrics/metrics_service.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/metrics/monitor.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/client_editor_role.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/client_viewer_role.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/exporter_editor_role.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/exporter_viewer_role.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role_binding.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/role.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/role_binding.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/service_account.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-deployment.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-ingress.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-route.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-service.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/secrets-job.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.schema.json
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.yaml
  • controller/deploy/helm/jumpstarter/model.py
  • controller/deploy/helm/jumpstarter/values.kind.yaml
  • controller/deploy/helm/jumpstarter/values.schema.json
  • controller/deploy/helm/jumpstarter/values.yaml
  • controller/deploy/operator/README.md
  • controller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go
  • controller/deploy/operator/test/e2e/e2e_test.go
  • controller/hack/deploy_with_helm.sh
  • controller/hack/deploy_with_operator.sh
  • controller/hack/install_helm.sh
  • controller/hack/utils
  • controller/internal/controller/suite_test.go
  • controller/internal/service/suite_test.go
  • e2e/compat/run.sh
  • e2e/compat/setup.sh
  • e2e/compat/tests-old-client.bats
  • e2e/compat/tests-old-controller.bats
  • e2e/setup-e2e.sh
  • e2e/test/compat_old_controller_test.go
  • e2e/tests.bats
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/__init__.py
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create.py
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create_test.py
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get.py
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install.py
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install_test.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/__init__.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/__init__.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/common.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/helm.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/helm_test.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl_test.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/operations.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/operations_test.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clusters.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/controller.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exceptions.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install_test.py
💤 Files with no reviewable changes (64)
  • .cursor/rules/working-with-operator.mdc
  • controller/deploy/helm/jumpstarter/.helmignore
  • controller/deploy/helm/jumpstarter/values.kind.yaml
  • .github/workflows/lint.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/exporter_editor_role.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role_binding.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/metrics/monitor.yaml
  • controller/deploy/helm/jumpstarter/Chart.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/Chart.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/exporter_viewer_role.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/role_binding.yaml
  • controller/deploy/helm/jumpstarter/values.schema.json
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/common.py
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/service_account.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-service.yaml
  • .github/workflows/build-images.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-ingress.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/_endpoints.tpl
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-route.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-service.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_clients.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/client_editor_role.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role.yaml
  • controller/deploy/helm/jumpstarter/values.yaml
  • controller/deploy/operator/README.md
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.schema.json
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clusters.py
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-route.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-ingress.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/role.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/secrets-job.yaml
  • controller/hack/install_helm.sh
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/client_viewer_role.yaml
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create_test.py
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-route.yaml
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/init.py
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-deployment.yaml
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/helm.py
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-ingress.yaml
  • controller/deploy/helm/jumpstarter/model.py
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/init.py
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-deployment.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-service.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-route.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_exporters.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_exporteraccesspolicies.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-deployment.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-service.yaml
  • controller/hack/deploy_with_helm.sh
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install_test.py
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install_test.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/init.py
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-ingress.yaml
  • e2e/test/compat_old_controller_test.go
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/model.py
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/metrics/metrics_service.yaml
  • e2e/compat/tests-old-controller.bats
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/helm_test.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install.py
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_leases.yaml
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install.py
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create.py

Comment on lines +296 to 299
BASEDOMAIN=$(kubectl get jumpstarter -n "${JS_NAMESPACE}" jumpstarter -o jsonpath='{.spec.baseDomain}')
export ENDPOINT="grpc.${BASEDOMAIN}:8082"
export LOGIN_ENDPOINT="login.${BASEDOMAIN}:8086"
log_info "Controller endpoint: $ENDPOINT"
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.

⚠️ Potential issue | 🟠 Major

Avoid hardcoded endpoint ports; read actual endpoints from the Jumpstarter CR.

Line 297 and Line 298 hardcode 8082/8086, which can break when deployment mode or endpoint config changes (e.g., ingress). Derive both values directly from spec to keep setup consistent with deployed config.

Proposed fix
-    local BASEDOMAIN
-    BASEDOMAIN=$(kubectl get jumpstarter -n "${JS_NAMESPACE}" jumpstarter -o jsonpath='{.spec.baseDomain}')
-    export ENDPOINT="grpc.${BASEDOMAIN}:8082"
-    export LOGIN_ENDPOINT="login.${BASEDOMAIN}:8086"
+    local CONTROLLER_ENDPOINT LOGIN_ENDPOINT_VALUE
+    CONTROLLER_ENDPOINT=$(kubectl get jumpstarter -n "${JS_NAMESPACE}" jumpstarter -o jsonpath='{.spec.controller.grpc.endpoints[0].address}')
+    LOGIN_ENDPOINT_VALUE=$(kubectl get jumpstarter -n "${JS_NAMESPACE}" jumpstarter -o jsonpath='{.spec.login.endpoints[0].address}')
+    if [ -z "${CONTROLLER_ENDPOINT}" ] || [ -z "${LOGIN_ENDPOINT_VALUE}" ]; then
+        log_error "Failed to resolve controller/login endpoints from Jumpstarter CR"
+        exit 1
+    fi
+    export ENDPOINT="${CONTROLLER_ENDPOINT}"
+    export LOGIN_ENDPOINT="${LOGIN_ENDPOINT_VALUE}"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e/setup-e2e.sh` around lines 296 - 299, The script currently hardcodes
ports when building ENDPOINT and LOGIN_ENDPOINT; instead query the Jumpstarter
CR for the actual endpoints/ports and use those values. Replace the kubectl
JSONPath that sets BASEDOMAIN/ENDPOINT/LOGIN_ENDPOINT with commands that read
the controller and login endpoint values from the CR spec (e.g., fields like
.spec.controllerEndpoint or .spec.endpoints.controller and .spec.loginEndpoint
or .spec.endpoints.login) and assign them to ENDPOINT and LOGIN_ENDPOINT (fall
back to the previous host:port construction only if those spec fields are
empty); update any references to BASEDOMAIN if you must derive host/port
separately so ENDPOINT and LOGIN_ENDPOINT reflect the CR configuration rather
than hardcoded ports.

e2e/tests.bats Outdated
Comment on lines +65 to +69
kubectl -n "${JS_NAMESPACE}" logs -l component=controller --tail=250 2>&1 >&2 || true

echo "" >&2
echo "--- Router logs (last 250 lines) ---" >&2
# operator uses component=router, helm uses control-plane=controller-router
kubectl -n "${JS_NAMESPACE}" logs -l component=router --tail=250 2>&1 >&2 \
|| kubectl -n "${JS_NAMESPACE}" logs -l control-plane=controller-router --tail=250 2>&1 >&2 || true
kubectl -n "${JS_NAMESPACE}" logs -l component=router --tail=250 2>&1 >&2 || true
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.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

tmpdir="$(mktemp -d)"

(
  bash -lc 'printf "stdout\n"; printf "stderr\n" >&2' 2>&1 >&2
) >"$tmpdir/current.stdout" 2>"$tmpdir/current.stderr"

(
  bash -lc 'printf "stdout\n"; printf "stderr\n" >&2' >&2
) >"$tmpdir/fixed.stdout" 2>"$tmpdir/fixed.stderr"

printf 'current.stdout:\n'
cat "$tmpdir/current.stdout"

printf '\ncurrent.stderr:\n'
cat "$tmpdir/current.stderr" || true

printf '\nfixed.stdout:\n'
cat "$tmpdir/fixed.stdout" || true

printf '\nfixed.stderr:\n'
cat "$tmpdir/fixed.stderr"

Repository: jumpstarter-dev/jumpstarter

Length of output: 359


Fix the redirection order in teardown log dumps.

Lines 65 and 69 use 2>&1 >&2 which sends both stdout and stderr to stdout instead of stderr. This causes kubectl errors to be routed away from Bats failure output. Use >&2 to send the command output directly to stderr.

Suggested fix
-    kubectl -n "${JS_NAMESPACE}" logs -l component=controller --tail=250 2>&1 >&2 || true
+    kubectl -n "${JS_NAMESPACE}" logs -l component=controller --tail=250 >&2 || true
...
-    kubectl -n "${JS_NAMESPACE}" logs -l component=router --tail=250 2>&1 >&2 || true
+    kubectl -n "${JS_NAMESPACE}" logs -l component=router --tail=250 >&2 || true
📝 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
kubectl -n "${JS_NAMESPACE}" logs -l component=controller --tail=250 2>&1 >&2 || true
echo "" >&2
echo "--- Router logs (last 250 lines) ---" >&2
# operator uses component=router, helm uses control-plane=controller-router
kubectl -n "${JS_NAMESPACE}" logs -l component=router --tail=250 2>&1 >&2 \
|| kubectl -n "${JS_NAMESPACE}" logs -l control-plane=controller-router --tail=250 2>&1 >&2 || true
kubectl -n "${JS_NAMESPACE}" logs -l component=router --tail=250 2>&1 >&2 || true
kubectl -n "${JS_NAMESPACE}" logs -l component=controller --tail=250 >&2 || true
echo "" >&2
echo "--- Router logs (last 250 lines) ---" >&2
kubectl -n "${JS_NAMESPACE}" logs -l component=router --tail=250 >&2 || true
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e/tests.bats` around lines 65 - 69, The teardown log dump redirection is
wrong: the kubectl log commands using `kubectl -n "${JS_NAMESPACE}" logs -l
component=controller --tail=250 2>&1 >&2` and the similar router line send both
streams to stdout instead of stderr; update those two commands (`kubectl -n
"${JS_NAMESPACE}" logs -l component=controller --tail=250 ...` and `kubectl -n
"${JS_NAMESPACE}" logs -l component=router --tail=250 ...`) to redirect their
output directly to stderr (use `>&2`) so kubectl errors are shown in Bats
failure output.

Comment on lines -56 to -58
old-controller)
label_filter="old-controller"
;;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why are we removing the old controller compat test?

#
# Environment variables:
# COMPAT_SCENARIO - "old-controller" or "old-client" (required)
# COMPAT_CONTROLLER_TAG - Controller image tag for old-controller scenario (default: v0.7.1)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why?

Copy link
Copy Markdown
Member

@mangelajo mangelajo Apr 9, 2026

Choose a reason for hiding this comment

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

ahh, no support in 0.7.1, I think we need to deploy the old controller (now 0.8.1) with the old operator ;)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ah, I see. Let me fix this.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If you can handle that, let's kill it 🗡️

@raballew raballew enabled auto-merge (squash) April 9, 2026 17:20
Copy link
Copy Markdown
Contributor

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@e2e/compat/setup.sh`:
- Around line 205-208: After applying the released operator-installer.yaml via
kubectl apply -f "${INSTALLER_URL}", create a Jumpstarter custom resource
instance so setup_test_environment() can read .spec.baseDomain; mirror the CR
creation from controller/hack/deploy_with_operator.sh (lines ~173-208) by
applying a Jumpstarter manifest (name as in deploy_with_operator.sh) with
spec.baseDomain set to the computed BASEDOMAIN (use the same namespace used by
the operator), ensuring this step runs immediately after the kubectl apply and
before calling setup_test_environment().
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fdb9e59c-c82e-4d79-ab26-f37ea140c28b

📥 Commits

Reviewing files that changed from the base of the PR and between fa102b3 and 0630037.

📒 Files selected for processing (3)
  • .github/workflows/e2e.yaml
  • Makefile
  • e2e/compat/setup.sh
🚧 Files skipped from review as they are similar to previous changes (2)
  • .github/workflows/e2e.yaml
  • Makefile

raballew and others added 14 commits April 11, 2026 09:24
Remove all Helm-related code, configuration, CI steps, and
documentation from the repository. The project has transitioned
to OLM operator-based deployment, making Helm artifacts dead code.

Changes:
- Delete controller/deploy/helm/ directory (43 files)
- Delete controller/hack/deploy_with_helm.sh and install_helm.sh
- Update controller Makefile to generate CRDs/RBAC directly to
  operator config paths and remove Helm targets
- Update Go test CRD paths to use operator config/crd/bases
- Remove jumpstarter_kubernetes install.py, cluster/helm.py and
  their test files
- Remove jumpstarter_cli_admin install.py and its test file
- Update all __init__.py exports to remove Helm symbols
- Update cluster/operations.py to always use operator install
- Update cluster/kubectl.py to use CRD-only detection
- Update CLI create.py and get.py to remove Helm options
- Remove publish-helm-charts job from build-images.yaml
- Remove lint-helm job from lint.yaml
- Remove Helm from controller-kind.yaml CI matrix
- Update e2e scripts to use operator-only deployment
- Update documentation and rule files

Closes jumpstarter-dev#445

Generated-By: Forge/20260409_114748_239149_5e586097

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… of swallowing

Flatten nested try/except in check_jumpstarter_installation so that
RuntimeError from run_command (e.g. kubectl not found, permission
errors) propagates to the outer handler that properly reports the
error. Previously the inner `except RuntimeError: pass` silently
swallowed the error, making it impossible for callers to distinguish
"not installed" from "failed to check".

Generated-By: Forge/20260409_114748_239149_5e586097

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rter_installation

After removing the nested Helm detection logic, the function complexity
is well under the C901 threshold. The suppression comment is no longer
needed.

Generated-By: Forge/20260409_114748_239149_5e586097

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Helm deployment method has been removed. Update the Makefile
comment and help text to no longer advertise helm as a valid option.

Generated-By: Forge/20260409_114748_239149_5e586097

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The chart_name/chartName field was only populated by the Helm detection
code path which has been removed. The field was permanently None,
making it dead structure in the API model.

Generated-By: Forge/20260409_114748_239149_5e586097

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The comment said COMPAT_CONTROLLER_TAG defaults to v0.7.1 but the
actual default on line 31 is v0.7.0.

Generated-By: Forge/20260409_114748_239149_5e586097

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… Helm chart repo

The Helm chart publishing CI job is being removed, so the function
querying quay.io/jumpstarter-dev/helm/jumpstarter for version tags
will return stale results. Switch to querying the operator image
repository (jumpstarter-dev/jumpstarter-operator) which continues
to receive new version tags with each release.

Generated-By: Forge/20260409_114748_239149_5e586097

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…setup

Instead of silently falling back to a default domain when the
Jumpstarter CR cannot be found, fail immediately with an actionable
error message. This prevents misleading test failures caused by
connecting to the wrong endpoint.

Generated-By: Forge/20260409_114748_239149_5e586097

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Only one deployment method (operator) remains, so the METHOD variable
is unnecessary indirection. Remove it from the root Makefile and the
controller Makefile, and drop redundant METHOD=operator arguments from
deploy-with-operator targets.

Generated-By: Forge/20260409_114748_239149_5e586097

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Since Helm support was removed, "operator" is the only deployment
method. Remove the METHOD variable, its branching logic, and the
parameterized print_deployment_success function throughout the
e2e scripts, CI workflows, and hack utilities.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ler)

v0.7.0 predates the monorepo merge and was only deployable via OCI Helm
chart. With Helm fully removed, the old-controller compat test cannot
deploy a v0.7.0 controller. Remove the test, its CI job, and simplify
the compat infrastructure to only support the old-client scenario.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.7.0 predated the operator installer and was only deployable via Helm.
Replace it with v0.8.1 which ships an operator-installer.yaml release
asset. Also bump old-client version from 0.7.1 to 0.8.1 so both compat
scenarios test against the previous release.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The revert commit brought back tests-old-controller.bats, but upstream
converted all bats tests to ginkgo. The ginkgo equivalent
(e2e/test/compat_old_controller_test.go) is the canonical test file.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@raballew raballew force-pushed the 042-remove-helm-charts branch from 0630037 to e15a5cc Compare April 11, 2026 07:27
- Create Jumpstarter CR after applying operator installer in compat
  setup, since the released installer only contains CRDs and operator
  deployment, not the CR instance
- Align Makefile install/uninstall/build-installer/undeploy targets with
  the manifests output path (deploy/operator/config/ instead of config/)
- Surface non-zero kubectl exit codes as errors in
  check_jumpstarter_installation instead of silently reporting
  installed=False
- Add test for non-zero exit code path in
  check_jumpstarter_installation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@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: 1

♻️ Duplicate comments (2)
python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl.py (1)

93-113: ⚠️ Potential issue | 🟠 Major

Handle non-zero CRD command exits explicitly.

Line 95 only handles success. If run_command returns non-zero, this currently looks like a clean “not installed” result instead of an execution failure (e.g., RBAC/context errors).

Proposed fix
-        returncode, stdout, _ = await run_command(crd_cmd)
-
-        if returncode == 0:
-            json_start = stdout.find("{")
-            if json_start >= 0:
-                json_output = stdout[json_start:]
-                crds = json.loads(json_output)
-            else:
-                crds = json.loads(stdout)
-            jumpstarter_crds = []
-            for item in crds.get("items", []):
-                name = item.get("metadata", {}).get("name", "")
-                if "jumpstarter.dev" in name:
-                    jumpstarter_crds.append(name)
-
-            if jumpstarter_crds:
-                result_data["has_crds"] = True
-                result_data["installed"] = True
-                result_data["namespace"] = namespace or "unknown"
-                result_data["status"] = "installed"
+        returncode, stdout, stderr = await run_command(crd_cmd)
+        if returncode != 0:
+            result_data["error"] = f"Failed to query CRDs (exit {returncode}): {stderr or stdout}"
+            return V1Alpha1JumpstarterInstance(**result_data)
+
+        json_start = stdout.find("{")
+        if json_start >= 0:
+            json_output = stdout[json_start:]
+            crds = json.loads(json_output)
+        else:
+            crds = json.loads(stdout)
+        jumpstarter_crds = []
+        for item in crds.get("items", []):
+            name = item.get("metadata", {}).get("name", "")
+            if "jumpstarter.dev" in name:
+                jumpstarter_crds.append(name)
+
+        if jumpstarter_crds:
+            result_data["has_crds"] = True
+            result_data["installed"] = True
+            result_data["namespace"] = namespace or "unknown"
+            result_data["status"] = "installed"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl.py`
around lines 93 - 113, The code currently treats any non-zero return from
run_command(crd_cmd) as a benign "not installed" path; change the logic in the
block that calls run_command so that when returncode != 0 you explicitly handle
the execution failure: read the captured stderr (the third value returned by
run_command), set result_data["status"] = "error" (or raise an informative
exception), include returncode and stderr (and namespace/context) in the error
information, and avoid marking result_data["installed"] = True — update the
branch around run_command/crd_cmd and the result_data assignments to reflect
this explicit error handling.
e2e/compat/setup.sh (1)

106-109: ⚠️ Potential issue | 🔴 Critical

Apply a Jumpstarter resource after the released installer.

The released operator-installer.yaml installs the operator/CRDs, but not the jumpstarter custom resource the operator reconciles. In the old-controller path that leaves nothing for the operator to deploy, so the gRPC wait loop below times out and the later .spec.baseDomain lookup also fails.

Please verify against the tagged release asset. Expected result: the installer contains no kind: Jumpstarter, which confirms this script must create one itself immediately after the kubectl apply.

#!/bin/bash
set -euo pipefail

tag="${COMPAT_CONTROLLER_TAG:-v0.8.1}"
tmp="$(mktemp)"
trap 'rm -f "$tmp"' EXIT

curl -LsSf \
  "https://github.com/jumpstarter-dev/jumpstarter/releases/download/${tag}/operator-installer.yaml" \
  -o "$tmp"

echo "== resource kinds in ${tag}/operator-installer.yaml =="
rg -n '^kind:\s*' "$tmp"

echo
echo "== Jumpstarter CRs in installer =="
rg -n '^kind:\s*Jumpstarter$' "$tmp" || true
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e/compat/setup.sh` around lines 106 - 109, After applying the released
operator-installer.yaml (the INSTALLER_URL built from COMPAT_CONTROLLER_TAG),
immediately create and apply a minimal Jumpstarter custom resource so the old
operator has something to reconcile; construct a Jumpstarter manifest
(apiVersion jumpstarter.dev/v1alpha1, kind Jumpstarter, metadata name e.g.
"jumpstarter") with the required spec (at least spec.baseDomain set from your
cluster/base domain variable) and kubectl apply it right after the kubectl apply
-f "${INSTALLER_URL}" line to avoid the gRPC wait loop timing out and the later
.spec.baseDomain lookup failing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@e2e/setup-e2e.sh`:
- Around line 282-288: The script assigns BASEDOMAIN from kubectl get
jumpstarter but doesn't validate it; if empty it exports invalid
ENDPOINT/LOGIN_ENDPOINT. After BASEDOMAIN=$(kubectl get jumpstarter ...), check
if BASEDOMAIN is empty/blank and if so print an error (including the
JS_NAMESPACE and the kubectl command context) and exit non‑zero to fail fast;
otherwise export ENDPOINT="grpc.${BASEDOMAIN}:8082" and
LOGIN_ENDPOINT="login.${BASEDOMAIN}:8086". Ensure this validation runs under the
existing set -e behavior so failures propagate.

---

Duplicate comments:
In `@e2e/compat/setup.sh`:
- Around line 106-109: After applying the released operator-installer.yaml (the
INSTALLER_URL built from COMPAT_CONTROLLER_TAG), immediately create and apply a
minimal Jumpstarter custom resource so the old operator has something to
reconcile; construct a Jumpstarter manifest (apiVersion
jumpstarter.dev/v1alpha1, kind Jumpstarter, metadata name e.g. "jumpstarter")
with the required spec (at least spec.baseDomain set from your cluster/base
domain variable) and kubectl apply it right after the kubectl apply -f
"${INSTALLER_URL}" line to avoid the gRPC wait loop timing out and the later
.spec.baseDomain lookup failing.

In
`@python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl.py`:
- Around line 93-113: The code currently treats any non-zero return from
run_command(crd_cmd) as a benign "not installed" path; change the logic in the
block that calls run_command so that when returncode != 0 you explicitly handle
the execution failure: read the captured stderr (the third value returned by
run_command), set result_data["status"] = "error" (or raise an informative
exception), include returncode and stderr (and namespace/context) in the error
information, and avoid marking result_data["installed"] = True — update the
branch around run_command/crd_cmd and the result_data assignments to reflect
this explicit error handling.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 43ff7ac7-0567-4906-a8b0-f68d4d33eba5

📥 Commits

Reviewing files that changed from the base of the PR and between 0630037 and e15a5cc.

📒 Files selected for processing (80)
  • .cursor/rules/working-with-operator.mdc
  • .github/workflows/build-images.yaml
  • .github/workflows/controller-kind.yaml
  • .github/workflows/e2e.yaml
  • .github/workflows/lint.yaml
  • Makefile
  • controller/Makefile
  • controller/deploy/helm/jumpstarter/.helmignore
  • controller/deploy/helm/jumpstarter/Chart.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/Chart.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/model.py
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/_endpoints.tpl
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-deployment.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-ingress.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-route.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-service.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-deployment.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-ingress.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-route.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-service.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_clients.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_exporteraccesspolicies.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_exporters.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_leases.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-ingress.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-route.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-service.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/metrics/metrics_service.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/metrics/monitor.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/client_editor_role.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/client_viewer_role.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/exporter_editor_role.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/exporter_viewer_role.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role_binding.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/role.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/role_binding.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/service_account.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-deployment.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-ingress.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-route.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-service.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/secrets-job.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.schema.json
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.yaml
  • controller/deploy/helm/jumpstarter/model.py
  • controller/deploy/helm/jumpstarter/values.kind.yaml
  • controller/deploy/helm/jumpstarter/values.schema.json
  • controller/deploy/helm/jumpstarter/values.yaml
  • controller/deploy/operator/README.md
  • controller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go
  • controller/hack/deploy_with_helm.sh
  • controller/hack/deploy_with_operator.sh
  • controller/hack/install_helm.sh
  • controller/hack/utils
  • controller/internal/controller/suite_test.go
  • controller/internal/service/suite_test.go
  • e2e/compat/setup.sh
  • e2e/setup-e2e.sh
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/__init__.py
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create.py
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create_test.py
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/get.py
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install.py
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install_test.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/__init__.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/__init__.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/common.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/helm.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/helm_test.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl_test.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/operations.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/operations_test.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clusters.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/controller.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exceptions.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install_test.py
💤 Files with no reviewable changes (62)
  • .cursor/rules/working-with-operator.mdc
  • controller/deploy/helm/jumpstarter/.helmignore
  • controller/deploy/helm/jumpstarter/Chart.yaml
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/clusters.py
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/Chart.yaml
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/common.py
  • controller/deploy/operator/README.md
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/exporter_editor_role.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/role_binding.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/client_editor_role.yaml
  • controller/deploy/helm/jumpstarter/values.schema.json
  • .github/workflows/lint.yaml
  • controller/deploy/helm/jumpstarter/values.kind.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role_binding.yaml
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/init.py
  • controller/deploy/helm/jumpstarter/values.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/service_account.yaml
  • controller/hack/install_helm.sh
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/exporter_viewer_role.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/leader_election_role.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/metrics/monitor.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-route.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/_endpoints.tpl
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/helm.py
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-service.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_clients.yaml
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create_test.py
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-service.yaml
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/init.py
  • controller/deploy/helm/jumpstarter/model.py
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-service.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-ingress.yaml
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/init.py
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/client_viewer_role.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/rbac/role.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-route.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.yaml
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install_test.py
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-route.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/cms/controller-cm.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-ingress.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/secrets-job.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_exporters.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-ingress.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-route.yaml
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install_test.py
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_exporteraccesspolicies.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/values.schema.json
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-deployment.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/controller-service.yaml
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/helm_test.py
  • controller/hack/deploy_with_helm.sh
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/create.py
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/router-deployment.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/crds/jumpstarter.dev_leases.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/additional-router-deployment.yaml
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/login-ingress.yaml
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/install.py
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/model.py
  • .github/workflows/build-images.yaml
  • python/packages/jumpstarter-cli-admin/jumpstarter_cli_admin/install.py
  • controller/deploy/helm/jumpstarter/charts/jumpstarter-controller/templates/metrics/metrics_service.yaml
✅ Files skipped from review due to trivial changes (4)
  • controller/internal/controller/suite_test.go
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/controller.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/exceptions.py
  • controller/deploy/operator/internal/controller/jumpstarter/jumpstarter_controller.go
🚧 Files skipped from review as they are similar to previous changes (8)
  • .github/workflows/controller-kind.yaml
  • controller/internal/service/suite_test.go
  • controller/hack/utils
  • .github/workflows/e2e.yaml
  • Makefile
  • controller/Makefile
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/operations_test.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/operations.py

If the Jumpstarter CR is missing or baseDomain is not set, exit
immediately instead of exporting invalid endpoints like grpc.:8082.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@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.

🧹 Nitpick comments (1)
python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl_test.py (1)

371-376: This doesn't actually exercise the custom minikube path.

Because Line 372 returns no contexts, list_clusters() exits before any downstream call can observe minikube="custom-minikube". Consider returning one context and asserting the follow-up cluster-info call receives the custom binary path too.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl_test.py`
around lines 371 - 376, The test test_list_clusters_custom_parameters currently
returns no contexts so list_clusters exits early; change the mock_get_contexts
return to include a context (e.g., ["some-context"]) so the code proceeds, then
assert that the subsequent call that invokes cluster info (the mock for
whichever helper is used to run minikube/cluster-info in list_clusters) was
called with minikube="custom-minikube" (and keep asserting
mock_get_contexts.assert_called_once_with("custom-kubectl")); update references
to the mocks used in this test (mock_get_contexts and the mock for
cluster-info/runner used by list_clusters) to validate both custom kubectl and
custom minikube are passed through.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl_test.py`:
- Around line 371-376: The test test_list_clusters_custom_parameters currently
returns no contexts so list_clusters exits early; change the mock_get_contexts
return to include a context (e.g., ["some-context"]) so the code proceeds, then
assert that the subsequent call that invokes cluster info (the mock for
whichever helper is used to run minikube/cluster-info in list_clusters) was
called with minikube="custom-minikube" (and keep asserting
mock_get_contexts.assert_called_once_with("custom-kubectl")); update references
to the mocks used in this test (mock_get_contexts and the mock for
cluster-info/runner used by list_clusters) to validate both custom kubectl and
custom minikube are passed through.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4b6a2325-119d-4569-a0dc-4bde621153da

📥 Commits

Reviewing files that changed from the base of the PR and between e15a5cc and 1863f3f.

📒 Files selected for processing (5)
  • controller/Makefile
  • e2e/compat/setup.sh
  • e2e/setup-e2e.sh
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl.py
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl_test.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • python/packages/jumpstarter-kubernetes/jumpstarter_kubernetes/cluster/kubectl.py

raballew and others added 2 commits April 11, 2026 09:54
The old-client compat test deploys the new controller via
deploy_new_controller(), which needs the operator image loaded into kind.
Download and load the pre-built operator image and manifest, matching
how the main e2e-tests job handles this.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The jumpstarter base package was never published at 0.8.1 on PyPI,
making the entire 0.8.1 client stack uninstallable. Fall back to 0.7.4
which is the latest version where all packages are available.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@raballew
Copy link
Copy Markdown
Member Author

@mangelajo ptal again. i have applied your suggestion but i think branch protection rules stop CI from passing.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove Helm and keep only operator-based deployment

2 participants