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
184 changes: 184 additions & 0 deletions .github/workflows/marketplace-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# SPDX-FileCopyrightText: © 2025 StreamKit Contributors
#
# SPDX-License-Identifier: MPL-2.0

name: Marketplace Build (Reusable)

on:
workflow_call:
inputs:
version:
description: "Marketplace version (e.g., 1.2.3)"
required: true
type: string
release_tag:
description: "Release tag for bundle URLs and registry PR"
required: true
type: string
registry_base_url:
description: "Registry base URL override"
required: false
type: string

env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
SHERPA_ONNX_VERSION: "1.12.17"
MARKETPLACE_VERSION: ${{ inputs.version }}
RELEASE_TAG: ${{ inputs.release_tag }}
REGISTRY_BASE_URL: ${{ inputs.registry_base_url || format('https://{0}.github.io/streamkit/registry', github.repository_owner) }}

jobs:
build-marketplace:
name: Build Marketplace Bundles
runs-on: ubuntu-22.04
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 wget libopenblas-dev zstd minisign patchelf python3-yaml

- name: Install sherpa-onnx
run: |
cd /tmp
wget https://github.com/k2-fsa/sherpa-onnx/releases/download/v${SHERPA_ONNX_VERSION}/sherpa-onnx-v${SHERPA_ONNX_VERSION}-linux-x64-shared.tar.bz2
tar xf sherpa-onnx-v${SHERPA_ONNX_VERSION}-linux-x64-shared.tar.bz2
sudo cp -r sherpa-onnx-v${SHERPA_ONNX_VERSION}-linux-x64-shared/lib/* /usr/local/lib/
sudo cp -r sherpa-onnx-v${SHERPA_ONNX_VERSION}-linux-x64-shared/include/* /usr/local/include/
sudo ldconfig

- name: Build CTranslate2
run: |
git clone --depth 1 --recurse-submodules --branch v4.5.0 https://github.com/OpenNMT/CTranslate2.git
cd CTranslate2
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release \
-DWITH_CUDA=OFF \
-DWITH_MKL=OFF \
-DWITH_OPENBLAS=ON \
-DOPENMP_RUNTIME=COMP \
-DBUILD_CLI=OFF \
..
make -j$(nproc)
sudo make install
sudo ldconfig

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

- name: Verify official plugins metadata is current
run: |
python3 scripts/marketplace/generate_official_plugins.py
git diff --exit-code -- marketplace/official-plugins.json

- name: Collect marketplace workspaces
id: marketplace-workspaces
run: |
python3 - <<'PY'
import json
import os
import pathlib
import sys

plugins_path = pathlib.Path("marketplace/official-plugins.json")
metadata = json.loads(plugins_path.read_text())
plugin_ids = [plugin["id"] for plugin in metadata.get("plugins", [])]
if not plugin_ids:
print("No plugins found in marketplace/official-plugins.json", file=sys.stderr)
sys.exit(1)

out_path = os.environ["GITHUB_OUTPUT"]
with open(out_path, "a", encoding="utf-8") as handle:
handle.write("workspaces<<EOF\n")
for plugin_id in plugin_ids:
handle.write(f"plugins/native/{plugin_id}\n")
handle.write("EOF\n")
PY

- uses: Swatinem/rust-cache@v2
with:
workspaces: ${{ steps.marketplace-workspaces.outputs.workspaces }}
cache-on-failure: true

- name: Build official plugins
run: |
bash scripts/marketplace/build_official_plugins.sh

- 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 registry artifacts
run: |
VERSION="${MARKETPLACE_VERSION#v}"
python3 scripts/marketplace/build_registry.py \
--plugins marketplace/official-plugins.json \
--version "${VERSION}" \
--bundle-base-url "https://github.com/${{ github.repository }}/releases/download/${RELEASE_TAG}" \
--registry-base-url "${REGISTRY_BASE_URL}" \
--bundles-out dist/bundles \
--registry-out dist/registry \
--signing-key /tmp/streamkit.key

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

- name: Upload marketplace bundles
uses: actions/upload-artifact@v4
with:
name: marketplace-bundles
path: dist/bundles/*.tar.zst

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

publish-registry:
name: Publish Registry (PR)
needs: [build-marketplace]
runs-on: ubuntu-22.04
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v5

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

- name: Update docs registry folder
run: |
rm -rf docs/public/registry
mkdir -p docs/public/registry
cp -R dist/registry/* docs/public/registry/

- name: Create pull request
uses: peter-evans/create-pull-request@v6
with:
branch: "registry/${{ env.RELEASE_TAG }}"
title: "chore(registry): publish marketplace registry for ${{ env.RELEASE_TAG }}"
commit-message: "chore(registry): publish marketplace registry for ${{ env.RELEASE_TAG }}"
body: |
Automated registry metadata update for `${{ env.RELEASE_TAG }}`.
base: main
59 changes: 59 additions & 0 deletions .github/workflows/marketplace-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# SPDX-FileCopyrightText: © 2025 StreamKit Contributors
#
# SPDX-License-Identifier: MPL-2.0

name: Marketplace Release

on:
workflow_dispatch:
inputs:
version:
description: "Marketplace version (e.g., 1.2.3)"
required: true
release_tag:
description: "Release tag (defaults to marketplace-v<version>)"
required: false
prerelease:
description: "Mark release as prerelease"
required: false
type: boolean
default: false

env:
RELEASE_TAG: ${{ inputs.release_tag || format('marketplace-v{0}', inputs.version) }}

jobs:
marketplace:
uses: ./.github/workflows/marketplace-build.yml
with:
version: ${{ inputs.version }}
release_tag: ${{ inputs.release_tag || format('marketplace-v{0}', inputs.version) }}

create-release:
name: Create Marketplace Release
needs: [marketplace]
runs-on: ubuntu-22.04
permissions:
contents: write
steps:
- uses: actions/checkout@v5

- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts

- name: Create Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ env.RELEASE_TAG }}
target_commitish: ${{ github.sha }}
name: "Marketplace ${{ inputs.version }}"
files: |
artifacts/**/marketplace-bundles/*.tar.zst
body: |
Marketplace bundles for version `${{ inputs.version }}`.
draft: false
prerelease: ${{ inputs.prerelease }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
13 changes: 11 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,15 @@ jobs:
streamkit-${{ github.ref_name }}-linux-x64.tar.gz
streamkit-${{ github.ref_name }}-linux-x64.tar.gz.sha256

marketplace:
uses: ./.github/workflows/marketplace-build.yml
with:
version: ${{ github.ref_name }}
release_tag: ${{ github.ref_name }}

create-release:
name: Create GitHub Release
needs: [build-linux-x64]
needs: [build-linux-x64, marketplace]
runs-on: ubuntu-22.04
permissions:
contents: write
Expand Down Expand Up @@ -120,7 +126,10 @@ jobs:
- name: Create Release
uses: softprops/action-gh-release@v2
with:
files: artifacts/**/*
files: |
artifacts/**/streamkit-*.tar.gz
artifacts/**/streamkit-*.tar.gz.sha256
artifacts/**/marketplace-bundles/*.tar.zst
body_path: changelog.md
draft: false
prerelease: ${{ contains(github.ref_name, '-rc') || contains(github.ref_name, '-beta') || contains(github.ref_name, '-alpha') }}
Expand Down
26 changes: 26 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,29 @@ Agent-assisted contributions are welcome, but should be **supervised** and **rev
- Official images are built from `Dockerfile` (CPU) and `Dockerfile.gpu` (GPU-tagged) via `.github/workflows/docker.yml`.
- `/healthz` is the lightweight health endpoint (also `/health`).
- Official images do not bundle ML models or plugins; they are expected to be mounted at runtime.

## Adding an official plugin

When making a plugin official and downloadable from the registry, update all of
the following:

- Plugin source under `plugins/native/<id>/` (crate metadata + README).
- Plugin metadata in `plugins/native/<id>/marketplace.yml` (id, entrypoint,
artifact path, models, licenses, homepage/repo).
- Generate `marketplace/official-plugins.json` with
`scripts/marketplace/generate_official_plugins.py` and commit the result.
- Build list in `scripts/marketplace/build_official_plugins.sh`.
- Build prerequisites in `.github/workflows/release.yml` if new system deps are
required to compile or package the plugin.
- Bundle/registry smoke check: run `scripts/marketplace/build_registry.py` and
`scripts/marketplace/verify_bundles.py` locally.
- Portability table in `marketplace/PORTABILITY_REVIEW.md` (NEEDED deps,
RUNPATH/RPATH, recommendation).
- Docs: add/update the plugin page under
`docs/src/content/docs/reference/plugins/` and list it in
`docs/src/content/docs/reference/plugins/index.md` if applicable.
- Runtime shared libs: if the plugin needs bundled `.so` files, ensure the
bundle includes them and the entrypoint RUNPATH uses `$ORIGIN`, and update the
portability gate in `scripts/marketplace/verify_bundles.py` as needed.
- **Human review required** before bundling any new third-party shared libraries
(licensing, security, size, and distro compatibility).
61 changes: 61 additions & 0 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,67 @@ This repo ships:
- Client CLI: `skit-cli` (crate: `streamkit-client`)
- Optional crates for other developers (crates.io)

## Marketplace registry + bundles

This release flow publishes signed registry metadata to GitHub Pages and bundle
artifacts to GitHub Releases.

### Setup (one-time)

```bash
# Generate an unencrypted minisign keypair for registry signing.
# Keep the secret key safe and commit the public key.
minisign -G -W -s /tmp/streamkit.key -p docs/public/registry/streamkit.pub
```

Set the GitHub Actions secret `MINISIGN_SECRET_KEY` to the contents of the
secret key file:

```bash
cat /tmp/streamkit.key
```

If `docs/public/registry/streamkit.pub` contains a placeholder, overwrite it
with the generated public key before tagging.

### System dependencies (v1)

- When present, `pocket-tts` requires OpenSSL 3 (`libssl.so.3`, `libcrypto.so.3`).
- Ubuntu: `libssl3`
- Native plugins expect system `libstdc++` and `libgcc_s`.

### Trigger a release

```bash
git tag vX.Y.Z
git push origin vX.Y.Z
```

### Marketplace-only release (decoupled)

Use the GitHub Actions workflow `Marketplace Release` with:

- `version`: marketplace version (e.g., `1.2.3`)
- `release_tag` (optional): defaults to `marketplace-v<version>`

This workflow publishes bundle assets to the GitHub Release for `release_tag`
and opens the registry PR without rebuilding the server/UI. Both tag releases
and marketplace-only releases share the same reusable marketplace workflow
(`.github/workflows/marketplace-build.yml`).

### Verify outputs

- GitHub Release includes `*-bundle.tar.zst` assets.
- Registry metadata is published after merging the registry PR:
`https://<org>.github.io/streamkit/registry/index.json`.
- Verify a manifest signature:

```bash
minisign -V -P "$(tail -n 1 docs/public/registry/streamkit.pub)" \
-m manifest.json \
-x manifest.minisig
```

## crates.io publishing

### Intended publish set
Expand Down
2 changes: 2 additions & 0 deletions docs/public/registry/streamkit.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
untrusted comment: minisign public key 81C485A94492F33F
RWQ/85JEqYXEgX+2kl7Rwd8AcpVjYciSLzvLggzivbGyIrDPjfmcqjYP
Loading
Loading