Skip to content

Commit 602ec36

Browse files
committed
refactor(ci): extract single-architecture Snap build workflow
Signed-off-by: Evan Lezar <elezar@nvidia.com>
1 parent e9c54e7 commit 602ec36

3 files changed

Lines changed: 246 additions & 142 deletions

File tree

‎.github/workflows/build-snap.yml‎

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
name: Build Snap
5+
6+
on:
7+
workflow_call:
8+
inputs:
9+
checkout-ref:
10+
required: true
11+
type: string
12+
artifact-layout:
13+
description: "Layout of the prebuilt binary artifacts (tarball or raw)"
14+
required: false
15+
type: string
16+
default: tarball
17+
arch:
18+
description: "Snap package architecture"
19+
required: true
20+
type: string
21+
runner:
22+
description: "GitHub Actions runner label"
23+
required: true
24+
type: string
25+
cli-artifact-name:
26+
required: false
27+
type: string
28+
default: ""
29+
cli-artifact-prefix:
30+
required: false
31+
type: string
32+
default: ""
33+
gateway-artifact-name:
34+
required: false
35+
type: string
36+
default: ""
37+
gateway-artifact-prefix:
38+
required: false
39+
type: string
40+
default: ""
41+
supervisor-artifact-name:
42+
required: false
43+
type: string
44+
default: ""
45+
supervisor-artifact-prefix:
46+
required: false
47+
type: string
48+
default: ""
49+
upload-channel:
50+
required: false
51+
type: string
52+
default: ""
53+
description: "Snap Store channel to upload to"
54+
github-environment:
55+
required: false
56+
type: string
57+
default: ""
58+
description: "GitHub deployment environment for approval gates"
59+
publish:
60+
required: false
61+
type: boolean
62+
default: false
63+
description: "Whether to upload the built Snap to the Snap Store"
64+
65+
secrets:
66+
publish-credentials:
67+
required: false
68+
description: "Snap Store credentials (SNAPCRAFT_STORE_CREDENTIALS)"
69+
70+
permissions:
71+
contents: read
72+
73+
defaults:
74+
run:
75+
shell: bash
76+
77+
jobs:
78+
build-snap:
79+
name: Build Snap (Linux ${{ inputs.arch }})
80+
runs-on: ${{ inputs.runner }}
81+
timeout-minutes: 60
82+
environment: ${{ inputs.publish && inputs.github-environment || '' }}
83+
steps:
84+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
85+
with:
86+
ref: ${{ inputs.checkout-ref }}
87+
fetch-depth: 0
88+
89+
- name: Install snapd
90+
run: |
91+
set -euo pipefail
92+
if ! command -v snapd >/dev/null 2>&1; then
93+
sudo apt-get update
94+
sudo apt-get install -y snapd
95+
fi
96+
sudo systemctl enable --now snapd.socket
97+
sudo systemctl start snapd
98+
sudo snap wait system seed.loaded
99+
100+
- name: Install LXD
101+
run: |
102+
set -euo pipefail
103+
sudo snap install lxd
104+
sudo usermod -aG lxd "$USER"
105+
sudo lxd waitready
106+
sudo lxd init --auto
107+
sudo iptables -P FORWARD ACCEPT
108+
sudo chgrp lxd /var/snap/lxd/common/lxd/unix.socket
109+
sudo chmod 660 /var/snap/lxd/common/lxd/unix.socket
110+
111+
- name: Install snapcraft
112+
run: sudo snap install snapcraft --classic
113+
114+
- name: Download prebuilt CLI binary
115+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
116+
with:
117+
name: ${{ inputs.cli-artifact-name || (inputs.artifact-layout == 'raw' && format('{0}-linux-{1}', inputs.cli-artifact-prefix, inputs.arch)) || format('cli-linux-{0}', inputs.arch) }}
118+
path: prebuilt/cli
119+
120+
- name: Download prebuilt gateway binary
121+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
122+
with:
123+
name: ${{ inputs.gateway-artifact-name || (inputs.artifact-layout == 'raw' && format('{0}-linux-{1}', inputs.gateway-artifact-prefix, inputs.arch)) || format('gateway-binary-linux-{0}', inputs.arch) }}
124+
path: prebuilt/gateway
125+
126+
- name: Download prebuilt sandbox binary
127+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
128+
with:
129+
name: ${{ inputs.supervisor-artifact-name || (inputs.artifact-layout == 'raw' && format('{0}-linux-{1}', inputs.supervisor-artifact-prefix, inputs.arch)) || format('supervisor-binary-linux-{0}', inputs.arch) }}
130+
path: prebuilt/sandbox
131+
132+
- name: Prepare snap build directory
133+
run: |
134+
set -euo pipefail
135+
case "${{ inputs.artifact-layout }}" in
136+
tarball)
137+
for directory in cli gateway sandbox; do
138+
for tarball in "prebuilt/$directory"/*.tar.gz; do
139+
test -f "$tarball" || continue
140+
tar -xzf "$tarball" -C "prebuilt/$directory"
141+
done
142+
done
143+
;;
144+
raw) ;;
145+
*)
146+
echo "unsupported artifact layout: ${{ inputs.artifact-layout }}" >&2
147+
exit 1
148+
;;
149+
esac
150+
151+
find_binary() {
152+
find "$1" -type f -name "$2" -print -quit
153+
}
154+
cli="$(find_binary prebuilt/cli openshell)"
155+
gateway="$(find_binary prebuilt/gateway openshell-gateway)"
156+
sandbox="$(find_binary prebuilt/sandbox openshell-sandbox)"
157+
test -n "$cli" && test -n "$gateway" && test -n "$sandbox"
158+
159+
mkdir -p snap/prebuilt/meta/gui
160+
install -m 0755 "$cli" snap/prebuilt/openshell
161+
install -m 0755 "$gateway" snap/prebuilt/openshell-gateway
162+
install -m 0755 "$sandbox" snap/prebuilt/openshell-sandbox
163+
install -m 0755 tasks/scripts/snap-gateway-wrapper.sh snap/prebuilt/openshell-gateway-wrapper
164+
cp LICENSE README.md snap/prebuilt/
165+
cp snap/local/term.desktop snap/prebuilt/meta/gui/term.desktop
166+
cp snap/local/icon.png snap/prebuilt/meta/gui/icon.png
167+
python3 tasks/scripts/release.py get-version --snap > snap/prebuilt/version
168+
169+
- name: Build snap
170+
run: |
171+
set -euo pipefail
172+
runtime_dir="/run/user/$(id -u)"
173+
sudo install -d -m 0700 -o "$(id -u)" -g "$(id -g)" "$runtime_dir"
174+
export XDG_RUNTIME_DIR="$runtime_dir"
175+
sg lxd -c "XDG_RUNTIME_DIR=${runtime_dir} snapcraft pack -v"
176+
177+
- name: Upload snapcraft logs on failure
178+
if: failure()
179+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
180+
with:
181+
name: snapcraft-logs-${{ inputs.arch }}
182+
path: "~/.local/state/snapcraft/log/snapcraft-*.log"
183+
retention-days: 7
184+
185+
- name: Capture Snap filename
186+
id: capture
187+
run: |
188+
set -euo pipefail
189+
snap_file=$(find . -maxdepth 1 -type f -name '*.snap' -printf '%f\n' | head -1)
190+
if [ -z "$snap_file" ]; then
191+
echo "::error::No .snap file found after snapcraft pack"
192+
exit 1
193+
fi
194+
echo "snap-file=$snap_file" >> "$GITHUB_OUTPUT"
195+
echo "Built Snap: $snap_file"
196+
197+
- name: Upload snap artifact (${{ inputs.arch }})
198+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
199+
with:
200+
name: snap-linux-${{ inputs.arch }}
201+
path: |
202+
${{ steps.capture.outputs.snap-file }}
203+
*.comp
204+
retention-days: 5
205+
206+
- name: Upload Snap to Snap Store
207+
if: inputs.publish
208+
env:
209+
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.publish-credentials }}
210+
INPUTS_UPLOAD_CHANNEL: ${{ inputs.upload-channel }}
211+
run: |
212+
set -euo pipefail
213+
snap_file="${{ steps.capture.outputs.snap-file }}"
214+
snap_name="${snap_file%.snap}"
215+
snap_name="${snap_name%%_*}"
216+
217+
component_args=()
218+
shopt -s nullglob
219+
for component in "${snap_name}"+*.comp; do
220+
echo "Adding component: $component"
221+
component_args+=(--component "$component")
222+
done
223+
224+
echo "Uploading $snap_file to ${INPUTS_UPLOAD_CHANNEL}"
225+
snapcraft upload --release "${INPUTS_UPLOAD_CHANNEL}" "$snap_file" "${component_args[@]}"

‎.github/workflows/release-dev.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ jobs:
257257
checkout-ref: ${{ github.sha }}
258258
upload-channel: latest/edge
259259
github-environment: latest/edge
260+
publish: true
260261
secrets:
261262
publish-credentials: ${{ secrets.SNAPCRAFT_STORE_CREDENTIALS }}
262263

0 commit comments

Comments
 (0)