Skip to content

Release

Release #12

Workflow file for this run

---
name: Release
on:
push:
tags: [v*.*.*]
workflow_dispatch:
inputs:
crates-io:
description: Publish iscc-lib to crates.io
type: boolean
default: false
pypi:
description: Publish iscc-lib to PyPI
type: boolean
default: false
npm:
description: Publish @iscc/lib and @iscc/wasm to npm
type: boolean
default: false
maven:
description: Publish iscc-lib to Maven Central
type: boolean
default: false
ffi:
description: Build and publish FFI tarballs to GitHub Releases
type: boolean
default: false
rubygems:
description: Publish iscc-lib to RubyGems
type: boolean
default: false
permissions:
contents: read
concurrency:
group: release
cancel-in-progress: false # Never cancel a release in progress
jobs:
# Publish Rust core crate to crates.io via OIDC trusted publishing
publish-crates-io:
name: Publish to crates.io
if: startsWith(github.ref, 'refs/tags/v') || inputs.crates-io
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Get workspace version
id: version
run: |
VERSION=$(grep -m1 '^version' Cargo.toml | sed 's/.*"\(.*\)"/\1/')
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Check version on registry
id: check
run: |
VERSION="${{ steps.version.outputs.version }}"
if cargo info iscc-lib 2>/dev/null | grep -q "version: $VERSION"; then
echo "Version $VERSION already published to crates.io, skipping"
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi
- name: Run tests
if: steps.check.outputs.skip != 'true'
run: cargo test --workspace --exclude iscc-rb
- name: Authenticate with crates.io
if: steps.check.outputs.skip != 'true'
id: crates-auth
uses: rust-lang/crates-io-auth-action@v1
- name: Publish iscc-lib
if: steps.check.outputs.skip != 'true'
run: cargo publish -p iscc-lib
env:
CARGO_REGISTRY_TOKEN: ${{ steps.crates-auth.outputs.token }}
# Build cross-platform Python wheels using maturin
build-wheels:
name: Build wheels (${{ matrix.target }})
if: startsWith(github.ref, 'refs/tags/v') || inputs.pypi
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-latest
target: x86_64
interpreter: python3.10
- os: macos-14
target: universal2-apple-darwin
interpreter: python3.10
- os: windows-latest
target: x64
interpreter: python
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Build wheel
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
args: --release --out dist --manifest-path crates/iscc-py/Cargo.toml -i
${{ matrix.interpreter }}
manylinux: auto
before-script-linux: |
# Put Python 3.10 first in PATH so maturin uses it for abi3 wheel tagging.
# Without this, the manylinux container defaults to Python 3.8 which is below
# the abi3-py310 minimum and produces a version-specific cp38 wheel instead.
export PATH="/opt/python/cp310-cp310/bin:$PATH"
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: wheels-${{ matrix.os }}-${{ matrix.target }}
path: dist
# Build source distribution
build-sdist:
name: Build sdist
if: startsWith(github.ref, 'refs/tags/v') || inputs.pypi
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build sdist
uses: PyO3/maturin-action@v1
with:
command: sdist
args: --out dist --manifest-path crates/iscc-py/Cargo.toml
- name: Upload sdist
uses: actions/upload-artifact@v4
with:
name: wheels-sdist
path: dist
# Smoke test Python wheel on Linux before publishing
test-wheels:
name: Test Python wheel
needs: [build-wheels]
if: startsWith(github.ref, 'refs/tags/v') || inputs.pypi
runs-on: ubuntu-latest
steps:
- uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Download wheel
uses: actions/download-artifact@v4
with:
name: wheels-ubuntu-latest-x86_64
path: dist
- name: Install and test
run: |
pip install dist/*.whl
python -c "from iscc_lib import conformance_selftest; assert conformance_selftest()"
# Publish all wheels and sdist to PyPI via OIDC trusted publishing
publish-pypi:
name: Publish to PyPI
needs: [build-wheels, build-sdist, test-wheels]
if: startsWith(github.ref, 'refs/tags/v') || inputs.pypi
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- name: Get workspace version
id: version
run: |
VERSION=$(grep -m1 '^version' Cargo.toml | sed 's/.*"\(.*\)"/\1/')
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Check version on registry
id: check
run: |
VERSION="${{ steps.version.outputs.version }}"
if curl -sf "https://pypi.org/pypi/iscc-lib/$VERSION/json" > /dev/null 2>&1; then
echo "Version $VERSION already published to PyPI, skipping"
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi
- name: Download all artifacts
if: steps.check.outputs.skip != 'true'
uses: actions/download-artifact@v4
with:
pattern: wheels-*
path: dist
merge-multiple: true
- name: Publish to PyPI
if: steps.check.outputs.skip != 'true'
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist
# Build napi-rs native addons for cross-platform npm publishing
build-napi:
name: Build napi (${{ matrix.target }})
if: startsWith(github.ref, 'refs/tags/v') || inputs.npm
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
- os: ubuntu-latest
target: aarch64-unknown-linux-gnu
- os: macos-14
target: aarch64-apple-darwin
- os: macos-14
target: x86_64-apple-darwin
- os: windows-latest
target: x86_64-pc-windows-msvc
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
- name: Install npm dependencies
run: npm install
working-directory: crates/iscc-napi
- name: Install cross-compiler
if: matrix.target == 'aarch64-unknown-linux-gnu'
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu
- name: Build native addon
run: npx napi build --platform --release --target ${{ matrix.target }}
working-directory: crates/iscc-napi
env:
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: napi-${{ matrix.target }}
path: crates/iscc-napi/*.node
# Smoke test NAPI native addon on Linux before publishing
test-napi:
name: Test NAPI addon
needs: [build-napi]
if: startsWith(github.ref, 'refs/tags/v') || inputs.npm
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: Download addon
uses: actions/download-artifact@v4
with:
name: napi-x86_64-unknown-linux-gnu
path: addon
- name: Test native addon
run: node -e "const m = require('./addon/iscc-lib.linux-x64-gnu.node'); if
(!m.conformance_selftest()) { throw new Error('conformance failed'); }"
# Publish @iscc/lib to npm
publish-npm-lib:
name: Publish @iscc/lib to npm
needs: [build-napi, test-napi]
if: startsWith(github.ref, 'refs/tags/v') || inputs.npm
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
registry-url: https://registry.npmjs.org
- name: Install npm dependencies
run: npm install
working-directory: crates/iscc-napi
- name: Download all napi artifacts
uses: actions/download-artifact@v4
with:
pattern: napi-*
path: crates/iscc-napi
merge-multiple: true
- name: Prepare npm packages
run: npx napi prepublish -t npm
working-directory: crates/iscc-napi
- name: Get workspace version
id: version
run: |
VERSION=$(grep -m1 '^version' Cargo.toml | sed 's/.*"\(.*\)"/\1/')
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Check version on registry
id: check
run: |
VERSION="${{ steps.version.outputs.version }}"
if npm view "@iscc/lib@$VERSION" version 2>/dev/null; then
echo "Version $VERSION already published to npm, skipping"
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi
- name: Publish to npm
if: steps.check.outputs.skip != 'true'
run: npm publish --provenance --access public
working-directory: crates/iscc-napi
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
# Build WASM package for npm publishing
build-wasm:
name: Build WASM package
if: startsWith(github.ref, 'refs/tags/v') || inputs.npm
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- name: Build WASM package
run: wasm-pack build --target web --release crates/iscc-wasm --features conformance
- name: Set npm package name and version
run: |
node <<'SCRIPT'
const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('crates/iscc-wasm/pkg/package.json', 'utf8'));
pkg.name = '@iscc/wasm';
pkg.repository = { type: 'git', url: 'https://github.com/iscc/iscc-lib' };
const toml = fs.readFileSync('Cargo.toml', 'utf8');
const m = toml.match(/^version\s*=\s*"(.+?)"/m);
if (m) pkg.version = m[1];
fs.writeFileSync('crates/iscc-wasm/pkg/package.json', JSON.stringify(pkg, null, 2) + '\n');
SCRIPT
- name: Upload WASM package
uses: actions/upload-artifact@v4
with:
name: wasm-pkg
path: crates/iscc-wasm/pkg/
# Smoke test WASM package on Linux before publishing
test-wasm:
name: Test WASM package
needs: [build-wasm]
if: startsWith(github.ref, 'refs/tags/v') || inputs.npm
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: Download WASM package
uses: actions/download-artifact@v4
with:
name: wasm-pkg
path: pkg
- name: Test WASM module
run: |
cat > smoke.mjs << 'SCRIPT'
import { readFileSync } from 'fs';
import init, { conformance_selftest } from './pkg/iscc_wasm.js';
const wasmBytes = readFileSync('./pkg/iscc_wasm_bg.wasm');
await init(wasmBytes);
if (!conformance_selftest()) { throw new Error('conformance failed'); }
SCRIPT
node smoke.mjs
# Publish @iscc/wasm to npm
publish-npm-wasm:
name: Publish @iscc/wasm to npm
needs: [build-wasm, test-wasm]
if: startsWith(github.ref, 'refs/tags/v') || inputs.npm
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/setup-node@v4
with:
node-version: '22'
registry-url: https://registry.npmjs.org
- name: Download WASM package
uses: actions/download-artifact@v4
with:
name: wasm-pkg
path: pkg
- name: Get package version
id: version
run: |
VERSION=$(node -p "require('./pkg/package.json').version")
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Check version on registry
id: check
run: |
VERSION="${{ steps.version.outputs.version }}"
if npm view "@iscc/wasm@$VERSION" version 2>/dev/null; then
echo "Version $VERSION already published to npm, skipping"
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi
- name: Publish to npm
if: steps.check.outputs.skip != 'true'
run: npm publish --provenance --access public
working-directory: pkg
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
# Build JNI native libraries for cross-platform JAR packaging
build-jni:
name: Build JNI (${{ matrix.native-dir }})
if: startsWith(github.ref, 'refs/tags/v') || inputs.maven
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
native-dir: linux-x86_64
lib-name: libiscc_jni.so
- os: ubuntu-latest
target: aarch64-unknown-linux-gnu
native-dir: linux-aarch64
lib-name: libiscc_jni.so
- os: macos-14
target: aarch64-apple-darwin
native-dir: macos-aarch64
lib-name: libiscc_jni.dylib
- os: macos-14
target: x86_64-apple-darwin
native-dir: macos-x86_64
lib-name: libiscc_jni.dylib
- os: windows-latest
target: x86_64-pc-windows-msvc
native-dir: windows-x86_64
lib-name: iscc_jni.dll
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
- name: Install cross-compiler
if: matrix.target == 'aarch64-unknown-linux-gnu'
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu
- name: Build JNI library
run: cargo build -p iscc-jni --release --target ${{ matrix.target }}
env:
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: jni-${{ matrix.native-dir }}
path: target/${{ matrix.target }}/release/${{ matrix.lib-name }}
# Assemble cross-platform JAR with bundled native libraries
assemble-jar:
name: Assemble JAR
needs: [build-jni]
if: startsWith(github.ref, 'refs/tags/v') || inputs.maven
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '17'
- name: Download JNI artifacts
uses: actions/download-artifact@v4
with:
pattern: jni-*
path: jni-staging
- name: Copy native libraries to resources
run: |
for dir in jni-staging/jni-*/; do
native_dir=$(basename "$dir" | sed 's/^jni-//')
dest="crates/iscc-jni/java/src/main/resources/META-INF/native/$native_dir"
mkdir -p "$dest"
cp "$dir"* "$dest/"
done
- name: Build JAR
run: mvn package -DskipTests -f crates/iscc-jni/java/pom.xml
- name: Upload JAR
uses: actions/upload-artifact@v4
with:
name: iscc-lib-jar
path: crates/iscc-jni/java/target/*.jar
# Smoke test JNI native libraries on Linux before publishing
test-jni:
name: Test JNI libraries
needs: [build-jni]
if: startsWith(github.ref, 'refs/tags/v') || inputs.maven
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '17'
- name: Download JNI artifacts
uses: actions/download-artifact@v4
with:
pattern: jni-*
path: jni-staging
- name: Copy native libraries to resources
run: |
for dir in jni-staging/jni-*/; do
native_dir=$(basename "$dir" | sed 's/^jni-//')
dest="crates/iscc-jni/java/src/main/resources/META-INF/native/$native_dir"
mkdir -p "$dest"
cp "$dir"* "$dest/"
done
- name: Run tests
run: mvn test -f crates/iscc-jni/java/pom.xml
# Publish Java JAR to Maven Central via Sonatype Central Portal
publish-maven:
name: Publish to Maven Central
needs: [build-jni, test-jni]
if: startsWith(github.ref, 'refs/tags/v') || inputs.maven
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '17'
server-id: central
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
- name: Get workspace version
id: version
run: |
VERSION=$(grep -m1 '^version' Cargo.toml | sed 's/.*"\(.*\)"/\1/')
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Check version on Maven Central
id: check
run: |
VERSION="${{ steps.version.outputs.version }}"
if curl -sf "https://search.maven.org/solrsearch/select?q=g:io.iscc+AND+a:iscc-lib+AND+v:$VERSION&rows=1&wt=json" | grep -q '"numFound":1'; then
echo "Version $VERSION already published to Maven Central, skipping"
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi
- name: Download JNI artifacts
if: steps.check.outputs.skip != 'true'
uses: actions/download-artifact@v4
with:
pattern: jni-*
path: jni-staging
- name: Copy native libraries to resources
if: steps.check.outputs.skip != 'true'
run: |
for dir in jni-staging/jni-*/; do
native_dir=$(basename "$dir" | sed 's/^jni-//')
dest="crates/iscc-jni/java/src/main/resources/META-INF/native/$native_dir"
mkdir -p "$dest"
cp "$dir"* "$dest/"
done
- name: Import GPG key
if: steps.check.outputs.skip != 'true'
run: |
echo "${{ secrets.MAVEN_GPG_PRIVATE_KEY }}" | gpg --batch --import || true
gpg --list-secret-keys --keyid-format LONG | grep -q "sec" || { echo "GPG key import failed"; exit 1; }
- name: Publish to Maven Central
if: steps.check.outputs.skip != 'true'
run: mvn deploy -Prelease -DskipTests -f crates/iscc-jni/java/pom.xml
env:
MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
# Build FFI shared/static libraries for C/C++ consumers
build-ffi:
name: Build FFI (${{ matrix.target }})
if: startsWith(github.ref, 'refs/tags/v') || inputs.ffi
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
lib-shared: libiscc_ffi.so
lib-static: libiscc_ffi.a
- os: ubuntu-latest
target: aarch64-unknown-linux-gnu
lib-shared: libiscc_ffi.so
lib-static: libiscc_ffi.a
- os: macos-14
target: aarch64-apple-darwin
lib-shared: libiscc_ffi.dylib
lib-static: libiscc_ffi.a
- os: macos-14
target: x86_64-apple-darwin
lib-shared: libiscc_ffi.dylib
lib-static: libiscc_ffi.a
- os: windows-latest
target: x86_64-pc-windows-msvc
lib-shared: iscc_ffi.dll
lib-static: iscc_ffi.lib
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
- name: Install cross-compiler
if: matrix.target == 'aarch64-unknown-linux-gnu'
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu
- name: Build FFI library
run: cargo build -p iscc-ffi --release --target ${{ matrix.target }}
env:
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
- name: Get workspace version
id: version
shell: bash
run: |
VERSION=$(grep -m1 '^version' Cargo.toml | sed 's/.*"\(.*\)"/\1/')
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Stage artifacts (Unix)
if: runner.os != 'Windows'
run: |
VERSION="${{ steps.version.outputs.version }}"
TARGET="${{ matrix.target }}"
DIR="iscc-ffi-v${VERSION}-${TARGET}"
mkdir -p "$DIR"
cp "target/${TARGET}/release/${{ matrix.lib-shared }}" "$DIR/"
cp "target/${TARGET}/release/${{ matrix.lib-static }}" "$DIR/"
cp crates/iscc-ffi/include/iscc.h "$DIR/"
cp LICENSE "$DIR/"
tar czf "${DIR}.tar.gz" "$DIR"
- name: Stage artifacts (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
$VERSION = "${{ steps.version.outputs.version }}"
$TARGET = "${{ matrix.target }}"
$DIR = "iscc-ffi-v${VERSION}-${TARGET}"
New-Item -ItemType Directory -Path $DIR -Force
Copy-Item "target/${TARGET}/release/iscc_ffi.dll" "$DIR/"
Copy-Item "target/${TARGET}/release/iscc_ffi.dll.lib" "$DIR/"
Copy-Item "target/${TARGET}/release/iscc_ffi.lib" "$DIR/"
Copy-Item "crates/iscc-ffi/include/iscc.h" "$DIR/"
Copy-Item "LICENSE" "$DIR/"
Compress-Archive -Path "$DIR" -DestinationPath "${DIR}.zip"
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ffi-${{ matrix.target }}
path: iscc-ffi-v*.*
# Smoke test FFI shared library on Linux before publishing
test-ffi:
name: Test FFI library
needs: [build-ffi]
if: startsWith(github.ref, 'refs/tags/v') || inputs.ffi
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Download FFI artifact
uses: actions/download-artifact@v4
with:
name: ffi-x86_64-unknown-linux-gnu
path: ffi-staging
- name: Extract and test
run: |
tar xzf ffi-staging/*.tar.gz
LIB_DIR=$(find . -maxdepth 1 -name 'iscc-ffi-v*' -type d)
cc -o test_iscc crates/iscc-ffi/tests/test_iscc.c \
-I"$LIB_DIR" -L"$LIB_DIR" -liscc_ffi -lpthread -ldl -lm
LD_LIBRARY_PATH="$LIB_DIR" ./test_iscc
# Publish FFI tarballs to GitHub Releases
publish-ffi:
name: Publish FFI to GitHub Releases
needs: [build-ffi, test-ffi]
if: startsWith(github.ref, 'refs/tags/v') || inputs.ffi
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: Get workspace version
id: version
run: |
VERSION=$(grep -m1 '^version' Cargo.toml | sed 's/.*"\(.*\)"/\1/')
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Download all FFI artifacts
uses: actions/download-artifact@v4
with:
pattern: ffi-*
path: ffi-staging
merge-multiple: true
- name: List artifacts
run: ls -lR ffi-staging/
- name: Upload release assets
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ startsWith(github.ref, 'refs/tags/v') && github.ref_name || format('v{0}', steps.version.outputs.version) }}
files: ffi-staging/iscc-ffi-v*.*
# Build cross-platform precompiled Ruby gems via rb-sys-dock
build-gem:
name: Build gem (${{ matrix.platform }})
if: startsWith(github.ref, 'refs/tags/v') || inputs.rubygems
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
platform:
- x86_64-linux
- aarch64-linux
- x86_64-darwin
- arm64-darwin
- x64-mingw-ucrt
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.3'
bundler-cache: true
working-directory: crates/iscc-rb
- name: Cross-compile gem
uses: oxidize-rb/actions/cross-gem@v1
with:
platform: ${{ matrix.platform }}
ruby-versions: 3.1, 3.2, 3.3
working-directory: crates/iscc-rb
# Pin to 0.9.123 (Ruby 3.4 build tool). The 0.9.124 image has Ruby 4.0
# which breaks RbSys::ExtensionTask. Must match rb_sys in Gemfile.lock.
tag: 0.9.123
- name: Upload gem
uses: actions/upload-artifact@v4
with:
name: gem-${{ matrix.platform }}
path: crates/iscc-rb/pkg/*-${{ matrix.platform }}.gem
# Smoke test Ruby gem on Linux before publishing
test-gem:
name: Test Ruby gem
needs: [build-gem]
if: startsWith(github.ref, 'refs/tags/v') || inputs.rubygems
runs-on: ubuntu-latest
steps:
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.3'
- name: Download gem
uses: actions/download-artifact@v4
with:
name: gem-x86_64-linux
path: gems
- name: Install and test
run: |
gem install gems/*.gem
ruby -e "require 'iscc_lib'; raise 'Conformance failed' unless IsccLib.conformance_selftest"
# Publish precompiled Ruby gems and source gem to RubyGems.org
publish-rubygems:
name: Publish to RubyGems
needs: [build-gem, test-gem]
if: startsWith(github.ref, 'refs/tags/v') || inputs.rubygems
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.3'
- name: Get workspace version
id: version
run: |
VERSION=$(grep -m1 '^version' Cargo.toml | sed 's/.*"\(.*\)"/\1/')
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Check version on RubyGems
id: check
run: |
VERSION="${{ steps.version.outputs.version }}"
if curl -sf "https://rubygems.org/api/v1/versions/iscc-lib.json" | grep -q "\"number\":\"$VERSION\""; then
echo "Version $VERSION already published to RubyGems, skipping"
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi
- name: Download gem artifacts
if: steps.check.outputs.skip != 'true'
uses: actions/download-artifact@v4
with:
pattern: gem-*
path: gems
merge-multiple: true
- name: Build source gem
if: steps.check.outputs.skip != 'true'
run: gem build iscc-lib.gemspec
working-directory: crates/iscc-rb
- name: Publish gems
if: steps.check.outputs.skip != 'true'
run: |
# Publish precompiled platform gems
for gem in gems/*.gem; do
echo "Publishing $gem"
gem push "$gem"
done
# Publish source gem (fallback for platforms without precompiled gems)
for gem in crates/iscc-rb/*.gem; do
echo "Publishing $gem"
gem push "$gem"
done
env:
GEM_HOST_API_KEY: ${{ secrets.GEM_HOST_API_KEY }}