name: release
on:
push:
tags: ["v*"]
workflow_dispatch:
inputs:
tag:
description: "Tag to build artifacts for (format: vX.Y.Z)."
required: true
type: string
permissions:
contents: read
env:
RELEASE_RUST_TOOLCHAIN: "1.88.0"
jobs:
release-context:
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.ctx.outputs.tag }}
version: ${{ steps.ctx.outputs.version }}
steps:
- id: ctx
shell: bash
run: |
set -euo pipefail
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
tag="${{ inputs.tag }}"
else
tag="${GITHUB_REF_NAME}"
fi
if [[ -z "$tag" || "$tag" != v* ]]; then
echo "error: release tag must use vX.Y.Z format, got '$tag'." >&2
exit 1
fi
if ! git ls-remote --exit-code --tags "https://github.com/${GITHUB_REPOSITORY}.git" "refs/tags/${tag}" >/dev/null; then
echo "error: requested tag '${tag}' does not exist on origin." >&2
echo "hint: create/push the tag first, then rerun release build." >&2
exit 1
fi
version="${tag#v}"
echo "tag=$tag" >> "$GITHUB_OUTPUT"
echo "version=$version" >> "$GITHUB_OUTPUT"
mkdir -p .scratch/release-metadata
cat > .scratch/release-metadata/metadata.json <<META
{
"tag": "${tag}",
"version": "${version}",
"source_sha": "${GITHUB_SHA}",
"source_ref": "${GITHUB_REF}",
"source_run_id": "${GITHUB_RUN_ID}",
"source_workflow": "${GITHUB_WORKFLOW}"
}
META
- uses: actions/upload-artifact@v4
with:
name: release-metadata
path: .scratch/release-metadata/metadata.json
if-no-files-found: error
build-native:
needs: [release-context]
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
platform: linux_amd64
- os: ubuntu-24.04-arm
target: aarch64-unknown-linux-gnu
platform: linux_arm64
- os: macos-15-intel
target: x86_64-apple-darwin
platform: darwin_amd64
- os: macos-latest
target: aarch64-apple-darwin
platform: darwin_arm64
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.release-context.outputs.tag }}
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ env.RELEASE_RUST_TOOLCHAIN }}
targets: ${{ matrix.target }}
- name: Install smoke-test tooling
shell: bash
run: |
if [[ "${{ matrix.os }}" == ubuntu-* ]]; then
sudo apt-get update
sudo apt-get install -y pkg-config
else
brew install pkg-config
fi
- name: Build binaries
run: cargo build --release --target ${{ matrix.target }} --bins
- name: Build shared library with stable identity
shell: bash
run: |
if [[ "${{ matrix.target }}" == *apple-darwin ]]; then
cargo rustc --release --target ${{ matrix.target }} --lib --crate-type=cdylib -- -C link-arg=-Wl,-install_name,@rpath/libplasmite.dylib
else
cargo rustc --release --target ${{ matrix.target }} --lib --crate-type=cdylib -- -C link-arg=-Wl,-soname,libplasmite.so
fi
- name: Build static library (optional artifact)
run: cargo rustc --release --target ${{ matrix.target }} --lib --crate-type=staticlib
- name: Package SDK
shell: bash
run: ./scripts/package_release_sdk.sh "${{ matrix.target }}" "${{ matrix.platform }}" "${{ needs.release-context.outputs.version }}"
- name: Smoke test packaged SDK
shell: bash
run: ./scripts/cross_artifact_smoke.sh "dist/plasmite_${{ needs.release-context.outputs.version }}_${{ matrix.platform }}.tar.gz"
- uses: actions/upload-artifact@v4
with:
name: dist-${{ matrix.target }}
path: dist/*.tar.gz
if-no-files-found: error
build-python-dist:
needs: [release-context]
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
platform: linux_amd64
upload_sdist: true
upload_wheel: false
- os: ubuntu-24.04-arm
target: aarch64-unknown-linux-gnu
platform: linux_arm64
upload_sdist: false
upload_wheel: false
- os: macos-15-intel
target: x86_64-apple-darwin
platform: darwin_amd64
upload_sdist: false
upload_wheel: true
- os: macos-latest
target: aarch64-apple-darwin
platform: darwin_arm64
upload_sdist: false
upload_wheel: true
- os: windows-latest
target: x86_64-pc-windows-msvc
platform: windows_amd64
upload_sdist: false
upload_wheel: true
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.release-context.outputs.tag }}
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ env.RELEASE_RUST_TOOLCHAIN }}
targets: ${{ matrix.target }}
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- uses: astral-sh/setup-uv@v5
- name: Build SDK artifacts for wheel bundling
shell: bash
run: |
cargo build --release --target "${{ matrix.target }}" --bins
if [[ "${{ matrix.target }}" == *windows-msvc ]]; then
cargo rustc --release --target "${{ matrix.target }}" --lib --crate-type=cdylib
elif [[ "${{ matrix.target }}" == *apple-darwin ]]; then
cargo rustc --release --target "${{ matrix.target }}" --lib --crate-type=cdylib -- -C link-arg=-Wl,-install_name,@rpath/libplasmite.dylib
else
cargo rustc --release --target "${{ matrix.target }}" --lib --crate-type=cdylib -- -C link-arg=-Wl,-soname,libplasmite.so
fi
- name: Build and smoke-test python wheel
shell: bash
env:
PLASMITE_SDK_DIR: ${{ github.workspace }}/target/${{ matrix.target }}/release
run: ./scripts/python_wheel_smoke.sh
- uses: actions/upload-artifact@v4
if: matrix.upload_wheel
with:
name: py-dist-${{ matrix.platform }}
path: bindings/python/dist/*.whl
if-no-files-found: error
- uses: actions/upload-artifact@v4
if: matrix.upload_sdist
with:
name: py-sdist
path: bindings/python/dist/*.tar.gz
if-no-files-found: error
build-node-native:
needs: [release-context]
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
platform: linux-x64
- os: ubuntu-24.04-arm
target: aarch64-unknown-linux-gnu
platform: linux-arm64
- os: macos-15-intel
target: x86_64-apple-darwin
platform: darwin-x64
- os: macos-latest
target: aarch64-apple-darwin
platform: darwin-arm64
- os: windows-latest
target: x86_64-pc-windows-msvc
platform: win32-x64
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.release-context.outputs.tag }}
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ env.RELEASE_RUST_TOOLCHAIN }}
targets: ${{ matrix.target }}
- uses: actions/setup-node@v4
with:
node-version: "20"
- run: cd bindings/node && npm ci
- name: Build SDK artifacts for matrix platform
shell: bash
run: |
cargo build --release --target "${{ matrix.target }}" --bins
if [[ "${{ matrix.target }}" == *windows-msvc ]]; then
cargo rustc --release --target "${{ matrix.target }}" --lib --crate-type=cdylib
elif [[ "${{ matrix.target }}" == *apple-darwin ]]; then
cargo rustc --release --target "${{ matrix.target }}" --lib --crate-type=cdylib -- -C link-arg=-Wl,-install_name,@rpath/libplasmite.dylib
else
cargo rustc --release --target "${{ matrix.target }}" --lib --crate-type=cdylib -- -C link-arg=-Wl,-soname,libplasmite.so
fi
- name: Build Node addon
env:
PLASMITE_LIB_DIR: ${{ github.workspace }}/target/${{ matrix.target }}/release
run: cd bindings/node && npm run build
- name: Stage node native payload
shell: bash
run: ./scripts/package_node_natives.sh "${{ matrix.platform }}" "${{ github.workspace }}/target/${{ matrix.target }}/release" "${{ github.workspace }}/bindings/node/index.node"
- name: Windows node pack/install smoke
if: matrix.platform == 'win32-x64'
shell: bash
env:
PLASMITE_SDK_DIR: ${{ github.workspace }}/target/${{ matrix.target }}/release
run: ./scripts/node_pack_smoke.sh
- uses: actions/upload-artifact@v4
with:
name: node-native-${{ matrix.platform }}
path: bindings/node/native/${{ matrix.platform }}/*
if-no-files-found: error
build-node-dist:
needs: [release-context, build-node-native]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.release-context.outputs.tag }}
- uses: actions/setup-node@v4
with:
node-version: "20"
- run: cd bindings/node && npm ci
- uses: actions/download-artifact@v4
with:
name: node-native-linux-x64
path: bindings/node/native/linux-x64
- uses: actions/download-artifact@v4
with:
name: node-native-darwin-x64
path: bindings/node/native/darwin-x64
- uses: actions/download-artifact@v4
with:
name: node-native-darwin-arm64
path: bindings/node/native/darwin-arm64
- uses: actions/download-artifact@v4
with:
name: node-native-linux-arm64
path: bindings/node/native/linux-arm64
continue-on-error: true
- uses: actions/download-artifact@v4
with:
name: node-native-win32-x64
path: bindings/node/native/win32-x64
- name: Restore native CLI execute bits
run: find bindings/node/native -type f -name plasmite -exec chmod +x {} +
- name: Report assembled platforms
run: |
echo "Assembled platforms:"
ls -la bindings/node/native/
for dir in bindings/node/native/*/; do
echo " $(basename "$dir"): $(ls "$dir" | wc -l) files"
done
- name: npm pack + install smoke (linux-x64 runtime)
env:
PLASMITE_SDK_DIR: ${{ github.workspace }}/target/x86_64-unknown-linux-gnu/release
run: |
tarball="$(cd bindings/node && npm pack --ignore-scripts --silent)"
workdir="$(mktemp -d)"
trap 'rm -rf "$workdir"; rm -f "bindings/node/${tarball}"' EXIT
cd "$workdir"
npm init -y >/dev/null
npm install "${GITHUB_WORKSPACE}/bindings/node/${tarball}" >/dev/null
node -e 'const { Client, Durability, RemoteClient } = require("plasmite"); const os = require("node:os"); const fs = require("node:fs"); const path = require("node:path"); const dir = fs.mkdtempSync(path.join(os.tmpdir(), "plasmite-node-release-")); const c = new Client(dir); const p = c.createPool("smoke", 1024*1024); p.appendJson(Buffer.from("{\"kind\":\"smoke\"}"), ["smoke"], Durability.Fast); p.close(); c.close(); const rc = new RemoteClient("http://127.0.0.1:9700"); if (!rc) throw new Error("missing remote");'
npx plasmite --version >/dev/null
mkdir -p "${GITHUB_WORKSPACE}/bindings/node/dist"
cp "${GITHUB_WORKSPACE}/bindings/node/${tarball}" "${GITHUB_WORKSPACE}/bindings/node/dist/"
- name: Build npm publish artifact
run: ls -la bindings/node/dist
- uses: actions/upload-artifact@v4
with:
name: node-dist
path: bindings/node/dist/plasmite-*.tgz
if-no-files-found: error