name: Publish
on:
push:
tags: ["v*"]
workflow_dispatch:
env:
CARGO_TERM_COLOR: always
jobs:
version:
name: Sync version
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v4
- id: version
run: echo "version=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT
- name: Update Cargo.toml versions
run: |
VERSION="${GITHUB_REF_NAME#v}"
sed -i "s/^version = \".*\"/version = \"$VERSION\"/" Cargo.toml
sed -i "s/^version = \".*\"/version = \"$VERSION\"/" bindings/python/Cargo.toml
sed -i "s/^version = \".*\"/version = \"$VERSION\"/" bindings/nodejs/Cargo.toml
sed -i "s/\"version\": \".*\"/\"version\": \"$VERSION\"/" bindings/nodejs/package.json
sed -i "s/^version = \".*\"/version = \"$VERSION\"/" bindings/python/pyproject.toml
sed -i "s/<version>.*<\/version>/<version>$VERSION<\/version>/" bindings/dotnet/SpeechMarkdown.nuspec
- uses: actions/upload-artifact@v4
with:
name: version-sync
path: |
Cargo.toml
bindings/python/Cargo.toml
bindings/python/pyproject.toml
bindings/nodejs/Cargo.toml
bindings/nodejs/package.json
bindings/dotnet/SpeechMarkdown.nuspec
test:
name: Test
needs: version
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: actions/download-artifact@v4
with:
name: version-sync
path: .
- uses: dtolnay/rust-toolchain@stable
- run: cargo test --all
- run: cargo test --test ffi_test
build-native:
name: Build native (${{ matrix.target }})
needs: test
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-pc-windows-msvc
os: windows-latest
lib: speechmarkdown_rust.dll
- target: aarch64-pc-windows-msvc
os: windows-latest
lib: speechmarkdown_rust.dll
- target: x86_64-apple-darwin
os: macos-latest
lib: libspeechmarkdown_rust.dylib
- target: aarch64-apple-darwin
os: macos-latest
lib: libspeechmarkdown_rust.dylib
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
lib: libspeechmarkdown_rust.so
- target: aarch64-unknown-linux-gnu
os: ubuntu-latest
lib: libspeechmarkdown_rust.so
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: version-sync
path: .
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Install cross-compilation tools
if: matrix.target == 'aarch64-unknown-linux-gnu'
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu
- name: Configure aarch64-linux linker
if: matrix.target == 'aarch64-unknown-linux-gnu'
run: echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
- run: cargo build --release --target ${{ matrix.target }}
- uses: actions/upload-artifact@v4
with:
name: native-${{ matrix.target }}
path: target/${{ matrix.target }}/release/${{ matrix.lib }}
publish-crate:
name: crates.io
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: actions/download-artifact@v4
with:
name: version-sync
path: .
- uses: dtolnay/rust-toolchain@stable
- run: cargo publish --allow-dirty
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
build-wheels:
name: Python wheel (${{ matrix.target }})
needs: test
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
target: x86_64-pc-windows-msvc
- os: macos-latest
target: aarch64-apple-darwin
- os: macos-latest
target: x86_64-apple-darwin
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
- os: ubuntu-latest
target: aarch64-unknown-linux-gnu
permissions:
contents: read
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: actions/download-artifact@v4
with:
name: version-sync
path: .
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Copy README for PyPI
run: cp README.md bindings/python/README.md
- name: Build wheel
uses: PyO3/maturin-action@v1
with:
command: build
target: ${{ matrix.target }}
args: --release --out dist -i python3.13
working-directory: bindings/python
sccache: "false"
manylinux: auto
- name: Build sdist
if: matrix.target == 'x86_64-unknown-linux-gnu'
uses: PyO3/maturin-action@v1
with:
command: sdist
args: --out dist-sdist
working-directory: bindings/python
sccache: "false"
- uses: actions/upload-artifact@v4
with:
name: wheels-${{ matrix.target }}
path: |
bindings/python/dist/*
bindings/python/dist-sdist/*
publish-pypi:
name: PyPI
needs: build-wheels
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/download-artifact@v4
with:
path: wheels-staging
pattern: wheels-*
merge-multiple: true
- name: Collect wheels
run: mkdir -p dist && find wheels-staging -type f \( -name '*.whl' -o -name '*.tar.gz' \) -exec mv {} dist/ \;
- uses: pypa/gh-action-pypi-publish@release/v1
build-npm:
name: Build npm (${{ matrix.target }})
needs: test
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: macos-latest
target: aarch64-apple-darwin
- os: macos-latest
target: x86_64-apple-darwin
- os: windows-latest
target: x86_64-pc-windows-msvc
- os: windows-latest
target: aarch64-pc-windows-msvc
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
- os: ubuntu-latest
target: aarch64-unknown-linux-gnu
- os: ubuntu-latest
target: x86_64-unknown-linux-musl
permissions:
contents: read
defaults:
run:
working-directory: bindings/nodejs
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: version-sync
path: .
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- uses: actions/setup-node@v4
with:
node-version: "24"
- name: Install cross-compilation tools (Linux aarch64)
if: matrix.target == 'aarch64-unknown-linux-gnu'
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
- name: Install musl tools
if: matrix.target == 'x86_64-unknown-linux-musl'
run: sudo apt-get update && sudo apt-get install -y musl-tools
- run: npm install @napi-rs/cli
- run: npx napi build --platform --release --target ${{ matrix.target }}
- uses: actions/upload-artifact@v4
with:
name: npm-${{ matrix.target }}
path: bindings/nodejs/*.node
publish-npm:
name: npm
needs: build-npm
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
defaults:
run:
working-directory: bindings/nodejs
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: version-sync
path: .
- uses: actions/setup-node@v4
with:
node-version: "24"
registry-url: "https://registry.npmjs.org"
- uses: actions/download-artifact@v4
with:
path: ${{ github.workspace }}/npm-artifacts
pattern: npm-*
merge-multiple: true
- name: Collect .node binaries
run: find ${{ github.workspace }}/npm-artifacts -name '*.node' -exec cp {} . \;
- name: Copy README
run: cp ${{ github.workspace }}/README.md .
- run: npm install @napi-rs/cli
- name: Publish
run: npm publish --provenance --access public --ignore-scripts
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
publish-nuget:
name: NuGet
needs: [test, build-native]
runs-on: windows-latest
permissions:
contents: read
id-token: write
defaults:
run:
working-directory: bindings/dotnet
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: version-sync
path: .
- uses: actions/download-artifact@v4
with:
path: ${{ github.workspace }}/artifacts
pattern: native-*
- name: Organize runtimes
shell: pwsh
run: |
$artifactsRoot = "${{ github.workspace }}/artifacts"
$mapping = @{
"native-x86_64-pc-windows-msvc" = "win-x64"
"native-aarch64-pc-windows-msvc" = "win-arm64"
"native-x86_64-apple-darwin" = "osx-x64"
"native-aarch64-apple-darwin" = "osx-arm64"
"native-x86_64-unknown-linux-gnu" = "linux-x64"
"native-aarch64-unknown-linux-gnu" = "linux-arm64"
}
foreach ($entry in $mapping.GetEnumerator()) {
$src = "$artifactsRoot/$($entry.Key)"
$dst = "runtimes/$($entry.Value)/native"
New-Item -ItemType Directory -Force -Path $dst
Copy-Item "$src/*" $dst
}
- name: Pack
run: dotnet pack SpeechMarkdown.nuspec -o output
- name: NuGet login
uses: NuGet/login@v1
id: nuget-login
with:
user: ${{ secrets.NUGET_USER }}
- name: Publish
shell: pwsh
run: |
$pkg = Get-ChildItem output/*.nupkg | Select-Object -First 1
dotnet nuget push $pkg.FullName --api-key ${{ steps.nuget-login.outputs.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json