From 0012a0dc9cb25e9de977ae10e99a83f3ef17b0b5 Mon Sep 17 00:00:00 2001 From: Kris Hicks Date: Mon, 15 Jun 2026 12:28:53 -0700 Subject: [PATCH] ci(e2e): reuse prebuilt gateway binaries Build OpenShell gateway and CLI binaries once in the reusable e2e workflow and share them with matrix jobs. This avoids having each e2e job having to compile the binaries independently. Teach the e2e gateway helpers and entrypoints to consume prebuilt binary paths when provided, while preserving local source-build behavior. Signed-off-by: Kris Hicks --- .github/workflows/e2e-test.yml | 47 ++++++++++++++++++++++++++++++++- e2e/rust/e2e-docker.sh | 4 ++- e2e/rust/e2e-kubernetes.sh | 4 ++- e2e/rust/e2e-podman.sh | 4 ++- e2e/support/gateway-common.sh | 48 +++++++++++++++++++++++++++------- tasks/test.toml | 6 ++--- 6 files changed, 97 insertions(+), 16 deletions(-) diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index a0e306ce5..53f066a66 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -23,8 +23,38 @@ permissions: packages: read jobs: + e2e-binaries: + name: E2E binaries + runs-on: ${{ inputs.runner }} + timeout-minutes: 20 + container: + image: ghcr.io/nvidia/openshell/ci:latest + credentials: + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + env: + MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + ref: ${{ inputs['checkout-ref'] || github.sha }} + + - name: Build gateway and CLI + run: | + cargo build -p openshell-server --bin openshell-gateway --features openshell-core/dev-settings + cargo build -p openshell-cli --bin openshell --features openshell-core/dev-settings + + - name: Upload e2e binaries + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: openshell-e2e-binaries + path: | + target/debug/openshell + target/debug/openshell-gateway + e2e: name: "E2E (${{ matrix.suite }})" + needs: e2e-binaries runs-on: ${{ inputs.runner }} timeout-minutes: 30 strategy: @@ -66,11 +96,22 @@ jobs: with: ref: ${{ inputs['checkout-ref'] || github.sha }} + - name: Download OpenShell e2e binaries + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: openshell-e2e-binaries + path: target/debug + + - name: Mark OpenShell e2e binaries executable + run: chmod +x target/debug/openshell target/debug/openshell-gateway + - name: Install OS test dependencies if: matrix.apt_packages != '' env: APT_PACKAGES: ${{ matrix.apt_packages }} - run: apt-get update && apt-get install -y ${APT_PACKAGES} && rm -rf /var/lib/apt/lists/* + run: | + # shellcheck disable=SC2086 + apt-get update && apt-get install -y ${APT_PACKAGES} && rm -rf /var/lib/apt/lists/* - name: Log in to GHCR with Docker run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin @@ -104,6 +145,8 @@ jobs: - name: Run tests env: OPENSHELL_SUPERVISOR_IMAGE: ${{ format('ghcr.io/nvidia/openshell/supervisor:{0}', inputs.image-tag) }} + OPENSHELL_E2E_PREBUILT_GATEWAY_BIN: ${{ github.workspace }}/target/debug/openshell-gateway + OPENSHELL_E2E_PREBUILT_CLI_BIN: ${{ github.workspace }}/target/debug/openshell E2E_CMD: ${{ matrix.cmd }} run: | if [ "${{ matrix.rootless }}" = "true" ]; then @@ -122,6 +165,8 @@ jobs: OPENSHELL_REGISTRY_HOST="${OPENSHELL_REGISTRY_HOST}" \ OPENSHELL_REGISTRY_USERNAME="${OPENSHELL_REGISTRY_USERNAME}" \ OPENSHELL_REGISTRY_PASSWORD="${OPENSHELL_REGISTRY_PASSWORD}" \ + OPENSHELL_E2E_PREBUILT_GATEWAY_BIN="${OPENSHELL_E2E_PREBUILT_GATEWAY_BIN}" \ + OPENSHELL_E2E_PREBUILT_CLI_BIN="${OPENSHELL_E2E_PREBUILT_CLI_BIN}" \ IMAGE_TAG="${IMAGE_TAG}" \ MISE_GITHUB_TOKEN="${MISE_GITHUB_TOKEN}" \ bash -c "${E2E_CMD}" diff --git a/e2e/rust/e2e-docker.sh b/e2e/rust/e2e-docker.sh index a020f87c8..30b0c7d91 100755 --- a/e2e/rust/e2e-docker.sh +++ b/e2e/rust/e2e-docker.sh @@ -12,7 +12,9 @@ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" E2E_TEST="${OPENSHELL_E2E_DOCKER_TEST:-smoke}" E2E_FEATURES="${OPENSHELL_E2E_DOCKER_FEATURES:-e2e,e2e-docker}" -cargo build -p openshell-cli --features openshell-core/dev-settings +if [ -z "${OPENSHELL_E2E_PREBUILT_GATEWAY_BIN:-}" ] || [ -z "${OPENSHELL_E2E_PREBUILT_CLI_BIN:-}" ]; then + cargo build -p openshell-cli --features openshell-core/dev-settings +fi exec "${ROOT}/e2e/with-docker-gateway.sh" \ cargo test --manifest-path "${ROOT}/e2e/rust/Cargo.toml" \ diff --git a/e2e/rust/e2e-kubernetes.sh b/e2e/rust/e2e-kubernetes.sh index 0644a0618..78e2a8c11 100755 --- a/e2e/rust/e2e-kubernetes.sh +++ b/e2e/rust/e2e-kubernetes.sh @@ -21,7 +21,9 @@ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" E2E_FEATURES="${OPENSHELL_E2E_KUBERNETES_FEATURES:-e2e,e2e-host-gateway,e2e-kubernetes}" -cargo build -p openshell-cli --features openshell-core/dev-settings +if [ -z "${OPENSHELL_E2E_PREBUILT_GATEWAY_BIN:-}" ] || [ -z "${OPENSHELL_E2E_PREBUILT_CLI_BIN:-}" ]; then + cargo build -p openshell-cli --features openshell-core/dev-settings +fi test_filter=() if [ -n "${OPENSHELL_E2E_KUBE_TEST:-}" ]; then diff --git a/e2e/rust/e2e-podman.sh b/e2e/rust/e2e-podman.sh index 5f325d0d2..10a81d9b1 100755 --- a/e2e/rust/e2e-podman.sh +++ b/e2e/rust/e2e-podman.sh @@ -12,7 +12,9 @@ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" E2E_TEST="${OPENSHELL_E2E_PODMAN_TEST:-}" E2E_FEATURES="${OPENSHELL_E2E_PODMAN_FEATURES:-e2e-podman}" -cargo build -p openshell-cli --features openshell-core/dev-settings +if [ -z "${OPENSHELL_E2E_PREBUILT_GATEWAY_BIN:-}" ] || [ -z "${OPENSHELL_E2E_PREBUILT_CLI_BIN:-}" ]; then + cargo build -p openshell-cli --features openshell-core/dev-settings +fi TEST_ARGS=( cargo test --manifest-path "${ROOT}/e2e/rust/Cargo.toml" diff --git a/e2e/support/gateway-common.sh b/e2e/support/gateway-common.sh index 8da3d0706..aaef6c2d2 100644 --- a/e2e/support/gateway-common.sh +++ b/e2e/support/gateway-common.sh @@ -172,17 +172,47 @@ e2e_build_gateway_binaries() { local target_var=$2 local gateway_var=$3 local cli_var=$4 - local target_dir + local resolved_target_dir + local prebuilt_gateway="${OPENSHELL_E2E_PREBUILT_GATEWAY_BIN:-}" + local prebuilt_cli="${OPENSHELL_E2E_PREBUILT_CLI_BIN:-}" local jobs=() + # CI workflows can build these once and share them across e2e jobs. When + # unset, keep the local developer path unchanged and build from source here. + if [ -n "${prebuilt_gateway}" ] || [ -n "${prebuilt_cli}" ]; then + local prebuilt_cli_dir + + if [ -z "${prebuilt_gateway}" ] || [ -z "${prebuilt_cli}" ]; then + echo "ERROR: set both OPENSHELL_E2E_PREBUILT_GATEWAY_BIN and OPENSHELL_E2E_PREBUILT_CLI_BIN, or neither." >&2 + exit 2 + fi + if [ ! -x "${prebuilt_gateway}" ]; then + echo "ERROR: OPENSHELL_E2E_PREBUILT_GATEWAY_BIN is not executable: ${prebuilt_gateway}" >&2 + exit 2 + fi + if [ ! -x "${prebuilt_cli}" ]; then + echo "ERROR: OPENSHELL_E2E_PREBUILT_CLI_BIN is not executable: ${prebuilt_cli}" >&2 + exit 2 + fi + + prebuilt_cli_dir="$(cd "$(dirname "${prebuilt_cli}")" && pwd)" + resolved_target_dir="${OPENSHELL_E2E_PREBUILT_TARGET_DIR:-$(cd "${prebuilt_cli_dir}/.." && pwd)}" + printf -v "${target_var}" '%s' "${resolved_target_dir}" + printf -v "${gateway_var}" '%s' "${prebuilt_gateway}" + printf -v "${cli_var}" '%s' "${prebuilt_cli}" + echo "Using prebuilt e2e gateway binary: ${prebuilt_gateway}" + echo "Using prebuilt e2e CLI binary: ${prebuilt_cli}" + return 0 + fi + if [ -n "${CARGO_BUILD_JOBS:-}" ]; then jobs=(-j "${CARGO_BUILD_JOBS}") fi - target_dir="$(e2e_cargo_target_dir "${root}")" - printf -v "${target_var}" '%s' "${target_dir}" - printf -v "${gateway_var}" '%s' "${target_dir}/debug/openshell-gateway" - printf -v "${cli_var}" '%s' "${target_dir}/debug/openshell" + resolved_target_dir="$(e2e_cargo_target_dir "${root}")" + printf -v "${target_var}" '%s' "${resolved_target_dir}" + printf -v "${gateway_var}" '%s' "${resolved_target_dir}/debug/openshell-gateway" + printf -v "${cli_var}" '%s' "${resolved_target_dir}/debug/openshell" echo "Building openshell-gateway..." cargo build "${jobs[@]}" \ @@ -194,12 +224,12 @@ e2e_build_gateway_binaries() { -p openshell-cli --bin openshell \ --features openshell-core/dev-settings - if [ ! -x "${target_dir}/debug/openshell-gateway" ]; then - echo "ERROR: expected openshell-gateway binary at ${target_dir}/debug/openshell-gateway" >&2 + if [ ! -x "${resolved_target_dir}/debug/openshell-gateway" ]; then + echo "ERROR: expected openshell-gateway binary at ${resolved_target_dir}/debug/openshell-gateway" >&2 exit 1 fi - if [ ! -x "${target_dir}/debug/openshell" ]; then - echo "ERROR: expected openshell CLI binary at ${target_dir}/debug/openshell" >&2 + if [ ! -x "${resolved_target_dir}/debug/openshell" ]; then + echo "ERROR: expected openshell CLI binary at ${resolved_target_dir}/debug/openshell" >&2 exit 1 fi } diff --git a/tasks/test.toml b/tasks/test.toml index cf031bd6f..c9acd2253 100644 --- a/tasks/test.toml +++ b/tasks/test.toml @@ -60,14 +60,14 @@ hide = true ["e2e:rust"] description = "Run Rust CLI e2e tests against a Docker-backed gateway" run = [ - "cargo build -p openshell-cli --features openshell-core/dev-settings", + "if [ -z \"${OPENSHELL_E2E_PREBUILT_GATEWAY_BIN:-}\" ] || [ -z \"${OPENSHELL_E2E_PREBUILT_CLI_BIN:-}\" ]; then cargo build -p openshell-cli --features openshell-core/dev-settings; fi", "e2e/with-docker-gateway.sh cargo test --manifest-path e2e/rust/Cargo.toml --features e2e-docker", ] ["e2e:websocket-conformance"] description = "Run focused WebSocket conformance e2e tests against a Docker-backed gateway" run = [ - "cargo build -p openshell-cli --features openshell-core/dev-settings", + "if [ -z \"${OPENSHELL_E2E_PREBUILT_GATEWAY_BIN:-}\" ] || [ -z \"${OPENSHELL_E2E_PREBUILT_CLI_BIN:-}\" ]; then cargo build -p openshell-cli --features openshell-core/dev-settings; fi", "e2e/with-docker-gateway.sh cargo test --manifest-path e2e/rust/Cargo.toml --features e2e-docker --test websocket_conformance", ] @@ -116,7 +116,7 @@ run = "e2e/rust/e2e-docker.sh" ["e2e:mechanistic-smoke"] description = "Run mechanistic L4 smoke against a Docker-backed gateway" run = [ - "cargo build -p openshell-cli --features openshell-core/dev-settings", + "if [ -z \"${OPENSHELL_E2E_PREBUILT_GATEWAY_BIN:-}\" ] || [ -z \"${OPENSHELL_E2E_PREBUILT_CLI_BIN:-}\" ]; then cargo build -p openshell-cli --features openshell-core/dev-settings; fi", "e2e/with-docker-gateway.sh bash -lc 'target/debug/openshell settings set --global --key agent_policy_proposals_enabled --value true --yes && OPENSHELL_BIN=$PWD/target/debug/openshell bash e2e/policy-advisor/mechanistic-smoke.sh'", ]