Skip to content

Commit 981606d

Browse files
authored
ci: build release binaries with Nix (#2977)
* ci: build release binaries with Nix Refs #1683 Signed-off-by: Simon Scatton <sscatton@nvidia.com> * ci: build VM artifacts with Nix Refs #1683 Signed-off-by: Simon Scatton <sscatton@nvidia.com> * ci: build images from Nix artifacts Refs #1683 Signed-off-by: Simon Scatton <sscatton@nvidia.com> * fix(nix): prevent host header leakage Signed-off-by: Simon Scatton <sscatton@nvidia.com> * ci: parallelize artifact builds Refs #1683 Signed-off-by: Simon Scatton <sscatton@nvidia.com> * ci: build external driver test artifacts Refs #1683 Signed-off-by: Simon Scatton <sscatton@nvidia.com> * fix(nix): disable mold in musl shells Signed-off-by: Simon Scatton <sscatton@nvidia.com> * ci: key Rust cache by Nix shell derivation Signed-off-by: Simon Scatton <sscatton@nvidia.com> * ci: refactor end-to-end workflows Signed-off-by: Simon Scatton <sscatton@nvidia.com> * ci: split platform binary workflows Signed-off-by: Simon Scatton <sscatton@nvidia.com> * ci: remove obsolete native build workflows Signed-off-by: Simon Scatton <sscatton@nvidia.com> * ci: replace disallowed mise action Signed-off-by: Simon Scatton <sscatton@nvidia.com> * ci: fix refactored e2e lanes Signed-off-by: Simon Scatton <sscatton@nvidia.com> * ci: check out local result action Signed-off-by: Simon Scatton <sscatton@nvidia.com> * ci: cache mise installations Signed-off-by: Simon Scatton <sscatton@nvidia.com> * ci: run docker builds on host runners Signed-off-by: Simon Scatton <sscatton@nvidia.com> * ci: disable unstable kubernetes e2e lanes Signed-off-by: Simon Scatton <sscatton@nvidia.com> * fix(ci): scope binary builds to cargo packages Signed-off-by: Simon Scatton <sscatton@nvidia.com> * fix(ci): address zizmor template injection findings Signed-off-by: Simon Scatton <sscatton@nvidia.com> * fix(ci): resolve remaining zizmor annotations Signed-off-by: Simon Scatton <sscatton@nvidia.com> --------- Signed-off-by: Simon Scatton <sscatton@nvidia.com>
1 parent 37072ee commit 981606d

46 files changed

Lines changed: 1909 additions & 2706 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
name: Build Docker Image
5+
description: Build and push one architecture of an OpenShell image
6+
7+
inputs:
8+
component:
9+
description: Docker image and Dockerfile name
10+
required: true
11+
binary:
12+
description: Binary staged in the Docker build context
13+
required: true
14+
triple:
15+
description: Binary artifact target triple
16+
required: true
17+
arch:
18+
description: Docker architecture name
19+
required: true
20+
platform:
21+
description: Docker platform
22+
required: true
23+
image-tag:
24+
description: Docker image tag
25+
required: true
26+
github-token:
27+
description: Token used to push the image
28+
required: true
29+
30+
runs:
31+
using: composite
32+
steps:
33+
- uses: ./.github/actions/setup-buildx
34+
with:
35+
buildkitd-config: /etc/buildkit/buildkitd.toml
36+
37+
- name: Log in to GHCR
38+
shell: bash
39+
run: echo "${INPUTS_GITHUB_TOKEN}" | docker login ghcr.io -u "${GITHUB_ACTOR}" --password-stdin
40+
env:
41+
INPUTS_GITHUB_TOKEN: ${{ inputs.github-token }}
42+
43+
- name: Download ${{ inputs.binary }}
44+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
45+
with:
46+
name: ${{ inputs.binary }}-${{ inputs.triple }}
47+
path: artifact
48+
49+
- name: Stage ${{ inputs.binary }}
50+
shell: bash
51+
run: install -Dm0755 artifact/${INPUTS_BINARY} deploy/docker/.build/prebuilt-binaries/${INPUTS_ARCH}/${INPUTS_BINARY}
52+
env:
53+
INPUTS_BINARY: ${{ inputs.binary }}
54+
INPUTS_ARCH: ${{ inputs.arch }}
55+
56+
- name: Build ${{ inputs.component }} image
57+
shell: bash
58+
env:
59+
IMAGE_TAG: ${{ inputs.image-tag }}
60+
INPUTS_PLATFORM: ${{ inputs.platform }}
61+
INPUTS_COMPONENT: ${{ inputs.component }}
62+
INPUTS_ARCH: ${{ inputs.arch }}
63+
run: |
64+
docker buildx build \
65+
--builder openshell \
66+
--platform ${INPUTS_PLATFORM} \
67+
--file deploy/docker/Dockerfile.${INPUTS_COMPONENT} \
68+
--target ${INPUTS_COMPONENT} \
69+
--tag ghcr.io/nvidia/openshell/${INPUTS_COMPONENT}:${IMAGE_TAG}-${INPUTS_ARCH} \
70+
--cache-from type=gha,scope=${INPUTS_COMPONENT}-${INPUTS_ARCH} \
71+
--cache-to type=gha,mode=max,scope=${INPUTS_COMPONENT}-${INPUTS_ARCH} \
72+
--provenance=mode=min \
73+
--attest type=sbom \
74+
--output type=image,push=true,oci-mediatypes=true,oci-artifact=true \
75+
.
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
name: Build Rust Binary
5+
description: Build, verify, package, and upload an auditable Rust binary
6+
7+
inputs:
8+
package:
9+
description: Cargo package that owns the binary
10+
required: true
11+
binary:
12+
description: Cargo binary name
13+
required: true
14+
triple:
15+
description: Rust target triple
16+
required: true
17+
dev-shell:
18+
description: Nix development shell used to build the binary
19+
required: true
20+
cargo-version:
21+
description: Cargo package version embedded in the binary
22+
required: true
23+
image-tag:
24+
description: Default supervisor image tag embedded in the binary
25+
required: false
26+
default: ""
27+
artifact-name:
28+
description: GitHub artifact name
29+
required: false
30+
default: ""
31+
extra-cargo-flags:
32+
description: Additional flags passed to cargo build
33+
required: false
34+
default: ""
35+
interpreter:
36+
description: ELF interpreter for a dynamically linked Linux binary
37+
required: false
38+
default: ""
39+
40+
runs:
41+
using: composite
42+
steps:
43+
- name: Hash development shell
44+
id: dev-shell
45+
shell: bash
46+
env:
47+
DEV_SHELL: ${{ inputs.dev-shell }}
48+
run: echo "hash=$(nix hash file --type sha256 --base16 "$(nix eval --raw "${DEV_SHELL}.drvPath")")" >> "$GITHUB_OUTPUT"
49+
50+
- name: Cache Rust artifacts
51+
uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
52+
with:
53+
shared-key: binaries-${{ inputs.binary }}-${{ inputs.triple }}-${{ steps.dev-shell.outputs.hash }}
54+
cache-on-failure: "true"
55+
cache-workspace-crates: "true"
56+
cache-bin: "false"
57+
cmd-format: nix develop ${{ inputs.dev-shell }} -c {0}
58+
59+
- name: Set version
60+
shell: nix develop ${{ inputs.dev-shell }} -c bash -euo pipefail {0}
61+
env:
62+
INPUTS_CARGO_VERSION: ${{ inputs.cargo-version }}
63+
run: sed -i "s/^version = \"0\\.0\\.0\"$/version = \"${INPUTS_CARGO_VERSION}\"/" Cargo.toml
64+
65+
- name: Build ${{ inputs.binary }}
66+
shell: nix develop ${{ inputs.dev-shell }} -c bash -euo pipefail {0}
67+
env:
68+
OPENSHELL_IMAGE_TAG: ${{ inputs.image-tag }}
69+
INPUTS_PACKAGE: ${{ inputs.package }}
70+
INPUTS_BINARY: ${{ inputs.binary }}
71+
INPUTS_EXTRA_CARGO_FLAGS: ${{ inputs.extra-cargo-flags }}
72+
run: GIT_DIR=/nonexistent cargo auditable build --release --package "${INPUTS_PACKAGE}" --bin "${INPUTS_BINARY}" ${INPUTS_EXTRA_CARGO_FLAGS}
73+
74+
- name: Verify ${{ inputs.binary }}
75+
shell: nix develop ${{ inputs.dev-shell }} -c bash -euo pipefail {0}
76+
env:
77+
INPUTS_BINARY: ${{ inputs.binary }}
78+
run: |
79+
# Confirm the binary runs and reports the expected name.
80+
target/release/${INPUTS_BINARY} --version | grep -q "^${INPUTS_BINARY} "
81+
# Confirm Syft can decode the embedded cargo-auditable metadata.
82+
SYFT_CHECK_FOR_APP_UPDATE=false syft file:target/release/${INPUTS_BINARY} -o cyclonedx-json | grep 'pkg:cargo/' > /dev/null
83+
84+
- name: Verify static linkage
85+
if: endsWith(inputs.triple, '-linux-musl')
86+
shell: nix develop ${{ inputs.dev-shell }} -c bash -euo pipefail {0}
87+
env:
88+
INPUTS_BINARY: ${{ inputs.binary }}
89+
run: tasks/scripts/verify-static-binary.sh target/release/${INPUTS_BINARY}
90+
91+
- name: Normalize Linux dynamic binary
92+
if: endsWith(inputs.triple, '-linux-gnu')
93+
shell: nix develop ${{ inputs.dev-shell }} -c bash -euo pipefail {0}
94+
env:
95+
INPUTS_BINARY: ${{ inputs.binary }}
96+
INPUTS_INTERPRETER: ${{ inputs.interpreter }}
97+
run: |
98+
binary=target/release/${INPUTS_BINARY}
99+
# Remove Nix store paths so the binary can run on other distributions.
100+
patchelf --set-interpreter "${INPUTS_INTERPRETER}" --remove-rpath "$binary"
101+
# Z3 must be embedded instead of loaded from the target system.
102+
test -z "$(patchelf --print-needed "$binary" | grep '^libz3')"
103+
# Reject symbols introduced after glibc 2.28.
104+
tasks/scripts/verify-glibc-symbols.sh 2.28 "$binary"
105+
106+
- name: Upload ${{ inputs.binary }}
107+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
108+
with:
109+
name: ${{ inputs.artifact-name || format('{0}-{1}', inputs.binary, inputs.triple) }}
110+
path: target/release/${{ inputs.binary }}
111+
compression-level: 0
112+
retention-days: 5
113+
if-no-files-found: error
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
name: Check job results
5+
description: Fail when any required upstream job did not succeed
6+
7+
inputs:
8+
results:
9+
description: JSON-encoded GitHub Actions needs context
10+
required: true
11+
12+
runs:
13+
using: composite
14+
steps:
15+
- name: Check required jobs
16+
shell: bash
17+
env:
18+
JOB_RESULTS: ${{ inputs.results }}
19+
run: |
20+
set -euo pipefail
21+
failures="$(
22+
jq -r '
23+
to_entries[]
24+
| select(.value.result != "success")
25+
| "\(.key) concluded \(.value.result)"
26+
' <<< "$JOB_RESULTS"
27+
)"
28+
if [ -n "$failures" ]; then
29+
while IFS= read -r failure; do
30+
echo "::error::$failure"
31+
done <<< "$failures"
32+
exit 1
33+
fi
Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,19 @@
11
name: Setup E2E CLI
22
description: Download an architecture-matched prebuilt OpenShell CLI for E2E tests
33

4-
inputs:
5-
artifact-prefix:
6-
description: Artifact name prefix; linux-<arch> is appended automatically
7-
required: true
8-
94
runs:
105
using: composite
116
steps:
127
- name: Download prebuilt CLI
138
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
149
with:
15-
name: ${{ format('{0}-linux-{1}', inputs.artifact-prefix, runner.arch == 'X64' && 'amd64' || 'arm64') }}
10+
name: ${{ runner.arch == 'X64' && 'openshell-x86_64-unknown-linux-musl' || 'openshell-aarch64-unknown-linux-musl' }}
1611
path: .e2e/prebuilt-cli
1712

1813
- name: Configure prebuilt CLI
1914
shell: bash
2015
run: |
21-
set -euo pipefail
2216
cli="$GITHUB_WORKSPACE/.e2e/prebuilt-cli/openshell"
23-
if [[ ! -f "$cli" ]]; then
24-
echo "downloaded artifact is missing $cli" >&2
25-
exit 1
26-
fi
2717
chmod +x "$cli"
2818
"$cli" --version
2919
echo "OPENSHELL_BIN=$cli" >> "$GITHUB_ENV"
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
name: Setup E2E Driver
5+
description: Download an architecture-matched standalone compute driver for E2E tests
6+
7+
inputs:
8+
binary:
9+
description: Compute driver binary name
10+
required: true
11+
12+
runs:
13+
using: composite
14+
steps:
15+
- name: Download prebuilt ${{ inputs.binary }}
16+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
17+
with:
18+
name: ${{ inputs.binary }}-${{ runner.arch == 'X64' && 'x86_64-unknown-linux-gnu' || 'aarch64-unknown-linux-gnu' }}
19+
path: .e2e/prebuilt-driver
20+
21+
- name: Configure prebuilt ${{ inputs.binary }}
22+
shell: bash
23+
run: | # zizmor: ignore[github-env] validated filename under the trusted workspace path
24+
if [[ ! "${INPUTS_BINARY}" =~ ^[a-zA-Z0-9._-]+$ ]]; then
25+
echo "invalid driver binary name: ${INPUTS_BINARY}" >&2
26+
exit 1
27+
fi
28+
driver="$GITHUB_WORKSPACE/.e2e/prebuilt-driver/${INPUTS_BINARY}"
29+
chmod +x "$driver"
30+
"$driver" --version
31+
echo "OPENSHELL_EXTERNAL_DRIVER_BIN=$driver" >> "$GITHUB_ENV"
32+
env:
33+
INPUTS_BINARY: ${{ inputs.binary }}

.github/actions/setup-e2e-gateway/action.yml

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,24 @@ name: Setup E2E Gateway
22
description: Download an architecture-matched prebuilt OpenShell gateway for E2E tests
33

44
inputs:
5-
artifact-prefix:
6-
description: Artifact name prefix; linux-<arch> is appended automatically
7-
required: true
5+
artifact-name:
6+
description: GitHub artifact name
7+
required: false
8+
default: ""
89

910
runs:
1011
using: composite
1112
steps:
1213
- name: Download prebuilt gateway
1314
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
1415
with:
15-
name: ${{ format('{0}-linux-{1}', inputs.artifact-prefix, runner.arch == 'X64' && 'amd64' || 'arm64') }}
16+
name: ${{ inputs.artifact-name || (runner.arch == 'X64' && 'openshell-gateway-x86_64-unknown-linux-gnu' || 'openshell-gateway-aarch64-unknown-linux-gnu') }}
1617
path: .e2e/prebuilt-gateway
1718

1819
- name: Configure prebuilt gateway
1920
shell: bash
2021
run: |
21-
set -euo pipefail
2222
gateway="$GITHUB_WORKSPACE/.e2e/prebuilt-gateway/openshell-gateway"
23-
if [[ ! -f "$gateway" ]]; then
24-
echo "downloaded artifact is missing $gateway" >&2
25-
exit 1
26-
fi
2723
chmod +x "$gateway"
2824
"$gateway" --version
2925
echo "OPENSHELL_GATEWAY_BIN=$gateway" >> "$GITHUB_ENV"

0 commit comments

Comments
 (0)