8f10353f0c
CI / lint (push) Has been cancelled
CI / js-syntax (push) Successful in 10m24s
CI / deps-audit (push) Has been cancelled
CI / test (push) Failing after 24m55s
CI / sast-bandit (push) Failing after 11m13s
CI / trivy (push) Failing after 9m32s
Docker Publish / build-and-push (push) Failing after 34m3s
148 lines
5.8 KiB
YAML
148 lines
5.8 KiB
YAML
name: Linux Release
|
|
|
|
on:
|
|
release:
|
|
types: [published]
|
|
# Manual test build: builds and scans both variants on the self-hosted runner
|
|
# but does NOT upload (no release to attach to). Lets you validate the runner
|
|
# toolchain and the CUDA build without cutting a release tag.
|
|
workflow_dispatch:
|
|
inputs:
|
|
version:
|
|
description: "Version for the test build (must be valid PEP 440, e.g. 0.0.0)"
|
|
required: false
|
|
default: "0.0.0"
|
|
|
|
permissions: {}
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
build-and-upload:
|
|
# Runner must be linux/x64 with rustup, Node.js, Docker, and sudo apt access.
|
|
runs-on: [self-hosted, linux, x64]
|
|
timeout-minutes: 90
|
|
permissions:
|
|
contents: write
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
steps:
|
|
- name: clean workspace
|
|
run: rm -rf .build dist
|
|
|
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
|
|
- name: install build dependencies
|
|
env:
|
|
DEBIAN_FRONTEND: noninteractive
|
|
run: |
|
|
# Tauri v2 build deps + tooling. webkit2gtk-4.1 matches the tauri = "2"
|
|
# crate; ffmpeg is a runtime dependency, not bundled.
|
|
#
|
|
# The self-hosted runner does NOT have passwordless sudo, so a bare
|
|
# `sudo apt-get` hangs forever at the password prompt. These packages are
|
|
# already installed on the persistent runner, so check first (dpkg needs
|
|
# no sudo) and skip apt entirely when everything is present. Only if a
|
|
# package is genuinely missing do we touch apt, via `sudo -n` (fails fast
|
|
# instead of prompting) so a release never hangs on sudo again.
|
|
PKGS="build-essential curl file wget libssl-dev libxdo-dev \
|
|
libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev"
|
|
missing=""
|
|
for p in $PKGS; do
|
|
dpkg -s "$p" >/dev/null 2>&1 || missing="$missing $p"
|
|
done
|
|
if [ -z "$missing" ]; then
|
|
echo "All build dependencies already installed; skipping apt."
|
|
exit 0
|
|
fi
|
|
echo "Missing packages:$missing"
|
|
if ! sudo -n true 2>/dev/null; then
|
|
echo "ERROR: build deps missing and passwordless sudo is not available." >&2
|
|
echo "Install on the runner: sudo apt-get install -y$missing" >&2
|
|
exit 1
|
|
fi
|
|
sudo -n apt-get update -o DPkg::Lock::Timeout=120
|
|
sudo -n apt-get install -y --no-install-recommends -o DPkg::Lock::Timeout=120 $missing
|
|
|
|
- name: install uv
|
|
run: |
|
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
|
|
|
- name: install rust toolchain
|
|
run: rustup default stable
|
|
|
|
- name: write version files
|
|
env:
|
|
DISPATCH_VERSION: ${{ inputs.version }}
|
|
# github.ref_name (evaluated by Actions) instead of $GITHUB_REF_NAME,
|
|
# which is only injected by runner >= 2.290 — empty on older
|
|
# self-hosted runners.
|
|
REF_NAME: ${{ github.ref_name }}
|
|
run: |
|
|
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
VERSION="${DISPATCH_VERSION#v}"
|
|
else
|
|
VERSION="${REF_NAME#v}"
|
|
fi
|
|
if [ -z "$VERSION" ]; then
|
|
echo "Could not determine a version" >&2
|
|
exit 1
|
|
fi
|
|
printf '{ "version": "%s" }\n' "$VERSION" > static/version.json
|
|
sed -i "s/^version = \".*\"/version = \"$VERSION\"/" desktop/src-tauri/Cargo.toml
|
|
sed -i "s/\"version\": \"[^\"]*\"/\"version\": \"$VERSION\"/" desktop/src-tauri/tauri.conf.json
|
|
sed -i "s/^version = \".*\"/version = \"$VERSION\"/" pyproject.toml
|
|
sed -i "s/\"version\": \"[^\"]*\"/\"version\": \"$VERSION\"/" desktop/package.json
|
|
echo "VERSION=$VERSION" >> "$GITHUB_ENV"
|
|
echo "Wrote version $VERSION to all version files"
|
|
|
|
- name: build Linux CPU
|
|
run: |
|
|
PACKAGE_NAME=StemDeck-Linux-x64 \
|
|
PACKAGE_VERSION="$VERSION" \
|
|
bash scripts/linux/make-portable.sh
|
|
# Drop the uncompressed stage but keep the tarball; frees disk for the
|
|
# larger NVIDIA build. The Tauri binary under target/ is preserved.
|
|
rm -rf dist/StemDeck-Linux-x64
|
|
|
|
- name: build Linux NVIDIA
|
|
run: |
|
|
# CPU_ONLY=0 keeps the CUDA torch wheel; SKIP_TAURI_BUILD=1 reuses the
|
|
# binary built in the CPU step (identical for both variants).
|
|
PACKAGE_NAME=StemDeck-Linux-x64.NVIDIA \
|
|
PACKAGE_VERSION="$VERSION" \
|
|
CPU_ONLY=0 \
|
|
SKIP_TAURI_BUILD=1 \
|
|
bash scripts/linux/make-portable.sh
|
|
rm -rf dist/StemDeck-Linux-x64.NVIDIA
|
|
|
|
- name: scan artifacts
|
|
run: |
|
|
echo "Artifacts staged in: $PWD/dist"
|
|
ls -lh dist
|
|
echo "SHA256 checksums:"
|
|
( cd dist && sha256sum *.tar.gz )
|
|
|
|
echo "Pulling latest ClamAV scanner image..."
|
|
docker pull clamav/clamav:latest
|
|
|
|
echo "Running ClamAV scan over dist/..."
|
|
docker run --rm -v "$PWD/dist:/scan:ro" clamav/clamav:latest \
|
|
clamscan --recursive --infected --bell /scan
|
|
echo "ClamAV scan completed successfully. No infected files reported."
|
|
|
|
- name: upload artifacts
|
|
# Only attach to a real release; a manual test build has nothing to upload to.
|
|
if: github.event_name == 'release'
|
|
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1
|
|
with:
|
|
files: |
|
|
dist/StemDeck-Linux-x64.tar.gz
|
|
dist/StemDeck-Linux-x64.tar.gz.sha256
|
|
dist/StemDeck-Linux-x64.NVIDIA.tar.gz
|
|
dist/StemDeck-Linux-x64.NVIDIA.tar.gz.sha256
|