name: Release Dev on: push: branches: [main] workflow_dispatch: permissions: contents: write packages: write defaults: run: shell: bash jobs: # --------------------------------------------------------------------------- # Compute all versions once at the start to avoid git-describe race conditions # --------------------------------------------------------------------------- compute-versions: name: Compute Versions runs-on: linux-amd64-cpu8 timeout-minutes: 5 container: image: ghcr.io/nvidia/openshell/ci:latest credentials: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} outputs: python_version: ${{ steps.v.outputs.python }} cargo_version: ${{ steps.v.outputs.cargo }} deb_version: ${{ steps.v.outputs.deb }} rpm_version: ${{ steps.v.outputs.rpm_version }} rpm_release: ${{ steps.v.outputs.rpm_release }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: 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: Compute all versions id: v run: | set -euo pipefail echo "python=$(uv run python tasks/scripts/release.py get-version --python)" >> "$GITHUB_OUTPUT" echo "cargo=$(uv run python tasks/scripts/release.py get-version --cargo)" >> "$GITHUB_OUTPUT" echo "deb=$(uv run python tasks/scripts/release.py get-version --deb)" >> "$GITHUB_OUTPUT" echo "rpm_version=$(uv run python tasks/scripts/release.py get-version --rpm-version)" >> "$GITHUB_OUTPUT" echo "rpm_release=$(uv run python tasks/scripts/release.py get-version --rpm-release)" >> "$GITHUB_OUTPUT" build-gateway: needs: [compute-versions] uses: ./.github/workflows/docker-build.yml with: component: gateway cargo-version: ${{ needs.compute-versions.outputs.cargo_version }} build-supervisor: needs: [compute-versions] uses: ./.github/workflows/docker-build.yml with: component: supervisor cargo-version: ${{ needs.compute-versions.outputs.cargo_version }} e2e: needs: [build-gateway, build-supervisor] uses: ./.github/workflows/e2e-test.yml with: image-tag: ${{ github.sha }} runner: linux-arm64-cpu8 tag-ghcr-dev: name: Tag GHCR Images as Dev needs: [build-gateway, build-supervisor, release-dev] runs-on: linux-amd64-cpu8 timeout-minutes: 10 steps: - name: Log in to GHCR run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin - name: Tag images as dev run: | set -euo pipefail REGISTRY="ghcr.io/nvidia/openshell" for component in gateway supervisor; do echo "Tagging ${REGISTRY}/${component}:${{ github.sha }} as dev..." docker buildx imagetools create \ --prefer-index=false \ -t "${REGISTRY}/${component}:dev" \ "${REGISTRY}/${component}:${{ github.sha }}" done build-python-wheels-linux: name: Build Python Wheels (Linux ${{ matrix.arch }}) needs: [compute-versions] strategy: matrix: include: - arch: amd64 runner: linux-amd64-cpu8 artifact: linux-amd64 task: python:build:linux:amd64 output_path: target/wheels/linux-amd64/*.whl - arch: arm64 runner: linux-arm64-cpu8 artifact: linux-arm64 task: python:build:linux:arm64 output_path: target/wheels/linux-arm64/*.whl runs-on: ${{ matrix.runner }} timeout-minutes: 120 container: image: ghcr.io/nvidia/openshell/ci:latest credentials: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} options: --privileged env: MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} OPENSHELL_IMAGE_TAG: dev steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: fetch-depth: 0 - name: Mark workspace safe for git run: git config --global --add safe.directory "$GITHUB_WORKSPACE" - name: Sync Python dependencies run: uv sync - name: Cache Rust target and registry uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2 with: shared-key: python-wheel-linux-${{ matrix.arch }} cache-directories: .cache/sccache cache-targets: "true" - name: Build Python wheels run: | set -euo pipefail OPENSHELL_CARGO_VERSION="${{ needs.compute-versions.outputs.cargo_version }}" mise run ${{ matrix.task }} ls -la ${{ matrix.output_path }} - name: Upload wheel artifacts uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: python-wheels-${{ matrix.artifact }} path: ${{ matrix.output_path }} retention-days: 5 build-python-wheel-macos: name: Build Python Wheel (macOS) needs: [compute-versions] runs-on: linux-amd64-cpu8 timeout-minutes: 120 container: image: ghcr.io/nvidia/openshell/ci:latest credentials: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} options: --privileged volumes: - /var/run/docker.sock:/var/run/docker.sock env: MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} OPENSHELL_IMAGE_TAG: dev steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: fetch-depth: 0 - name: Log in to GHCR run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin - name: Set up Docker Buildx uses: ./.github/actions/setup-buildx - name: Mark workspace safe for git run: git config --global --add safe.directory "$GITHUB_WORKSPACE" - name: Sync Python dependencies run: uv sync - name: Build Python wheel run: | set -euo pipefail OPENSHELL_CARGO_VERSION="${{ needs.compute-versions.outputs.cargo_version }}" mise run python:build:macos ls -la target/wheels/*.whl - name: Upload wheel artifacts uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: python-wheels-macos path: target/wheels/*.whl retention-days: 5 # --------------------------------------------------------------------------- # Build CLI binaries (Linux musl — static, native on each arch) # # Builds run directly on the CI host (glibc Ubuntu). Zig provides musl # C/C++ toolchains for bundled-z3 and ring, and is also used as the linker. # --------------------------------------------------------------------------- build-cli-linux: name: Build CLI (Linux ${{ matrix.arch }}) needs: [compute-versions] strategy: matrix: include: - arch: amd64 runner: linux-amd64-cpu8 target: x86_64-unknown-linux-musl zig_target: x86_64-linux-musl - arch: arm64 runner: linux-arm64-cpu8 target: aarch64-unknown-linux-musl zig_target: aarch64-linux-musl runs-on: ${{ matrix.runner }} timeout-minutes: 60 container: image: ghcr.io/nvidia/openshell/ci:latest credentials: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} options: --privileged env: MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} OPENSHELL_IMAGE_TAG: dev steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: 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: Install tools run: mise install --locked - name: Cache Rust target and registry uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2 with: shared-key: cli-musl-${{ matrix.arch }} cache-directories: .cache/sccache cache-targets: "true" - name: Add Rust musl target run: mise x -- rustup target add ${{ matrix.target }} - name: Set up zig musl wrappers run: | set -euo pipefail ZIG="$(mise which zig)" ZIG_TARGET="${{ matrix.zig_target }}" mkdir -p /tmp/zig-musl # cc-rs injects --target= (for example # aarch64-unknown-linux-musl), which zig does not parse. Strip any # caller-provided --target and use the wrapper's zig-native 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 "${{ matrix.target }}" | tr '-' '_') TARGET_ENV_UPPER=${TARGET_ENV^^} # Use zig for C/C++ compilation and final linking. 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" # Let zig own CRT/startfiles to avoid duplicate _start symbols. echo "CARGO_TARGET_${TARGET_ENV_UPPER}_RUSTFLAGS=-Clink-self-contained=no" >> "$GITHUB_ENV" # z3 built with zig c++ uses libc++ symbols (std::__1::*). # Override z3-sys default (stdc++) so Rust links the matching runtime. echo "CXXSTDLIB=c++" >> "$GITHUB_ENV" - name: Patch workspace version if: needs.compute-versions.outputs.cargo_version != '' run: | set -euo pipefail sed -i -E '/^\[workspace\.package\]/,/^\[/{s/^version[[:space:]]*=[[:space:]]*".*"/version = "'"${{ needs.compute-versions.outputs.cargo_version }}"'"/}' Cargo.toml - name: Build ${{ matrix.target }} run: mise x -- cargo build --release --target ${{ matrix.target }} -p openshell-cli --features bundled-z3 - name: sccache stats if: always() run: mise x -- sccache --show-stats - name: Package binary run: | set -euo pipefail mkdir -p artifacts tar -czf artifacts/openshell-${{ matrix.target }}.tar.gz \ -C target/${{ matrix.target }}/release openshell ls -lh artifacts/ - name: Upload artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: cli-linux-${{ matrix.arch }} path: artifacts/*.tar.gz retention-days: 5 # --------------------------------------------------------------------------- # Build CLI binary (macOS aarch64 via osxcross) # --------------------------------------------------------------------------- build-cli-macos: name: Build CLI (macOS) needs: [compute-versions] runs-on: linux-amd64-cpu8 timeout-minutes: 60 container: image: ghcr.io/nvidia/openshell/ci:latest credentials: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} options: --privileged volumes: - /var/run/docker.sock:/var/run/docker.sock env: MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: 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: Log in to GHCR run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin - name: Set up Docker Buildx uses: ./.github/actions/setup-buildx - name: Build macOS binary via Docker run: | set -euo pipefail docker buildx build \ --file deploy/docker/Dockerfile.cli-macos \ --build-arg OPENSHELL_CARGO_VERSION="${{ needs.compute-versions.outputs.cargo_version }}" \ --build-arg OPENSHELL_IMAGE_TAG=dev \ --build-arg CARGO_TARGET_CACHE_SCOPE="${{ github.sha }}" \ --target binary \ --output type=local,dest=out/ \ . - name: Package binary run: | set -euo pipefail mkdir -p artifacts tar -czf artifacts/openshell-aarch64-apple-darwin.tar.gz \ -C out openshell ls -lh artifacts/ - name: Upload artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: cli-macos path: artifacts/*.tar.gz retention-days: 5 # --------------------------------------------------------------------------- # Build standalone gateway binaries (Linux GNU — glibc 2.31 floor) # --------------------------------------------------------------------------- build-gateway-binary-linux: name: Build Gateway Binary (Linux ${{ matrix.arch }}) needs: [compute-versions] strategy: matrix: include: - arch: amd64 runner: linux-amd64-cpu8 target: x86_64-unknown-linux-gnu zig_target: x86_64-unknown-linux-gnu.2.31 - arch: arm64 runner: linux-arm64-cpu8 target: aarch64-unknown-linux-gnu zig_target: aarch64-unknown-linux-gnu.2.31 runs-on: ${{ matrix.runner }} timeout-minutes: 60 container: image: ghcr.io/nvidia/openshell/ci:latest credentials: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} options: --privileged env: MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: 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: Install tools run: mise install --locked - name: Cache Rust target and registry uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2 with: shared-key: gateway-binary-gnu-${{ matrix.arch }} cache-directories: .cache/sccache cache-targets: "true" - name: Patch workspace version if: needs.compute-versions.outputs.cargo_version != '' run: | set -euo pipefail sed -i -E '/^\[workspace\.package\]/,/^\[/{s/^version[[:space:]]*=[[:space:]]*".*"/version = "'"${{ needs.compute-versions.outputs.cargo_version }}"'"/}' Cargo.toml - name: Build ${{ matrix.zig_target }} env: OPENSHELL_IMAGE_TAG: ${{ github.sha }} run: | set -euo pipefail mise x -- rustup target add ${{ matrix.target }} mise x -- cargo zigbuild --release --target ${{ matrix.zig_target }} -p openshell-server --bin openshell-gateway --features bundled-z3 mkdir -p artifacts/bin install -m 0755 target/${{ matrix.target }}/release/openshell-gateway artifacts/bin/openshell-gateway - name: Verify packaged binary run: | set -euo pipefail OUTPUT="$(artifacts/bin/openshell-gateway --version)" echo "$OUTPUT" grep -q '^openshell-gateway ' <<<"$OUTPUT" ldd artifacts/bin/openshell-gateway || true if ldd artifacts/bin/openshell-gateway | grep -q 'libz3'; then echo "gateway binary must not depend on shared libz3; build with bundled-z3" >&2 exit 1 fi - name: Verify glibc symbol floor run: tasks/scripts/verify-glibc-symbols.sh 2.31 artifacts/bin/openshell-gateway - name: sccache stats if: always() run: mise x -- sccache --show-stats - name: Package binary run: | set -euo pipefail mkdir -p artifacts tar -czf artifacts/openshell-gateway-${{ matrix.target }}.tar.gz \ -C artifacts/bin openshell-gateway ls -lh artifacts/ - name: Upload artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: gateway-binary-linux-${{ matrix.arch }} path: artifacts/*.tar.gz retention-days: 5 # --------------------------------------------------------------------------- # Build standalone gateway binary (macOS aarch64 via osxcross) # --------------------------------------------------------------------------- build-gateway-binary-macos: name: Build Gateway Binary (macOS) needs: [compute-versions] runs-on: linux-amd64-cpu8 timeout-minutes: 60 container: image: ghcr.io/nvidia/openshell/ci:latest credentials: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} options: --privileged volumes: - /var/run/docker.sock:/var/run/docker.sock env: MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: 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: Log in to GHCR run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin - name: Set up Docker Buildx uses: ./.github/actions/setup-buildx - name: Build macOS binary via Docker run: | set -euo pipefail docker buildx build \ --file deploy/docker/Dockerfile.gateway-macos \ --build-arg OPENSHELL_CARGO_VERSION="${{ needs.compute-versions.outputs.cargo_version }}" \ --build-arg OPENSHELL_IMAGE_TAG=dev \ --build-arg CARGO_TARGET_CACHE_SCOPE="${{ github.sha }}" \ --target binary \ --output type=local,dest=out/ \ . - name: Verify packaged binary shape run: | set -euo pipefail test -x out/openshell-gateway - name: Package binary run: | set -euo pipefail mkdir -p artifacts tar -czf artifacts/openshell-gateway-aarch64-apple-darwin.tar.gz \ -C out openshell-gateway ls -lh artifacts/ - name: Upload artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: gateway-binary-macos path: artifacts/*.tar.gz retention-days: 5 # --------------------------------------------------------------------------- # Build standalone supervisor binaries (Linux GNU — native on each arch) # --------------------------------------------------------------------------- build-supervisor-binary-linux: name: Build Supervisor Binary (Linux ${{ matrix.arch }}) needs: [compute-versions] strategy: matrix: include: - arch: amd64 runner: linux-amd64-cpu8 target: x86_64-unknown-linux-gnu - arch: arm64 runner: linux-arm64-cpu8 target: aarch64-unknown-linux-gnu runs-on: ${{ matrix.runner }} timeout-minutes: 60 container: image: ghcr.io/nvidia/openshell/ci:latest credentials: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} options: --privileged env: MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: 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: Install tools run: mise install --locked - name: Cache Rust target and registry uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2 with: shared-key: supervisor-binary-gnu-${{ matrix.arch }} cache-directories: .cache/sccache cache-targets: "true" - name: Patch workspace version if: needs.compute-versions.outputs.cargo_version != '' run: | set -euo pipefail sed -i -E '/^\[workspace\.package\]/,/^\[/{s/^version[[:space:]]*=[[:space:]]*".*"/version = "'"${{ needs.compute-versions.outputs.cargo_version }}"'"/}' Cargo.toml - name: Build ${{ matrix.target }} run: | set -euo pipefail mise x -- cargo build --release --target ${{ matrix.target }} -p openshell-sandbox --bin openshell-sandbox - name: Verify packaged binary run: | set -euo pipefail OUTPUT="$(target/${{ matrix.target }}/release/openshell-sandbox --version)" echo "$OUTPUT" grep -q '^openshell-sandbox ' <<<"$OUTPUT" - name: sccache stats if: always() run: mise x -- sccache --show-stats - name: Package binary run: | set -euo pipefail mkdir -p artifacts tar -czf artifacts/openshell-sandbox-${{ matrix.target }}.tar.gz \ -C target/${{ matrix.target }}/release openshell-sandbox ls -lh artifacts/ - name: Upload artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: supervisor-binary-linux-${{ matrix.arch }} path: artifacts/*.tar.gz retention-days: 5 build-driver-vm-linux: name: Build Driver VM Linux needs: [compute-versions] uses: ./.github/workflows/driver-vm-linux.yml with: cargo-version: ${{ needs.compute-versions.outputs.cargo_version }} image-tag: dev checkout-ref: ${{ github.sha }} secrets: inherit build-driver-vm-macos: name: Build Driver VM macOS needs: [compute-versions] uses: ./.github/workflows/driver-vm-macos.yml with: cargo-version: ${{ needs.compute-versions.outputs.cargo_version }} image-tag: dev checkout-ref: ${{ github.sha }} secrets: inherit build-deb: name: Build Debian Packages needs: [compute-versions, build-cli-linux, build-gateway-binary-linux, build-driver-vm-linux] uses: ./.github/workflows/deb-package.yml with: deb-version: ${{ needs.compute-versions.outputs.deb_version }} checkout-ref: ${{ github.sha }} secrets: inherit build-snap: name: Build Snap needs: [compute-versions] uses: ./.github/workflows/snap-package.yml with: checkout-ref: ${{ github.sha }} upload-channel: latest/edge github-environment: latest/edge secrets: publish-credentials: ${{ secrets.SNAPCRAFT_STORE_CREDENTIALS }} build-rpm: name: Build RPM Packages needs: [compute-versions, build-cli-linux, build-gateway-binary-linux] uses: ./.github/workflows/rpm-package.yml with: checkout-ref: ${{ github.sha }} rpm-version: ${{ needs.compute-versions.outputs.rpm_version }} rpm-release: ${{ needs.compute-versions.outputs.rpm_release }} cargo-version: ${{ needs.compute-versions.outputs.cargo_version }} secrets: inherit smoke-linux-dev-artifacts: name: Smoke Linux Dev Artifacts (${{ matrix.name }}) needs: [build-gateway-binary-linux, build-driver-vm-linux, build-deb] timeout-minutes: 20 strategy: fail-fast: false matrix: include: - name: ubuntu-22.04-deb-amd64 runner: linux-amd64-cpu8 image: ubuntu:22.04 artifact_arch: amd64 - name: ubuntu-22.04-deb-arm64 runner: linux-arm64-cpu8 image: ubuntu:22.04 artifact_arch: arm64 runs-on: ${{ matrix.runner }} container: image: ${{ matrix.image }} steps: - name: Download Debian package artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: deb-linux-${{ matrix.artifact_arch }} path: package-input/ - name: Smoke Debian package on Ubuntu 22.04 run: | set -euo pipefail apt-get update apt-get install -y --no-install-recommends ./package-input/*.deb openshell-gateway --version /usr/libexec/openshell/openshell-driver-vm --version # --------------------------------------------------------------------------- # Create / update the dev GitHub Release with CLI, gateway, driver, and wheels # --------------------------------------------------------------------------- release-dev: name: Release Dev needs: [compute-versions, build-cli-linux, build-cli-macos, build-gateway-binary-linux, build-gateway-binary-macos, build-supervisor-binary-linux, build-python-wheels-linux, build-python-wheel-macos, e2e, build-driver-vm-linux, build-driver-vm-macos, build-deb, build-rpm, build-snap, smoke-linux-dev-artifacts] runs-on: linux-amd64-cpu8 timeout-minutes: 10 permissions: contents: write id-token: write attestations: write artifact-metadata: write outputs: wheel_filenames: ${{ steps.wheel_filenames.outputs.wheel_filenames }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Download all CLI artifacts uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: cli-* path: release/ merge-multiple: true - name: Download gateway binary artifacts uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: gateway-binary-* path: release/ merge-multiple: true - name: Download supervisor binary artifacts uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: supervisor-binary-* path: release/ merge-multiple: true - name: Download VM driver artifacts uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: driver-vm-* path: release/ merge-multiple: true - name: Download wheel artifacts uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: python-wheels-* path: release/ merge-multiple: true - name: Download Debian package artifacts uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: deb-linux-* path: release/ merge-multiple: true - name: Download RPM package artifacts uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: rpm-linux-* path: release/ merge-multiple: true - name: Download snap artifacts uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: snap-linux-* path: release/ merge-multiple: true - name: Normalize dev package filenames run: | set -euo pipefail shopt -s nullglob move_one() { local dest="$1" shift local matches=("$@") if [ "${#matches[@]}" -ne 1 ]; then echo "expected exactly one source for ${dest}, found ${#matches[@]}: ${matches[*]-}" >&2 exit 1 fi mv "${matches[0]}" "release/${dest}" } move_one openshell-dev-amd64.deb release/openshell_*_amd64.deb move_one openshell-dev-arm64.deb release/openshell_*_arm64.deb move_one openshell-dev-x86_64.rpm release/openshell-[0-9]*.x86_64.rpm move_one openshell-dev-aarch64.rpm release/openshell-[0-9]*.aarch64.rpm move_one openshell-gateway-dev-x86_64.rpm release/openshell-gateway-[0-9]*.x86_64.rpm move_one openshell-gateway-dev-aarch64.rpm release/openshell-gateway-[0-9]*.aarch64.rpm ls -la release/ - name: Capture wheel filenames id: wheel_filenames run: | set -euo pipefail ls -la release/*.whl WHEEL_FILENAMES=$(ls release/*.whl | xargs -n1 basename | sort | paste -sd, -) echo "wheel_filenames=${WHEEL_FILENAMES}" >> "$GITHUB_OUTPUT" - name: Generate checksums run: | set -euo pipefail cd release sha256sum \ openshell-x86_64-unknown-linux-musl.tar.gz \ openshell-aarch64-unknown-linux-musl.tar.gz \ openshell-aarch64-apple-darwin.tar.gz \ openshell-driver-vm-x86_64-unknown-linux-gnu.tar.gz \ openshell-driver-vm-aarch64-unknown-linux-gnu.tar.gz \ openshell-driver-vm-aarch64-apple-darwin.tar.gz \ *.deb \ openshell-*.rpm \ *.whl > openshell-checksums-sha256.txt cat openshell-checksums-sha256.txt sha256sum \ openshell-gateway-x86_64-unknown-linux-gnu.tar.gz \ openshell-gateway-aarch64-unknown-linux-gnu.tar.gz \ openshell-gateway-aarch64-apple-darwin.tar.gz > openshell-gateway-checksums-sha256.txt cat openshell-gateway-checksums-sha256.txt sha256sum \ openshell-sandbox-x86_64-unknown-linux-gnu.tar.gz \ openshell-sandbox-aarch64-unknown-linux-gnu.tar.gz > openshell-sandbox-checksums-sha256.txt cat openshell-sandbox-checksums-sha256.txt - name: Generate Homebrew formula run: | set -euo pipefail python3 tasks/scripts/release.py generate-homebrew-formula \ --release-tag dev \ --release-dir release \ --output release/openshell.rb cat release/openshell.rb - name: Attest VM driver artifacts uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4 with: subject-path: | release/openshell-driver-vm-x86_64-unknown-linux-gnu.tar.gz release/openshell-driver-vm-aarch64-unknown-linux-gnu.tar.gz release/openshell-driver-vm-aarch64-apple-darwin.tar.gz - name: Prune managed assets from dev release uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 with: script: | const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/'); // Fetch the dev release let release; try { release = await github.rest.repos.getReleaseByTag({ owner, repo, tag: 'dev' }); } catch (err) { if (err.status === 404) { core.info('No existing dev release found; skipping wheel pruning.'); return; } throw err; } const assets = release.data.assets; core.info(`=== Current dev release assets (${assets.length} total) ===`); for (const a of assets) { core.info(` ${String(a.id).padStart(12)} ${a.name}`); } const managed = (name) => ( name.startsWith('openshell') && ( name.endsWith('.tar.gz') || name.endsWith('.txt') || name.endsWith('.whl') || name.endsWith('.deb') || name.endsWith('.rpm') ) ); let deleted = 0, skipped = 0; for (const asset of assets) { if (managed(asset.name)) { core.info(`Deleting managed dev asset: ${asset.name} (id=${asset.id})`); await github.rest.repos.deleteReleaseAsset({ owner, repo, asset_id: asset.id }); deleted++; } else { core.info(`Skipping unmanaged asset: ${asset.name}`); skipped++; } } core.info(`Summary: deleted=${deleted}, skipped=${skipped}`); - name: Move dev tag run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" git tag -fa dev -m "Latest Dev" "${GITHUB_SHA}" git push --force origin dev - name: Create / update GitHub Release uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 with: name: OpenShell Development Build prerelease: true tag_name: dev target_commitish: ${{ github.sha }} body: | This build is automatically published on every commit to main that passes CI. > **NOTE**: This is a development build, not a tagged release, and may be unstable. ### Quick install ``` curl -LsSf https://raw.githubusercontent.com/NVIDIA/OpenShell/main/install.sh | OPENSHELL_VERSION=dev sh ``` files: | release/openshell-x86_64-unknown-linux-musl.tar.gz release/openshell-aarch64-unknown-linux-musl.tar.gz release/openshell-aarch64-apple-darwin.tar.gz release/openshell-dev-amd64.deb release/openshell-dev-arm64.deb release/openshell-*.rpm release/*.snap release/openshell-gateway-x86_64-unknown-linux-gnu.tar.gz release/openshell-gateway-aarch64-unknown-linux-gnu.tar.gz release/openshell-gateway-aarch64-apple-darwin.tar.gz release/openshell-sandbox-x86_64-unknown-linux-gnu.tar.gz release/openshell-sandbox-aarch64-unknown-linux-gnu.tar.gz release/openshell-driver-vm-x86_64-unknown-linux-gnu.tar.gz release/openshell-driver-vm-aarch64-unknown-linux-gnu.tar.gz release/openshell-driver-vm-aarch64-apple-darwin.tar.gz release/*.whl release/openshell.rb release/openshell-checksums-sha256.txt release/openshell-gateway-checksums-sha256.txt release/openshell-sandbox-checksums-sha256.txt release-helm: name: Release Helm Chart (OCI, dev) needs: [release-dev, tag-ghcr-dev] runs-on: ubuntu-latest timeout-minutes: 10 permissions: packages: write steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - uses: ./.github/actions/release-helm-oci with: chart-version: 0.0.0-dev app-version: dev release-kind: dev pin-sha: ${{ github.sha }} trigger-wheel-publish: name: Trigger Wheel Publish needs: [compute-versions, release-dev] runs-on: [self-hosted, nv] timeout-minutes: 10 steps: - name: Trigger GitLab CI env: GITLAB_CI_TRIGGER_TOKEN: ${{ secrets.GITLAB_CI_TRIGGER_TOKEN }} GITLAB_CI_TRIGGER_URL: ${{ secrets.GITLAB_CI_TRIGGER_URL }} RELEASE_VERSION: ${{ needs.compute-versions.outputs.python_version }} WHEEL_FILENAMES: ${{ needs.release-dev.outputs.wheel_filenames }} run: | set -euo pipefail if [ -z "${WHEEL_FILENAMES}" ]; then echo "No wheel filenames provided by build job" >&2 exit 1 fi response=$(curl -X POST \ --fail \ --silent \ --show-error \ -F "token=${GITLAB_CI_TRIGGER_TOKEN}" \ -F "ref=main" \ -F "variables[PIPELINE_ACTION]=publish_wheels" \ -F "variables[GITHUB_REPOSITORY]=${GITHUB_REPOSITORY}" \ -F "variables[COMMIT_SHA]=${GITHUB_SHA}" \ -F "variables[RELEASE_TAG]=dev" \ -F "variables[RELEASE_VERSION]=${RELEASE_VERSION}" \ -F "variables[RELEASE_KIND]=dev" \ -F "variables[WHEEL_FILENAMES]=${WHEEL_FILENAMES}" \ "${GITLAB_CI_TRIGGER_URL}") pipeline_id=$(printf '%s' "$response" | sed -n 's/.*"id":\([0-9][0-9]*\).*/\1/p') pipeline_status=$(printf '%s' "$response" | sed -n 's/.*"status":"\([^"]*\)".*/\1/p') echo "Triggered GitLab pipeline ${pipeline_id:-unknown} with status=${pipeline_status:-unknown}"