From 22aa2c995380e989c047080cc0a5290efe6119e5 Mon Sep 17 00:00:00 2001 From: James Sturtevant Date: Sat, 7 Nov 2026 17:36:22 -0800 Subject: [PATCH 1/7] docs: clarify setup requirements and organize demos Signed-off-by: James Sturtevant --- README.md | 15 +++++++++++++-- cli/tests/dev.rs | 2 +- .../local-worker-workspace/.gitignore | 0 .../local-worker-workspace/lampyr.workspace.yaml | 0 .../services/api/Dockerfile | 0 .../services/api/Dockerfile.rootfs | 0 .../services/api/lampyr.yaml | 0 .../local-worker-workspace/services/api/server.js | 0 .../services/processor/Dockerfile | 0 .../services/processor/Dockerfile.rootfs | 0 .../services/processor/lampyr.yaml | 0 .../services/processor/server.js | 0 .../services/reused/Dockerfile | 0 .../services/reused/Dockerfile.rootfs | 0 .../services/reused/lampyr.yaml | 0 .../services/reused/server.js | 0 docs/cli/dev.md | 6 +++--- lampyr.workspace.yaml | 2 -- 18 files changed, 17 insertions(+), 8 deletions(-) rename {samples => demos}/local-worker-workspace/.gitignore (100%) rename {samples => demos}/local-worker-workspace/lampyr.workspace.yaml (100%) rename {samples => demos}/local-worker-workspace/services/api/Dockerfile (100%) rename {samples => demos}/local-worker-workspace/services/api/Dockerfile.rootfs (100%) rename {samples => demos}/local-worker-workspace/services/api/lampyr.yaml (100%) rename {samples => demos}/local-worker-workspace/services/api/server.js (100%) rename {samples => demos}/local-worker-workspace/services/processor/Dockerfile (100%) rename {samples => demos}/local-worker-workspace/services/processor/Dockerfile.rootfs (100%) rename {samples => demos}/local-worker-workspace/services/processor/lampyr.yaml (100%) rename {samples => demos}/local-worker-workspace/services/processor/server.js (100%) rename {samples => demos}/local-worker-workspace/services/reused/Dockerfile (100%) rename {samples => demos}/local-worker-workspace/services/reused/Dockerfile.rootfs (100%) rename {samples => demos}/local-worker-workspace/services/reused/lampyr.yaml (100%) rename {samples => demos}/local-worker-workspace/services/reused/server.js (100%) delete mode 100644 lampyr.workspace.yaml diff --git a/README.md b/README.md index 7dda745..e242d1c 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,20 @@ short-lived, hardware-isolated microVMs when work arrives. ## Getting started +### Prerequisites + +Install [Docker with Buildx](https://docs.docker.com/get-started/get-docker/) +and [kubectl](https://kubernetes.io/docs/tasks/tools/) on your `PATH`. +For the release installer below, also install the GitHub CLI (`gh`) and +authenticate with `gh auth login`. + +On Linux, also enable [KVM](https://documentation.ubuntu.com/server/how-to/virtualisation/libvirt/) +(Ubuntu setup guide). Your user must have read/write access to `/dev/kvm`. + ### Install the CLI Install `ly` and its platform bundle from the latest release on Linux/amd64 or -macOS/arm64. The installer checks every archive's checksum and GitHub +macOS/arm64. Use WSL on Windows. The installer checks every archive's checksum and GitHub attestation; see [`ly setup`](docs/cli/setup.md) for the verified install. ```bash @@ -50,7 +60,8 @@ export PATH="$HOME/.local/bin:$PATH" ly doctor ``` -To build `ly` from a checkout instead, run `just build-ly`. +To build `ly` from a checkout instead, run `just build-ly` and add it to your +`PATH` with `export PATH="$PWD/build:$PATH"`. ### Walkthrough diff --git a/cli/tests/dev.rs b/cli/tests/dev.rs index f3042a3..ee87be9 100644 --- a/cli/tests/dev.rs +++ b/cli/tests/dev.rs @@ -6,7 +6,7 @@ use std::process::Command; use lampyr_cli::project::Project; fn fixture() -> std::path::PathBuf { - std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("../samples/local-worker-workspace") + std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("../demos/local-worker-workspace") } #[test] diff --git a/samples/local-worker-workspace/.gitignore b/demos/local-worker-workspace/.gitignore similarity index 100% rename from samples/local-worker-workspace/.gitignore rename to demos/local-worker-workspace/.gitignore diff --git a/samples/local-worker-workspace/lampyr.workspace.yaml b/demos/local-worker-workspace/lampyr.workspace.yaml similarity index 100% rename from samples/local-worker-workspace/lampyr.workspace.yaml rename to demos/local-worker-workspace/lampyr.workspace.yaml diff --git a/samples/local-worker-workspace/services/api/Dockerfile b/demos/local-worker-workspace/services/api/Dockerfile similarity index 100% rename from samples/local-worker-workspace/services/api/Dockerfile rename to demos/local-worker-workspace/services/api/Dockerfile diff --git a/samples/local-worker-workspace/services/api/Dockerfile.rootfs b/demos/local-worker-workspace/services/api/Dockerfile.rootfs similarity index 100% rename from samples/local-worker-workspace/services/api/Dockerfile.rootfs rename to demos/local-worker-workspace/services/api/Dockerfile.rootfs diff --git a/samples/local-worker-workspace/services/api/lampyr.yaml b/demos/local-worker-workspace/services/api/lampyr.yaml similarity index 100% rename from samples/local-worker-workspace/services/api/lampyr.yaml rename to demos/local-worker-workspace/services/api/lampyr.yaml diff --git a/samples/local-worker-workspace/services/api/server.js b/demos/local-worker-workspace/services/api/server.js similarity index 100% rename from samples/local-worker-workspace/services/api/server.js rename to demos/local-worker-workspace/services/api/server.js diff --git a/samples/local-worker-workspace/services/processor/Dockerfile b/demos/local-worker-workspace/services/processor/Dockerfile similarity index 100% rename from samples/local-worker-workspace/services/processor/Dockerfile rename to demos/local-worker-workspace/services/processor/Dockerfile diff --git a/samples/local-worker-workspace/services/processor/Dockerfile.rootfs b/demos/local-worker-workspace/services/processor/Dockerfile.rootfs similarity index 100% rename from samples/local-worker-workspace/services/processor/Dockerfile.rootfs rename to demos/local-worker-workspace/services/processor/Dockerfile.rootfs diff --git a/samples/local-worker-workspace/services/processor/lampyr.yaml b/demos/local-worker-workspace/services/processor/lampyr.yaml similarity index 100% rename from samples/local-worker-workspace/services/processor/lampyr.yaml rename to demos/local-worker-workspace/services/processor/lampyr.yaml diff --git a/samples/local-worker-workspace/services/processor/server.js b/demos/local-worker-workspace/services/processor/server.js similarity index 100% rename from samples/local-worker-workspace/services/processor/server.js rename to demos/local-worker-workspace/services/processor/server.js diff --git a/samples/local-worker-workspace/services/reused/Dockerfile b/demos/local-worker-workspace/services/reused/Dockerfile similarity index 100% rename from samples/local-worker-workspace/services/reused/Dockerfile rename to demos/local-worker-workspace/services/reused/Dockerfile diff --git a/samples/local-worker-workspace/services/reused/Dockerfile.rootfs b/demos/local-worker-workspace/services/reused/Dockerfile.rootfs similarity index 100% rename from samples/local-worker-workspace/services/reused/Dockerfile.rootfs rename to demos/local-worker-workspace/services/reused/Dockerfile.rootfs diff --git a/samples/local-worker-workspace/services/reused/lampyr.yaml b/demos/local-worker-workspace/services/reused/lampyr.yaml similarity index 100% rename from samples/local-worker-workspace/services/reused/lampyr.yaml rename to demos/local-worker-workspace/services/reused/lampyr.yaml diff --git a/samples/local-worker-workspace/services/reused/server.js b/demos/local-worker-workspace/services/reused/server.js similarity index 100% rename from samples/local-worker-workspace/services/reused/server.js rename to demos/local-worker-workspace/services/reused/server.js diff --git a/docs/cli/dev.md b/docs/cli/dev.md index 61f38ad..5291565 100644 --- a/docs/cli/dev.md +++ b/docs/cli/dev.md @@ -166,13 +166,13 @@ never be copied to a different architecture or hypervisor for deployment. ### Executable multi-service example -`samples/local-worker-workspace/` contains dependency-free Node.js +`demos/local-worker-workspace/` contains dependency-free Node.js Standalone Applications. Its API has several HTTP handlers, calls a fresh processor, emits a CloudEvent to that processor, and calls a service explicitly configured for reuse: ```bash -ly dev samples/local-worker-workspace +ly dev demos/local-worker-workspace curl http://worker-api.default.localhost:8080/invoke curl http://worker-api.default.localhost:8080/emit curl http://worker-api.default.localhost:8080/reuse @@ -269,7 +269,7 @@ No Hyperlight source checkout, Cargo overrides or runtime descriptor is needed: ```bash just build-ly -build/ly dev samples/local-worker-workspace --port 8080 +build/ly dev demos/local-worker-workspace --port 8080 ``` Lampyr downloads and verifies the released v0.21.0 executable and matching diff --git a/lampyr.workspace.yaml b/lampyr.workspace.yaml deleted file mode 100644 index f127330..0000000 --- a/lampyr.workspace.yaml +++ /dev/null @@ -1,2 +0,0 @@ -apiVersion: lampyr.dev/v1alpha1 -kind: Workspace From cfe1712a26a0be9273c68a7276cf1cc777d3d5a4 Mon Sep 17 00:00:00 2001 From: James Sturtevant Date: Sat, 7 Nov 2026 19:01:33 -0800 Subject: [PATCH 2/7] fixup! docs: clarify setup requirements and organize demos Signed-off-by: James Sturtevant --- scripts/tests/test_preview_workflow.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/scripts/tests/test_preview_workflow.py b/scripts/tests/test_preview_workflow.py index d8866f7..d34d7c5 100644 --- a/scripts/tests/test_preview_workflow.py +++ b/scripts/tests/test_preview_workflow.py @@ -604,6 +604,31 @@ def test_arm64_provider_builds_are_parallel_and_cached(self): self.assertIn("FROM --platform=$BUILDPLATFORM golang:", dockerfile) self.assertIn('GOOS="$TARGETOS" GOARCH="$TARGETARCH"', dockerfile) + def test_checkout_cluster_workflow_uses_a_separate_workspace(self): + self.assertFalse((ROOT / "lampyr.workspace.yaml").exists()) + justfile = (ROOT / "Justfile").read_text(encoding="utf-8") + self.assertIn('env_var_or_default("LAMPYR_WORKSPACE", repo-root / "build/workspace")', justfile) + self.assertIn('build/ly scaffold workspace "{{workspace}}"', justfile) + for recipe in ["cluster-install", "cluster-install-k3d", "cluster-install-azure"]: + with self.subTest(recipe=recipe): + dry_run = subprocess.run( + ["just", "--dry-run", recipe, *(["provider.yaml"] if recipe.endswith("azure") else [])], + cwd=ROOT, + check=True, + text=True, + capture_output=True, + ) + self.assertIn("scaffold workspace", dry_run.stderr) + self.assertIn(f'--workspace "{ROOT / "build/workspace"}"', dry_run.stderr) + job = self.ci["jobs"]["new-developer-workflow"] + self.assertEqual(job["env"]["LAMPYR_WORKSPACE"], "${{ github.workspace }}/build/workspace") + apps = named(job, "Run, build and deploy the demo apps")["run"] + self.assertIn('cd "$LAMPYR_WORKSPACE"', apps) + self.assertIn('"$repo/build/ly" scaffold service "$app"', apps) + cleanup = named(job, "Call the deployed apps through Kourier")["run"] + self.assertIn('build/ly delete "$LAMPYR_WORKSPACE/services/demo-app"', cleanup) + self.assertIn('--workspace "$LAMPYR_WORKSPACE"', cleanup) + def test_new_developer_timeout_leaves_diagnostic_headroom(self): job = self.ci["jobs"]["new-developer-workflow"] diagnostics = named(job, "Collect diagnostics")["timeout-minutes"] From c6b41238d392289c4d537153d401e1f1449c2ee3 Mon Sep 17 00:00:00 2001 From: James Sturtevant Date: Sat, 7 Nov 2026 19:09:54 -0800 Subject: [PATCH 3/7] fixup! docs: clarify setup requirements and organize demos Signed-off-by: James Sturtevant --- .github/workflows/ci.yml | 21 +++++++++------ Justfile | 32 ++++++++++++---------- docs/cli/cluster.md | 37 +++++++++++++++++++------- docs/cluster-k3d.md | 18 +++++++------ docs/cluster-kind.md | 20 ++++++++------ scripts/tests/test_preview_workflow.py | 25 ++++++++++++++++- 6 files changed, 105 insertions(+), 48 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0999e06..47aa0f8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1234,6 +1234,8 @@ jobs: new-developer-workflow: needs: [cluster-inputs] runs-on: ubuntu-latest + env: + LAMPYR_WORKSPACE: ${{ github.workspace }}/build/workspace # Above the steps' own limits: a step that times out fails, and failed # steps get diagnostics; a job that times out is cancelled instead. timeout-minutes: 50 @@ -1306,6 +1308,7 @@ jobs: # runner paths explicitly. exec sudo --user="$(id --user --name)" /usr/bin/env \ "PATH=$PATH" \ + "LAMPYR_WORKSPACE=$LAMPYR_WORKSPACE" \ "GITHUB_ENV=$GITHUB_ENV" \ "GITHUB_OUTPUT=$GITHUB_OUTPUT" \ "GITHUB_PATH=$GITHUB_PATH" \ @@ -1412,20 +1415,22 @@ jobs: - name: Run, build and deploy the demo apps timeout-minutes: 25 run: | + repo="$PWD" + cd "$LAMPYR_WORKSPACE" answers() { curl --fail --silent --show-error --max-time 10 \ -H "Host: $app.default.localhost" http://127.0.0.1:8080/test \ | tee /dev/stderr | grep "hello from $app" > /dev/null } for app in demo-app second-app; do - build/ly scaffold service "$app" + "$repo/build/ly" scaffold service "$app" service="services/$app" - source scripts/runtime-examples.sh + source "$repo/scripts/runtime-examples.sh" expose_workspace_services "$PWD" # Each app says its own name, so a response shows which one answered. sed --in-place "s/hello from Hyperlight edge/hello from $app/" "$service/handler.js" grep --quiet "hello from $app" "$service/handler.js" - build/ly dev --port 8080 "$service" > "$RUNNER_TEMP/$app-dev.log" 2>&1 & + "$repo/build/ly" dev --port 8080 "$service" > "$RUNNER_TEMP/$app-dev.log" 2>&1 & dev=$! ok= for _ in $(seq 120); do @@ -1435,8 +1440,8 @@ jobs: done if [ -z "$ok" ]; then cat "$RUNNER_TEMP/$app-dev.log"; exit 1; fi - build/ly build "$service" - build/ly deploy --image "localhost:5002/$app:v1" "$service" + "$repo/build/ly" build "$service" + "$repo/build/ly" deploy --image "localhost:5002/$app:v1" "$service" # ly build rewrote the rootfs that ly dev is running from. kill -0 "$dev" || { cat "$RUNNER_TEMP/$app-dev.log"; exit 1; } answers || { cat "$RUNNER_TEMP/$app-dev.log"; exit 1; } @@ -1466,10 +1471,10 @@ jobs: | tee /dev/stderr | grep "hello from $app" > /dev/null done # Free the smoke-test homes before the walkthrough deploys its own app. - build/ly delete services/demo-app - build/ly delete services/second-app + build/ly delete "$LAMPYR_WORKSPACE/services/demo-app" + build/ly delete "$LAMPYR_WORKSPACE/services/second-app" # The walkthrough owns a separate disposable installation and registry. - build/ly cluster uninstall --provider kind --delete-cluster + build/ly cluster uninstall --provider kind --delete-cluster --workspace "$LAMPYR_WORKSPACE" - name: Check that /dev/kvm is unchanged if: always() diff --git a/Justfile b/Justfile index a6ee584..82e253d 100644 --- a/Justfile +++ b/Justfile @@ -11,6 +11,7 @@ mod upstream 'upstream/Justfile' repo-root := justfile_directory() exe-suffix := if os() == "windows" { ".exe" } else { "" } +developer-workspace := env_var_or_default("LAMPYR_WORKSPACE", repo-root / "build/workspace") # Kind release installed by `just install-kind` in every workflow (CI, release # gates, Copilot); providers/kind/templates/kind-config.yaml pins its node image. @@ -198,38 +199,41 @@ install-mm: mkdir -p "{{repo-root}}/build/tools"; \ tar --extract --gzip --file "$dir/mm.tar.gz" --directory "{{repo-root}}/build/tools" mm +prepare-workspace workspace=developer-workspace: build-ly + if [[ ! -f "{{workspace}}/lampyr.workspace.yaml" ]]; then build/ly scaffold workspace "{{workspace}}"; fi + # Install the complete preview platform into a Kind cluster. -cluster-install: build-ly - build/ly cluster install --provider kind --allow-docker +cluster-install workspace=developer-workspace: (prepare-workspace workspace) + build/ly cluster install --provider kind --allow-docker --workspace "{{workspace}}" # Install Lampyr using the independently packaged k3d provider. -cluster-install-k3d: build-ly - build/ly cluster install --provider k3d --allow-docker +cluster-install-k3d workspace=developer-workspace: (prepare-workspace workspace) + build/ly cluster install --provider k3d --allow-docker --workspace "{{workspace}}" # Test the provider lifecycle and every committed runtime example on k3d. test-k3d-integration: build-ly k3d::build cli::runtime-images bash "{{repo-root}}/scripts/test-k3d-integration.sh" # Report the health of every required preview platform component. -cluster-health: build-ly - build/ly cluster health +cluster-health workspace=developer-workspace: build-ly + build/ly cluster health --workspace "{{workspace}}" # Remove preview platform resources. -cluster-uninstall: build-ly - build/ly cluster uninstall +cluster-uninstall workspace=developer-workspace: build-ly + build/ly cluster uninstall --workspace "{{workspace}}" # Create or configure an AKS cluster with the latest regional Kubernetes version. -cluster-install-azure config name="lampyr": build-ly - build/ly cluster install --provider azure --name "{{name}}" --provider-config "{{config}}" --approve-provider-manifests +cluster-install-azure config name="lampyr" workspace=developer-workspace: (prepare-workspace workspace) + build/ly cluster install --provider azure --name "{{name}}" --provider-config "{{config}}" --approve-provider-manifests --workspace "{{workspace}}" # Report AKS and Lampyr platform health. -cluster-health-azure name="lampyr": build-ly - build/ly cluster health --context "aks-{{name}}" +cluster-health-azure name="lampyr" workspace=developer-workspace: build-ly + build/ly cluster health --context "aks-{{name}}" --workspace "{{workspace}}" # Remove Lampyr from AKS while retaining the cluster by default. -cluster-uninstall-azure name="lampyr" delete-cluster="false": build-ly - args=(--provider azure --name "{{name}}" --context "aks-{{name}}" --approve-provider-manifests); \ +cluster-uninstall-azure name="lampyr" delete-cluster="false" workspace=developer-workspace: build-ly + args=(--provider azure --name "{{name}}" --context "aks-{{name}}" --approve-provider-manifests --workspace "{{workspace}}"); \ if [[ "{{delete-cluster}}" == "true" ]]; then args+=(--delete-cluster); fi; \ build/ly cluster uninstall "${args[@]}" diff --git a/docs/cli/cluster.md b/docs/cli/cluster.md index d823f60..b0f50f1 100644 --- a/docs/cli/cluster.md +++ b/docs/cli/cluster.md @@ -9,11 +9,18 @@ is optional: its guest only provisions infrastructure and returns a standard kub `ly` owns Kubernetes, platform installation, Eventing, source lifecycle, and health; it contains no Kind, k3d, or Azure provisioning implementation. +From a checkout, create a customer Workspace before installing. The examples +below use `build/workspace`; use an existing Workspace instead if you have one: + +```bash +build/ly scaffold workspace build/workspace +``` + ```bash build/ly cluster install --provider kind --name lampyr \ - --allow-docker -build/ly cluster health -build/ly cluster uninstall --delete-cluster + --allow-docker --workspace build/workspace +build/ly cluster health --workspace build/workspace +build/ly cluster uninstall --delete-cluster --workspace build/workspace ``` Without `--provider`, commands use the existing kubeconfig/context directly: @@ -29,9 +36,9 @@ domain: services.example.com ``` ```bash -build/ly cluster install --context customer -build/ly cluster health --context customer -build/ly cluster uninstall --context customer +build/ly cluster install --context customer --workspace build/workspace +build/ly cluster health --context customer --workspace build/workspace +build/ly cluster uninstall --context customer --workspace build/workspace ``` The defaults are `ghcr.io/hyperlight-dev/lampyr/fiberd:preview` and @@ -61,6 +68,18 @@ All cluster lifecycle commands read bootstrap manifests from the Workspace's customer-editable; Lampyr Home retains the immutable runtime and provider artifacts. +The checkout's `just cluster-install` recipes create `build/workspace` if it +does not exist. `just cluster-health` and `just cluster-uninstall` select the +same Workspace. Set `LAMPYR_WORKSPACE` to use another Workspace for these +recipes. The checkout root does not need a `lampyr.workspace.yaml` file. + +Existing installations remain bound to their original Workspace and are not +moved automatically. If an installation used the checkout root, manage it +from the previous checkout revision that still has its manifest. Use a new +installation name for a separate Workspace; `--workspace` does not reassign +an existing installation. Keep the old installation state until its resources +have been accounted for and cleaned up. + | Option | Purpose | |---|---| | `--provider ID` | External provider identity, not a built-in enumeration. | @@ -93,7 +112,7 @@ registryPort: 5002 ```bash build/ly cluster install --provider kind --provider-config kind.yaml \ - --allow-docker + --allow-docker --workspace build/workspace ``` The provider scaffolds complete infrastructure into `infra//` @@ -104,7 +123,7 @@ k3d accepts the same port and prebuilt-image settings, with a k3d v1alpha5 `source` rather than Kind YAML: ```bash -build/ly cluster install --provider k3d --allow-docker +build/ly cluster install --provider k3d --allow-docker --workspace build/workspace ``` It owns a dedicated registry rather than reusing a shared one. Select an @@ -141,7 +160,7 @@ zygoteRegistries: ```bash build/ly cluster install --provider azure --eventing \ --provider-config azure.yaml \ - --approve-provider-manifests + --approve-provider-manifests --workspace build/workspace ``` The Azure guest signs in using its dedicated per-installation cache. Host diff --git a/docs/cluster-k3d.md b/docs/cluster-k3d.md index 36d424b..f37093d 100644 --- a/docs/cluster-k3d.md +++ b/docs/cluster-k3d.md @@ -30,14 +30,16 @@ from (see [Preview images](contributing.md#preview-images)): `just preview-mirror-images` writes their `controllerManifest`, `grantImage` and `helperImage` to `build/preview-kind.yaml`, whose keys the k3d provider takes too. `just template-tools` builds the fiberd template tools that -`ly build` and `ly deploy` run. Then, from the repository Workspace: +`ly build` and `ly deploy` run. Then, from the checkout, create a separate +customer Workspace and select it for cluster commands: ```bash just preview-mirror-images destination=REGISTRY/lampyr just build-ly k3d::build cli::runtime-images template-tools +build/ly scaffold workspace k3d-demo build/ly cluster install --provider k3d --name lampyr-k3d \ - --provider-config build/preview-kind.yaml --allow-docker -build/ly cluster health --context k3d-lampyr-k3d + --provider-config build/preview-kind.yaml --allow-docker --workspace k3d-demo +build/ly cluster health --context k3d-lampyr-k3d --workspace k3d-demo ``` `just use-cluster-inputs` does not work for k3d: it serves built images from @@ -70,7 +72,7 @@ httpsPort: 18443 ```bash build/ly cluster install --provider k3d --name lampyr-k3d \ - --provider-config k3d.yaml --allow-docker + --provider-config k3d.yaml --allow-docker --workspace k3d-demo ``` Omit `httpPort` and `httpsPort` (or use zero) for dynamically assigned ports. @@ -85,10 +87,9 @@ All six [runtime examples](examples.md) are provider-neutral: Node.js, Python, Go, Rust, and .NET use the same source and manifests on Kind and k3d. There are no k3d-specific forks to keep synchronized. -Create a workspace and copy the example into its services directory: +Copy the example into the Workspace created above: ```bash -build/ly scaffold workspace k3d-demo cp -R docs/examples/hello-nodejs k3d-demo/services/hello-nodejs ``` @@ -141,13 +142,14 @@ customer source. Remove only the platform, retaining K3s and the local registry: ```bash -build/ly cluster uninstall --context k3d-lampyr-k3d +build/ly cluster uninstall --context k3d-lampyr-k3d --workspace k3d-demo ``` Remove the owned cluster, tools container, image volume, registry, and network: ```bash -build/ly cluster uninstall --provider k3d --name lampyr-k3d --delete-cluster +build/ly cluster uninstall --provider k3d --name lampyr-k3d --delete-cluster \ + --workspace k3d-demo ``` The provider refuses to adopt unrelated clusters or delete replaced diff --git a/docs/cluster-kind.md b/docs/cluster-kind.md index c5aaee8..f7cc7c0 100644 --- a/docs/cluster-kind.md +++ b/docs/cluster-kind.md @@ -25,7 +25,8 @@ With `ly` installed from a release (see the provider, runtime images and fiberd-k8s-controller inputs: ```bash -ly cluster install --provider kind --allow-docker +ly scaffold workspace kind-demo +ly cluster install --provider kind --allow-docker --workspace kind-demo ``` From a repository checkout: @@ -36,10 +37,14 @@ just kind::build just cli::runtime-images just upstream::cluster-inputs build/cluster-inputs LAMPYR_CLUSTER_INPUTS=$PWD/build/cluster-inputs just use-cluster-inputs 5002 +build/ly scaffold workspace kind-demo build/ly cluster install --provider kind \ - --allow-docker + --allow-docker --workspace kind-demo ``` +The release and checkout commands above are alternatives. Both create a +customer Workspace before installation; the source checkout is not a Workspace. + A release's platform installs fiberd-k8s-controller and the images its grant Pods run by default, but a checkout has none to install. `just upstream::cluster-inputs` builds them from the commits @@ -85,11 +90,10 @@ Deployment creates one grant Pod per CapacityGrant, running stock fiberd with Lampyr's helper. fiberd-k8s-controller issues each Pod's grant and renews it automatically. -Create a workspace, then build and deploy its default app to the local registry. -The scaffold exposes `app` through `ingress.services`: +Build and deploy the default app in the Workspace created above to the local +registry. The scaffold exposes `app` through `ingress.services`: ```bash -build/ly scaffold workspace kind-demo build/ly build kind-demo/services/app build/ly deploy --image localhost:5002/app:v1 kind-demo/services/app ``` @@ -114,7 +118,7 @@ Broker, install explicitly with: ```bash build/ly cluster install --provider kind --eventing \ - --allow-docker + --allow-docker --workspace kind-demo ``` This installs the pinned Eventing 1.23.0 manifests. The InMemoryChannel-backed @@ -124,13 +128,13 @@ available only on Azure-provider installations. ## Check health ```bash -build/ly cluster health +build/ly cluster health --workspace kind-demo ``` ## Remove Lampyr ```bash -build/ly cluster uninstall +build/ly cluster uninstall --workspace kind-demo ``` Add `--delete-cluster` to remove the Kind cluster as well. See diff --git a/scripts/tests/test_preview_workflow.py b/scripts/tests/test_preview_workflow.py index d34d7c5..3222ded 100644 --- a/scripts/tests/test_preview_workflow.py +++ b/scripts/tests/test_preview_workflow.py @@ -614,14 +614,37 @@ def test_checkout_cluster_workflow_uses_a_separate_workspace(self): dry_run = subprocess.run( ["just", "--dry-run", recipe, *(["provider.yaml"] if recipe.endswith("azure") else [])], cwd=ROOT, + env=dict(os.environ, LAMPYR_WORKSPACE=str(ROOT / "build/workspace")), check=True, text=True, capture_output=True, ) self.assertIn("scaffold workspace", dry_run.stderr) self.assertIn(f'--workspace "{ROOT / "build/workspace"}"', dry_run.stderr) + with tempfile.TemporaryDirectory() as directory: + workspace = str(Path(directory) / "customer workspace") + for recipe, arguments in [ + ("cluster-install", []), + ("cluster-install-k3d", []), + ("cluster-install-azure", ["provider.yaml"]), + ("cluster-health", []), + ("cluster-uninstall", []), + ("cluster-health-azure", []), + ("cluster-uninstall-azure", []), + ]: + with self.subTest(recipe=recipe, workspace=workspace): + dry_run = subprocess.run( + ["just", "--dry-run", recipe, *arguments], + cwd=ROOT, + env=dict(os.environ, LAMPYR_WORKSPACE=workspace), + check=True, + text=True, + capture_output=True, + ) + self.assertIn(f'--workspace "{workspace}"', dry_run.stderr) job = self.ci["jobs"]["new-developer-workflow"] self.assertEqual(job["env"]["LAMPYR_WORKSPACE"], "${{ github.workspace }}/build/workspace") + self.assertIn('"LAMPYR_WORKSPACE=$LAMPYR_WORKSPACE"', named(job, "Join the kvm group")["run"]) apps = named(job, "Run, build and deploy the demo apps")["run"] self.assertIn('cd "$LAMPYR_WORKSPACE"', apps) self.assertIn('"$repo/build/ly" scaffold service "$app"', apps) @@ -1061,7 +1084,7 @@ def test_documented_installs_take_the_built_controller_inputs_as_defaults(self): self.assertIn("registry_port=5500", walkthrough) self.assertIn("ly build services/app", walkthrough) self.assertIn( - 'build/ly build "$service"', + '"$repo/build/ly" build "$service"', named(jobs["new-developer-workflow"], "Run, build and deploy the demo apps")["run"], ) From 3e92ad9d946f2919498300472e37f6517224d314 Mon Sep 17 00:00:00 2001 From: James Sturtevant Date: Sat, 7 Nov 2026 20:35:48 -0800 Subject: [PATCH 4/7] fixup! docs: clarify setup requirements and organize demos Signed-off-by: James Sturtevant --- .github/workflows/ci.yml | 13 +++---- Justfile | 37 +++++++++--------- docs/cli/cluster.md | 37 +++++++++--------- docs/cluster-k3d.md | 36 +++++++++--------- docs/cluster-kind.md | 33 ++++++++-------- scripts/tests/test_preview_workflow.py | 52 ++++++++++---------------- 6 files changed, 98 insertions(+), 110 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 47aa0f8..c9b5e16 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1234,8 +1234,6 @@ jobs: new-developer-workflow: needs: [cluster-inputs] runs-on: ubuntu-latest - env: - LAMPYR_WORKSPACE: ${{ github.workspace }}/build/workspace # Above the steps' own limits: a step that times out fails, and failed # steps get diagnostics; a job that times out is cancelled instead. timeout-minutes: 50 @@ -1308,7 +1306,6 @@ jobs: # runner paths explicitly. exec sudo --user="$(id --user --name)" /usr/bin/env \ "PATH=$PATH" \ - "LAMPYR_WORKSPACE=$LAMPYR_WORKSPACE" \ "GITHUB_ENV=$GITHUB_ENV" \ "GITHUB_OUTPUT=$GITHUB_OUTPUT" \ "GITHUB_PATH=$GITHUB_PATH" \ @@ -1416,7 +1413,7 @@ jobs: timeout-minutes: 25 run: | repo="$PWD" - cd "$LAMPYR_WORKSPACE" + cd build/workspace answers() { curl --fail --silent --show-error --max-time 10 \ -H "Host: $app.default.localhost" http://127.0.0.1:8080/test \ @@ -1462,6 +1459,8 @@ jobs: - name: Call the deployed apps through Kourier timeout-minutes: 10 run: | + repo="$PWD" + cd build/workspace kubectl port-forward -n kourier-system svc/kourier 8080:80 & forward=$! trap 'kill "$forward" 2> /dev/null || true' EXIT @@ -1471,10 +1470,10 @@ jobs: | tee /dev/stderr | grep "hello from $app" > /dev/null done # Free the smoke-test homes before the walkthrough deploys its own app. - build/ly delete "$LAMPYR_WORKSPACE/services/demo-app" - build/ly delete "$LAMPYR_WORKSPACE/services/second-app" + "$repo/build/ly" delete services/demo-app + "$repo/build/ly" delete services/second-app # The walkthrough owns a separate disposable installation and registry. - build/ly cluster uninstall --provider kind --delete-cluster --workspace "$LAMPYR_WORKSPACE" + "$repo/build/ly" cluster uninstall --provider kind --delete-cluster - name: Check that /dev/kvm is unchanged if: always() diff --git a/Justfile b/Justfile index 82e253d..7f58fe0 100644 --- a/Justfile +++ b/Justfile @@ -11,7 +11,6 @@ mod upstream 'upstream/Justfile' repo-root := justfile_directory() exe-suffix := if os() == "windows" { ".exe" } else { "" } -developer-workspace := env_var_or_default("LAMPYR_WORKSPACE", repo-root / "build/workspace") # Kind release installed by `just install-kind` in every workflow (CI, release # gates, Copilot); providers/kind/templates/kind-config.yaml pins its node image. @@ -199,43 +198,45 @@ install-mm: mkdir -p "{{repo-root}}/build/tools"; \ tar --extract --gzip --file "$dir/mm.tar.gz" --directory "{{repo-root}}/build/tools" mm -prepare-workspace workspace=developer-workspace: build-ly - if [[ ! -f "{{workspace}}/lampyr.workspace.yaml" ]]; then build/ly scaffold workspace "{{workspace}}"; fi +prepare-workspace: build-ly + if [[ ! -f build/workspace/lampyr.workspace.yaml ]]; then build/ly scaffold workspace build/workspace; fi # Install the complete preview platform into a Kind cluster. -cluster-install workspace=developer-workspace: (prepare-workspace workspace) - build/ly cluster install --provider kind --allow-docker --workspace "{{workspace}}" +cluster-install: prepare-workspace + cd build/workspace && ../ly cluster install --provider kind --allow-docker # Install Lampyr using the independently packaged k3d provider. -cluster-install-k3d workspace=developer-workspace: (prepare-workspace workspace) - build/ly cluster install --provider k3d --allow-docker --workspace "{{workspace}}" +cluster-install-k3d: prepare-workspace + cd build/workspace && ../ly cluster install --provider k3d --allow-docker # Test the provider lifecycle and every committed runtime example on k3d. test-k3d-integration: build-ly k3d::build cli::runtime-images bash "{{repo-root}}/scripts/test-k3d-integration.sh" # Report the health of every required preview platform component. -cluster-health workspace=developer-workspace: build-ly - build/ly cluster health --workspace "{{workspace}}" +cluster-health: build-ly + cd build/workspace && ../ly cluster health # Remove preview platform resources. -cluster-uninstall workspace=developer-workspace: build-ly - build/ly cluster uninstall --workspace "{{workspace}}" +cluster-uninstall: build-ly + cd build/workspace && ../ly cluster uninstall # Create or configure an AKS cluster with the latest regional Kubernetes version. -cluster-install-azure config name="lampyr" workspace=developer-workspace: (prepare-workspace workspace) - build/ly cluster install --provider azure --name "{{name}}" --provider-config "{{config}}" --approve-provider-manifests --workspace "{{workspace}}" +cluster-install-azure config name="lampyr": prepare-workspace + config="{{config}}"; \ + if [[ "$config" != /* ]]; then config="$PWD/$config"; fi; \ + cd build/workspace && ../ly cluster install --provider azure --name "{{name}}" --provider-config "$config" --approve-provider-manifests # Report AKS and Lampyr platform health. -cluster-health-azure name="lampyr" workspace=developer-workspace: build-ly - build/ly cluster health --context "aks-{{name}}" --workspace "{{workspace}}" +cluster-health-azure name="lampyr": build-ly + cd build/workspace && ../ly cluster health --context "aks-{{name}}" # Remove Lampyr from AKS while retaining the cluster by default. -cluster-uninstall-azure name="lampyr" delete-cluster="false" workspace=developer-workspace: build-ly - args=(--provider azure --name "{{name}}" --context "aks-{{name}}" --approve-provider-manifests --workspace "{{workspace}}"); \ +cluster-uninstall-azure name="lampyr" delete-cluster="false": build-ly + args=(--provider azure --name "{{name}}" --context "aks-{{name}}" --approve-provider-manifests); \ if [[ "{{delete-cluster}}" == "true" ]]; then args+=(--delete-cluster); fi; \ - build/ly cluster uninstall "${args[@]}" + cd build/workspace && ../ly cluster uninstall "${args[@]}" # Build every locally produced binary. build: setup-hluk build-fiberd build-control-plane build-ly build-eventgrid diff --git a/docs/cli/cluster.md b/docs/cli/cluster.md index b0f50f1..a2e822e 100644 --- a/docs/cli/cluster.md +++ b/docs/cli/cluster.md @@ -9,18 +9,20 @@ is optional: its guest only provisions infrastructure and returns a standard kub `ly` owns Kubernetes, platform installation, Eventing, source lifecycle, and health; it contains no Kind, k3d, or Azure provisioning implementation. -From a checkout, create a customer Workspace before installing. The examples -below use `build/workspace`; use an existing Workspace instead if you have one: +From a checkout, put `ly` on your `PATH`, then create and enter a Workspace. +If you already have a Workspace, enter it instead of scaffolding another: ```bash -build/ly scaffold workspace build/workspace +repo_root="$PWD" +export PATH="$repo_root/build:$PATH" +ly scaffold workspace cluster-demo +cd cluster-demo ``` ```bash -build/ly cluster install --provider kind --name lampyr \ - --allow-docker --workspace build/workspace -build/ly cluster health --workspace build/workspace -build/ly cluster uninstall --delete-cluster --workspace build/workspace +ly cluster install --provider kind --name lampyr --allow-docker +ly cluster health +ly cluster uninstall --delete-cluster ``` Without `--provider`, commands use the existing kubeconfig/context directly: @@ -36,9 +38,9 @@ domain: services.example.com ``` ```bash -build/ly cluster install --context customer --workspace build/workspace -build/ly cluster health --context customer --workspace build/workspace -build/ly cluster uninstall --context customer --workspace build/workspace +ly cluster install --context customer +ly cluster health --context customer +ly cluster uninstall --context customer ``` The defaults are `ghcr.io/hyperlight-dev/lampyr/fiberd:preview` and @@ -69,9 +71,9 @@ customer-editable; Lampyr Home retains the immutable runtime and provider artifacts. The checkout's `just cluster-install` recipes create `build/workspace` if it -does not exist. `just cluster-health` and `just cluster-uninstall` select the -same Workspace. Set `LAMPYR_WORKSPACE` to use another Workspace for these -recipes. The checkout root does not need a `lampyr.workspace.yaml` file. +does not exist, then enter it before running `ly`. `just cluster-health` and +`just cluster-uninstall` run from the same Workspace. The checkout root does +not need a `lampyr.workspace.yaml` file. Existing installations remain bound to their original Workspace and are not moved automatically. If an installation used the checkout root, manage it @@ -111,8 +113,7 @@ registryPort: 5002 ``` ```bash -build/ly cluster install --provider kind --provider-config kind.yaml \ - --allow-docker --workspace build/workspace +ly cluster install --provider kind --provider-config kind.yaml --allow-docker ``` The provider scaffolds complete infrastructure into `infra//` @@ -123,7 +124,7 @@ k3d accepts the same port and prebuilt-image settings, with a k3d v1alpha5 `source` rather than Kind YAML: ```bash -build/ly cluster install --provider k3d --allow-docker --workspace build/workspace +ly cluster install --provider k3d --allow-docker ``` It owns a dedicated registry rather than reusing a shared one. Select an @@ -158,9 +159,9 @@ zygoteRegistries: ``` ```bash -build/ly cluster install --provider azure --eventing \ +ly cluster install --provider azure --eventing \ --provider-config azure.yaml \ - --approve-provider-manifests --workspace build/workspace + --approve-provider-manifests ``` The Azure guest signs in using its dedicated per-installation cache. Host diff --git a/docs/cluster-k3d.md b/docs/cluster-k3d.md index f37093d..b0078af 100644 --- a/docs/cluster-k3d.md +++ b/docs/cluster-k3d.md @@ -30,16 +30,19 @@ from (see [Preview images](contributing.md#preview-images)): `just preview-mirror-images` writes their `controllerManifest`, `grantImage` and `helperImage` to `build/preview-kind.yaml`, whose keys the k3d provider takes too. `just template-tools` builds the fiberd template tools that -`ly build` and `ly deploy` run. Then, from the checkout, create a separate -customer Workspace and select it for cluster commands: +`ly build` and `ly deploy` run. Then, from the checkout, create a Workspace +and enter it before running cluster commands: ```bash +repo_root="$PWD" just preview-mirror-images destination=REGISTRY/lampyr just build-ly k3d::build cli::runtime-images template-tools -build/ly scaffold workspace k3d-demo -build/ly cluster install --provider k3d --name lampyr-k3d \ - --provider-config build/preview-kind.yaml --allow-docker --workspace k3d-demo -build/ly cluster health --context k3d-lampyr-k3d --workspace k3d-demo +export PATH="$repo_root/build:$PATH" +ly scaffold workspace k3d-demo +cd k3d-demo +ly cluster install --provider k3d --name lampyr-k3d \ + --provider-config "$repo_root/build/preview-kind.yaml" --allow-docker +ly cluster health --context k3d-lampyr-k3d ``` `just use-cluster-inputs` does not work for k3d: it serves built images from @@ -60,7 +63,7 @@ takes one `--provider-config` file, so start it from a copy of `build/preview-kind.yaml` to keep the controller inputs: ```bash -cp build/preview-kind.yaml k3d.yaml +cp "$repo_root/build/preview-kind.yaml" k3d.yaml ``` ```yaml @@ -71,8 +74,8 @@ httpsPort: 18443 ``` ```bash -build/ly cluster install --provider k3d --name lampyr-k3d \ - --provider-config k3d.yaml --allow-docker --workspace k3d-demo +ly cluster install --provider k3d --name lampyr-k3d \ + --provider-config k3d.yaml --allow-docker ``` Omit `httpPort` and `httpsPort` (or use zero) for dynamically assigned ports. @@ -90,10 +93,10 @@ There are no k3d-specific forks to keep synchronized. Copy the example into the Workspace created above: ```bash -cp -R docs/examples/hello-nodejs k3d-demo/services/hello-nodejs +cp -R "$repo_root/docs/examples/hello-nodejs" services/hello-nodejs ``` -In `k3d-demo/lampyr.workspace.yaml`, explicitly expose the example: +In `lampyr.workspace.yaml`, explicitly expose the example: ```yaml apiVersion: lampyr.dev/v1alpha1 @@ -105,9 +108,9 @@ ingress: Build and deploy using the default registry port: ```bash -build/ly build k3d-demo/services/hello-nodejs -build/ly deploy --context k3d-lampyr-k3d \ - --image localhost:5002/hello-nodejs:v1 k3d-demo/services/hello-nodejs +ly build services/hello-nodejs +ly deploy --context k3d-lampyr-k3d \ + --image localhost:5002/hello-nodejs:v1 services/hello-nodejs ``` Substitute any example directory and image name from the runtime table. If @@ -142,14 +145,13 @@ customer source. Remove only the platform, retaining K3s and the local registry: ```bash -build/ly cluster uninstall --context k3d-lampyr-k3d --workspace k3d-demo +ly cluster uninstall --context k3d-lampyr-k3d ``` Remove the owned cluster, tools container, image volume, registry, and network: ```bash -build/ly cluster uninstall --provider k3d --name lampyr-k3d --delete-cluster \ - --workspace k3d-demo +ly cluster uninstall --provider k3d --name lampyr-k3d --delete-cluster ``` The provider refuses to adopt unrelated clusters or delete replaced diff --git a/docs/cluster-kind.md b/docs/cluster-kind.md index f7cc7c0..25d8b09 100644 --- a/docs/cluster-kind.md +++ b/docs/cluster-kind.md @@ -24,26 +24,26 @@ With `ly` installed from a release (see the [README](https://github.com/hyperlight-dev/lampyr#install-the-cli)), the platform already carries the provider, runtime images and fiberd-k8s-controller inputs: -```bash -ly scaffold workspace kind-demo -ly cluster install --provider kind --allow-docker --workspace kind-demo -``` - -From a repository checkout: +From a repository checkout, prepare the CLI and runtime inputs instead: ```bash +repo_root="$PWD" just build-ly just kind::build just cli::runtime-images just upstream::cluster-inputs build/cluster-inputs LAMPYR_CLUSTER_INPUTS=$PWD/build/cluster-inputs just use-cluster-inputs 5002 -build/ly scaffold workspace kind-demo -build/ly cluster install --provider kind \ - --allow-docker --workspace kind-demo +export PATH="$repo_root/build:$PATH" ``` -The release and checkout commands above are alternatives. Both create a -customer Workspace before installation; the source checkout is not a Workspace. +With either installation, create a Workspace and run the remaining commands +from inside it: + +```bash +ly scaffold workspace kind-demo +cd kind-demo +ly cluster install --provider kind --allow-docker +``` A release's platform installs fiberd-k8s-controller and the images its grant Pods run by default, but a checkout has none to install. @@ -94,8 +94,8 @@ Build and deploy the default app in the Workspace created above to the local registry. The scaffold exposes `app` through `ingress.services`: ```bash -build/ly build kind-demo/services/app -build/ly deploy --image localhost:5002/app:v1 kind-demo/services/app +ly build services/app +ly deploy --image localhost:5002/app:v1 services/app ``` `ly deploy` tags and pushes the locally built image automatically. Do not pass @@ -117,8 +117,7 @@ To add Knative Eventing and an InMemoryChannel-backed Broker, install explicitly with: ```bash -build/ly cluster install --provider kind --eventing \ - --allow-docker --workspace kind-demo +ly cluster install --provider kind --eventing --allow-docker ``` This installs the pinned Eventing 1.23.0 manifests. The InMemoryChannel-backed @@ -128,13 +127,13 @@ available only on Azure-provider installations. ## Check health ```bash -build/ly cluster health --workspace kind-demo +ly cluster health ``` ## Remove Lampyr ```bash -build/ly cluster uninstall --workspace kind-demo +ly cluster uninstall ``` Add `--delete-cluster` to remove the Kind cluster as well. See diff --git a/scripts/tests/test_preview_workflow.py b/scripts/tests/test_preview_workflow.py index 3222ded..277fcef 100644 --- a/scripts/tests/test_preview_workflow.py +++ b/scripts/tests/test_preview_workflow.py @@ -607,50 +607,36 @@ def test_arm64_provider_builds_are_parallel_and_cached(self): def test_checkout_cluster_workflow_uses_a_separate_workspace(self): self.assertFalse((ROOT / "lampyr.workspace.yaml").exists()) justfile = (ROOT / "Justfile").read_text(encoding="utf-8") - self.assertIn('env_var_or_default("LAMPYR_WORKSPACE", repo-root / "build/workspace")', justfile) - self.assertIn('build/ly scaffold workspace "{{workspace}}"', justfile) - for recipe in ["cluster-install", "cluster-install-k3d", "cluster-install-azure"]: + self.assertIn("build/ly scaffold workspace build/workspace", justfile) + for recipe, arguments in [ + ("cluster-install", []), + ("cluster-install-k3d", []), + ("cluster-install-azure", ["provider.yaml"]), + ("cluster-health", []), + ("cluster-uninstall", []), + ("cluster-health-azure", []), + ("cluster-uninstall-azure", []), + ]: with self.subTest(recipe=recipe): dry_run = subprocess.run( - ["just", "--dry-run", recipe, *(["provider.yaml"] if recipe.endswith("azure") else [])], + ["just", "--dry-run", recipe, *arguments], cwd=ROOT, - env=dict(os.environ, LAMPYR_WORKSPACE=str(ROOT / "build/workspace")), check=True, text=True, capture_output=True, ) - self.assertIn("scaffold workspace", dry_run.stderr) - self.assertIn(f'--workspace "{ROOT / "build/workspace"}"', dry_run.stderr) - with tempfile.TemporaryDirectory() as directory: - workspace = str(Path(directory) / "customer workspace") - for recipe, arguments in [ - ("cluster-install", []), - ("cluster-install-k3d", []), - ("cluster-install-azure", ["provider.yaml"]), - ("cluster-health", []), - ("cluster-uninstall", []), - ("cluster-health-azure", []), - ("cluster-uninstall-azure", []), - ]: - with self.subTest(recipe=recipe, workspace=workspace): - dry_run = subprocess.run( - ["just", "--dry-run", recipe, *arguments], - cwd=ROOT, - env=dict(os.environ, LAMPYR_WORKSPACE=workspace), - check=True, - text=True, - capture_output=True, - ) - self.assertIn(f'--workspace "{workspace}"', dry_run.stderr) + self.assertIn("cd build/workspace", dry_run.stderr) + self.assertNotIn("--workspace", dry_run.stderr) + if recipe.startswith("cluster-install"): + self.assertIn("scaffold workspace", dry_run.stderr) job = self.ci["jobs"]["new-developer-workflow"] - self.assertEqual(job["env"]["LAMPYR_WORKSPACE"], "${{ github.workspace }}/build/workspace") - self.assertIn('"LAMPYR_WORKSPACE=$LAMPYR_WORKSPACE"', named(job, "Join the kvm group")["run"]) apps = named(job, "Run, build and deploy the demo apps")["run"] - self.assertIn('cd "$LAMPYR_WORKSPACE"', apps) + self.assertIn("cd build/workspace", apps) self.assertIn('"$repo/build/ly" scaffold service "$app"', apps) cleanup = named(job, "Call the deployed apps through Kourier")["run"] - self.assertIn('build/ly delete "$LAMPYR_WORKSPACE/services/demo-app"', cleanup) - self.assertIn('--workspace "$LAMPYR_WORKSPACE"', cleanup) + self.assertIn("cd build/workspace", cleanup) + self.assertIn('"$repo/build/ly" delete services/demo-app', cleanup) + self.assertNotIn("--workspace", cleanup) def test_new_developer_timeout_leaves_diagnostic_headroom(self): job = self.ci["jobs"]["new-developer-workflow"] From 976737cf120591d369b4702411bf511b48918eb1 Mon Sep 17 00:00:00 2001 From: James Sturtevant Date: Sun, 8 Nov 2026 16:23:16 -0800 Subject: [PATCH 5/7] fixup! docs: clarify setup requirements and organize demos Signed-off-by: James Sturtevant --- scripts/tests/test_preview_workflow.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/tests/test_preview_workflow.py b/scripts/tests/test_preview_workflow.py index 277fcef..a71b805 100644 --- a/scripts/tests/test_preview_workflow.py +++ b/scripts/tests/test_preview_workflow.py @@ -638,6 +638,13 @@ def test_checkout_cluster_workflow_uses_a_separate_workspace(self): self.assertIn('"$repo/build/ly" delete services/demo-app', cleanup) self.assertNotIn("--workspace", cleanup) + def test_kind_lifecycle_enters_its_scaffolded_workspace(self): + script = KIND_INTEGRATION.read_text(encoding="utf-8") + self.assertIn( + '"$repo_root/build/ly" scaffold workspace "$project" >/dev/null\ncd "$project"', + script, + ) + def test_new_developer_timeout_leaves_diagnostic_headroom(self): job = self.ci["jobs"]["new-developer-workflow"] diagnostics = named(job, "Collect diagnostics")["timeout-minutes"] From f8991115afadc02039c1cdcdd4ef4d61355906b8 Mon Sep 17 00:00:00 2001 From: James Sturtevant Date: Sun, 8 Nov 2026 16:26:48 -0800 Subject: [PATCH 6/7] fixup! docs: clarify setup requirements and organize demos Signed-off-by: James Sturtevant --- scripts/test-kind-integration.sh | 1 + scripts/tests/test_preview_workflow.py | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/scripts/test-kind-integration.sh b/scripts/test-kind-integration.sh index 85c935e..e5dff6f 100755 --- a/scripts/test-kind-integration.sh +++ b/scripts/test-kind-integration.sh @@ -92,6 +92,7 @@ fi if [[ "$suite" == "full" || "$suite" == "runtime" || "$runtime_extras" == 1 ]]; then prepare_fiberd_template_tools "$repo_root" fi +cd "$project" cleanup() { status=$? diff --git a/scripts/tests/test_preview_workflow.py b/scripts/tests/test_preview_workflow.py index a71b805..314555f 100644 --- a/scripts/tests/test_preview_workflow.py +++ b/scripts/tests/test_preview_workflow.py @@ -640,9 +640,14 @@ def test_checkout_cluster_workflow_uses_a_separate_workspace(self): def test_kind_lifecycle_enters_its_scaffolded_workspace(self): script = KIND_INTEGRATION.read_text(encoding="utf-8") - self.assertIn( - '"$repo_root/build/ly" scaffold workspace "$project" >/dev/null\ncd "$project"', - script, + self.assertIn('\ncd "$project"\n', script) + self.assertLess( + script.index('prepare_fiberd_template_tools "$repo_root"'), + script.index('\ncd "$project"\n'), + ) + self.assertLess( + script.index('\ncd "$project"\n'), + script.index('PATH="$project/docker-only-bin" "$repo_root/build/ly" cluster install'), ) def test_new_developer_timeout_leaves_diagnostic_headroom(self): From 22e5b11caa290418d23861f92c410a837ea00d31 Mon Sep 17 00:00:00 2001 From: James Sturtevant Date: Sun, 8 Nov 2026 17:27:39 -0800 Subject: [PATCH 7/7] fixup! docs: clarify setup requirements and organize demos Signed-off-by: James Sturtevant --- docs/cli/cluster.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/docs/cli/cluster.md b/docs/cli/cluster.md index a2e822e..d709399 100644 --- a/docs/cli/cluster.md +++ b/docs/cli/cluster.md @@ -70,11 +70,6 @@ All cluster lifecycle commands read bootstrap manifests from the Workspace's customer-editable; Lampyr Home retains the immutable runtime and provider artifacts. -The checkout's `just cluster-install` recipes create `build/workspace` if it -does not exist, then enter it before running `ly`. `just cluster-health` and -`just cluster-uninstall` run from the same Workspace. The checkout root does -not need a `lampyr.workspace.yaml` file. - Existing installations remain bound to their original Workspace and are not moved automatically. If an installation used the checkout root, manage it from the previous checkout revision that still has its manifest. Use a new