From ddba590810b4ef02eea7391df75b2bd29ee932cc Mon Sep 17 00:00:00 2001 From: Zygmunt Krynicki Date: Tue, 26 May 2026 14:12:04 +0200 Subject: [PATCH 1/5] ci: add snap build and publish pipeline Add a snap-package.yml reusable workflow for building snaps on amd64 and arm64, and wire it into release-dev.yml and release-tag.yml. The release canary ubuntu-snap job downloads the snap from release-dev artifacts using actions/download-artifact with run-id instead of fetching it via an unauthenticated GitHub API call. This is consistent with how all other package types (deb, rpm, etc.) are consumed across the tree and avoids rate-limiting issues. The snap job only runs on workflow_run triggers (not dispatch) since artifacts are only available from a prior release-dev run. The docker snap dependency (sudo snap install docker) is required before installing the openshell snap which plugs the docker interface. Signed-off-by: Zygmunt Krynicki --- .github/workflows/release-canary.yml | 39 +++++++++ .github/workflows/release-dev.yml | 21 ++++- .github/workflows/release-tag.yml | 21 ++++- .github/workflows/snap-package.yml | 118 +++++++++++++++++++++++++++ snapcraft.yaml | 3 +- 5 files changed, 198 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/snap-package.yml diff --git a/.github/workflows/release-canary.yml b/.github/workflows/release-canary.yml index 9c209d0c9..0f6655718 100644 --- a/.github/workflows/release-canary.yml +++ b/.github/workflows/release-canary.yml @@ -7,6 +7,7 @@ on: types: [completed] permissions: + actions: read contents: read defaults: @@ -72,6 +73,44 @@ jobs: curl -LsSf https://raw.githubusercontent.com/NVIDIA/OpenShell/${{ github.event.workflow_run.head_sha || github.sha }}/install.sh | sh openshell status + ubuntu-snap: + name: Ubuntu Snap + if: ${{ github.event.workflow_run.conclusion == 'success' }} + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - name: Install snapd + run: | + sudo apt-get update + sudo apt-get install -y snapd + sudo systemctl start snapd + + - name: Install Docker snap + run: | + sudo snap install docker + + - name: Download snap from release-dev artifacts + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + run-id: ${{ github.event.workflow_run.id }} + pattern: snap-linux-amd64 + path: release/ + + - name: Install snap (dangerous — from release, not store) + run: | + sudo snap install ./release/*.snap --dangerous + + - name: Connect interfaces + run: | + sudo snap connect openshell:docker docker:docker-daemon + sudo snap connect openshell:log-observe + sudo snap connect openshell:system-observe + sudo snap connect openshell:ssh-keys + + - name: Check status + run: | + openshell status + kubernetes: name: Kubernetes Helm (kind) if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }} diff --git a/.github/workflows/release-dev.yml b/.github/workflows/release-dev.yml index 5c8eac435..921295503 100644 --- a/.github/workflows/release-dev.yml +++ b/.github/workflows/release-dev.yml @@ -647,6 +647,17 @@ jobs: 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] @@ -697,7 +708,7 @@ jobs: # --------------------------------------------------------------------------- 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, build-driver-vm-linux, build-driver-vm-macos, build-deb, build-rpm, smoke-linux-dev-artifacts] + 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, 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: @@ -759,6 +770,13 @@ jobs: 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 @@ -914,6 +932,7 @@ jobs: 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 diff --git a/.github/workflows/release-tag.yml b/.github/workflows/release-tag.yml index fc0f47480..de6a5b6f4 100644 --- a/.github/workflows/release-tag.yml +++ b/.github/workflows/release-tag.yml @@ -683,6 +683,17 @@ jobs: checkout-ref: ${{ inputs.tag || github.ref }} secrets: inherit + build-snap: + name: Build Snap + needs: [compute-versions] + uses: ./.github/workflows/snap-package.yml + with: + checkout-ref: ${{ inputs.tag || github.ref }} + upload-channel: latest/stable + github-environment: latest/stable + secrets: + publish-credentials: ${{ secrets.SNAPCRAFT_STORE_CREDENTIALS }} + build-rpm: name: Build RPM Packages needs: [compute-versions, build-cli-linux, build-gateway-binary-linux] @@ -807,7 +818,7 @@ jobs: # --------------------------------------------------------------------------- release: name: Release - 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, tag-ghcr-release, build-driver-vm-linux, build-driver-vm-macos, build-deb, build-rpm, smoke-linux-release-artifacts] + 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, tag-ghcr-release, build-driver-vm-linux, build-driver-vm-macos, build-deb, build-rpm, build-snap, smoke-linux-release-artifacts] runs-on: linux-amd64-cpu8 timeout-minutes: 10 permissions: @@ -871,6 +882,13 @@ jobs: 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: Capture wheel filenames id: wheel_filenames run: | @@ -966,6 +984,7 @@ jobs: release/openshell-aarch64-apple-darwin.tar.gz release/openshell_*.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 diff --git a/.github/workflows/snap-package.yml b/.github/workflows/snap-package.yml new file mode 100644 index 000000000..633bcc02f --- /dev/null +++ b/.github/workflows/snap-package.yml @@ -0,0 +1,118 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +name: Snap Package + +on: + workflow_call: + inputs: + checkout-ref: + required: true + type: string + upload-channel: + required: true + type: string + description: "Snap Store channel to upload to (e.g., latest/edge, latest/candidate, latest/stable)" + github-environment: + required: true + type: string + description: "GitHub deployment environment for approval gates (e.g., latest/edge, latest/stable)" + + secrets: + publish-credentials: + required: true + description: "Snap Store credentials (SNAPCRAFT_STORE_CREDENTIALS)" + +permissions: + contents: read + +defaults: + run: + shell: bash + +jobs: + build-snap: + name: Build Snap (Linux ${{ matrix.arch }}) + strategy: + matrix: + include: + - arch: amd64 + runner: linux-amd64-cpu8 + - arch: arm64 + runner: linux-arm64-cpu8 + runs-on: ${{ matrix.runner }} + timeout-minutes: 60 + environment: ${{ inputs.github-environment }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + ref: ${{ inputs.checkout-ref }} + fetch-depth: 0 + + - name: Install snapd + run: | + set -euo pipefail + if ! command -v snapd >/dev/null 2>&1; then + sudo apt-get update + sudo apt-get install -y snapd + fi + sudo systemctl enable --now snapd.socket + sudo systemctl start snapd + sudo snap wait system seed.loaded + + - name: Install LXD + run: | + set -euo pipefail + sudo snap install lxd + sudo usermod -aG lxd $USER + sudo lxd init --auto + + - name: Install snapcraft + run: | + set -euo pipefail + sudo snap install snapcraft --classic + + - name: Build snap + run: | + set -euo pipefail + snapcraft pack -v + + - name: Capture snap filename + id: capture + run: | + set -euo pipefail + SNAP_FILE=$(ls -1 *.snap 2>/dev/null | head -1) + if [ -z "$SNAP_FILE" ]; then + echo "ERROR: No .snap file found after snapcraft pack" + exit 1 + fi + echo "snap-file=${SNAP_FILE}" >> $GITHUB_OUTPUT + echo "Built snap: ${SNAP_FILE}" + + - name: Upload snap artifact (${{ matrix.arch }}) + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: snap-linux-${{ matrix.arch }} + path: | + ${{ steps.capture.outputs.snap-file }} + *.comp + retention-days: 5 + + - name: Upload snap to Snap Store + env: + SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.publish-credentials }} + run: | + set -euo pipefail + SNAP_FILE="${{ steps.capture.outputs.snap-file }}" + SNAP_NAME="${SNAP_FILE%.snap}" + SNAP_NAME="${SNAP_NAME%%_*}" + + COMPONENT_ARGS=() + shopt -s nullglob + for comp in "${SNAP_NAME}"+*.comp; do + echo "Adding component: $comp" + COMPONENT_ARGS+=(--component "$comp") + done + + echo "Uploading $SNAP_FILE to ${{ inputs.upload-channel }}" + snapcraft upload --release "${{ inputs.upload-channel }}" "$SNAP_FILE" "${COMPONENT_ARGS[@]}" diff --git a/snapcraft.yaml b/snapcraft.yaml index 6257ca851..f17dd8a58 100644 --- a/snapcraft.yaml +++ b/snapcraft.yaml @@ -12,8 +12,7 @@ description: | LLM inference routing. base: core24 -# TODO: this prevents publishing a snap to latest/stable. -grade: devel +grade: stable confinement: strict license: Apache-2.0 website: https://docs.nvidia.com/openshell/latest/index.html From b3871a0bcbfc22a87a51802cf27b3885fd3f4331 Mon Sep 17 00:00:00 2001 From: Zygmunt Krynicki Date: Wed, 27 May 2026 20:04:06 +0200 Subject: [PATCH 2/5] ci: chmod lxd socket 666 for build, fix docker firewall Signed-off-by: Zygmunt Krynicki --- .github/workflows/snap-package.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/snap-package.yml b/.github/workflows/snap-package.yml index 633bcc02f..3bfa3fec7 100644 --- a/.github/workflows/snap-package.yml +++ b/.github/workflows/snap-package.yml @@ -64,6 +64,8 @@ jobs: run: | set -euo pipefail sudo snap install lxd + sudo iptables -P FORWARD ACCEPT + sudo chmod 666 /var/snap/lxd/common/lxd/unix.socket sudo usermod -aG lxd $USER sudo lxd init --auto From b182a8f6c0f73028fba09f4631d1237f18f722b4 Mon Sep 17 00:00:00 2001 From: Zygmunt Krynicki Date: Wed, 27 May 2026 20:17:46 +0200 Subject: [PATCH 3/5] ci: upload snapcraft failure logs --- .github/workflows/snap-package.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/snap-package.yml b/.github/workflows/snap-package.yml index 3bfa3fec7..390a7d36e 100644 --- a/.github/workflows/snap-package.yml +++ b/.github/workflows/snap-package.yml @@ -79,6 +79,14 @@ jobs: set -euo pipefail snapcraft pack -v + - name: Upload snapcraft logs on failure + if: failure() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: snapcraft-logs + path: "~/.local/state/snapcraft/log/snapcraft-*.log" + retention-days: 7 + - name: Capture snap filename id: capture run: | From 3542c9081e8a5cdd7cef3824a4b2249265895837 Mon Sep 17 00:00:00 2001 From: Zygmunt Krynicki Date: Wed, 27 May 2026 20:20:38 +0200 Subject: [PATCH 4/5] ci: wait for lxd to be ready Signed-off-by: Zygmunt Krynicki --- .github/workflows/snap-package.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/snap-package.yml b/.github/workflows/snap-package.yml index 390a7d36e..a0d55bfc7 100644 --- a/.github/workflows/snap-package.yml +++ b/.github/workflows/snap-package.yml @@ -68,6 +68,7 @@ jobs: sudo chmod 666 /var/snap/lxd/common/lxd/unix.socket sudo usermod -aG lxd $USER sudo lxd init --auto + sudo lxd waitready - name: Install snapcraft run: | From 25f5efab4fbe865b8bad6921a2a0bfafb379b1b6 Mon Sep 17 00:00:00 2001 From: Drew Newberry Date: Wed, 27 May 2026 11:31:08 -0700 Subject: [PATCH 5/5] wip --- .github/workflows/snap-package.yml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/snap-package.yml b/.github/workflows/snap-package.yml index a0d55bfc7..5a05d28d6 100644 --- a/.github/workflows/snap-package.yml +++ b/.github/workflows/snap-package.yml @@ -64,11 +64,12 @@ jobs: run: | set -euo pipefail sudo snap install lxd - sudo iptables -P FORWARD ACCEPT - sudo chmod 666 /var/snap/lxd/common/lxd/unix.socket - sudo usermod -aG lxd $USER - sudo lxd init --auto + sudo usermod -aG lxd "$USER" sudo lxd waitready + sudo lxd init --auto + sudo iptables -P FORWARD ACCEPT + sudo chgrp lxd /var/snap/lxd/common/lxd/unix.socket + sudo chmod 660 /var/snap/lxd/common/lxd/unix.socket - name: Install snapcraft run: | @@ -78,7 +79,10 @@ jobs: - name: Build snap run: | set -euo pipefail - snapcraft pack -v + runtime_dir="/run/user/$(id -u)" + sudo install -d -m 0700 -o "$(id -u)" -g "$(id -g)" "$runtime_dir" + export XDG_RUNTIME_DIR="$runtime_dir" + sg lxd -c "XDG_RUNTIME_DIR=${runtime_dir} snapcraft pack -v" - name: Upload snapcraft logs on failure if: failure()