From 73883cfa8192bff7bb42447cfd95eee8208b0752 Mon Sep 17 00:00:00 2001 From: Matthew Grossman Date: Wed, 4 Nov 2026 10:02:40 -0800 Subject: [PATCH 1/4] ci(e2e): build macOS binaries without blocking Linux jobs Branch E2E built the macOS binaries in the same reusable workflow call as the Linux binaries, so every Linux consumer waited for the macOS runners. Add linux and macos inputs to build-binaries and build-vm-driver, and call them separately in Branch E2E. The result jobs still depend on the macOS builds, so a macOS build failure still fails them. Release workflows keep both inputs at their defaults. Signed-off-by: Matthew Grossman --- .github/workflows/branch-e2e.yml | 35 ++++++++++++++++-- .github/workflows/build-binaries.yml | 51 +++++++++++++++++++++------ .github/workflows/build-vm-driver.yml | 37 +++++++++++++++---- CI.md | 2 +- 4 files changed, 104 insertions(+), 21 deletions(-) diff --git a/.github/workflows/branch-e2e.yml b/.github/workflows/branch-e2e.yml index 0f59ab2a81..00f9f26d85 100644 --- a/.github/workflows/branch-e2e.yml +++ b/.github/workflows/branch-e2e.yml @@ -108,6 +108,20 @@ jobs: uses: ./.github/workflows/build-binaries.yml with: cargo-version: ${{ needs.version.outputs.cargo }} + macos: false + secrets: + CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} + + # macOS runners can queue for a long time. A separate call lets Linux + # consumers start as soon as the Linux binaries are ready. + build-binaries-macos: + needs: version + permissions: + contents: read + uses: ./.github/workflows/build-binaries.yml + with: + cargo-version: ${{ needs.version.outputs.cargo }} + linux: false secrets: CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} @@ -245,6 +259,19 @@ jobs: uses: ./.github/workflows/build-vm-driver.yml with: cargo-version: ${{ needs.version.outputs.cargo }} + macos: false + secrets: + CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} + + build-vm-driver-macos: + needs: [pr_metadata, version, build-binaries, build-binaries-macos] + if: needs.pr_metadata.outputs.run_core_e2e == 'true' + permissions: + contents: read + uses: ./.github/workflows/build-vm-driver.yml + with: + cargo-version: ${{ needs.version.outputs.cargo }} + linux: false secrets: CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} @@ -632,6 +659,8 @@ jobs: name: Core E2E result needs: - pr_metadata + - build-binaries-macos + - build-vm-driver-macos - conformance-integration - feature-specific-integration - driver-specific-integration @@ -661,7 +690,7 @@ jobs: gpu-e2e-result: name: GPU E2E result - needs: [pr_metadata, gpu-e2e] + needs: [pr_metadata, build-binaries-macos, gpu-e2e] if: always() && needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_gpu_e2e == 'true' runs-on: ubuntu-latest steps: @@ -674,7 +703,7 @@ jobs: kubernetes-ha-e2e-result: name: Kubernetes HA E2E result - needs: [pr_metadata, kubernetes-ha-e2e] + needs: [pr_metadata, build-binaries-macos, kubernetes-ha-e2e] if: always() && needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_kubernetes_ha_e2e == 'true' runs-on: ubuntu-latest steps: @@ -687,7 +716,7 @@ jobs: kubernetes-credential-drivers-e2e-result: name: Kubernetes Credential Drivers E2E result - needs: [pr_metadata, kubernetes-credential-drivers-e2e] + needs: [pr_metadata, build-binaries-macos, kubernetes-credential-drivers-e2e] if: always() && needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_kubernetes_credential_drivers_e2e == 'true' runs-on: ubuntu-latest steps: diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries.yml index 1289968d14..559da3c677 100644 --- a/.github/workflows/build-binaries.yml +++ b/.github/workflows/build-binaries.yml @@ -17,6 +17,16 @@ on: required: false type: string default: "" + linux: + description: Build the Linux binaries. + required: false + type: boolean + default: true + macos: + description: Build the macOS binaries. + required: false + type: boolean + default: true secrets: CACHIX_AUTH_TOKEN: required: true @@ -30,6 +40,7 @@ env: jobs: cli: name: openshell (${{ matrix.triple }}) + if: inputs.linux env: PACKAGE: openshell-cli BINARY: openshell @@ -40,8 +51,6 @@ jobs: runner: linux-amd64-cpu8 - triple: aarch64-unknown-linux-musl runner: linux-arm64-cpu8 - - triple: aarch64-apple-darwin - runner: macos-15-xlarge runs-on: ${{ matrix.runner }} timeout-minutes: 60 steps: &build_steps @@ -64,6 +73,7 @@ jobs: prover: name: openshell-prover (${{ matrix.triple }}) + if: inputs.linux env: PACKAGE: openshell-prover-cli BINARY: openshell-prover @@ -74,14 +84,13 @@ jobs: runner: linux-amd64-cpu8 - triple: aarch64-unknown-linux-musl runner: linux-arm64-cpu8 - - triple: aarch64-apple-darwin - runner: macos-15-xlarge runs-on: ${{ matrix.runner }} timeout-minutes: 60 steps: *build_steps gateway: name: openshell-gateway (${{ matrix.triple }}) + if: inputs.linux env: PACKAGE: openshell-gateway BINARY: openshell-gateway @@ -92,14 +101,13 @@ jobs: runner: linux-amd64-cpu8 - triple: aarch64-unknown-linux-gnu runner: linux-arm64-cpu8 - - triple: aarch64-apple-darwin - runner: macos-15-xlarge runs-on: ${{ matrix.runner }} timeout-minutes: 60 steps: *build_steps runtimes: name: ${{ matrix.binary }} (${{ matrix.triple }}) + if: inputs.linux env: PACKAGE: ${{ matrix.package }} BINARY: ${{ matrix.binary }} @@ -122,16 +130,13 @@ jobs: binary: openshell-supervisor triple: aarch64-unknown-linux-gnu runner: linux-arm64-cpu8 - - package: openshell-supervisor - binary: openshell-supervisor - triple: aarch64-apple-darwin - runner: macos-15-xlarge runs-on: ${{ matrix.runner }} timeout-minutes: 60 steps: *build_steps vm-init: name: openshell-vm-init (${{ matrix.triple }}) + if: inputs.linux env: PACKAGE: openshell-driver-vm BINARY: openshell-vm-init @@ -146,3 +151,29 @@ jobs: runs-on: ${{ matrix.runner }} timeout-minutes: 60 steps: *build_steps + + macos: + name: ${{ matrix.binary }} (${{ matrix.triple }}) + if: inputs.macos + env: + PACKAGE: ${{ matrix.package }} + BINARY: ${{ matrix.binary }} + strategy: + fail-fast: false + matrix: + include: + - package: openshell-cli + binary: openshell + triple: aarch64-apple-darwin + - package: openshell-prover-cli + binary: openshell-prover + triple: aarch64-apple-darwin + - package: openshell-gateway + binary: openshell-gateway + triple: aarch64-apple-darwin + - package: openshell-supervisor + binary: openshell-supervisor + triple: aarch64-apple-darwin + runs-on: macos-15-xlarge + timeout-minutes: 60 + steps: *build_steps diff --git a/.github/workflows/build-vm-driver.yml b/.github/workflows/build-vm-driver.yml index a93f6928da..068fff5b73 100644 --- a/.github/workflows/build-vm-driver.yml +++ b/.github/workflows/build-vm-driver.yml @@ -17,6 +17,16 @@ on: required: false type: string default: "" + linux: + description: Build the Linux VM drivers. + required: false + type: boolean + default: true + macos: + description: Build the macOS VM driver. + required: false + type: boolean + default: true secrets: CACHIX_AUTH_TOKEN: required: true @@ -25,27 +35,26 @@ permissions: contents: read jobs: - build: + linux: name: openshell-driver-vm (${{ matrix.triple }}) + if: inputs.linux strategy: matrix: include: - arch: x86_64 triple: x86_64-unknown-linux-gnu runner: linux-amd64-cpu8 + entitlements-file: "" - arch: aarch64 triple: aarch64-unknown-linux-gnu runner: linux-arm64-cpu8 - - arch: aarch64 - triple: aarch64-apple-darwin - runner: macos-15-xlarge - entitlements-file: crates/openshell-driver-vm/entitlements.plist + entitlements-file: "" runs-on: ${{ matrix.runner }} timeout-minutes: 60 - defaults: + defaults: &build_defaults run: shell: nix develop -c bash -euo pipefail {0} - steps: + steps: &build_steps - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false @@ -111,3 +120,17 @@ jobs: cargo-version: ${{ inputs['cargo-version'] }} supervisor-image-tag: ${{ inputs['supervisor-image-tag'] }} entitlements-file: ${{ matrix.entitlements-file }} + + macos: + name: openshell-driver-vm (${{ matrix.triple }}) + if: inputs.macos + strategy: + matrix: + include: + - arch: aarch64 + triple: aarch64-apple-darwin + entitlements-file: crates/openshell-driver-vm/entitlements.plist + runs-on: macos-15-xlarge + timeout-minutes: 60 + defaults: *build_defaults + steps: *build_steps diff --git a/CI.md b/CI.md index a1a1b8bc77..a1e1988149 100644 --- a/CI.md +++ b/CI.md @@ -691,7 +691,7 @@ The bot's full administrator documentation is internal to NVIDIA. The only comma |---|---| | `.github/workflows/branch-checks.yml` | Required non-E2E checks. Triggers on `push: pull-request/[0-9]+` for PR mirrors and `merge_group` for queued merges. | | `.github/workflows/branch-e2e.yml` | Standard, GPU, Kubernetes HA, and Kubernetes credential-driver E2E. PR mirror pushes use `test:e2e`, `test:e2e-gpu`, and `test:e2e-kubernetes` labels; merge groups do not run E2E. | -| `.github/workflows/build-binaries.yml`, `build-vm-driver.yml` | Shared binary matrices used by branch and release workflows. The VM driver remains separate because its build consumes the runtime binaries. | +| `.github/workflows/build-binaries.yml`, `build-vm-driver.yml` | Shared binary matrices used by branch and release workflows. The VM driver remains separate because its build consumes the runtime binaries. Branch E2E calls each workflow twice, once with `macos: false` and once with `linux: false`, so Linux jobs don't wait for macOS runners. | | `.github/workflows/build-images.yml` | Builds and pushes multi-platform images, then uploads the same OCI images as workflow artifacts. | | `.github/workflows/package-release-binaries.yml` | Packages raw build artifacts into release tarballs without rebuilding them. | | `.github/workflows/e2e-docker-test.yml`, `e2e-podman-test.yml`, `e2e-vm-test.yml`, `e2e-kubernetes-test.yml` | Reusable runtime lanes called directly by branch and release workflows. Callers select suites and declare only the artifacts each runtime consumes. | From b49f7e04110f4110e24083c8b508bb9cf3dd27ca Mon Sep 17 00:00:00 2001 From: Matthew Grossman Date: Wed, 4 Nov 2026 10:05:09 -0800 Subject: [PATCH 2/4] ci(e2e): build tmachine test inputs before packages finish Prepare tmachine inputs built the test archives, test workload images, and Helm chart after the DEB and RPM builds finished, which added about three minutes before any tmachine suite could start. None of them use the packages. Build them in a Branch E2E job that needs only PR metadata, and let prepare download the result through a new test-inputs-artifact-name input. Other callers of prepare-integration-inputs leave the input empty and still build in place with the same steps. Signed-off-by: Matthew Grossman --- .github/workflows/branch-e2e.yml | 43 ++++++++++++++++++- .../workflows/prepare-integration-inputs.yml | 18 ++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/.github/workflows/branch-e2e.yml b/.github/workflows/branch-e2e.yml index 00f9f26d85..e0befe158a 100644 --- a/.github/workflows/branch-e2e.yml +++ b/.github/workflows/branch-e2e.yml @@ -309,8 +309,48 @@ jobs: rpm-release: ${{ needs.version.outputs.rpm_release }} cargo-version: ${{ needs.version.outputs.cargo }} + # Test inputs don't depend on the packages, so build them while the packages + # build instead of in prepare-integration. + build-tmachine-test-inputs: + name: Build tmachine test inputs + needs: [pr_metadata] + if: needs.pr_metadata.outputs.run_integration == 'true' + permissions: + contents: read + runs-on: ubuntu-24.04 + timeout-minutes: 30 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + ref: ${{ github.sha }} + - uses: ./.github/actions/setup-nix + - name: Build test archives + run: | + # Retry dependency preparation, then generate artifacts once. + nix build --no-link .#build-artifacts-test-archives || nix build --no-link .#build-artifacts-test-archives + nix run .#build-artifacts-test-archives + - name: Build test workload images + run: | + # Retry dependency preparation, then generate artifacts once. + nix build --no-link .#build-artifacts-test-images || nix build --no-link .#build-artifacts-test-images + nix run .#build-artifacts-test-images + - name: Package Helm chart + run: | + # Retry dependency preparation, then generate artifacts once. + nix build --no-link .#build-artifacts-helm || nix build --no-link .#build-artifacts-helm + nix run .#build-artifacts-helm + - name: Upload tmachine test inputs + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: openshell-tmachine-test-inputs + path: artifacts + compression-level: 0 + retention-days: 5 + if-no-files-found: error + prepare-integration: - needs: [pr_metadata, build-binaries, build-images, build-deb, build-rpm] + needs: [pr_metadata, build-binaries, build-images, build-deb, build-rpm, build-tmachine-test-inputs] if: needs.pr_metadata.outputs.run_integration == 'true' permissions: actions: read @@ -320,6 +360,7 @@ jobs: with: deb-artifact-name: deb-linux-amd64 rpm-artifact-name: rpm-linux-x86_64 + test-inputs-artifact-name: openshell-tmachine-test-inputs # Run driver-independent conformance tests. conformance-integration: diff --git a/.github/workflows/prepare-integration-inputs.yml b/.github/workflows/prepare-integration-inputs.yml index 7b2bf62ab1..9a8784285e 100644 --- a/.github/workflows/prepare-integration-inputs.yml +++ b/.github/workflows/prepare-integration-inputs.yml @@ -26,6 +26,11 @@ on: required: false type: string default: "" + test-inputs-artifact-name: + description: Prebuilt test archives, test workload images, and Helm chart; built here when empty + required: false + type: string + default: "" outputs: source_sha: description: Source revision of the candidate artifacts @@ -66,6 +71,7 @@ jobs: persist-credentials: false - uses: ./.github/actions/setup-nix + if: inputs['test-inputs-artifact-name'] == '' - name: Download CLI artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 @@ -151,19 +157,31 @@ jobs: docker tag "ghcr.io/nvidia/openshell/supervisor:${IMAGE_TAG}" openshell/supervisor:tmachine docker save --output artifacts/images/openshell-supervisor-tmachine.tar openshell/supervisor:tmachine + - name: Download test inputs + if: inputs['test-inputs-artifact-name'] != '' + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: ${{ inputs['test-inputs-artifact-name'] }} + path: artifacts + github-token: ${{ github.token }} + run-id: ${{ inputs['artifact-run-id'] || github.run_id }} + - name: Build test archives + if: inputs['test-inputs-artifact-name'] == '' run: | # Retry dependency preparation, then generate artifacts once. nix build --no-link .#build-artifacts-test-archives || nix build --no-link .#build-artifacts-test-archives nix run .#build-artifacts-test-archives - name: Build test workload images + if: inputs['test-inputs-artifact-name'] == '' run: | # Retry dependency preparation, then generate artifacts once. nix build --no-link .#build-artifacts-test-images || nix build --no-link .#build-artifacts-test-images nix run .#build-artifacts-test-images - name: Package Helm chart + if: inputs['test-inputs-artifact-name'] == '' run: | # Retry dependency preparation, then generate artifacts once. nix build --no-link .#build-artifacts-helm || nix build --no-link .#build-artifacts-helm From ed3e029b4d26b43f7f4874ef372fb75d3394a3d3 Mon Sep 17 00:00:00 2001 From: Matthew Grossman Date: Wed, 4 Nov 2026 13:10:49 -0800 Subject: [PATCH 3/4] ci(e2e): split binary builds into per-platform workflows Branch E2E used flags on the shared build workflows to keep Linux and macOS apart. Make each platform its own reusable workflow instead, with a plain matrix, so a consumer depends only on the platforms it needs and adding a platform means adding a workflow rather than another flag. Move the VM driver build steps shared by both platforms into a composite action. Release workflows call both platforms and keep their existing gating. Signed-off-by: Matthew Grossman --- .github/actions/build-vm-driver/action.yml | 75 ++++++++++ .github/workflows/branch-e2e.yml | 64 ++++----- ...-binaries.yml => build-binaries-linux.yml} | 43 +----- .github/workflows/build-binaries-macos.yml | 63 ++++++++ .github/workflows/build-vm-driver-linux.yml | 58 ++++++++ .github/workflows/build-vm-driver-macos.yml | 55 +++++++ .github/workflows/build-vm-driver.yml | 136 ------------------ .github/workflows/release-build.yml | 44 ++++-- .github/workflows/release-dev.yml | 50 +++++-- CI.md | 2 +- 10 files changed, 353 insertions(+), 237 deletions(-) create mode 100644 .github/actions/build-vm-driver/action.yml rename .github/workflows/{build-binaries.yml => build-binaries-linux.yml} (77%) create mode 100644 .github/workflows/build-binaries-macos.yml create mode 100644 .github/workflows/build-vm-driver-linux.yml create mode 100644 .github/workflows/build-vm-driver-macos.yml delete mode 100644 .github/workflows/build-vm-driver.yml diff --git a/.github/actions/build-vm-driver/action.yml b/.github/actions/build-vm-driver/action.yml new file mode 100644 index 0000000000..7942058d94 --- /dev/null +++ b/.github/actions/build-vm-driver/action.yml @@ -0,0 +1,75 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +name: Build VM Driver +description: Assemble the compressed VM runtime and build openshell-driver-vm + +inputs: + arch: + description: Guest architecture used to select the Linux sandbox and VM init artifacts + required: true + triple: + description: Rust target triple of the driver + required: true + supervisor-artifact: + description: Artifact containing the openshell-supervisor binary embedded in the runtime + required: true + cargo-version: + description: Cargo package version embedded in the binary + required: true + supervisor-image-tag: + description: Default supervisor image tag embedded in the binary + required: false + default: "" + entitlements-file: + description: Path to an entitlements plist for macOS ad-hoc codesigning + required: false + default: "" +runs: + using: composite + steps: + - name: Download openshell-sandbox + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: openshell-sandbox-${{ inputs.arch }}-unknown-linux-musl + path: sandbox + + - name: Download openshell-supervisor + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: ${{ inputs.supervisor-artifact }} + path: supervisor + + - name: Download VM guest init + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: openshell-vm-init-${{ inputs.arch }}-unknown-linux-musl + path: vm-init + + - name: Build VM runtime + shell: nix develop -c bash -euo pipefail {0} + run: | + # HTTP 416 is not retried by Nix; restart the build once on failure. + nix build .#vm-runtime || nix build .#vm-runtime + + - name: Assemble compressed VM runtime + shell: nix develop -c bash -euo pipefail {0} + run: | + compressed_dir="${RUNNER_TEMP}/vm-runtime-compressed" + install -d "$compressed_dir" + cp result/compressed/*.zst "$compressed_dir/" + zstd -19 -T1 sandbox/openshell-sandbox -o "$compressed_dir/openshell-sandbox.zst" + zstd -19 -T1 supervisor/openshell-supervisor -o "$compressed_dir/openshell-supervisor.zst" + zstd -19 -T1 vm-init/openshell-vm-init -o "$compressed_dir/openshell-vm-init.zst" + + - name: Build openshell-driver-vm + uses: ./.github/actions/build-rust-binary + env: + OPENSHELL_VM_RUNTIME_COMPRESSED_DIR: ${{ runner.temp }}/vm-runtime-compressed + with: + package: openshell-driver-vm + binary: openshell-driver-vm + triple: ${{ inputs.triple }} + cargo-version: ${{ inputs.cargo-version }} + supervisor-image-tag: ${{ inputs.supervisor-image-tag }} + entitlements-file: ${{ inputs.entitlements-file }} diff --git a/.github/workflows/branch-e2e.yml b/.github/workflows/branch-e2e.yml index e0befe158a..4057c0a6ea 100644 --- a/.github/workflows/branch-e2e.yml +++ b/.github/workflows/branch-e2e.yml @@ -101,27 +101,23 @@ jobs: echo "rpm_release=$rpm_release" } >> "$GITHUB_OUTPUT" - build-binaries: + build-binaries-linux: needs: version permissions: contents: read - uses: ./.github/workflows/build-binaries.yml + uses: ./.github/workflows/build-binaries-linux.yml with: cargo-version: ${{ needs.version.outputs.cargo }} - macos: false secrets: CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} - # macOS runners can queue for a long time. A separate call lets Linux - # consumers start as soon as the Linux binaries are ready. build-binaries-macos: needs: version permissions: contents: read - uses: ./.github/workflows/build-binaries.yml + uses: ./.github/workflows/build-binaries-macos.yml with: cargo-version: ${{ needs.version.outputs.cargo }} - linux: false secrets: CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} @@ -160,7 +156,7 @@ jobs: # The conformance program, built once per architecture for the host lanes. # It lives in its own workspace and is not released, so it is not part of - # build-binaries.yml. + # build-binaries-linux.yml. build-conformance: name: openshell-conformance (${{ matrix.triple }}) needs: [pr_metadata] @@ -251,32 +247,30 @@ jobs: triple: ${{ matrix.triple }} cargo-version: ${{ needs.version.outputs.cargo }} - build-vm-driver: - needs: [pr_metadata, version, build-binaries] + build-vm-driver-linux: + needs: [pr_metadata, version, build-binaries-linux] if: needs.pr_metadata.outputs.run_core_e2e == 'true' permissions: contents: read - uses: ./.github/workflows/build-vm-driver.yml + uses: ./.github/workflows/build-vm-driver-linux.yml with: cargo-version: ${{ needs.version.outputs.cargo }} - macos: false secrets: CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} build-vm-driver-macos: - needs: [pr_metadata, version, build-binaries, build-binaries-macos] + needs: [pr_metadata, version, build-binaries-linux, build-binaries-macos] if: needs.pr_metadata.outputs.run_core_e2e == 'true' permissions: contents: read - uses: ./.github/workflows/build-vm-driver.yml + uses: ./.github/workflows/build-vm-driver-macos.yml with: cargo-version: ${{ needs.version.outputs.cargo }} - linux: false secrets: CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} build-images: - needs: [pr_metadata, build-binaries] + needs: [pr_metadata, build-binaries-linux] if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_any_e2e == 'true' permissions: contents: read @@ -285,7 +279,7 @@ jobs: build-deb: name: Build Debian packages - needs: [pr_metadata, version, build-binaries, build-vm-driver] + needs: [pr_metadata, version, build-binaries-linux, build-vm-driver-linux] if: needs.pr_metadata.outputs.run_integration == 'true' permissions: contents: read @@ -297,7 +291,7 @@ jobs: build-rpm: name: Build RPM packages - needs: [pr_metadata, version, build-binaries] + needs: [pr_metadata, version, build-binaries-linux] if: needs.pr_metadata.outputs.run_integration == 'true' permissions: actions: read @@ -350,7 +344,7 @@ jobs: if-no-files-found: error prepare-integration: - needs: [pr_metadata, build-binaries, build-images, build-deb, build-rpm, build-tmachine-test-inputs] + needs: [pr_metadata, build-binaries-linux, build-images, build-deb, build-rpm, build-tmachine-test-inputs] if: needs.pr_metadata.outputs.run_integration == 'true' permissions: actions: read @@ -428,7 +422,7 @@ jobs: ] docker-e2e: - needs: [pr_metadata, build-binaries, build-conformance, build-images] + needs: [pr_metadata, build-binaries-linux, build-conformance, build-images] if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true' permissions: actions: read @@ -441,7 +435,7 @@ jobs: runner: linux-arm64-cpu8 podman-e2e: - needs: [pr_metadata, build-binaries, build-conformance, build-images] + needs: [pr_metadata, build-binaries-linux, build-conformance, build-images] if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true' permissions: actions: read @@ -455,7 +449,7 @@ jobs: [{"suite":"ci","runner":"ubuntu-26.04","podman_major":"5","podman_package_version":"5.7.0+ds2-3build1","conmon_package_version":"2.1.13+ds1-2","cmd":"mise run --no-deps --skip-deps e2e:podman:ci"}] podman-additional-ca-e2e: - needs: [pr_metadata, build-binaries, build-conformance, build-images] + needs: [pr_metadata, build-binaries-linux, build-conformance, build-images] if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true' permissions: actions: read @@ -469,7 +463,7 @@ jobs: [{"suite":"additional-ca","runner":"ubuntu-26.04","podman_major":"5","podman_package_version":"5.7.0+ds2-3build1","conmon_package_version":"2.1.13+ds1-2","cmd":"OPENSHELL_E2E_PODMAN_TEST=additional_ca mise run --no-deps --skip-deps e2e:podman"}] vm-e2e: - needs: [pr_metadata, build-binaries, build-conformance, build-vm-driver] + needs: [pr_metadata, build-binaries-linux, build-conformance, build-vm-driver-linux] if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true' permissions: actions: read @@ -480,7 +474,7 @@ jobs: prebuilt-conformance: true vm-additional-ca-e2e: - needs: [pr_metadata, build-binaries, build-conformance, build-vm-driver] + needs: [pr_metadata, build-binaries-linux, build-conformance, build-vm-driver-linux] if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true' permissions: actions: read @@ -493,7 +487,7 @@ jobs: test-name: additional_ca docker-external-driver-e2e: - needs: [pr_metadata, build-binaries, build-conformance, build-gateway-plain, build-external-drivers, build-images] + needs: [pr_metadata, build-binaries-linux, build-conformance, build-gateway-plain, build-external-drivers, build-images] if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true' permissions: actions: read @@ -510,7 +504,7 @@ jobs: [{"suite":"external-driver","cmd":"mise run --no-deps --skip-deps e2e:docker:external-driver","apt_packages":"openssh-client","python_proto":false,"mcp":false}] podman-external-driver-e2e: - needs: [pr_metadata, build-binaries, build-conformance, build-gateway-plain, build-external-drivers, build-images] + needs: [pr_metadata, build-binaries-linux, build-conformance, build-gateway-plain, build-external-drivers, build-images] if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true' permissions: actions: read @@ -526,7 +520,7 @@ jobs: [{"suite":"external-driver","runner":"ubuntu-26.04","podman_major":"5","podman_package_version":"5.7.0+ds2-3build1","conmon_package_version":"2.1.13+ds1-2","cmd":"mise run --no-deps --skip-deps e2e:podman:external-driver"}] vm-external-driver-e2e: - needs: [pr_metadata, build-binaries, build-conformance, build-gateway-plain, build-vm-driver] + needs: [pr_metadata, build-binaries-linux, build-conformance, build-gateway-plain, build-vm-driver-linux] if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true' permissions: actions: read @@ -540,7 +534,7 @@ jobs: e2e-task: e2e:vm:external-driver gpu-e2e: - needs: [pr_metadata, build-binaries, build-images] + needs: [pr_metadata, build-binaries-linux, build-images] if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_gpu_e2e == 'true' permissions: actions: read @@ -551,7 +545,7 @@ jobs: image-tag: ${{ github.sha }} kubernetes-e2e: - needs: [pr_metadata, build-binaries, build-conformance, build-images] + needs: [pr_metadata, build-binaries-linux, build-conformance, build-images] if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true' strategy: fail-fast: false @@ -582,7 +576,7 @@ jobs: test-name: ${{ matrix.test_name }} kubernetes-app-listener-e2e: - needs: [pr_metadata, build-binaries, build-conformance, build-images] + needs: [pr_metadata, build-binaries-linux, build-conformance, build-images] if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true' strategy: fail-fast: false @@ -620,7 +614,7 @@ jobs: listener-takeover: ${{ matrix.takeover }} kubernetes-workspace-managed-e2e: - needs: [pr_metadata, build-binaries, build-conformance, build-images] + needs: [pr_metadata, build-binaries-linux, build-conformance, build-images] if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true' permissions: actions: read @@ -634,7 +628,7 @@ jobs: e2e-task: e2e:kubernetes:workspace-managed kubernetes-external-driver-e2e: - needs: [pr_metadata, build-binaries, build-conformance, build-gateway-plain, build-external-drivers, build-images] + needs: [pr_metadata, build-binaries-linux, build-conformance, build-gateway-plain, build-external-drivers, build-images] if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true' permissions: actions: read @@ -651,7 +645,7 @@ jobs: cluster-images: sandbox supervisor kubernetes-workspace-operator-e2e: - needs: [pr_metadata, build-binaries, build-conformance, build-images] + needs: [pr_metadata, build-binaries-linux, build-conformance, build-images] if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true' permissions: actions: read @@ -665,7 +659,7 @@ jobs: e2e-task: e2e:kubernetes:workspace-operator kubernetes-ha-e2e: - needs: [pr_metadata, build-binaries, build-conformance, build-images] + needs: [pr_metadata, build-binaries-linux, build-conformance, build-images] if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_kubernetes_ha_e2e == 'true' permissions: actions: read @@ -683,7 +677,7 @@ jobs: use-envoy-gateway: true kubernetes-credential-drivers-e2e: - needs: [pr_metadata, build-binaries, build-conformance, build-images] + needs: [pr_metadata, build-binaries-linux, build-conformance, build-images] if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_kubernetes_credential_drivers_e2e == 'true' permissions: actions: read diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries-linux.yml similarity index 77% rename from .github/workflows/build-binaries.yml rename to .github/workflows/build-binaries-linux.yml index 559da3c677..1adf9be0e2 100644 --- a/.github/workflows/build-binaries.yml +++ b/.github/workflows/build-binaries-linux.yml @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -name: Build Binaries +name: Build Linux Binaries on: workflow_call: @@ -17,16 +17,6 @@ on: required: false type: string default: "" - linux: - description: Build the Linux binaries. - required: false - type: boolean - default: true - macos: - description: Build the macOS binaries. - required: false - type: boolean - default: true secrets: CACHIX_AUTH_TOKEN: required: true @@ -40,7 +30,6 @@ env: jobs: cli: name: openshell (${{ matrix.triple }}) - if: inputs.linux env: PACKAGE: openshell-cli BINARY: openshell @@ -73,7 +62,6 @@ jobs: prover: name: openshell-prover (${{ matrix.triple }}) - if: inputs.linux env: PACKAGE: openshell-prover-cli BINARY: openshell-prover @@ -90,7 +78,6 @@ jobs: gateway: name: openshell-gateway (${{ matrix.triple }}) - if: inputs.linux env: PACKAGE: openshell-gateway BINARY: openshell-gateway @@ -107,7 +94,6 @@ jobs: runtimes: name: ${{ matrix.binary }} (${{ matrix.triple }}) - if: inputs.linux env: PACKAGE: ${{ matrix.package }} BINARY: ${{ matrix.binary }} @@ -136,7 +122,6 @@ jobs: vm-init: name: openshell-vm-init (${{ matrix.triple }}) - if: inputs.linux env: PACKAGE: openshell-driver-vm BINARY: openshell-vm-init @@ -151,29 +136,3 @@ jobs: runs-on: ${{ matrix.runner }} timeout-minutes: 60 steps: *build_steps - - macos: - name: ${{ matrix.binary }} (${{ matrix.triple }}) - if: inputs.macos - env: - PACKAGE: ${{ matrix.package }} - BINARY: ${{ matrix.binary }} - strategy: - fail-fast: false - matrix: - include: - - package: openshell-cli - binary: openshell - triple: aarch64-apple-darwin - - package: openshell-prover-cli - binary: openshell-prover - triple: aarch64-apple-darwin - - package: openshell-gateway - binary: openshell-gateway - triple: aarch64-apple-darwin - - package: openshell-supervisor - binary: openshell-supervisor - triple: aarch64-apple-darwin - runs-on: macos-15-xlarge - timeout-minutes: 60 - steps: *build_steps diff --git a/.github/workflows/build-binaries-macos.yml b/.github/workflows/build-binaries-macos.yml new file mode 100644 index 0000000000..e5f7d09648 --- /dev/null +++ b/.github/workflows/build-binaries-macos.yml @@ -0,0 +1,63 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +name: Build macOS Binaries + +on: + workflow_call: + inputs: + cargo-version: + required: true + type: string + supervisor-image-tag: + required: false + type: string + default: "" + checkout-ref: + required: false + type: string + default: "" + secrets: + CACHIX_AUTH_TOKEN: + required: true + +permissions: + contents: read + +jobs: + build: + name: ${{ matrix.binary }} (${{ matrix.triple }}) + strategy: + fail-fast: false + matrix: + include: + - package: openshell-cli + binary: openshell + triple: aarch64-apple-darwin + - package: openshell-prover-cli + binary: openshell-prover + triple: aarch64-apple-darwin + - package: openshell-gateway + binary: openshell-gateway + triple: aarch64-apple-darwin + - package: openshell-supervisor + binary: openshell-supervisor + triple: aarch64-apple-darwin + runs-on: macos-15-xlarge + timeout-minutes: 60 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + ref: ${{ inputs.checkout-ref || github.sha }} + - uses: ./.github/actions/setup-nix + with: + prepare-shell: "true" + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} + - uses: ./.github/actions/build-rust-binary + with: + package: ${{ matrix.package }} + binary: ${{ matrix.binary }} + triple: ${{ matrix.triple }} + cargo-version: ${{ inputs.cargo-version }} + supervisor-image-tag: ${{ inputs.supervisor-image-tag }} diff --git a/.github/workflows/build-vm-driver-linux.yml b/.github/workflows/build-vm-driver-linux.yml new file mode 100644 index 0000000000..e6676d5b2a --- /dev/null +++ b/.github/workflows/build-vm-driver-linux.yml @@ -0,0 +1,58 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +name: Build Linux VM Driver + +on: + workflow_call: + inputs: + cargo-version: + required: true + type: string + supervisor-image-tag: + required: false + type: string + default: "" + checkout-ref: + required: false + type: string + default: "" + secrets: + CACHIX_AUTH_TOKEN: + required: true + +permissions: + contents: read + +jobs: + build: + name: openshell-driver-vm (${{ matrix.triple }}) + strategy: + matrix: + include: + - arch: x86_64 + triple: x86_64-unknown-linux-gnu + runner: linux-amd64-cpu8 + - arch: aarch64 + triple: aarch64-unknown-linux-gnu + runner: linux-arm64-cpu8 + runs-on: ${{ matrix.runner }} + timeout-minutes: 60 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + ref: ${{ inputs['checkout-ref'] || github.sha }} + + - uses: ./.github/actions/setup-nix + with: + prepare-shell: "true" + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} + + - uses: ./.github/actions/build-vm-driver + with: + arch: ${{ matrix.arch }} + triple: ${{ matrix.triple }} + supervisor-artifact: openshell-supervisor-${{ matrix.arch }}-unknown-linux-gnu + cargo-version: ${{ inputs['cargo-version'] }} + supervisor-image-tag: ${{ inputs['supervisor-image-tag'] }} diff --git a/.github/workflows/build-vm-driver-macos.yml b/.github/workflows/build-vm-driver-macos.yml new file mode 100644 index 0000000000..ad2cfba13c --- /dev/null +++ b/.github/workflows/build-vm-driver-macos.yml @@ -0,0 +1,55 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +name: Build macOS VM Driver + +on: + workflow_call: + inputs: + cargo-version: + required: true + type: string + supervisor-image-tag: + required: false + type: string + default: "" + checkout-ref: + required: false + type: string + default: "" + secrets: + CACHIX_AUTH_TOKEN: + required: true + +permissions: + contents: read + +jobs: + build: + name: openshell-driver-vm (${{ matrix.triple }}) + strategy: + matrix: + include: + - arch: aarch64 + triple: aarch64-apple-darwin + runs-on: macos-15-xlarge + timeout-minutes: 60 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + ref: ${{ inputs['checkout-ref'] || github.sha }} + + - uses: ./.github/actions/setup-nix + with: + prepare-shell: "true" + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} + + - uses: ./.github/actions/build-vm-driver + with: + arch: ${{ matrix.arch }} + triple: ${{ matrix.triple }} + supervisor-artifact: openshell-supervisor-${{ matrix.arch }}-apple-darwin + cargo-version: ${{ inputs['cargo-version'] }} + supervisor-image-tag: ${{ inputs['supervisor-image-tag'] }} + entitlements-file: crates/openshell-driver-vm/entitlements.plist diff --git a/.github/workflows/build-vm-driver.yml b/.github/workflows/build-vm-driver.yml deleted file mode 100644 index 068fff5b73..0000000000 --- a/.github/workflows/build-vm-driver.yml +++ /dev/null @@ -1,136 +0,0 @@ -# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 - -name: Build VM Driver - -on: - workflow_call: - inputs: - cargo-version: - required: true - type: string - supervisor-image-tag: - required: false - type: string - default: "" - checkout-ref: - required: false - type: string - default: "" - linux: - description: Build the Linux VM drivers. - required: false - type: boolean - default: true - macos: - description: Build the macOS VM driver. - required: false - type: boolean - default: true - secrets: - CACHIX_AUTH_TOKEN: - required: true - -permissions: - contents: read - -jobs: - linux: - name: openshell-driver-vm (${{ matrix.triple }}) - if: inputs.linux - strategy: - matrix: - include: - - arch: x86_64 - triple: x86_64-unknown-linux-gnu - runner: linux-amd64-cpu8 - entitlements-file: "" - - arch: aarch64 - triple: aarch64-unknown-linux-gnu - runner: linux-arm64-cpu8 - entitlements-file: "" - runs-on: ${{ matrix.runner }} - timeout-minutes: 60 - defaults: &build_defaults - run: - shell: nix develop -c bash -euo pipefail {0} - steps: &build_steps - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - ref: ${{ inputs['checkout-ref'] || github.sha }} - - - uses: ./.github/actions/setup-nix - with: - prepare-shell: "true" - cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} - - - name: Download openshell-sandbox - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: openshell-sandbox-${{ matrix.arch }}-unknown-linux-musl - path: sandbox - - - name: Download openshell-supervisor - if: endsWith(matrix.triple, '-unknown-linux-gnu') - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: openshell-supervisor-${{ matrix.arch }}-unknown-linux-gnu - path: supervisor - - - name: Download native macOS host supervisor - if: endsWith(matrix.triple, '-apple-darwin') - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: openshell-supervisor-aarch64-apple-darwin - path: host-supervisor - - - name: Download VM guest init - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: openshell-vm-init-${{ matrix.arch }}-unknown-linux-musl - path: vm-init - - - name: Build VM runtime - run: | - # HTTP 416 is not retried by Nix; restart the build once on failure. - nix build .#vm-runtime || nix build .#vm-runtime - - - name: Assemble compressed VM runtime - run: | - compressed_dir="${RUNNER_TEMP}/vm-runtime-compressed" - host_supervisor="supervisor/openshell-supervisor" - if [[ "${{ matrix.triple }}" == *-apple-darwin ]]; then - host_supervisor="host-supervisor/openshell-supervisor" - fi - install -d "$compressed_dir" - cp result/compressed/*.zst "$compressed_dir/" - zstd -19 -T1 sandbox/openshell-sandbox -o "$compressed_dir/openshell-sandbox.zst" - zstd -19 -T1 "$host_supervisor" -o "$compressed_dir/openshell-supervisor.zst" - zstd -19 -T1 vm-init/openshell-vm-init -o "$compressed_dir/openshell-vm-init.zst" - - - name: Build openshell-driver-vm - uses: ./.github/actions/build-rust-binary - env: - OPENSHELL_VM_RUNTIME_COMPRESSED_DIR: ${{ runner.temp }}/vm-runtime-compressed - with: - package: openshell-driver-vm - binary: openshell-driver-vm - triple: ${{ matrix.triple }} - cargo-version: ${{ inputs['cargo-version'] }} - supervisor-image-tag: ${{ inputs['supervisor-image-tag'] }} - entitlements-file: ${{ matrix.entitlements-file }} - - macos: - name: openshell-driver-vm (${{ matrix.triple }}) - if: inputs.macos - strategy: - matrix: - include: - - arch: aarch64 - triple: aarch64-apple-darwin - entitlements-file: crates/openshell-driver-vm/entitlements.plist - runs-on: macos-15-xlarge - timeout-minutes: 60 - defaults: *build_defaults - steps: *build_steps diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index c85d29d2fc..2ffc73b2ce 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -116,11 +116,11 @@ jobs: echo "source_sha=$(git rev-parse HEAD)" } >> "$GITHUB_OUTPUT" - build-binaries: + build-binaries-linux: needs: compute-versions permissions: contents: read - uses: ./.github/workflows/build-binaries.yml + uses: ./.github/workflows/build-binaries-linux.yml with: cargo-version: ${{ needs.compute-versions.outputs.cargo_version }} supervisor-image-tag: ${{ needs.compute-versions.outputs.semver }} @@ -128,11 +128,35 @@ jobs: secrets: CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} - build-vm-driver: - needs: [compute-versions, build-binaries] + build-binaries-macos: + needs: compute-versions + permissions: + contents: read + uses: ./.github/workflows/build-binaries-macos.yml + with: + cargo-version: ${{ needs.compute-versions.outputs.cargo_version }} + supervisor-image-tag: ${{ needs.compute-versions.outputs.semver }} + checkout-ref: ${{ needs.compute-versions.outputs.source_sha }} + secrets: + CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} + + build-vm-driver-linux: + needs: [compute-versions, build-binaries-linux] + permissions: + contents: read + uses: ./.github/workflows/build-vm-driver-linux.yml + with: + cargo-version: ${{ needs.compute-versions.outputs.cargo_version }} + supervisor-image-tag: ${{ needs.compute-versions.outputs.semver }} + checkout-ref: ${{ needs.compute-versions.outputs.source_sha }} + secrets: + CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} + + build-vm-driver-macos: + needs: [compute-versions, build-binaries-linux, build-binaries-macos] permissions: contents: read - uses: ./.github/workflows/build-vm-driver.yml + uses: ./.github/workflows/build-vm-driver-macos.yml with: cargo-version: ${{ needs.compute-versions.outputs.cargo_version }} supervisor-image-tag: ${{ needs.compute-versions.outputs.semver }} @@ -141,7 +165,7 @@ jobs: CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} package-binaries: - needs: [compute-versions, build-binaries, build-vm-driver] + needs: [compute-versions, build-binaries-linux, build-binaries-macos, build-vm-driver-linux, build-vm-driver-macos] permissions: actions: read contents: read @@ -150,7 +174,7 @@ jobs: checkout-ref: ${{ needs.compute-versions.outputs.source_sha }} build-images: - needs: [compute-versions, build-binaries] + needs: [compute-versions, build-binaries-linux, build-binaries-macos] permissions: contents: read packages: write @@ -202,7 +226,7 @@ jobs: build-deb: name: Build Debian Packages - needs: [compute-versions, build-binaries, build-vm-driver] + needs: [compute-versions, build-binaries-linux, build-binaries-macos, build-vm-driver-linux, build-vm-driver-macos] uses: ./.github/workflows/deb-package.yml with: deb-version: ${{ needs.compute-versions.outputs.deb_version }} @@ -210,14 +234,14 @@ jobs: build-snap: name: Build Snap - needs: [compute-versions, build-binaries] + needs: [compute-versions, build-binaries-linux, build-binaries-macos] uses: ./.github/workflows/snap-package.yml with: checkout-ref: ${{ needs.compute-versions.outputs.source_sha }} build-rpm: name: Build RPM Packages - needs: [compute-versions, build-binaries] + needs: [compute-versions, build-binaries-linux, build-binaries-macos] uses: ./.github/workflows/rpm-package.yml with: checkout-ref: ${{ needs.compute-versions.outputs.source_sha }} diff --git a/.github/workflows/release-dev.yml b/.github/workflows/release-dev.yml index 71db45ffb1..1e77854af3 100644 --- a/.github/workflows/release-dev.yml +++ b/.github/workflows/release-dev.yml @@ -59,11 +59,11 @@ jobs: echo "rpm_release=$(uv run python tasks/scripts/release.py get-version --dev --rpm-release)" } >> "$GITHUB_OUTPUT" - build-binaries: + build-binaries-linux: needs: compute-versions permissions: contents: read - uses: ./.github/workflows/build-binaries.yml + uses: ./.github/workflows/build-binaries-linux.yml with: cargo-version: ${{ needs.compute-versions.outputs.cargo_version }} supervisor-image-tag: dev @@ -71,11 +71,35 @@ jobs: secrets: CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} - build-vm-driver: - needs: [compute-versions, build-binaries] + build-binaries-macos: + needs: compute-versions + permissions: + contents: read + uses: ./.github/workflows/build-binaries-macos.yml + with: + cargo-version: ${{ needs.compute-versions.outputs.cargo_version }} + supervisor-image-tag: dev + checkout-ref: ${{ github.sha }} + secrets: + CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} + + build-vm-driver-linux: + needs: [compute-versions, build-binaries-linux] + permissions: + contents: read + uses: ./.github/workflows/build-vm-driver-linux.yml + with: + cargo-version: ${{ needs.compute-versions.outputs.cargo_version }} + supervisor-image-tag: dev + checkout-ref: ${{ github.sha }} + secrets: + CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} + + build-vm-driver-macos: + needs: [compute-versions, build-binaries-linux, build-binaries-macos] permissions: contents: read - uses: ./.github/workflows/build-vm-driver.yml + uses: ./.github/workflows/build-vm-driver-macos.yml with: cargo-version: ${{ needs.compute-versions.outputs.cargo_version }} supervisor-image-tag: dev @@ -84,7 +108,7 @@ jobs: CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} package-binaries: - needs: [build-binaries, build-vm-driver] + needs: [build-binaries-linux, build-binaries-macos, build-vm-driver-linux, build-vm-driver-macos] permissions: actions: read contents: read @@ -93,7 +117,7 @@ jobs: checkout-ref: ${{ github.sha }} build-images: - needs: build-binaries + needs: [build-binaries-linux, build-binaries-macos] permissions: contents: read packages: write @@ -102,7 +126,7 @@ jobs: checkout-ref: ${{ github.sha }} prepare-integration: - needs: [build-binaries, build-deb, build-images, build-rpm] + needs: [build-binaries-linux, build-binaries-macos, build-deb, build-images, build-rpm] permissions: actions: read contents: read @@ -141,7 +165,7 @@ jobs: CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} docker-e2e: - needs: [build-binaries, build-images] + needs: [build-binaries-linux, build-binaries-macos, build-images] permissions: actions: read contents: read @@ -153,7 +177,7 @@ jobs: runner: linux-arm64-cpu8 vm-e2e: - needs: [build-binaries, build-vm-driver] + needs: [build-binaries-linux, build-binaries-macos, build-vm-driver-linux, build-vm-driver-macos] permissions: actions: read contents: read @@ -227,7 +251,7 @@ jobs: build-deb: name: Build Debian Packages - needs: [compute-versions, build-binaries, build-vm-driver] + needs: [compute-versions, build-binaries-linux, build-binaries-macos, build-vm-driver-linux, build-vm-driver-macos] uses: ./.github/workflows/deb-package.yml with: deb-version: ${{ needs.compute-versions.outputs.deb_version }} @@ -235,14 +259,14 @@ jobs: build-snap: name: Build snap - needs: [compute-versions, build-binaries] + needs: [compute-versions, build-binaries-linux, build-binaries-macos] uses: ./.github/workflows/snap-package.yml with: checkout-ref: ${{ github.sha }} build-rpm: name: Build RPM Packages - needs: [compute-versions, build-binaries] + needs: [compute-versions, build-binaries-linux, build-binaries-macos] uses: ./.github/workflows/rpm-package.yml with: checkout-ref: ${{ github.sha }} diff --git a/CI.md b/CI.md index a1e1988149..66052d4e6b 100644 --- a/CI.md +++ b/CI.md @@ -691,7 +691,7 @@ The bot's full administrator documentation is internal to NVIDIA. The only comma |---|---| | `.github/workflows/branch-checks.yml` | Required non-E2E checks. Triggers on `push: pull-request/[0-9]+` for PR mirrors and `merge_group` for queued merges. | | `.github/workflows/branch-e2e.yml` | Standard, GPU, Kubernetes HA, and Kubernetes credential-driver E2E. PR mirror pushes use `test:e2e`, `test:e2e-gpu`, and `test:e2e-kubernetes` labels; merge groups do not run E2E. | -| `.github/workflows/build-binaries.yml`, `build-vm-driver.yml` | Shared binary matrices used by branch and release workflows. The VM driver remains separate because its build consumes the runtime binaries. Branch E2E calls each workflow twice, once with `macos: false` and once with `linux: false`, so Linux jobs don't wait for macOS runners. | +| `.github/workflows/build-binaries-{linux,macos}.yml`, `build-vm-driver-{linux,macos}.yml` | Shared per-platform binary matrices used by branch and release workflows. Each platform is its own workflow, so a consumer depends only on the platforms it needs. The VM driver remains separate because its build consumes the runtime binaries; both platforms share the steps in `.github/actions/build-vm-driver`. | | `.github/workflows/build-images.yml` | Builds and pushes multi-platform images, then uploads the same OCI images as workflow artifacts. | | `.github/workflows/package-release-binaries.yml` | Packages raw build artifacts into release tarballs without rebuilding them. | | `.github/workflows/e2e-docker-test.yml`, `e2e-podman-test.yml`, `e2e-vm-test.yml`, `e2e-kubernetes-test.yml` | Reusable runtime lanes called directly by branch and release workflows. Callers select suites and declare only the artifacts each runtime consumes. | From 6cf3a7852356b307fb938a40161903c0d3dc895a Mon Sep 17 00:00:00 2001 From: Matthew Grossman Date: Mon, 9 Nov 2026 12:35:25 -0800 Subject: [PATCH 4/4] ci(release): inline VM driver build steps in the platform workflows Release builds check out the release tag, so a local action used by the VM driver workflows must exist in that tag. A tag cut before the shared build-vm-driver action landed would not have it, which breaks promoting or re-qualifying that tag. Keep the steps inline in each platform workflow instead. Signed-off-by: Matthew Grossman --- .github/actions/build-vm-driver/action.yml | 75 --------------------- .github/workflows/build-vm-driver-linux.yml | 44 +++++++++++- .github/workflows/build-vm-driver-macos.yml | 44 +++++++++++- CI.md | 2 +- 4 files changed, 83 insertions(+), 82 deletions(-) delete mode 100644 .github/actions/build-vm-driver/action.yml diff --git a/.github/actions/build-vm-driver/action.yml b/.github/actions/build-vm-driver/action.yml deleted file mode 100644 index 7942058d94..0000000000 --- a/.github/actions/build-vm-driver/action.yml +++ /dev/null @@ -1,75 +0,0 @@ -# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 - -name: Build VM Driver -description: Assemble the compressed VM runtime and build openshell-driver-vm - -inputs: - arch: - description: Guest architecture used to select the Linux sandbox and VM init artifacts - required: true - triple: - description: Rust target triple of the driver - required: true - supervisor-artifact: - description: Artifact containing the openshell-supervisor binary embedded in the runtime - required: true - cargo-version: - description: Cargo package version embedded in the binary - required: true - supervisor-image-tag: - description: Default supervisor image tag embedded in the binary - required: false - default: "" - entitlements-file: - description: Path to an entitlements plist for macOS ad-hoc codesigning - required: false - default: "" -runs: - using: composite - steps: - - name: Download openshell-sandbox - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: openshell-sandbox-${{ inputs.arch }}-unknown-linux-musl - path: sandbox - - - name: Download openshell-supervisor - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: ${{ inputs.supervisor-artifact }} - path: supervisor - - - name: Download VM guest init - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: openshell-vm-init-${{ inputs.arch }}-unknown-linux-musl - path: vm-init - - - name: Build VM runtime - shell: nix develop -c bash -euo pipefail {0} - run: | - # HTTP 416 is not retried by Nix; restart the build once on failure. - nix build .#vm-runtime || nix build .#vm-runtime - - - name: Assemble compressed VM runtime - shell: nix develop -c bash -euo pipefail {0} - run: | - compressed_dir="${RUNNER_TEMP}/vm-runtime-compressed" - install -d "$compressed_dir" - cp result/compressed/*.zst "$compressed_dir/" - zstd -19 -T1 sandbox/openshell-sandbox -o "$compressed_dir/openshell-sandbox.zst" - zstd -19 -T1 supervisor/openshell-supervisor -o "$compressed_dir/openshell-supervisor.zst" - zstd -19 -T1 vm-init/openshell-vm-init -o "$compressed_dir/openshell-vm-init.zst" - - - name: Build openshell-driver-vm - uses: ./.github/actions/build-rust-binary - env: - OPENSHELL_VM_RUNTIME_COMPRESSED_DIR: ${{ runner.temp }}/vm-runtime-compressed - with: - package: openshell-driver-vm - binary: openshell-driver-vm - triple: ${{ inputs.triple }} - cargo-version: ${{ inputs.cargo-version }} - supervisor-image-tag: ${{ inputs.supervisor-image-tag }} - entitlements-file: ${{ inputs.entitlements-file }} diff --git a/.github/workflows/build-vm-driver-linux.yml b/.github/workflows/build-vm-driver-linux.yml index e6676d5b2a..bdca89ce02 100644 --- a/.github/workflows/build-vm-driver-linux.yml +++ b/.github/workflows/build-vm-driver-linux.yml @@ -38,6 +38,9 @@ jobs: runner: linux-arm64-cpu8 runs-on: ${{ matrix.runner }} timeout-minutes: 60 + defaults: + run: + shell: nix develop -c bash -euo pipefail {0} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -49,10 +52,45 @@ jobs: prepare-shell: "true" cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} - - uses: ./.github/actions/build-vm-driver + - name: Download openshell-sandbox + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - arch: ${{ matrix.arch }} + name: openshell-sandbox-${{ matrix.arch }}-unknown-linux-musl + path: sandbox + + - name: Download openshell-supervisor + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: openshell-supervisor-${{ matrix.arch }}-unknown-linux-gnu + path: supervisor + + - name: Download VM guest init + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: openshell-vm-init-${{ matrix.arch }}-unknown-linux-musl + path: vm-init + + - name: Build VM runtime + run: | + # HTTP 416 is not retried by Nix; restart the build once on failure. + nix build .#vm-runtime || nix build .#vm-runtime + + - name: Assemble compressed VM runtime + run: | + compressed_dir="${RUNNER_TEMP}/vm-runtime-compressed" + install -d "$compressed_dir" + cp result/compressed/*.zst "$compressed_dir/" + zstd -19 -T1 sandbox/openshell-sandbox -o "$compressed_dir/openshell-sandbox.zst" + zstd -19 -T1 supervisor/openshell-supervisor -o "$compressed_dir/openshell-supervisor.zst" + zstd -19 -T1 vm-init/openshell-vm-init -o "$compressed_dir/openshell-vm-init.zst" + + - name: Build openshell-driver-vm + uses: ./.github/actions/build-rust-binary + env: + OPENSHELL_VM_RUNTIME_COMPRESSED_DIR: ${{ runner.temp }}/vm-runtime-compressed + with: + package: openshell-driver-vm + binary: openshell-driver-vm triple: ${{ matrix.triple }} - supervisor-artifact: openshell-supervisor-${{ matrix.arch }}-unknown-linux-gnu cargo-version: ${{ inputs['cargo-version'] }} supervisor-image-tag: ${{ inputs['supervisor-image-tag'] }} diff --git a/.github/workflows/build-vm-driver-macos.yml b/.github/workflows/build-vm-driver-macos.yml index ad2cfba13c..b210014eb0 100644 --- a/.github/workflows/build-vm-driver-macos.yml +++ b/.github/workflows/build-vm-driver-macos.yml @@ -34,6 +34,9 @@ jobs: triple: aarch64-apple-darwin runs-on: macos-15-xlarge timeout-minutes: 60 + defaults: + run: + shell: nix develop -c bash -euo pipefail {0} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -45,11 +48,46 @@ jobs: prepare-shell: "true" cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} - - uses: ./.github/actions/build-vm-driver + - name: Download openshell-sandbox + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: - arch: ${{ matrix.arch }} + name: openshell-sandbox-${{ matrix.arch }}-unknown-linux-musl + path: sandbox + + - name: Download openshell-supervisor + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: openshell-supervisor-${{ matrix.arch }}-apple-darwin + path: supervisor + + - name: Download VM guest init + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: openshell-vm-init-${{ matrix.arch }}-unknown-linux-musl + path: vm-init + + - name: Build VM runtime + run: | + # HTTP 416 is not retried by Nix; restart the build once on failure. + nix build .#vm-runtime || nix build .#vm-runtime + + - name: Assemble compressed VM runtime + run: | + compressed_dir="${RUNNER_TEMP}/vm-runtime-compressed" + install -d "$compressed_dir" + cp result/compressed/*.zst "$compressed_dir/" + zstd -19 -T1 sandbox/openshell-sandbox -o "$compressed_dir/openshell-sandbox.zst" + zstd -19 -T1 supervisor/openshell-supervisor -o "$compressed_dir/openshell-supervisor.zst" + zstd -19 -T1 vm-init/openshell-vm-init -o "$compressed_dir/openshell-vm-init.zst" + + - name: Build openshell-driver-vm + uses: ./.github/actions/build-rust-binary + env: + OPENSHELL_VM_RUNTIME_COMPRESSED_DIR: ${{ runner.temp }}/vm-runtime-compressed + with: + package: openshell-driver-vm + binary: openshell-driver-vm triple: ${{ matrix.triple }} - supervisor-artifact: openshell-supervisor-${{ matrix.arch }}-apple-darwin cargo-version: ${{ inputs['cargo-version'] }} supervisor-image-tag: ${{ inputs['supervisor-image-tag'] }} entitlements-file: crates/openshell-driver-vm/entitlements.plist diff --git a/CI.md b/CI.md index 66052d4e6b..9c9f9cdd16 100644 --- a/CI.md +++ b/CI.md @@ -691,7 +691,7 @@ The bot's full administrator documentation is internal to NVIDIA. The only comma |---|---| | `.github/workflows/branch-checks.yml` | Required non-E2E checks. Triggers on `push: pull-request/[0-9]+` for PR mirrors and `merge_group` for queued merges. | | `.github/workflows/branch-e2e.yml` | Standard, GPU, Kubernetes HA, and Kubernetes credential-driver E2E. PR mirror pushes use `test:e2e`, `test:e2e-gpu`, and `test:e2e-kubernetes` labels; merge groups do not run E2E. | -| `.github/workflows/build-binaries-{linux,macos}.yml`, `build-vm-driver-{linux,macos}.yml` | Shared per-platform binary matrices used by branch and release workflows. Each platform is its own workflow, so a consumer depends only on the platforms it needs. The VM driver remains separate because its build consumes the runtime binaries; both platforms share the steps in `.github/actions/build-vm-driver`. | +| `.github/workflows/build-binaries-{linux,macos}.yml`, `build-vm-driver-{linux,macos}.yml` | Shared per-platform binary matrices used by branch and release workflows. Each platform is its own workflow, so a consumer depends only on the platforms it needs. The VM driver remains separate because its build consumes the runtime binaries. Its build steps stay inline rather than in a local action because release builds check out the release tag, which may predate the action. | | `.github/workflows/build-images.yml` | Builds and pushes multi-platform images, then uploads the same OCI images as workflow artifacts. | | `.github/workflows/package-release-binaries.yml` | Packages raw build artifacts into release tarballs without rebuilding them. | | `.github/workflows/e2e-docker-test.yml`, `e2e-podman-test.yml`, `e2e-vm-test.yml`, `e2e-kubernetes-test.yml` | Reusable runtime lanes called directly by branch and release workflows. Callers select suites and declare only the artifacts each runtime consumes. |