Skip to content

Commit e2639e7

Browse files
committed
feat(ci): add shadow-rust-native-build workflow for OS-49 Phase 4 (PR 4a)
Builds openshell-gateway and openshell-sandbox natively per-arch on the nv-gha-runners shared CPU pool with a GHA-backed sccache, and uploads the resulting binaries as artifacts shaped for Dockerfile.images' BINARY_SOURCE=prebuilt path (added in #945). Dispatch manually 4-5 times after merge to collect cold + warm numbers and compare against the Rust portion of docker-build.yml's ARC baseline. PR 4c will wire these artifacts into the real pipeline once numbers land. Refs OS-128. Signed-off-by: Jonas Toelke <jtoelke@nvidia.com>
1 parent cd5c16d commit e2639e7

1 file changed

Lines changed: 156 additions & 0 deletions

File tree

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
name: Shadow — Rust Native Build (openshell-gateway / openshell-sandbox)
5+
6+
# OS-49 Phase 4 / PR 4a — non-blocking shadow that builds openshell-gateway
7+
# and openshell-sandbox natively per-arch on the nv-gha-runners shared CPU
8+
# pool (`linux-{amd64,arm64}-cpu8`) with a GHA-backed sccache, and uploads
9+
# the resulting binaries as artifacts. Reuses the pattern from PR #853's
10+
# release-dev.yml "Build standalone {gateway,supervisor} binaries" jobs.
11+
#
12+
# The artifacts match the layout PR 4c expects when consuming `BINARY_SOURCE=
13+
# prebuilt` (wired up in #945): one binary per (component, arch), staged to
14+
# `deploy/docker/.build/prebuilt-binaries/<arch>/openshell-{gateway,sandbox}`.
15+
#
16+
# Dispatch 4-5 times after merge to collect cold + warm numbers and compare
17+
# against the Rust portion of docker-build.yml's 17.5 m ARC baseline. Success
18+
# criteria, gotchas, and dependency graph live on the OS-128 Linear issue.
19+
20+
on:
21+
# workflow_dispatch only — keeps this shadow off main's required-check
22+
# surface and avoids cluttering CI history with non-blocking failures
23+
# while we're still collecting Phase 4 data. Dispatch from the Actions
24+
# UI to collect cold/warm-cache numbers.
25+
workflow_dispatch:
26+
27+
permissions:
28+
contents: read
29+
packages: read
30+
31+
env:
32+
CARGO_TERM_COLOR: always
33+
CARGO_INCREMENTAL: "0"
34+
MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35+
# Route sccache (already RUSTC_WRAPPER in mise.toml) to the GHA cache
36+
# backend instead of the EKS memcached used by ARC.
37+
SCCACHE_GHA_ENABLED: "true"
38+
39+
jobs:
40+
rust-native-build:
41+
name: ${{ matrix.component }} (${{ matrix.arch }})
42+
strategy:
43+
fail-fast: false
44+
matrix:
45+
component: [gateway, sandbox]
46+
arch: [amd64, arm64]
47+
include:
48+
- component: gateway
49+
crate: openshell-server
50+
binary: openshell-gateway
51+
- component: sandbox
52+
crate: openshell-sandbox
53+
binary: openshell-sandbox
54+
- arch: amd64
55+
runner: linux-amd64-cpu8
56+
target: x86_64-unknown-linux-gnu
57+
- arch: arm64
58+
runner: linux-arm64-cpu8
59+
target: aarch64-unknown-linux-gnu
60+
runs-on: ${{ matrix.runner }}
61+
env:
62+
# Partition the GHA sccache cache per (component, arch). Without this,
63+
# concurrent matrix jobs collide on the same cache key and later-starting
64+
# writers hit 409 Conflict (PR #961 fix for shadow-shared-cpu-spike).
65+
SCCACHE_GHA_VERSION: ${{ matrix.component }}-${{ matrix.arch }}
66+
container:
67+
image: ghcr.io/nvidia/openshell/ci:latest
68+
credentials:
69+
username: ${{ github.actor }}
70+
password: ${{ secrets.GITHUB_TOKEN }}
71+
timeout-minutes: 60
72+
steps:
73+
- uses: actions/checkout@v4
74+
with:
75+
fetch-depth: 0
76+
77+
- name: Mark workspace safe for git
78+
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
79+
80+
- name: Fetch tags
81+
run: git fetch --tags --force
82+
83+
- name: Install tools
84+
run: mise install
85+
86+
- name: Configure GHA sccache backend
87+
# Exposes ACTIONS_CACHE_URL / ACTIONS_RUNTIME_TOKEN so sccache (wrapped
88+
# around rustc via mise's RUSTC_WRAPPER) can initialize the GHA cache.
89+
uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9
90+
91+
- name: Cache Rust target and registry
92+
uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2
93+
with:
94+
shared-key: shadow-rust-native-${{ matrix.component }}-${{ matrix.arch }}
95+
cache-directories: .cache/sccache
96+
cache-targets: "true"
97+
98+
- name: Compute cargo version
99+
id: version
100+
run: |
101+
set -euo pipefail
102+
echo "cargo_version=$(uv run python tasks/scripts/release.py get-version --cargo)" >> "$GITHUB_OUTPUT"
103+
104+
- name: Patch workspace version
105+
if: steps.version.outputs.cargo_version != ''
106+
run: |
107+
set -euo pipefail
108+
sed -i -E '/^\[workspace\.package\]/,/^\[/{s/^version[[:space:]]*=[[:space:]]*".*"/version = "'"${{ steps.version.outputs.cargo_version }}"'"/}' Cargo.toml
109+
110+
- name: Build ${{ matrix.binary }} (${{ matrix.target }})
111+
# Matches docker-build.yml's default EXTRA_CARGO_FEATURES so the
112+
# binary content is byte-comparable to what Dockerfile.images produces
113+
# today (precondition for PR 4c's drop-in swap).
114+
run: |
115+
set -euo pipefail
116+
mise x -- cargo build \
117+
--release \
118+
--target ${{ matrix.target }} \
119+
-p ${{ matrix.crate }} \
120+
--bin ${{ matrix.binary }} \
121+
--features openshell-core/dev-settings
122+
123+
- name: Verify packaged binary
124+
run: |
125+
set -euo pipefail
126+
BIN="target/${{ matrix.target }}/release/${{ matrix.binary }}"
127+
OUTPUT="$("$BIN" --version)"
128+
echo "$OUTPUT"
129+
grep -q "^${{ matrix.binary }} " <<<"$OUTPUT"
130+
# Record glibc linkage so drift from the Ubuntu noble runtime base
131+
# image is visible in logs (not asserted — the runtime check lands
132+
# when PR 4c builds images on top of these artifacts).
133+
ldd --version | head -1
134+
ldd "$BIN" | head -20 || true
135+
136+
- name: sccache stats
137+
if: always()
138+
run: mise x -- sccache --show-stats
139+
140+
- name: Stage binary for prebuilt layout
141+
# Shape mirrors `deploy/docker/.build/prebuilt-binaries/<arch>/<bin>`
142+
# so PR 4c can download the artifact directly into the build context.
143+
run: |
144+
set -euo pipefail
145+
STAGE="prebuilt-binaries/${{ matrix.arch }}"
146+
mkdir -p "$STAGE"
147+
install -m 0755 "target/${{ matrix.target }}/release/${{ matrix.binary }}" "$STAGE/${{ matrix.binary }}"
148+
ls -lh "$STAGE/"
149+
150+
- name: Upload artifact
151+
uses: actions/upload-artifact@v4
152+
with:
153+
name: rust-binary-${{ matrix.component }}-linux-${{ matrix.arch }}
154+
path: prebuilt-binaries/${{ matrix.arch }}/${{ matrix.binary }}
155+
retention-days: 5
156+
if-no-files-found: error

0 commit comments

Comments
 (0)