Contributor Guide#
Development guide for Jupyter K8s — the Kubernetes operator for Jupyter notebooks and interactive IDEs.
Prerequisites#
Go (version from
go.mod)Docker or Finch (container runtime)
Helm (v3.12+)
Kind (for local clusters)
kubectl
Install all toolchain dependencies:
make deps
Project setup#
Fork and clone the repository to your local workspace, then run:
make deps
make build
Build#
make build
Lint#
make lint-fix # auto-fix where possible
make lint # check only
Unit tests#
Run all unit tests:
make test
Run specific tests#
Target a single package:
go test ./internal/controller/... -v
Target a single test function:
go test ./internal/controller/... -run TestNewWorkspaceIdleChecker_Success -v
Get targeted coverage#
Generate a coverage report for a specific package:
go test ./internal/controller/... -coverprofile=cover.out
go tool cover -html=cover.out
Code review#
Pull requests are reviewed automatically by roborev, which posts a review comment on each revision. You can run the same review locally before pushing to catch issues early.
Install roborev from roborev.io, then:
make review
This reviews your current branch against main using whatever AI coding agent you have
installed (claude-code, codex, gemini, and others), with no daemon or background process. It
shares the policy file (.roborev.toml) with CI. CI runs the full matrix defined there (the
default and security review types); a local run does a single review, so push to get the
complete CI review.
To review every commit automatically instead of on demand (opt-in):
make review-setup # one-time: installs the roborev post-commit hook
roborev show HEAD # view the latest review
roborev refine # iterate: review, fix, repeat
Local review is optional; CI reviews every PR regardless.
Local cluster#
Container runtime#
The Makefile defaults to Finch (CONTAINER_TOOL=finch). To use Docker instead, pass the override:
make setup-kind CONTAINER_TOOL=docker
make deploy-kind CONTAINER_TOOL=docker
Or export it for the session:
export CONTAINER_TOOL=docker
Setup#
Create a Kind cluster and deploy the operator:
make setup-kind
make deploy-kind
What gets deployed#
make deploy-kind installs the Helm chart into the jupyter-k8s-system namespace with:
CRDs — Workspace, WorkspaceTemplate, WorkspaceAccessStrategy
Manager — a single pod running both the controller and the Extension API server
JWT Secret — HMAC signing key for the Extension API
JWT Rotator — a CronJob that rotates the signing key
Use kubectl#
After deploy-kind, your kubectl context points to the Kind cluster. Use it directly:
make kubectl-kind # switch context if needed
kubectl get pods -n jupyter-k8s-system
kubectl logs -n jupyter-k8s-system deployment/jupyter-k8s-controller-manager
Apply samples#
Deploy sample workspaces from config/samples/:
make apply-samples
kubectl get workspaces
Remove them:
make delete-samples
Port forward to a workspace#
Connect to a running workspace in your browser:
make port-forward
This lists available workspaces, prompts you for one, and opens a port-forward on localhost:8888 (macOS) or hostname:9888 (Linux).
Teardown#
make teardown-kind
End-to-end tests#
Run#
E2E tests spin up a separate Kind cluster:
make test-e2e
Run focused tests#
make test-e2e-focus FOCUS="Workspace Access Strategy"
Lint#
make lint-e2e
Helm chart#
When modifying the Helm chart, edit files under /api, /config, and /hack, then regenerate:
make helm-generate # outputs to dist/chart/
make helm-lint
make helm-test # results in dist/test-output-crd-only/
Documentation#
Build#
make docs # render diagrams + build HTML
make docs-serve # live-reload dev server on :8080
Diagrams#
Architecture diagrams live as D2 source files in diagrams/. The build renders them to SVG:
make docs-diagrams # renders diagrams/*.d2 → docs/source/_static/img/diagrams/*.svg
Edit .d2 files directly, then run make docs to see the result. See diagrams/AGENT.md for conventions.
Structure#
Source files live in docs/source/. The site uses Sphinx + MyST Markdown with the Shibuya theme. See docs/AGENT.md for formatting rules.
AWS development (ECR)#
Push images to an AWS ECR registry:
make setup-aws EKS_CLUSTER_NAME=<cluster> AWS_REGION=<region>
make load-images-aws
make kubectl-aws
Guided chart deployment and testing lives in jupyter-k8s-aws.
Release process#
Releases run via GitHub Actions workflow dispatch:
A maintainer triggers the
Releaseworkflow with a version (e.g.v0.2.0).The pipeline builds images and pushes them to the staging registry (
ghcr.io/jupyter-infra/staging).It packages the Helm chart and pushes it to the staging OCI registry.
E2E tests run against the staged artifacts.
On success, the pipeline promotes images and chart to the production registry (
ghcr.io/jupyter-infra).A GitHub Release appears with auto-generated release notes.
Before submitting a PR#
make build
make lint
make test
make helm-test
Project structure#
Directory |
Contents |
|---|---|
|
CRD Go types and markers |
|
Reconciliation loops |
|
Mutating and admission webhooks |
|
Extension API server (Connection APIs) |
|
Auth middleware handling workspace access |
|
JWT key rotation image for CronJob |
|
Controller-side plugin adapter interfaces |
|
AWS-specific adapter (SSM orchestration) |
|
Kubebuilder kustomize overlays |
|
Generated Helm chart output |
|
Container images (auth middleware, rotator, reference apps) |
|
Sphinx documentation source |
|
D2 architecture diagram sources |