Files
OpenShell/.github/workflows/branch-e2e.yml
Simon Scatton bcf96e4900 chore(nix): unify Linux cross-compilation toolchains (#3242)
* chore(nix): unify native and cross-compilation toolchains

Replace the separate GNU and musl development shells with one shell that
provides explicit toolchains for x86_64 and aarch64 Linux, plus native
Darwin on macOS. Cargo selects the compiler, assembler, archiver, and
linker through target-specific environment variables.

Build GNU targets against a glibc 2.28 sysroot with static GCC runtimes
and use the musl toolchains for static Linux executables. Build Z3 and
AWS-LC with each target's stdenv and expose AWS-LC libraries and Rust
bindings through its target-specific system directory.

Keep Darwin system libraries on the unprocessed Apple SDK and prevent
the Rust toolchain from propagating replacement libraries into the shell.
Include the compiler and libc fixes needed for Darwin-to-Linux builds.

Share dependency and environment wiring through mkToolchain, keep compiler
wrappers in the Linux and Darwin modules, and group the pinned GNU build
environment under glibc-2.28. Document the toolchain boundaries in the build
architecture overview.

Validation: actionlint and nix fmt pass. The toolchain refactor preserves
the shell derivations for x86_64 Linux, aarch64 Linux, and aarch64 Darwin.

Signed-off-by: Simon Scatton <sscatton@nvidia.com>

* ci(nix): use the default shell for binary builds

Remove the dev-shell input and its matrix and workflow plumbing.
Use the host default shell for builds and cache hashing.

Signed-off-by: Simon Scatton <sscatton@nvidia.com>

* ci(nix): build release binaries with explicit Cargo targets

Use target-specific artifact paths and rely on the Nix toolchains for
linkage. Remove post-link rewriting, platform linkage checks, and the
unused interpreter input. Update the build architecture documentation.

Signed-off-by: Simon Scatton <sscatton@nvidia.com>

* refactor(nix): reuse glibc and GCC build recipes

Use a pinned historical Nixpkgs recipe for glibc 2.28 and rebuild GCC 15
against it instead of maintaining separate runtime builds. Keep only
compatibility adjustments needed by the current build tools.

Assemble the sysroot from glibc outputs and static native libraries. Use
standard ELF interpreters and resolve Rust's explicit gcc_s dependency
through the static GCC archives.

Allow 90 minutes for Rust branch checks to accommodate cold toolchain
builds. Validate the Linux release matrix locally; Darwin remains for CI.

Signed-off-by: Simon Scatton <sscatton@nvidia.com>

* fix(nix): disable obsolete RPC tools in glibc

Avoid building rpcgen against the Darwin SDK, which does not expose stat64.

Signed-off-by: Simon Scatton <sscatton@nvidia.com>

---------

Signed-off-by: Simon Scatton <sscatton@nvidia.com>
2026-09-10 14:27:12 +00:00

504 lines
18 KiB
YAML

name: Branch E2E Checks
on:
merge_group:
types: [checks_requested]
push:
branches:
- "pull-request/[0-9]+"
workflow_dispatch: {}
permissions: {}
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
pr_metadata:
name: Resolve PR metadata
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
should_run: ${{ steps.gate.outputs.should_run }}
run_core_e2e: ${{ steps.labels.outputs.run_core_e2e }}
run_gpu_e2e: ${{ steps.labels.outputs.run_gpu_e2e }}
run_kubernetes_ha_e2e: ${{ steps.labels.outputs.run_kubernetes_ha_e2e }}
run_kubernetes_credential_drivers_e2e: ${{ steps.labels.outputs.run_kubernetes_credential_drivers_e2e }}
run_any_e2e: ${{ steps.labels.outputs.run_any_e2e }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- id: gate
uses: ./.github/actions/pr-gate
- id: labels
if: steps.gate.outputs.should_run == 'true'
env:
EVENT_NAME: ${{ github.event_name }}
LABELS_JSON: ${{ steps.gate.outputs.labels_json }}
shell: bash
run: |
set -euo pipefail
case "$EVENT_NAME" in
push)
run_core_e2e="$(jq -r 'index("test:e2e") != null' <<< "$LABELS_JSON")"
run_gpu_e2e="$(jq -r 'index("test:e2e-gpu") != null' <<< "$LABELS_JSON")"
run_kubernetes_ha_e2e=false
run_kubernetes_credential_drivers_e2e=false
;;
merge_group)
# Merge groups have no PR labels. When GPU E2E is required as documented
# in CI.md, skipping it leaves the gate pending until the queue times out
# and ejects the PR. HA stays off until stable.
run_core_e2e=true
run_gpu_e2e=true
run_kubernetes_ha_e2e=false
run_kubernetes_credential_drivers_e2e=false
;;
*)
run_core_e2e=true
run_gpu_e2e=true
run_kubernetes_ha_e2e=false
run_kubernetes_credential_drivers_e2e=false
;;
esac
if [ "$run_core_e2e" = "true" ] || [ "$run_gpu_e2e" = "true" ] || [ "$run_kubernetes_ha_e2e" = "true" ] || [ "$run_kubernetes_credential_drivers_e2e" = "true" ]; then
run_any_e2e=true
else
run_any_e2e=false
fi
{
echo "run_core_e2e=$run_core_e2e"
echo "run_gpu_e2e=$run_gpu_e2e"
echo "run_kubernetes_ha_e2e=$run_kubernetes_ha_e2e"
echo "run_kubernetes_credential_drivers_e2e=$run_kubernetes_credential_drivers_e2e"
echo "run_any_e2e=$run_any_e2e"
} >> "$GITHUB_OUTPUT"
version:
needs: [pr_metadata]
if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_any_e2e == 'true'
permissions:
contents: read
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
cargo: ${{ steps.version.outputs.cargo }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- name: Compute version
id: version
run: |
cargo="$(python3 tasks/scripts/release.py get-version --cargo)"
echo "cargo=$cargo" >> "$GITHUB_OUTPUT"
build-cli:
needs: version
permissions:
contents: read
uses: ./.github/workflows/build-cli-binaries.yml
with:
cargo-version: ${{ needs.version.outputs.cargo }}
secrets: inherit
build-conformance:
needs: [pr_metadata, version]
if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_any_e2e == 'true'
permissions:
contents: read
strategy:
matrix:
include:
- triple: x86_64-unknown-linux-musl
runner: linux-amd64-cpu8
- triple: aarch64-unknown-linux-musl
runner: linux-arm64-cpu8
uses: ./.github/workflows/build-binaries.yml
with:
package: openshell-conformance-cli
binary: openshell-conformance
artifact-name: openshell-conformance-${{ matrix.triple }}
triple: ${{ matrix.triple }}
runner: ${{ matrix.runner }}
cargo-version: ${{ needs.version.outputs.cargo }}
secrets: inherit
build-sandbox:
needs: version
permissions:
contents: read
uses: ./.github/workflows/build-sandbox-binaries.yml
with:
cargo-version: ${{ needs.version.outputs.cargo }}
secrets: inherit
build-gateway:
needs: version
permissions:
contents: read
uses: ./.github/workflows/build-gateway-binaries.yml
with:
cargo-version: ${{ needs.version.outputs.cargo }}
secrets: inherit
build-gateway-plain:
needs: [pr_metadata, version]
if: needs.pr_metadata.outputs.run_core_e2e == 'true'
permissions:
contents: read
strategy:
matrix:
include:
- triple: x86_64-unknown-linux-gnu
runner: linux-amd64-cpu8
- triple: aarch64-unknown-linux-gnu
runner: linux-arm64-cpu8
uses: ./.github/workflows/build-binaries.yml
with:
package: openshell-gateway
binary: openshell-gateway
artifact-name: openshell-gateway-plain-${{ matrix.triple }}
triple: ${{ matrix.triple }}
runner: ${{ matrix.runner }}
cargo-version: ${{ needs.version.outputs.cargo }}
extra-cargo-flags: --no-default-features
secrets: inherit
build-driver-docker:
needs: [pr_metadata, version]
if: needs.pr_metadata.outputs.run_core_e2e == 'true'
permissions:
contents: read
uses: ./.github/workflows/build-binaries.yml
with:
package: openshell-driver-docker
binary: openshell-driver-docker
triple: aarch64-unknown-linux-gnu
runner: linux-arm64-cpu8
cargo-version: ${{ needs.version.outputs.cargo }}
secrets: inherit
build-driver-podman:
needs: [pr_metadata, version]
if: needs.pr_metadata.outputs.run_core_e2e == 'true'
permissions:
contents: read
uses: ./.github/workflows/build-binaries.yml
with:
package: openshell-driver-podman
binary: openshell-driver-podman
triple: x86_64-unknown-linux-gnu
runner: linux-amd64-cpu8
cargo-version: ${{ needs.version.outputs.cargo }}
secrets: inherit
build-driver-kubernetes:
needs: [pr_metadata, version]
if: needs.pr_metadata.outputs.run_core_e2e == 'true'
permissions:
contents: read
uses: ./.github/workflows/build-binaries.yml
with:
package: openshell-driver-kubernetes
binary: openshell-driver-kubernetes
triple: x86_64-unknown-linux-gnu
runner: linux-amd64-cpu8
cargo-version: ${{ needs.version.outputs.cargo }}
secrets: inherit
build-vm-driver:
needs: [pr_metadata, version, build-sandbox]
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 }}
secrets: inherit
build-gateway-image:
needs: [pr_metadata, build-gateway]
if: >-
needs.pr_metadata.outputs.should_run == 'true' &&
(needs.pr_metadata.outputs.run_core_e2e == 'true' ||
needs.pr_metadata.outputs.run_kubernetes_ha_e2e == 'true' ||
needs.pr_metadata.outputs.run_kubernetes_credential_drivers_e2e == 'true')
permissions:
contents: read
packages: write
uses: ./.github/workflows/docker-build.yml
with:
component: gateway
binary: openshell-gateway
target-suffix: unknown-linux-gnu
secrets: inherit
build-supervisor-image:
needs: [pr_metadata, build-sandbox]
if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_any_e2e == 'true'
permissions:
contents: read
packages: write
uses: ./.github/workflows/docker-build.yml
with:
component: supervisor
binary: openshell-sandbox
target-suffix: unknown-linux-musl
secrets: inherit
docker-e2e:
needs: [pr_metadata, build-cli, build-conformance, build-gateway, build-supervisor-image]
if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true'
permissions:
actions: read
contents: read
packages: read
uses: ./.github/workflows/e2e-docker-test.yml
with:
image-tag: ${{ github.sha }}
runner: linux-arm64-cpu8
conformance-artifact-prefix: openshell-conformance
podman-e2e:
needs: [pr_metadata, build-cli, build-conformance, build-gateway, build-supervisor-image]
if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true'
permissions:
actions: read
contents: read
packages: read
uses: ./.github/workflows/e2e-podman-test.yml
with:
image-tag: ${{ github.sha }}
conformance-artifact-prefix: openshell-conformance
vm-e2e:
needs: [pr_metadata, build-cli, build-conformance, build-gateway, build-vm-driver]
if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true'
permissions:
actions: read
contents: read
packages: read
uses: ./.github/workflows/e2e-vm-test.yml
with:
conformance-artifact-prefix: openshell-conformance
docker-external-driver-e2e:
needs: [pr_metadata, build-cli, build-conformance, build-gateway-plain, build-driver-docker, build-supervisor-image]
if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true'
permissions:
actions: read
contents: read
packages: read
uses: ./.github/workflows/e2e-docker-test.yml
with:
image-tag: ${{ github.sha }}
runner: linux-arm64-cpu8
gateway-artifact: openshell-gateway-plain-aarch64-unknown-linux-gnu
external-driver-binary: openshell-driver-docker
conformance-artifact-prefix: openshell-conformance
suite-matrix: >-
[{"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-cli, build-conformance, build-gateway-plain, build-driver-podman, build-supervisor-image]
if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true'
permissions:
actions: read
contents: read
packages: read
uses: ./.github/workflows/e2e-podman-test.yml
with:
image-tag: ${{ github.sha }}
gateway-artifact: openshell-gateway-plain-x86_64-unknown-linux-gnu
external-driver-binary: openshell-driver-podman
conformance-artifact-prefix: openshell-conformance
suite-matrix: >-
[{"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-cli, build-conformance, build-gateway-plain, build-vm-driver]
if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true'
permissions:
actions: read
contents: read
packages: read
uses: ./.github/workflows/e2e-vm-test.yml
with:
gateway-artifact: openshell-gateway-plain-x86_64-unknown-linux-gnu
suite-name: external-driver
e2e-task: e2e:vm:external-driver
conformance-artifact-prefix: openshell-conformance
gpu-e2e:
needs: [pr_metadata, build-cli, build-conformance, build-gateway, build-supervisor-image]
if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_gpu_e2e == 'true'
permissions:
actions: read
contents: read
packages: read
uses: ./.github/workflows/e2e-gpu-test.yaml
with:
image-tag: ${{ github.sha }}
conformance-artifact-prefix: openshell-conformance
kubernetes-e2e:
needs: [pr_metadata, build-cli, build-conformance, build-gateway-image, build-supervisor-image]
if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true'
strategy:
fail-fast: false
matrix:
include:
- agent_sandbox_api: v1beta1
agent_sandbox_version: v0.5.0
topology: combined
extra_helm_values: ""
- agent_sandbox_api: v1alpha1
agent_sandbox_version: v0.4.6
topology: combined
extra_helm_values: ""
- agent_sandbox_api: v1beta1
agent_sandbox_version: v0.5.0
topology: sidecar
extra_helm_values: deploy/helm/openshell/ci/values-sidecar.yaml
permissions:
actions: read
contents: read
packages: read
uses: ./.github/workflows/e2e-kubernetes-test.yml
with:
image-tag: ${{ github.sha }}
job-name: Kubernetes E2E (Rust smoke, ${{ matrix.topology }}, Agent Sandbox ${{ matrix.agent_sandbox_api }})
agent-sandbox-version: ${{ matrix.agent_sandbox_version }}
extra-helm-values: ${{ matrix.extra_helm_values }}
conformance-artifact-prefix: openshell-conformance
kubernetes-workspace-managed-e2e:
needs: [pr_metadata, build-cli, build-conformance, build-gateway-image, build-supervisor-image]
if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true'
permissions:
actions: read
contents: read
packages: read
uses: ./.github/workflows/e2e-kubernetes-test.yml
with:
image-tag: ${{ github.sha }}
job-name: Kubernetes E2E (workspace managed mode)
e2e-task: e2e:kubernetes:workspace-managed
conformance-artifact-prefix: openshell-conformance
kubernetes-external-driver-e2e:
needs: [pr_metadata, build-cli, build-conformance, build-gateway-plain, build-driver-kubernetes, build-supervisor-image]
if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true'
permissions:
actions: read
contents: read
packages: read
uses: ./.github/workflows/e2e-kubernetes-test.yml
with:
image-tag: ${{ github.sha }}
job-name: Kubernetes E2E (external compute driver)
e2e-task: e2e:kubernetes:external-driver
gateway-artifact: openshell-gateway-plain-x86_64-unknown-linux-gnu
external-driver-binary: openshell-driver-kubernetes
cluster-images: supervisor
conformance-artifact-prefix: openshell-conformance
kubernetes-workspace-operator-e2e:
needs: [pr_metadata, build-cli, build-conformance, build-gateway-image, build-supervisor-image]
if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true'
permissions:
actions: read
contents: read
packages: read
uses: ./.github/workflows/e2e-kubernetes-test.yml
with:
image-tag: ${{ github.sha }}
job-name: Kubernetes E2E (workspace operator mode)
e2e-task: e2e:kubernetes:workspace-operator
conformance-artifact-prefix: openshell-conformance
kubernetes-ha-e2e:
needs: [pr_metadata, build-cli, build-conformance, build-gateway-image, build-supervisor-image]
if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_kubernetes_ha_e2e == 'true'
permissions:
actions: read
contents: read
packages: read
uses: ./.github/workflows/e2e-kubernetes-test.yml
with:
image-tag: ${{ github.sha }}
job-name: Kubernetes HA E2E (Rust smoke)
extra-helm-values: deploy/helm/openshell/ci/values-high-availability.yaml
external-postgres-secret: openshell-ha-pg
conformance-artifact-prefix: openshell-conformance
kubernetes-credential-drivers-e2e:
needs: [pr_metadata, build-cli, build-conformance, build-gateway-image, build-supervisor-image]
if: needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_kubernetes_credential_drivers_e2e == 'true'
permissions:
actions: read
contents: read
packages: read
uses: ./.github/workflows/e2e-kubernetes-test.yml
with:
image-tag: ${{ github.sha }}
job-name: Kubernetes Credential Drivers E2E
e2e-task: e2e:kubernetes:credential-drivers
conformance-artifact-prefix: openshell-conformance
core-e2e-result:
name: Core E2E result
needs: [pr_metadata, docker-e2e, podman-e2e, vm-e2e, docker-external-driver-e2e, podman-external-driver-e2e, vm-external-driver-e2e, kubernetes-e2e, kubernetes-external-driver-e2e, kubernetes-workspace-managed-e2e, kubernetes-workspace-operator-e2e]
if: always() && needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_core_e2e == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: ./.github/actions/check-job-results
with:
results: ${{ toJSON(needs) }}
gpu-e2e-result:
name: GPU E2E result
needs: [pr_metadata, gpu-e2e]
if: always() && needs.pr_metadata.outputs.should_run == 'true' && needs.pr_metadata.outputs.run_gpu_e2e == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: ./.github/actions/check-job-results
with:
results: ${{ toJSON(needs) }}
kubernetes-ha-e2e-result:
name: Kubernetes HA E2E result
needs: [pr_metadata, 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:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: ./.github/actions/check-job-results
with:
results: ${{ toJSON(needs) }}
kubernetes-credential-drivers-e2e-result:
name: Kubernetes Credential Drivers E2E result
needs: [pr_metadata, 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:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: ./.github/actions/check-job-results
with:
results: ${{ toJSON(needs) }}