Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 142 additions & 1 deletion .github/workflows/marketplace-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ on:
description: "Registry base URL override"
required: false
type: string
build_cuda:
description: "Also build CUDA bundle variants on the self-hosted GPU runner"
required: false
type: boolean
default: true
secrets:
MINISIGN_SECRET_KEY:
required: true
Expand All @@ -28,6 +33,9 @@ env:
RUST_BACKTRACE: 1
RUSTC_WRAPPER: sccache
SHERPA_ONNX_VERSION: "1.12.17"
# GPU (CUDA-enabled) sherpa-onnx shared build; vendored into cuda variants so
# the execution-provider-agnostic plugin .so dispatches to the GPU at runtime.
SHERPA_ONNX_GPU_ARCHIVE: "sherpa-onnx-v1.12.17-linux-x64-gpu-shared.tar.bz2"
MINISIGN_DEB_URL: "http://launchpadlibrarian.net/780165111/minisign_0.12-1_amd64.deb"
REGISTRY_BASE_URL: ${{ inputs.registry_base_url || 'https://streamkit.dev/registry' }}

Expand Down Expand Up @@ -210,9 +218,142 @@ jobs:
path: ~/.cache/sccache
key: sccache-marketplace-${{ runner.os }}-${{ hashFiles('plugins/**/Cargo.lock') }}

build-marketplace-cuda:
name: Build Marketplace CUDA Variants
needs: [build-marketplace]
if: ${{ inputs.build_cuda }}
# GPU variants are best-effort: a failure on the (potentially flaky)
# self-hosted runner must never regress CPU registry publishing or per-plugin
# releases. continue-on-error keeps the overall workflow green so downstream
# CPU jobs still run; the failure is still visible on this job.
continue-on-error: true
# Self-hosted NVIDIA (Ada) runner: CUDA toolkit + nvcc must be preinstalled.
# Adjust the labels to match your runner registration if they differ.
runs-on: [self-hosted, linux, x64, gpu]
Comment on lines +221 to +232

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 Release workflow always invokes the CUDA job, which requires the self-hosted GPU runner

build_cuda defaults to true (.github/workflows/marketplace-build.yml:14-18) and marketplace-release.yml:18 calls the reusable workflow without passing build_cuda, so build-marketplace-cuda (which targets runs-on: [self-hosted, linux, x64, gpu]) always runs on release. continue-on-error: true makes the job's conclusion success even if its steps fail, and publish-registry/create-releases use always()/job-success semantics, so a failing GPU build degrades gracefully. However, if no runner with those labels is registered, the job stays queued indefinitely rather than failing — and downstream jobs (needs: [..., build-marketplace-cuda]) wait for it to complete, stalling the entire release. This is acceptable given the workflow is manual (workflow_dispatch) and the only caller, but it does hard-couple releases to GPU runner availability.

Open in Devin Review (Staging)

Was this helpful? React with 👍 or 👎 to provide feedback.

Debug

Playground

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, and by design for now: the workflow is workflow_dispatch-only with a single caller, so coupling releases to GPU-runner availability is acceptable. If no runner with the [self-hosted, linux, x64, gpu] labels is registered the job stays queued rather than failing, which would stall downstream jobs — the mitigation is operational (ensure the runner is registered, or pass build_cuda=false to skip it). If we later want releases to be fully decoupled from GPU availability we can add a timeout or split the CUDA build into its own non-blocking workflow; tracking that as a follow-up rather than expanding this PR.

permissions:
contents: read
steps:
- uses: actions/checkout@v5

- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y cmake pkg-config libclang-dev libfontconfig1-dev wget libopenblas-dev zstd patchelf python3-yaml python3-tomli libfdk-aac-dev \
build-essential g++ libharfbuzz-dev libfreetype6-dev \
libegl1-mesa-dev libgl1-mesa-dev libgbm-dev libdrm-dev libunwind-dev \
libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \
gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad \
libdbus-1-dev libpulse-dev libxkbcommon-dev nasm

- name: Install minisign
run: |
deb_path="/tmp/minisign.deb"
wget -O "${deb_path}" "${MINISIGN_DEB_URL}"
if ! sudo dpkg -i "${deb_path}"; then
echo "dpkg failed, retrying with apt-get"
sudo env NEEDRESTART_MODE=a apt-get install -y "${deb_path}" || true
fi
command -v minisign >/dev/null

- name: Install CUDA-enabled sherpa-onnx
run: |
cd /tmp
wget "https://github.com/k2-fsa/sherpa-onnx/releases/download/v${SHERPA_ONNX_VERSION}/${SHERPA_ONNX_GPU_ARCHIVE}"
tar xf "${SHERPA_ONNX_GPU_ARCHIVE}"
dir="${SHERPA_ONNX_GPU_ARCHIVE%.tar.bz2}"
sudo cp -r "${dir}/lib/." /usr/local/lib/
sudo cp -r "${dir}/include/." /usr/local/include/
sudo ldconfig

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.95.0"

- name: Restore sccache cache
uses: actions/cache/restore@v4
with:
path: ~/.cache/sccache
key: sccache-marketplace-cuda-${{ runner.os }}-${{ hashFiles('plugins/**/Cargo.lock') }}
restore-keys: |
sccache-marketplace-cuda-${{ runner.os }}-

- uses: mozilla-actions/sccache-action@v0.0.9

- name: Build CUDA plugins
run: |
bash scripts/marketplace/build_official_plugins_cuda.sh
Comment thread
staging-devin-ai-integration[bot] marked this conversation as resolved.

- name: Download CPU registry
uses: actions/download-artifact@v4
with:
name: marketplace-registry
path: dist/registry-cpu

- name: Write minisign key
env:
MINISIGN_SECRET_KEY: ${{ secrets.MINISIGN_SECRET_KEY }}
run: |
if [ -z "${MINISIGN_SECRET_KEY}" ]; then
echo "MINISIGN_SECRET_KEY is not set"
exit 1
fi
echo "${MINISIGN_SECRET_KEY}" > /tmp/streamkit.key
chmod 600 /tmp/streamkit.key

- name: Build CUDA registry variants
run: |
python3 scripts/marketplace/build_registry.py \
--plugins marketplace/official-plugins.json \
--existing-registry dist/registry-cpu \
--accelerator cuda \
--bundle-url-template "https://github.com/${{ github.repository }}/releases/download/plugin-{plugin_id}-v{version}" \
--registry-base-url "${REGISTRY_BASE_URL}" \
--bundles-out dist/bundles-cuda \
--registry-out dist/registry \
--signing-key /tmp/streamkit.key \
--new-plugins-out dist/new-plugins-cuda.json
Comment thread
staging-devin-ai-integration[bot] marked this conversation as resolved.

- name: Verify CUDA bundle portability
run: |
python3 scripts/marketplace/verify_bundles.py \
--plugins marketplace/official-plugins.json \
--bundles dist/bundles-cuda \
--accelerator cuda

- name: Upload CUDA bundles
uses: actions/upload-artifact@v4
with:
name: marketplace-bundles-cuda
path: dist/bundles-cuda/*.tar.zst
if-no-files-found: ignore

- name: Upload new CUDA plugins manifest
uses: actions/upload-artifact@v4
with:
name: new-plugins-cuda
path: dist/new-plugins-cuda.json

- name: Upload merged registry metadata
uses: actions/upload-artifact@v4
with:
name: marketplace-registry
overwrite: true
path: dist/registry/**

- name: Save sccache cache
if: always()
uses: actions/cache/save@v4
with:
path: ~/.cache/sccache
key: sccache-marketplace-cuda-${{ runner.os }}-${{ hashFiles('plugins/**/Cargo.lock') }}

publish-registry:
name: Publish Registry (PR)
needs: [build-marketplace]
needs: [build-marketplace, build-marketplace-cuda]
Comment thread
staging-devin-ai-integration[bot] marked this conversation as resolved.
# A successful CPU build is sufficient to publish; the CUDA job is optional
# and, when it runs, supersedes the artifact with a merged registry.
if: ${{ always() && needs.build-marketplace.result == 'success' }}
runs-on: ubuntu-22.04
permissions:
contents: write
Expand Down
37 changes: 37 additions & 0 deletions .github/workflows/marketplace-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,20 @@ jobs:
name: new-plugins
path: artifacts

- name: Download CUDA bundles
uses: actions/download-artifact@v4
continue-on-error: true
with:
name: marketplace-bundles-cuda
path: artifacts/bundles-cuda

- name: Download new CUDA plugins manifest
uses: actions/download-artifact@v4
continue-on-error: true
with:
name: new-plugins-cuda
path: artifacts/cuda
Comment thread
staging-devin-ai-integration[bot] marked this conversation as resolved.

- name: Load plugin metadata
id: plugins
run: |
Expand Down Expand Up @@ -108,3 +122,26 @@ jobs:
if result.returncode != 0:
print(f'::warning::Skipping {tag}: release may already exist')
"

- name: Attach CUDA bundles to releases
if: hashFiles('artifacts/cuda/new-plugins-cuda.json') != ''
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
python3 -c "
import json, os, pathlib, subprocess

data = json.load(open('artifacts/cuda/new-plugins-cuda.json'))
for plugin in data.get('plugins', []):
pid = plugin['id']
version = plugin['version']
tag = f'plugin-{pid}-v{version}'
bundle = f'artifacts/bundles-cuda/{pid}-{version}-cuda-bundle.tar.zst'
if not pathlib.Path(bundle).exists():
print(f'::warning::Missing CUDA bundle for {tag}: {bundle}')
continue
print(f'Uploading CUDA bundle to {tag}')
result = subprocess.run(['gh', 'release', 'upload', tag, bundle, '--clobber'])
if result.returncode != 0:
print(f'::warning::Failed to upload CUDA bundle for {tag}')
"
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading