From 98865765c6045d38682c7d7eae0effabf5bb0da2 Mon Sep 17 00:00:00 2001 From: Dimitar Mirchev <28221091+dimityrmirchev@users.noreply.github.com> Date: Mon, 6 Jul 2026 18:04:18 +0300 Subject: [PATCH] ci: verify each compute driver can be compiled out Adds verify-drivers-compiled-out.sh, a mise task that exercises the per-driver Cargo features, and a matching step in the branch-checks workflow. The script mirrors verify-telemetry-compiled-out.sh: a table of stable driver-exclusive marker strings pulled from each driver crate, with present/absent/only modes. The 'only' mode asserts presence for a selected driver list AND absence for every other driver in one sweep, so a single script invocation covers both directions per build. The mise task exercises: default (all four drivers present), each single-driver build, one mixed feature set (docker+podman), and a zero-driver extension-only build that must link cleanly and must contain none of the four driver markers. After the zero-driver build the task also runs `cargo test -p openshell-server --lib --no-default-features` so the #[cfg]-gated extension-only unit tests actually execute in CI rather than being silently skipped by the default-features test job. The telemetry-off task uses a mixed --features driver-...,driver-... gateway build so the telemetry-marker absence check still exercises a representative in-tree-driver build path. Signed-off-by: Dimitar Mirchev <28221091+dimityrmirchev@users.noreply.github.com> --- .github/workflows/branch-checks.yml | 3 + crates/openshell-driver-docker/src/lib.rs | 9 + crates/openshell-driver-kubernetes/src/lib.rs | 9 + crates/openshell-driver-podman/src/lib.rs | 9 + crates/openshell-server/src/compute/vm.rs | 11 ++ tasks/rust.toml | 36 +++- tasks/scripts/verify-drivers-compiled-out.sh | 155 ++++++++++++++++++ 7 files changed, 230 insertions(+), 2 deletions(-) create mode 100755 tasks/scripts/verify-drivers-compiled-out.sh diff --git a/.github/workflows/branch-checks.yml b/.github/workflows/branch-checks.yml index 5a80331ba..5f505d89b 100644 --- a/.github/workflows/branch-checks.yml +++ b/.github/workflows/branch-checks.yml @@ -127,6 +127,9 @@ jobs: - name: Verify telemetry can be compiled out run: mise run rust:verify:telemetry-off + - name: Verify each compute driver can be compiled out + run: mise run rust:verify:drivers-off + - name: sccache stats if: always() run: | diff --git a/crates/openshell-driver-docker/src/lib.rs b/crates/openshell-driver-docker/src/lib.rs index 2f89c2229..599b834a8 100644 --- a/crates/openshell-driver-docker/src/lib.rs +++ b/crates/openshell-driver-docker/src/lib.rs @@ -5,6 +5,15 @@ #![allow(clippy::result_large_err)] +/// Compile-out guard: greppable proof this crate is linked into a binary. +/// +/// `tasks/scripts/verify-drivers-compiled-out.sh` asserts this string is +/// present when `--features driver-docker` is on and absent when it is +/// off. `#[used]` prevents dead-code elimination; the linker cannot drop it. +/// Do not remove without updating the verify script. +#[used] +static COMPILE_MARKER: &str = "OPENSHELL_DRIVER_MARKER:docker"; + use bollard::Docker; use bollard::errors::Error as BollardError; use bollard::models::{ diff --git a/crates/openshell-driver-kubernetes/src/lib.rs b/crates/openshell-driver-kubernetes/src/lib.rs index 7c56c8de5..17bb60798 100644 --- a/crates/openshell-driver-kubernetes/src/lib.rs +++ b/crates/openshell-driver-kubernetes/src/lib.rs @@ -12,3 +12,12 @@ pub use config::{ }; pub use driver::{KubernetesComputeDriver, KubernetesDriverError}; pub use grpc::ComputeDriverService; + +/// Compile-out guard: greppable proof this crate is linked into a binary. +/// +/// `tasks/scripts/verify-drivers-compiled-out.sh` asserts this string is +/// present when `--features driver-kubernetes` is on and absent when it is +/// off. `#[used]` prevents dead-code elimination; the linker cannot drop it. +/// Do not remove without updating the verify script. +#[used] +static COMPILE_MARKER: &str = "OPENSHELL_DRIVER_MARKER:kubernetes"; diff --git a/crates/openshell-driver-podman/src/lib.rs b/crates/openshell-driver-podman/src/lib.rs index 5847a10ea..f25fee53a 100644 --- a/crates/openshell-driver-podman/src/lib.rs +++ b/crates/openshell-driver-podman/src/lib.rs @@ -13,3 +13,12 @@ pub(crate) mod watcher; pub use config::PodmanComputeConfig; pub use driver::PodmanComputeDriver; pub use grpc::ComputeDriverService; + +/// Compile-out guard: greppable proof this crate is linked into a binary. +/// +/// `tasks/scripts/verify-drivers-compiled-out.sh` asserts this string is +/// present when `--features driver-podman` is on and absent when it is +/// off. `#[used]` prevents dead-code elimination; the linker cannot drop it. +/// Do not remove without updating the verify script. +#[used] +static COMPILE_MARKER: &str = "OPENSHELL_DRIVER_MARKER:podman"; diff --git a/crates/openshell-server/src/compute/vm.rs b/crates/openshell-server/src/compute/vm.rs index be88047f3..0ca21bb10 100644 --- a/crates/openshell-server/src/compute/vm.rs +++ b/crates/openshell-server/src/compute/vm.rs @@ -56,6 +56,17 @@ use tonic::transport::Endpoint; #[cfg(unix)] use tower::service_fn; +/// Compile-out guard: greppable proof `driver-vm` is compiled in. +/// +/// `tasks/scripts/verify-drivers-compiled-out.sh` asserts this string is +/// present when `--features driver-vm` is on and absent when it is off. +/// The VM driver runs out-of-process and has no in-server crate dependency, +/// so this marker lives with the launcher plumbing gated by the feature. +/// `#[used]` prevents dead-code elimination. Do not remove without +/// updating the verify script. +#[used] +static COMPILE_MARKER: &str = "OPENSHELL_DRIVER_MARKER:vm"; + const DRIVER_BIN_NAME: &str = "openshell-driver-vm"; const COMPUTE_DRIVER_SOCKET_RUN_DIR: &str = "run"; const COMPUTE_DRIVER_SOCKET_NAME: &str = "compute-driver.sock"; diff --git a/tasks/rust.toml b/tasks/rust.toml index f035193fd..d5b51ef72 100644 --- a/tasks/rust.toml +++ b/tasks/rust.toml @@ -39,9 +39,41 @@ run = [ # markers, so the absent checks below can never become silently vacuous. "cargo build -p openshell-server --bin openshell-gateway", "tasks/scripts/verify-telemetry-compiled-out.sh present target/debug/openshell-gateway", - # Guard: telemetry-free builds must contain no telemetry markers. - "cargo build -p openshell-server --bin openshell-gateway --no-default-features", + # Guard: telemetry-free builds must contain no telemetry markers. The + # gateway needs at least one compute driver to link, so build with a + # single-driver feature set that excludes telemetry. + "cargo build -p openshell-server --bin openshell-gateway --no-default-features --features driver-kubernetes,driver-docker,driver-podman,driver-vm", "tasks/scripts/verify-telemetry-compiled-out.sh absent target/debug/openshell-gateway", "cargo build -p openshell-sandbox --bin openshell-sandbox --no-default-features", "tasks/scripts/verify-telemetry-compiled-out.sh absent target/debug/openshell-sandbox", ] + +["rust:verify:drivers-off"] +description = "Verify each compute driver can be compiled out via per-driver cargo features" +run = [ + # Positive control: the default build carries every driver's markers. + "cargo build -p openshell-server --bin openshell-gateway", + "tasks/scripts/verify-drivers-compiled-out.sh present all target/debug/openshell-gateway", + + # Each single-driver build carries only that driver's markers. + "cargo build -p openshell-server --bin openshell-gateway --no-default-features --features driver-kubernetes", + "tasks/scripts/verify-drivers-compiled-out.sh only kubernetes target/debug/openshell-gateway", + "cargo build -p openshell-server --bin openshell-gateway --no-default-features --features driver-docker", + "tasks/scripts/verify-drivers-compiled-out.sh only docker target/debug/openshell-gateway", + "cargo build -p openshell-server --bin openshell-gateway --no-default-features --features driver-podman", + "tasks/scripts/verify-drivers-compiled-out.sh only podman target/debug/openshell-gateway", + "cargo build -p openshell-server --bin openshell-gateway --no-default-features --features driver-vm", + "tasks/scripts/verify-drivers-compiled-out.sh only vm target/debug/openshell-gateway", + + # Mixed feature set: verifies driver features compose additively. + "cargo build -p openshell-server --bin openshell-gateway --no-default-features --features driver-docker,driver-podman", + "tasks/scripts/verify-drivers-compiled-out.sh only docker,podman target/debug/openshell-gateway", + + # Zero-driver build is a valid extension-only gateway shape. Assert both + # that the binary links and that none of the built-in driver markers survived. + "cargo build -p openshell-server --bin openshell-gateway --no-default-features", + "tasks/scripts/verify-drivers-compiled-out.sh absent all target/debug/openshell-gateway", + # The zero-driver profile also gates the extension-only unit test paths. Run the library test + # suite under --no-default-features so those assertions actually execute. + "cargo test -p openshell-server --lib --no-default-features", +] diff --git a/tasks/scripts/verify-drivers-compiled-out.sh b/tasks/scripts/verify-drivers-compiled-out.sh new file mode 100755 index 000000000..36055f27b --- /dev/null +++ b/tasks/scripts/verify-drivers-compiled-out.sh @@ -0,0 +1,155 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +# Verify whether compute-driver code is present in a compiled binary. +# +# Per-driver Cargo features (driver-kubernetes, driver-docker, driver-podman, +# driver-vm) on openshell-server, all default-on, gate the driver crates and +# their in-server plumbing. Building with --no-default-features and enabling +# only a subset must produce a binary that carries only those drivers. This +# guard inspects a built binary for markers that only exist when a given +# driver is compiled in. +# +# Markers are strings baked into each driver's code and must not overlap +# with other drivers or shared code. The `present` positive control fails +# loudly if a marker goes stale, so `absent` checks can never become +# silently vacuous. + +set -euo pipefail + +# Marker table: DRIVER=marker_that_only_appears_when_that_driver_is_compiled_in +# +# Each driver crate declares a `#[used] static COMPILE_MARKER` holding a +# well-known byte string; the VM driver's marker lives in compute::vm behind +# `#[cfg(feature = "driver-vm")]`. `#[used]` prevents dead-code elimination +# so the marker survives every optimization level and strip mode. Keep these +# in sync with the driver crates. +declare -A MARKERS=( + [kubernetes]="OPENSHELL_DRIVER_MARKER:kubernetes" + [docker]="OPENSHELL_DRIVER_MARKER:docker" + [podman]="OPENSHELL_DRIVER_MARKER:podman" + [vm]="OPENSHELL_DRIVER_MARKER:vm" +) + +ALL_DRIVERS=(kubernetes docker podman vm) + +usage() { + cat >&2 <<'EOF' +Usage: + verify-drivers-compiled-out.sh present + Assert the driver's markers ARE present. Use as a positive control. + verify-drivers-compiled-out.sh absent + Assert the driver's markers are NOT present. + verify-drivers-compiled-out.sh only + Assert markers are present for each listed driver AND absent for + each unlisted one. Covers presence + absence in a single pass. + +Drivers: kubernetes docker podman vm (or 'all') +EOF +} + +if [[ $# -lt 3 ]]; then + usage + exit 2 +fi + +mode=$1 +selector=$2 +binary=$3 + +if [[ ! -f $binary ]]; then + echo "error: binary not found: $binary" >&2 + exit 2 +fi +if ! command -v strings >/dev/null 2>&1; then + echo "error: 'strings' (binutils) is required to inspect the binary" >&2 + exit 2 +fi + +dump=$(strings -a "$binary") +failed=0 + +# Assert that $1 marker appears at least once in $dump for driver $2. +assert_present() { + local driver=$1 + local marker=${MARKERS[$driver]} + local count + count=$(grep -c -F "$marker" <<<"$dump" || true) + if [[ $count -eq 0 ]]; then + echo "FAIL: driver '$driver' marker '$marker' missing from $(basename "$binary")" >&2 + failed=1 + else + echo "OK: driver '$driver' compiled in ($count occurrence(s) of '$marker')" + fi +} + +# Assert that $1 marker does NOT appear in $dump for driver $2. +assert_absent() { + local driver=$1 + local marker=${MARKERS[$driver]} + local count + count=$(grep -c -F "$marker" <<<"$dump" || true) + if [[ $count -ne 0 ]]; then + echo "FAIL: driver '$driver' marker '$marker' found in $(basename "$binary") ($count occurrence(s)); driver was not compiled out" >&2 + failed=1 + else + echo "OK: driver '$driver' compiled out (0 occurrences of '$marker')" + fi +} + +# Expand 'all' or a comma-separated list into the SELECTED array in the +# caller's scope. Exits 2 on any unknown driver. Runs in the current shell +# so that exit propagates — do not call this from a subshell or process +# substitution. +resolve_drivers() { + local input=$1 + SELECTED=() + if [[ $input == "all" ]]; then + SELECTED=("${ALL_DRIVERS[@]}") + return + fi + local drivers + IFS=',' read -r -a drivers <<<"$input" + for d in "${drivers[@]}"; do + if [[ -z ${MARKERS[$d]+set} ]]; then + echo "error: unknown driver '$d'. known: ${ALL_DRIVERS[*]}" >&2 + exit 2 + fi + SELECTED+=("$d") + done +} + +resolve_drivers "$selector" + +case "$mode" in + present) + for d in "${SELECTED[@]}"; do + assert_present "$d" + done + ;; + absent) + for d in "${SELECTED[@]}"; do + assert_absent "$d" + done + ;; + only) + declare -A present_set=() + for d in "${SELECTED[@]}"; do + present_set[$d]=1 + done + for d in "${ALL_DRIVERS[@]}"; do + if [[ -n ${present_set[$d]+set} ]]; then + assert_present "$d" + else + assert_absent "$d" + fi + done + ;; + *) + usage + exit 2 + ;; +esac + +exit "$failed"