mirror of
https://github.com/NVIDIA/OpenShell.git
synced 2026-10-15 05:09:44 +08:00
Bumps [actions/checkout](https://github.com/actions/checkout) from 7.0.0 to 7.0.1. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0...3d3c42e5aac5ba805825da76410c181273ba90b1) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
308 lines
11 KiB
YAML
308 lines
11 KiB
YAML
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
name: Rust Image Binary Build (openshell-gateway / openshell-sandbox / openshell-cli)
|
|
|
|
# Build Rust binaries per Linux architecture before the Docker image build
|
|
# consumes them as prebuilt artifacts. Gateway images use GNU-linked binaries
|
|
# for the NVIDIA distroless C/C++ runtime; supervisor and cli images use musl/static
|
|
# binaries so the final image can remain scratch. Gateway GNU binaries are
|
|
# built with an explicit glibc 2.28 floor so image, package, and tarball
|
|
# artifacts share the same host portability contract.
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
component:
|
|
description: "Binary component to build (gateway, sandbox, or cli)"
|
|
required: true
|
|
type: string
|
|
arch:
|
|
description: "Linux architecture to build (amd64 or arm64)"
|
|
required: true
|
|
type: string
|
|
cargo-version:
|
|
description: "Pre-computed cargo version (skips internal git-based computation)"
|
|
required: false
|
|
type: string
|
|
default: ""
|
|
features:
|
|
description: "Cargo features to enable"
|
|
required: false
|
|
type: string
|
|
default: ""
|
|
retention-days:
|
|
description: "Artifact retention period"
|
|
required: false
|
|
type: number
|
|
default: 5
|
|
artifact-name:
|
|
description: "Artifact name override"
|
|
required: false
|
|
type: string
|
|
default: ""
|
|
checkout-ref:
|
|
description: "Git ref to check out for build inputs (defaults to the workflow SHA)"
|
|
required: false
|
|
type: string
|
|
default: ""
|
|
image-tag:
|
|
description: "Supervisor image tag to bake into gateway binaries"
|
|
required: false
|
|
type: string
|
|
default: ""
|
|
permissions:
|
|
contents: read
|
|
packages: read
|
|
|
|
env:
|
|
CARGO_TERM_COLOR: always
|
|
CARGO_INCREMENTAL: "0"
|
|
MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
# Route sccache (already RUSTC_WRAPPER in mise.toml) to the GHA cache
|
|
# backend instead of the EKS memcached used by ARC.
|
|
SCCACHE_GHA_ENABLED: "true"
|
|
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
|
|
jobs:
|
|
rust-native-build:
|
|
name: ${{ inputs.component }} (${{ inputs.arch }})
|
|
runs-on: ${{ inputs.arch == 'arm64' && 'linux-arm64-cpu8' || 'linux-amd64-cpu8' }}
|
|
timeout-minutes: 60
|
|
env:
|
|
COMPONENT: ${{ inputs.component }}
|
|
ARCH: ${{ inputs.arch }}
|
|
FEATURES: ${{ inputs.features }}
|
|
# Partition the GHA sccache cache per (component, arch). Without this,
|
|
# concurrent jobs collide on the same cache key and later-starting
|
|
# writers hit 409 Conflict.
|
|
SCCACHE_GHA_VERSION: ${{ inputs.component }}-${{ inputs.arch }}
|
|
container:
|
|
image: ghcr.io/nvidia/openshell/ci:latest
|
|
credentials:
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
ref: ${{ inputs['checkout-ref'] || github.sha }}
|
|
fetch-depth: 0
|
|
|
|
- name: Mark workspace safe for git
|
|
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
|
|
|
- name: Fetch tags
|
|
run: git fetch --tags --force
|
|
|
|
- name: Configure GHA sccache backend
|
|
# Exposes ACTIONS_CACHE_URL / ACTIONS_RUNTIME_TOKEN before `mise install`
|
|
# compiles cargo-installed tools through RUSTC_WRAPPER=sccache.
|
|
uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10
|
|
|
|
- name: Install tools
|
|
run: mise install --locked
|
|
|
|
- name: Resolve build target
|
|
id: target
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
case "$COMPONENT" in
|
|
gateway)
|
|
crate=openshell-server
|
|
binary=openshell-gateway
|
|
zig_target=
|
|
;;
|
|
sandbox)
|
|
crate=openshell-sandbox
|
|
binary=openshell-sandbox
|
|
zig_target=
|
|
;;
|
|
cli)
|
|
crate=openshell-cli
|
|
binary=openshell
|
|
zig_target=
|
|
;;
|
|
*)
|
|
echo "unsupported component: $COMPONENT" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
case "$ARCH" in
|
|
amd64)
|
|
if [[ "$COMPONENT" == "sandbox" || "$COMPONENT" == "cli" ]]; then
|
|
target=x86_64-unknown-linux-musl
|
|
zig_target=x86_64-linux-musl
|
|
else
|
|
target=x86_64-unknown-linux-gnu
|
|
zig_target=x86_64-unknown-linux-gnu.2.28
|
|
fi
|
|
;;
|
|
arm64)
|
|
if [[ "$COMPONENT" == "sandbox" || "$COMPONENT" == "cli" ]]; then
|
|
target=aarch64-unknown-linux-musl
|
|
zig_target=aarch64-linux-musl
|
|
else
|
|
target=aarch64-unknown-linux-gnu
|
|
zig_target=aarch64-unknown-linux-gnu.2.28
|
|
fi
|
|
;;
|
|
*)
|
|
echo "unsupported arch: $ARCH" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
{
|
|
echo "crate=$crate"
|
|
echo "binary=$binary"
|
|
echo "target=$target"
|
|
echo "zig_target=$zig_target"
|
|
} >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Cache Rust target and registry
|
|
uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2
|
|
with:
|
|
shared-key: rust-native-${{ inputs.component }}-${{ inputs.arch }}-zig-wrapper-${{ hashFiles('tasks/scripts/setup-zig-cc-wrapper.sh') }}
|
|
cache-directories: .cache/sccache
|
|
cache-targets: "true"
|
|
|
|
- name: Compute cargo version
|
|
id: version
|
|
run: |
|
|
set -euo pipefail
|
|
if [[ -n "${{ inputs['cargo-version'] }}" ]]; then
|
|
echo "cargo_version=${{ inputs['cargo-version'] }}" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "cargo_version=$(uv run python tasks/scripts/release.py get-version --cargo)" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
- name: Patch workspace version
|
|
if: steps.version.outputs.cargo_version != ''
|
|
run: |
|
|
set -euo pipefail
|
|
sed -i -E '/^\[workspace\.package\]/,/^\[/{s/^version[[:space:]]*=[[:space:]]*".*"/version = "'"${{ steps.version.outputs.cargo_version }}"'"/}' Cargo.toml
|
|
|
|
- name: Set up zig musl wrappers
|
|
if: contains(steps.target.outputs.target, 'musl')
|
|
run: |
|
|
set -euo pipefail
|
|
ZIG="$(mise which zig)"
|
|
ZIG_TARGET="${{ steps.target.outputs.zig_target }}"
|
|
mkdir -p /tmp/zig-musl
|
|
|
|
# cc-rs injects --target=<rust-triple>, which zig does not parse.
|
|
# Strip caller-provided --target and use the wrapper's zig target.
|
|
for tool in cc c++; do
|
|
printf '#!/bin/bash\nargs=()\nfor arg in "$@"; do\n case "$arg" in\n --target=*) ;;\n *) args+=("$arg") ;;\n esac\ndone\nexec "%s" %s --target=%s "${args[@]}"\n' \
|
|
"$ZIG" "$tool" "$ZIG_TARGET" > "/tmp/zig-musl/${tool}"
|
|
chmod +x "/tmp/zig-musl/${tool}"
|
|
done
|
|
|
|
TARGET_ENV=$(echo "${{ steps.target.outputs.target }}" | tr '-' '_')
|
|
TARGET_ENV_UPPER=${TARGET_ENV^^}
|
|
|
|
echo "CC_${TARGET_ENV}=/tmp/zig-musl/cc" >> "$GITHUB_ENV"
|
|
echo "CXX_${TARGET_ENV}=/tmp/zig-musl/c++" >> "$GITHUB_ENV"
|
|
echo "CARGO_TARGET_${TARGET_ENV_UPPER}_LINKER=/tmp/zig-musl/cc" >> "$GITHUB_ENV"
|
|
echo "CARGO_TARGET_${TARGET_ENV_UPPER}_RUSTFLAGS=-Clink-self-contained=no" >> "$GITHUB_ENV"
|
|
|
|
- name: Set up zig glibc wrappers
|
|
if: inputs.component == 'gateway'
|
|
run: tasks/scripts/setup-zig-cc-wrapper.sh "${{ steps.target.outputs.zig_target }}" "${{ steps.target.outputs.zig_target }}" /tmp/zig-gnu
|
|
|
|
- name: Build ${{ steps.target.outputs.binary }} (${{ steps.target.outputs.zig_target || steps.target.outputs.target }})
|
|
env:
|
|
# Preserve the release-codegen setting used by the old Dockerfile
|
|
# Rust build path so image artifacts keep the same release profile.
|
|
CARGO_PROFILE_RELEASE_CODEGEN_UNITS: "1"
|
|
OPENSHELL_IMAGE_TAG: ${{ inputs['image-tag'] }}
|
|
run: |
|
|
set -euo pipefail
|
|
# z3 built with zig c++ uses libc++ symbols (std::__1::*).
|
|
# Override z3-sys default (stdc++) so Rust links the matching runtime.
|
|
if [[ "${{ inputs.component }}" == "cli" ]]; then
|
|
echo "CXXSTDLIB=c++" >> "$GITHUB_ENV"
|
|
fi
|
|
|
|
mise x -- rustup target add "${{ steps.target.outputs.target }}"
|
|
|
|
cargo_cmd=(cargo build)
|
|
build_target="${{ steps.target.outputs.target }}"
|
|
args=()
|
|
|
|
if [[ "${{ inputs.component }}" == "gateway" ]]; then
|
|
cargo_cmd=(cargo zigbuild)
|
|
build_target="${{ steps.target.outputs.zig_target }}"
|
|
args+=(--features bundled-z3)
|
|
fi
|
|
args+=(
|
|
--release
|
|
--target "$build_target"
|
|
-p "${{ steps.target.outputs.crate }}"
|
|
--bin "${{ steps.target.outputs.binary }}"
|
|
)
|
|
if [[ -n "$FEATURES" ]]; then
|
|
args+=(--features "$FEATURES")
|
|
fi
|
|
if [[ -n "${{ steps.version.outputs.cargo_version }}" ]]; then
|
|
export GIT_DIR=/nonexistent
|
|
fi
|
|
mise x -- "${cargo_cmd[@]}" "${args[@]}"
|
|
|
|
- name: Verify packaged binary
|
|
run: |
|
|
set -euo pipefail
|
|
BIN="target/${{ steps.target.outputs.target }}/release/${{ steps.target.outputs.binary }}"
|
|
OUTPUT="$("$BIN" --version)"
|
|
echo "$OUTPUT"
|
|
grep -q "^${{ steps.target.outputs.binary }} " <<<"$OUTPUT"
|
|
# Record linkage so image runtime drift is visible in logs.
|
|
ldd --version
|
|
ldd "$BIN" || true
|
|
if [[ "${{ inputs.component }}" == "gateway" ]] && ldd "$BIN" | grep -q 'libz3'; then
|
|
echo "gateway binary must not depend on shared libz3; enable bundled-z3 for image artifacts" >&2
|
|
exit 1
|
|
fi
|
|
|
|
- name: Verify glibc symbol floor
|
|
if: inputs.component == 'gateway'
|
|
run: |
|
|
set -euo pipefail
|
|
BIN="target/${{ steps.target.outputs.target }}/release/${{ steps.target.outputs.binary }}"
|
|
tasks/scripts/verify-glibc-symbols.sh 2.28 "$BIN"
|
|
|
|
- name: Stage binary for prebuilt layout
|
|
run: |
|
|
set -euo pipefail
|
|
STAGE="prebuilt-binaries/$ARCH"
|
|
mkdir -p "$STAGE"
|
|
install -m 0755 \
|
|
"target/${{ steps.target.outputs.target }}/release/${{ steps.target.outputs.binary }}" \
|
|
"$STAGE/${{ steps.target.outputs.binary }}"
|
|
ls -lh "$STAGE/"
|
|
|
|
- name: Upload artifact
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
with:
|
|
name: ${{ inputs['artifact-name'] != '' && inputs['artifact-name'] || format('rust-binary-{0}-linux-{1}', inputs.component, inputs.arch) }}
|
|
path: prebuilt-binaries/${{ inputs.arch }}/${{ steps.target.outputs.binary }}
|
|
retention-days: ${{ inputs['retention-days'] }}
|
|
if-no-files-found: error
|
|
|
|
- name: sccache stats
|
|
if: always()
|
|
run: |
|
|
set +e
|
|
stats_bin="${SCCACHE_PATH:-sccache}"
|
|
"$stats_bin" --show-stats
|
|
status=$?
|
|
if [[ $status -ne 0 ]]; then
|
|
echo "::warning::sccache stats unavailable (exit $status)"
|
|
fi
|
|
exit 0
|