Skip to content

Commit 985da40

Browse files
authored
chore(release): add marketplace bundles, portability gate, docs (#36)
* chore(release): add marketplace bundles, portability gate, and docs * chore: update AGENTS.md * chore(ci): reuse marketplace workflow and document it * chore(ci): review plugins metadata * chore: avoid hardcoded plugin names
1 parent 0726093 commit 985da40

File tree

20 files changed

+1419
-2
lines changed

20 files changed

+1419
-2
lines changed
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# SPDX-FileCopyrightText: © 2025 StreamKit Contributors
2+
#
3+
# SPDX-License-Identifier: MPL-2.0
4+
5+
name: Marketplace Build (Reusable)
6+
7+
on:
8+
workflow_call:
9+
inputs:
10+
version:
11+
description: "Marketplace version (e.g., 1.2.3)"
12+
required: true
13+
type: string
14+
release_tag:
15+
description: "Release tag for bundle URLs and registry PR"
16+
required: true
17+
type: string
18+
registry_base_url:
19+
description: "Registry base URL override"
20+
required: false
21+
type: string
22+
23+
env:
24+
CARGO_TERM_COLOR: always
25+
RUST_BACKTRACE: 1
26+
SHERPA_ONNX_VERSION: "1.12.17"
27+
MARKETPLACE_VERSION: ${{ inputs.version }}
28+
RELEASE_TAG: ${{ inputs.release_tag }}
29+
REGISTRY_BASE_URL: ${{ inputs.registry_base_url || format('https://{0}.github.io/streamkit/registry', github.repository_owner) }}
30+
31+
jobs:
32+
build-marketplace:
33+
name: Build Marketplace Bundles
34+
runs-on: ubuntu-22.04
35+
permissions:
36+
contents: read
37+
steps:
38+
- uses: actions/checkout@v5
39+
40+
- name: Install system dependencies
41+
run: |
42+
sudo apt-get update
43+
sudo apt-get install -y cmake pkg-config libclang-dev wget libopenblas-dev zstd minisign patchelf python3-yaml
44+
45+
- name: Install sherpa-onnx
46+
run: |
47+
cd /tmp
48+
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
49+
tar xf sherpa-onnx-v${SHERPA_ONNX_VERSION}-linux-x64-shared.tar.bz2
50+
sudo cp -r sherpa-onnx-v${SHERPA_ONNX_VERSION}-linux-x64-shared/lib/* /usr/local/lib/
51+
sudo cp -r sherpa-onnx-v${SHERPA_ONNX_VERSION}-linux-x64-shared/include/* /usr/local/include/
52+
sudo ldconfig
53+
54+
- name: Build CTranslate2
55+
run: |
56+
git clone --depth 1 --recurse-submodules --branch v4.5.0 https://github.com/OpenNMT/CTranslate2.git
57+
cd CTranslate2
58+
mkdir build && cd build
59+
cmake -DCMAKE_BUILD_TYPE=Release \
60+
-DWITH_CUDA=OFF \
61+
-DWITH_MKL=OFF \
62+
-DWITH_OPENBLAS=ON \
63+
-DOPENMP_RUNTIME=COMP \
64+
-DBUILD_CLI=OFF \
65+
..
66+
make -j$(nproc)
67+
sudo make install
68+
sudo ldconfig
69+
70+
- name: Install Rust toolchain
71+
uses: dtolnay/rust-toolchain@master
72+
with:
73+
toolchain: "1.92.0"
74+
75+
- name: Verify official plugins metadata is current
76+
run: |
77+
python3 scripts/marketplace/generate_official_plugins.py
78+
git diff --exit-code -- marketplace/official-plugins.json
79+
80+
- name: Collect marketplace workspaces
81+
id: marketplace-workspaces
82+
run: |
83+
python3 - <<'PY'
84+
import json
85+
import os
86+
import pathlib
87+
import sys
88+
89+
plugins_path = pathlib.Path("marketplace/official-plugins.json")
90+
metadata = json.loads(plugins_path.read_text())
91+
plugin_ids = [plugin["id"] for plugin in metadata.get("plugins", [])]
92+
if not plugin_ids:
93+
print("No plugins found in marketplace/official-plugins.json", file=sys.stderr)
94+
sys.exit(1)
95+
96+
out_path = os.environ["GITHUB_OUTPUT"]
97+
with open(out_path, "a", encoding="utf-8") as handle:
98+
handle.write("workspaces<<EOF\n")
99+
for plugin_id in plugin_ids:
100+
handle.write(f"plugins/native/{plugin_id}\n")
101+
handle.write("EOF\n")
102+
PY
103+
104+
- uses: Swatinem/rust-cache@v2
105+
with:
106+
workspaces: ${{ steps.marketplace-workspaces.outputs.workspaces }}
107+
cache-on-failure: true
108+
109+
- name: Build official plugins
110+
run: |
111+
bash scripts/marketplace/build_official_plugins.sh
112+
113+
- name: Write minisign key
114+
env:
115+
MINISIGN_SECRET_KEY: ${{ secrets.MINISIGN_SECRET_KEY }}
116+
run: |
117+
if [ -z "${MINISIGN_SECRET_KEY}" ]; then
118+
echo "MINISIGN_SECRET_KEY is not set"
119+
exit 1
120+
fi
121+
echo "${MINISIGN_SECRET_KEY}" > /tmp/streamkit.key
122+
chmod 600 /tmp/streamkit.key
123+
124+
- name: Build registry artifacts
125+
run: |
126+
VERSION="${MARKETPLACE_VERSION#v}"
127+
python3 scripts/marketplace/build_registry.py \
128+
--plugins marketplace/official-plugins.json \
129+
--version "${VERSION}" \
130+
--bundle-base-url "https://github.com/${{ github.repository }}/releases/download/${RELEASE_TAG}" \
131+
--registry-base-url "${REGISTRY_BASE_URL}" \
132+
--bundles-out dist/bundles \
133+
--registry-out dist/registry \
134+
--signing-key /tmp/streamkit.key
135+
136+
- name: Verify marketplace bundle portability
137+
run: |
138+
python3 scripts/marketplace/verify_bundles.py \
139+
--plugins marketplace/official-plugins.json \
140+
--bundles dist/bundles
141+
142+
- name: Upload marketplace bundles
143+
uses: actions/upload-artifact@v4
144+
with:
145+
name: marketplace-bundles
146+
path: dist/bundles/*.tar.zst
147+
148+
- name: Upload registry metadata
149+
uses: actions/upload-artifact@v4
150+
with:
151+
name: marketplace-registry
152+
path: dist/registry/**
153+
154+
publish-registry:
155+
name: Publish Registry (PR)
156+
needs: [build-marketplace]
157+
runs-on: ubuntu-22.04
158+
permissions:
159+
contents: write
160+
pull-requests: write
161+
steps:
162+
- uses: actions/checkout@v5
163+
164+
- name: Download registry artifact
165+
uses: actions/download-artifact@v4
166+
with:
167+
name: marketplace-registry
168+
path: dist/registry
169+
170+
- name: Update docs registry folder
171+
run: |
172+
rm -rf docs/public/registry
173+
mkdir -p docs/public/registry
174+
cp -R dist/registry/* docs/public/registry/
175+
176+
- name: Create pull request
177+
uses: peter-evans/create-pull-request@v6
178+
with:
179+
branch: "registry/${{ env.RELEASE_TAG }}"
180+
title: "chore(registry): publish marketplace registry for ${{ env.RELEASE_TAG }}"
181+
commit-message: "chore(registry): publish marketplace registry for ${{ env.RELEASE_TAG }}"
182+
body: |
183+
Automated registry metadata update for `${{ env.RELEASE_TAG }}`.
184+
base: main
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# SPDX-FileCopyrightText: © 2025 StreamKit Contributors
2+
#
3+
# SPDX-License-Identifier: MPL-2.0
4+
5+
name: Marketplace Release
6+
7+
on:
8+
workflow_dispatch:
9+
inputs:
10+
version:
11+
description: "Marketplace version (e.g., 1.2.3)"
12+
required: true
13+
release_tag:
14+
description: "Release tag (defaults to marketplace-v<version>)"
15+
required: false
16+
prerelease:
17+
description: "Mark release as prerelease"
18+
required: false
19+
type: boolean
20+
default: false
21+
22+
env:
23+
RELEASE_TAG: ${{ inputs.release_tag || format('marketplace-v{0}', inputs.version) }}
24+
25+
jobs:
26+
marketplace:
27+
uses: ./.github/workflows/marketplace-build.yml
28+
with:
29+
version: ${{ inputs.version }}
30+
release_tag: ${{ inputs.release_tag || format('marketplace-v{0}', inputs.version) }}
31+
32+
create-release:
33+
name: Create Marketplace Release
34+
needs: [marketplace]
35+
runs-on: ubuntu-22.04
36+
permissions:
37+
contents: write
38+
steps:
39+
- uses: actions/checkout@v5
40+
41+
- name: Download all artifacts
42+
uses: actions/download-artifact@v4
43+
with:
44+
path: artifacts
45+
46+
- name: Create Release
47+
uses: softprops/action-gh-release@v2
48+
with:
49+
tag_name: ${{ env.RELEASE_TAG }}
50+
target_commitish: ${{ github.sha }}
51+
name: "Marketplace ${{ inputs.version }}"
52+
files: |
53+
artifacts/**/marketplace-bundles/*.tar.zst
54+
body: |
55+
Marketplace bundles for version `${{ inputs.version }}`.
56+
draft: false
57+
prerelease: ${{ inputs.prerelease }}
58+
env:
59+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/release.yml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,15 @@ jobs:
8080
streamkit-${{ github.ref_name }}-linux-x64.tar.gz
8181
streamkit-${{ github.ref_name }}-linux-x64.tar.gz.sha256
8282
83+
marketplace:
84+
uses: ./.github/workflows/marketplace-build.yml
85+
with:
86+
version: ${{ github.ref_name }}
87+
release_tag: ${{ github.ref_name }}
88+
8389
create-release:
8490
name: Create GitHub Release
85-
needs: [build-linux-x64]
91+
needs: [build-linux-x64, marketplace]
8692
runs-on: ubuntu-22.04
8793
permissions:
8894
contents: write
@@ -120,7 +126,10 @@ jobs:
120126
- name: Create Release
121127
uses: softprops/action-gh-release@v2
122128
with:
123-
files: artifacts/**/*
129+
files: |
130+
artifacts/**/streamkit-*.tar.gz
131+
artifacts/**/streamkit-*.tar.gz.sha256
132+
artifacts/**/marketplace-bundles/*.tar.zst
124133
body_path: changelog.md
125134
draft: false
126135
prerelease: ${{ contains(github.ref_name, '-rc') || contains(github.ref_name, '-beta') || contains(github.ref_name, '-alpha') }}

AGENTS.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,29 @@ Agent-assisted contributions are welcome, but should be **supervised** and **rev
3232
- Official images are built from `Dockerfile` (CPU) and `Dockerfile.gpu` (GPU-tagged) via `.github/workflows/docker.yml`.
3333
- `/healthz` is the lightweight health endpoint (also `/health`).
3434
- Official images do not bundle ML models or plugins; they are expected to be mounted at runtime.
35+
36+
## Adding an official plugin
37+
38+
When making a plugin official and downloadable from the registry, update all of
39+
the following:
40+
41+
- Plugin source under `plugins/native/<id>/` (crate metadata + README).
42+
- Plugin metadata in `plugins/native/<id>/marketplace.yml` (id, entrypoint,
43+
artifact path, models, licenses, homepage/repo).
44+
- Generate `marketplace/official-plugins.json` with
45+
`scripts/marketplace/generate_official_plugins.py` and commit the result.
46+
- Build list in `scripts/marketplace/build_official_plugins.sh`.
47+
- Build prerequisites in `.github/workflows/release.yml` if new system deps are
48+
required to compile or package the plugin.
49+
- Bundle/registry smoke check: run `scripts/marketplace/build_registry.py` and
50+
`scripts/marketplace/verify_bundles.py` locally.
51+
- Portability table in `marketplace/PORTABILITY_REVIEW.md` (NEEDED deps,
52+
RUNPATH/RPATH, recommendation).
53+
- Docs: add/update the plugin page under
54+
`docs/src/content/docs/reference/plugins/` and list it in
55+
`docs/src/content/docs/reference/plugins/index.md` if applicable.
56+
- Runtime shared libs: if the plugin needs bundled `.so` files, ensure the
57+
bundle includes them and the entrypoint RUNPATH uses `$ORIGIN`, and update the
58+
portability gate in `scripts/marketplace/verify_bundles.py` as needed.
59+
- **Human review required** before bundling any new third-party shared libraries
60+
(licensing, security, size, and distro compatibility).

RELEASING.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,67 @@ This repo ships:
1212
- Client CLI: `skit-cli` (crate: `streamkit-client`)
1313
- Optional crates for other developers (crates.io)
1414

15+
## Marketplace registry + bundles
16+
17+
This release flow publishes signed registry metadata to GitHub Pages and bundle
18+
artifacts to GitHub Releases.
19+
20+
### Setup (one-time)
21+
22+
```bash
23+
# Generate an unencrypted minisign keypair for registry signing.
24+
# Keep the secret key safe and commit the public key.
25+
minisign -G -W -s /tmp/streamkit.key -p docs/public/registry/streamkit.pub
26+
```
27+
28+
Set the GitHub Actions secret `MINISIGN_SECRET_KEY` to the contents of the
29+
secret key file:
30+
31+
```bash
32+
cat /tmp/streamkit.key
33+
```
34+
35+
If `docs/public/registry/streamkit.pub` contains a placeholder, overwrite it
36+
with the generated public key before tagging.
37+
38+
### System dependencies (v1)
39+
40+
- When present, `pocket-tts` requires OpenSSL 3 (`libssl.so.3`, `libcrypto.so.3`).
41+
- Ubuntu: `libssl3`
42+
- Native plugins expect system `libstdc++` and `libgcc_s`.
43+
44+
### Trigger a release
45+
46+
```bash
47+
git tag vX.Y.Z
48+
git push origin vX.Y.Z
49+
```
50+
51+
### Marketplace-only release (decoupled)
52+
53+
Use the GitHub Actions workflow `Marketplace Release` with:
54+
55+
- `version`: marketplace version (e.g., `1.2.3`)
56+
- `release_tag` (optional): defaults to `marketplace-v<version>`
57+
58+
This workflow publishes bundle assets to the GitHub Release for `release_tag`
59+
and opens the registry PR without rebuilding the server/UI. Both tag releases
60+
and marketplace-only releases share the same reusable marketplace workflow
61+
(`.github/workflows/marketplace-build.yml`).
62+
63+
### Verify outputs
64+
65+
- GitHub Release includes `*-bundle.tar.zst` assets.
66+
- Registry metadata is published after merging the registry PR:
67+
`https://<org>.github.io/streamkit/registry/index.json`.
68+
- Verify a manifest signature:
69+
70+
```bash
71+
minisign -V -P "$(tail -n 1 docs/public/registry/streamkit.pub)" \
72+
-m manifest.json \
73+
-x manifest.minisig
74+
```
75+
1576
## crates.io publishing
1677

1778
### Intended publish set

docs/public/registry/streamkit.pub

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
untrusted comment: minisign public key 81C485A94492F33F
2+
RWQ/85JEqYXEgX+2kl7Rwd8AcpVjYciSLzvLggzivbGyIrDPjfmcqjYP

0 commit comments

Comments
 (0)