Files
OpenShell/.github/workflows/supervisor-static-validate.yml
Emilien MacchiandMrunal Patel 3e191558b3 feat(build): add glibc-static supervisor libc variant (#2682)
The supervisor binary runs inside sandbox images whose libc and glibc
version are unknown at build time, so it must be statically linked. Add
SUPERVISOR_LIBC to select between the default musl variant and a new
glibc-static variant that builds the GNU target with +crt-static.

glibc-static has no cross-compile path: zig cc accepts -static for
*-linux-gnu targets and emits a dynamically linked binary anyway. The
staging script therefore refuses a cross-arch request for that variant
rather than silently degrading linkage, and requires a native
per-architecture build.

Add verify-static-binary.sh, run after every supervisor build in both the
staging script and CI so linkage cannot regress unnoticed for either
variant. It inspects via readelf (or greadelf/llvm-readelf) and fails closed
rather than trusting the tool's exit status: every inspection must produce no
diagnostics, the input must be an executable ELF (ET_EXEC, or ET_DYN with
DF_1_PIE) whose PT_LOAD segments all lie within the file, whose dynamic table
agrees with PT_DYNAMIC, and which carries no PT_INTERP and no DT_NEEDED. That
rejects a dynamically linked, truncated, corrupt, non-ELF, or shared-object
input that naive parsing would misread as static. Hosts without any inspector
(e.g. macOS, which ships no binutils) skip with a warning; Linux, including
CI, requires one and fails closed.

No image or release workflow builds the glibc-static variant, so add a
dedicated supervisor-static-validate workflow that builds it on both
architectures and runs the verifier. rust-native-build.yml uses self-hosted
runners, which reject pull_request-triggered jobs, so it validates in the merge
queue and on pushes to main that touch the build inputs, plus a nightly
schedule, so the GNU + crt-static build branch cannot regress unnoticed.

The default is unchanged, so image, release, and CI behavior is identical.
Selecting glibc-static statically links LGPL glibc into a redistributed
binary, which is why it is opt-in.

Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
Co-authored-by: Mrunal Patel <mrunalp@gmail.com>
2026-08-11 17:43:09 +00:00

71 lines
2.5 KiB
YAML

# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
name: Supervisor Static Linkage Validation
# The glibc-static supervisor variant (SUPERVISOR_LIBC=glibc-static) has no
# other CI caller: docker-build.yml builds the default musl variant, so the
# GNU + crt-static build branch and its native-only, per-arch requirements are
# never exercised by image or release CI. Build the variant here on both
# architectures so it cannot regress unnoticed. rust-native-build.yml runs
# verify-static-binary.sh for the sandbox component, which fails the job on any
# dynamic linkage.
#
# Linkage can change from a new/updated dependency or a source change, not just
# from the build scripts, so the push path filters cover the workspace manifests
# and crate sources in addition to the build tooling. A nightly schedule is the
# unfiltered backstop for anything the filters miss.
#
# rust-native-build.yml runs on NVIDIA self-hosted runners, which reject jobs
# triggered by `pull_request`. This workflow therefore follows the repo's
# self-hosted convention (see branch-checks.yml / branch-e2e.yml): validate in
# the merge queue (pre-merge), on push to main (post-merge), nightly, and on
# demand — never on `pull_request`.
on:
merge_group:
types: [checks_requested]
push:
branches: [main]
paths:
- "Cargo.toml"
- "Cargo.lock"
- "crates/**"
- "rust-toolchain.toml"
- "mise.toml"
- "mise.lock"
- ".cargo/config.toml"
- "tasks/scripts/stage-prebuilt-binaries.sh"
- "tasks/scripts/verify-static-binary.sh"
- ".github/workflows/rust-native-build.yml"
- ".github/workflows/supervisor-static-validate.yml"
schedule:
# Nightly (04:17 UTC) unfiltered run so a linkage regression cannot slip
# through the path filters unnoticed. Schedules run only on the default branch.
- cron: "17 4 * * *"
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
permissions:
contents: read
packages: read
jobs:
glibc-static:
name: glibc-static supervisor (${{ matrix.arch }})
strategy:
fail-fast: false
matrix:
arch: [amd64, arm64]
uses: ./.github/workflows/rust-native-build.yml
with:
component: sandbox
arch: ${{ matrix.arch }}
supervisor-libc: glibc-static
artifact-name: supervisor-glibc-static-${{ matrix.arch }}
retention-days: 1
secrets: inherit