Skip to content

chore(release): bump version to 0.8.14 #60

chore(release): bump version to 0.8.14

chore(release): bump version to 0.8.14 #60

Workflow file for this run

name: Release
on:
push:
tags:
- "v*"
permissions:
contents: write
actions: write
env:
CARGO_TERM_COLOR: always
jobs:
# ── Tests must pass before release ─────────────────────────────
test:
name: Test
runs-on: ubuntu-latest
env:
A3S_DEPS_STUB: "1"
steps:
- uses: actions/checkout@v4
- name: Init submodules
run: git -c http.extraheader= submodule update --init --recursive
- uses: dtolnay/rust-toolchain@stable
- name: Install protoc
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
- name: Create stub libkrun for linking
run: |
echo "void krun_stub(void) {}" > /tmp/krun_stub.c
gcc -shared -o /tmp/libkrun.so /tmp/krun_stub.c
sudo cp /tmp/libkrun.so /usr/lib/
sudo ldconfig
- uses: Swatinem/rust-cache@v2
with:
workspaces: src
- run: cd src && cargo test --workspace --lib
# ── Build matrix ───────────────────────────────────────────────
build:
name: Build (${{ matrix.target }})
needs: test
strategy:
matrix:
include:
- target: linux-x86_64
os: ubuntu-latest
rust_target: x86_64-unknown-linux-musl
guest_target: x86_64-unknown-linux-musl
build_cri: true
- target: linux-arm64
os: ubuntu-24.04-arm
rust_target: aarch64-unknown-linux-musl
guest_target: aarch64-unknown-linux-musl
build_cri: true
- target: macos-arm64
os: macos-14
rust_target: ""
guest_target: aarch64-unknown-linux-musl
build_cri: false
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Init submodules
run: |
git -c http.extraheader= submodule update --init --recursive
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.guest_target }}
- name: Install dependencies (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential pkg-config libssl-dev \
musl-tools libclang-dev patchelf protobuf-compiler
- name: Install dependencies (macOS)
if: runner.os == 'macOS'
run: |
brew install lld llvm protobuf
pip3 install --break-system-packages ziglang
cargo install cargo-zigbuild
- uses: Swatinem/rust-cache@v2
with:
workspaces: src
key: release-${{ matrix.target }}
- name: Build host binaries
run: |
cd src
cargo build --release -p a3s-box-cli -p a3s-box-shim
if [ "${{ matrix.build_cri }}" = "true" ]; then
cargo build --release -p a3s-box-cri
fi
- name: Build guest binaries
run: |
cd src
if [ "${{ runner.os }}" = "macOS" ]; then
cargo zigbuild --release \
-p a3s-box-guest-init \
--target ${{ matrix.guest_target }}
else
cargo build --release \
-p a3s-box-guest-init \
--target ${{ matrix.guest_target }}
fi
- name: Package release
run: |
TAG="${GITHUB_REF#refs/tags/}"
DIR="a3s-box-${TAG}-${{ matrix.target }}"
mkdir -p "$DIR/lib"
cp src/target/release/a3s-box "$DIR/"
cp src/target/release/a3s-box-shim "$DIR/"
if [ "${{ matrix.build_cri }}" = "true" ]; then
cp src/target/release/a3s-box-cri "$DIR/"
fi
cp "src/target/${{ matrix.guest_target }}/release/a3s-box-guest-init" "$DIR/"
# Find and copy libkrun/libkrunfw shared libraries from build output
BUILD_DIR=$(find src/target/release/build -name "out" -path "*libkrun*" -type d | head -1)
if [ -n "$BUILD_DIR" ]; then
find "$BUILD_DIR" -name "libkrun*" \( -name "*.dylib" -o -name "*.so*" \) -exec cp {} "$DIR/lib/" \;
find "$BUILD_DIR" -name "libkrunfw*" \( -name "*.dylib" -o -name "*.so*" \) -exec cp {} "$DIR/lib/" \;
fi
# Fix rpath for macOS binaries to look in ../lib relative to bin
if [ "${{ runner.os }}" = "macOS" ]; then
for bin in "$DIR/a3s-box" "$DIR/a3s-box-shim"; do
install_name_tool -add_rpath @executable_path/../lib "$bin" 2>/dev/null || true
install_name_tool -add_rpath @executable_path/lib "$bin" 2>/dev/null || true
done
fi
# Fix rpath for Linux binaries
if [ "${{ runner.os }}" = "Linux" ]; then
for bin in "$DIR/a3s-box" "$DIR/a3s-box-shim"; do
patchelf --set-rpath '$ORIGIN/lib' "$bin" 2>/dev/null || true
done
if [ "${{ matrix.build_cri }}" = "true" ]; then
patchelf --set-rpath '$ORIGIN/lib' "$DIR/a3s-box-cri" 2>/dev/null || true
fi
fi
cp README.md "$DIR/" 2>/dev/null || true
cp LICENSE "$DIR/" 2>/dev/null || true
# List package contents
echo "Package contents:"
ls -lhR "$DIR/"
tar czf "${DIR}.tar.gz" "$DIR"
echo "ASSET=${DIR}.tar.gz" >> "$GITHUB_ENV"
- uses: actions/upload-artifact@v4
with:
name: ${{ matrix.target }}
path: ${{ env.ASSET }}
# ── Create GitHub Release ──────────────────────────────────────
# ── Windows launcher build ─────────────────────────────────────
build-windows:
name: Build Windows (WHPX Backend)
needs: test
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Init submodules
run: git -c http.extraheader= submodule update --init --recursive
- uses: dtolnay/rust-toolchain@stable
with:
targets: x86_64-pc-windows-msvc
- uses: Swatinem/rust-cache@v2
with:
workspaces: src
key: release-windows
- name: Build Windows runtime and launcher
run: |
cd src
# Build runtime with Windows WHPX backend
cargo build --release -p a3s-box-runtime --target x86_64-pc-windows-msvc
# Build Windows launcher (not in workspace)
cd win-launcher
cargo build --release --target x86_64-pc-windows-msvc
- name: Package Windows release
shell: bash
run: |
TAG="${GITHUB_REF#refs/tags/}"
DIR="a3s-box-${TAG}-windows-x86_64"
mkdir -p "$DIR/lib"
# Copy launcher
cp src/win-launcher/target/x86_64-pc-windows-msvc/release/a3s-box-win.exe "$DIR/"
# Copy krun.dll from prebuilt
if [ -f "src/deps/libkrun-sys/prebuilt/x86_64-pc-windows-msvc/krun.dll" ]; then
cp src/deps/libkrun-sys/prebuilt/x86_64-pc-windows-msvc/krun.dll "$DIR/lib/"
fi
# Copy README and LICENSE
cp README.md "$DIR/" 2>/dev/null || true
cp LICENSE "$DIR/" 2>/dev/null || true
# List package contents
echo "Package contents:"
ls -lhR "$DIR/"
# Create zip archive (Windows-friendly)
powershell Compress-Archive -Path "$DIR" -DestinationPath "${DIR}.zip"
echo "ASSET=${DIR}.zip" >> "$GITHUB_ENV"
- uses: actions/upload-artifact@v4
with:
name: windows-x86_64
path: ${{ env.ASSET }}
release:
name: GitHub Release
needs: [build, build-windows]
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
path: artifacts
- name: List artifacts
run: find artifacts -type f
- name: Create release
uses: softprops/action-gh-release@v2
with:
name: ${{ github.ref_name }}
generate_release_notes: true
files: |
artifacts/**/*.tar.gz
artifacts/**/*.zip
# ── Publish to crates.io ───────────────────────────────────────
publish-crates:
name: Publish to crates.io
needs: release
runs-on: ubuntu-latest
env:
A3S_DEPS_STUB: "1"
steps:
- uses: actions/checkout@v4
- name: Init submodules
run: git -c http.extraheader= submodule update --init --recursive
- uses: dtolnay/rust-toolchain@stable
- name: Install protoc
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
- name: Create stub libkrun for linking
run: |
echo "void krun_stub(void) {}" > /tmp/krun_stub.c
gcc -shared -o /tmp/libkrun.so /tmp/krun_stub.c
sudo cp /tmp/libkrun.so /usr/lib/
sudo ldconfig
- uses: Swatinem/rust-cache@v2
with:
workspaces: src
- name: Publish crates
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: |
cd src
for crate in a3s-libkrun-sys a3s-box-core a3s-box-runtime a3s-box-sdk; do
echo "Publishing $crate..."
cargo publish -p "$crate" --allow-dirty 2>&1 || echo "Skipped $crate (may already be published)"
sleep 30
done
# ── Publish Python SDK to PyPI (native via maturin) ────────────
publish-pypi:
name: Publish to PyPI (${{ matrix.target }})
needs: release
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64
- os: ubuntu-24.04-arm
target: aarch64
- os: macos-14
target: aarch64
- os: windows-latest
target: x86_64
runs-on: ${{ matrix.os }}
env:
A3S_DEPS_STUB: "1"
steps:
- uses: actions/checkout@v4
- name: Init submodules
run: git -c http.extraheader= submodule update --init --recursive
- uses: dtolnay/rust-toolchain@stable
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install protoc (Linux)
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
- name: Install protoc (macOS)
if: runner.os == 'macOS'
run: brew install protobuf
- name: Install protoc (Windows)
if: runner.os == 'Windows'
run: choco install protoc
- name: Create stub libkrun for linking (Linux)
if: runner.os == 'Linux'
run: |
echo "void krun_stub(void) {}" > /tmp/krun_stub.c
gcc -shared -o /tmp/libkrun.so /tmp/krun_stub.c
sudo cp /tmp/libkrun.so /usr/lib/
sudo ldconfig
- name: Create stub libkrun for linking (macOS)
if: runner.os == 'macOS'
run: |
echo "void krun_stub(void) {}" > /tmp/krun_stub.c
cc -shared -o /tmp/libkrun.dylib /tmp/krun_stub.c
sudo mkdir -p /usr/local/lib
sudo cp /tmp/libkrun.dylib /usr/local/lib/
- name: Create stub libkrun for linking (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
# Use prebuilt krun.dll from libkrun-sys
$stubDir = "$env:USERPROFILE\.cargo\lib"
New-Item -ItemType Directory -Force -Path $stubDir
# Copy from prebuilt if exists, otherwise create minimal stub
if (Test-Path "src\deps\libkrun-sys\prebuilt\x86_64-pc-windows-msvc\krun.dll") {
Copy-Item "src\deps\libkrun-sys\prebuilt\x86_64-pc-windows-msvc\krun.dll" $stubDir
Copy-Item "src\deps\libkrun-sys\prebuilt\x86_64-pc-windows-msvc\krun.lib" $stubDir -ErrorAction SilentlyContinue
} else {
# Create minimal stub DLL using gcc (MinGW)
"void krun_stub(void) {}" | Out-File -FilePath krun_stub.c -Encoding ASCII
gcc -shared -o krun.dll krun_stub.c
Copy-Item krun.dll $stubDir
}
- name: Install maturin
run: pip install maturin
- name: Build wheel
env:
LIBRARY_PATH: /usr/local/lib
run: |
cd sdk/python
maturin build --release --strip
- name: Upload wheel
env:
MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
run: |
cd sdk/python
maturin upload --skip-existing target/wheels/*.whl
# ── Publish Node.js SDK to npm (native via napi-rs) ────────────
publish-npm:
name: Publish to npm (${{ matrix.target }})
needs: release
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
- os: ubuntu-24.04-arm
target: aarch64-unknown-linux-gnu
- os: macos-14
target: aarch64-apple-darwin
- os: windows-latest
target: x86_64-pc-windows-msvc
runs-on: ${{ matrix.os }}
env:
A3S_DEPS_STUB: "1"
steps:
- uses: actions/checkout@v4
- name: Init submodules
run: git -c http.extraheader= submodule update --init --recursive
- uses: actions/setup-node@v4
with:
node-version: "20"
registry-url: "https://registry.npmjs.org"
- uses: dtolnay/rust-toolchain@stable
- name: Install dependencies (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y build-essential pkg-config libssl-dev libclang-dev protobuf-compiler
echo "void krun_stub(void) {}" > /tmp/krun_stub.c
gcc -shared -o /tmp/libkrun.so /tmp/krun_stub.c
sudo cp /tmp/libkrun.so /usr/lib/
sudo ldconfig
- name: Install dependencies (macOS)
if: runner.os == 'macOS'
run: |
brew install protobuf
echo "void krun_stub(void) {}" > /tmp/krun_stub.c
cc -shared -o /tmp/libkrun.dylib /tmp/krun_stub.c
sudo mkdir -p /usr/local/lib
sudo cp /tmp/libkrun.dylib /usr/local/lib/
- name: Install dependencies (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
choco install protoc
# Use prebuilt krun.dll from libkrun-sys
$stubDir = "$env:USERPROFILE\.cargo\lib"
New-Item -ItemType Directory -Force -Path $stubDir
if (Test-Path "src\deps\libkrun-sys\prebuilt\x86_64-pc-windows-msvc\krun.dll") {
Copy-Item "src\deps\libkrun-sys\prebuilt\x86_64-pc-windows-msvc\krun.dll" $stubDir
Copy-Item "src\deps\libkrun-sys\prebuilt\x86_64-pc-windows-msvc\krun.lib" $stubDir -ErrorAction SilentlyContinue
} else {
"void krun_stub(void) {}" | Out-File -FilePath krun_stub.c -Encoding ASCII
gcc -shared -o krun.dll krun_stub.c
Copy-Item krun.dll $stubDir
}
- name: Build native module
env:
LIBRARY_PATH: /usr/local/lib
run: |
cd sdk/node
npm install
npx napi build --platform --release
- name: Publish
if: matrix.target == 'x86_64-unknown-linux-gnu'
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
cd sdk/node
VERSION=$(node -p "require('./package.json').version")
if npm view @a3s-lab/box@$VERSION version 2>/dev/null; then
echo "Version $VERSION already published to npm, skipping"
else
npm publish --access public --ignore-scripts
fi
# ── Update Homebrew Formula ────────────────────────────────────
publish-homebrew:
name: Update Homebrew
needs: release
runs-on: ubuntu-latest
steps:
- name: Wait for release assets
run: sleep 15
- name: Extract version
id: version
run: |
TAG="${GITHUB_REF#refs/tags/}"
VERSION="${TAG#v}"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Download release tarballs and compute SHA256
run: |
TAG="${{ steps.version.outputs.tag }}"
BASE="https://github.com/A3S-Lab/Box/releases/download/${TAG}"
for target in linux-x86_64 linux-arm64 macos-arm64; do
FILE="a3s-box-${TAG}-${target}.tar.gz"
curl -sL "${BASE}/${FILE}" -o "${FILE}"
SHA=$(shasum -a 256 "${FILE}" | awk '{print $1}')
echo "SHA_${target//-/_}=${SHA}" >> "$GITHUB_ENV"
echo "${target}: ${SHA}"
done
- name: Checkout homebrew-tap
uses: actions/checkout@v4
with:
repository: A3S-Lab/homebrew-tap
token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
path: homebrew-tap
- name: Update formula
run: |
TAG="${{ steps.version.outputs.tag }}"
VERSION="${{ steps.version.outputs.version }}"
cat > homebrew-tap/Formula/a3s-box.rb <<FORMULA
class A3sBox < Formula
desc "MicroVM sandbox runtime with TEE support"
homepage "https://github.com/A3S-Lab/Box"
version "${VERSION}"
license "MIT"
on_macos do
on_arm do
url "https://github.com/A3S-Lab/Box/releases/download/${TAG}/a3s-box-${TAG}-macos-arm64.tar.gz"
sha256 "${SHA_macos_arm64}"
end
end
on_linux do
on_arm do
url "https://github.com/A3S-Lab/Box/releases/download/${TAG}/a3s-box-${TAG}-linux-arm64.tar.gz"
sha256 "${SHA_linux_arm64}"
end
on_intel do
url "https://github.com/A3S-Lab/Box/releases/download/${TAG}/a3s-box-${TAG}-linux-x86_64.tar.gz"
sha256 "${SHA_linux_x86_64}"
end
end
def install
bin.install "a3s-box"
bin.install "a3s-box-shim"
bin.install "a3s-box-guest-init"
bin.install "a3s-box-cri" if File.exist?("a3s-box-cri")
lib.install Dir["lib/*"] if Dir.exist?("lib")
end
test do
assert_match "a3s-box", shell_output("#{bin}/a3s-box --version")
end
end
FORMULA
# Remove leading whitespace from heredoc
sed -i 's/^ //' homebrew-tap/Formula/a3s-box.rb
- name: Push formula
run: |
cd homebrew-tap
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add Formula/a3s-box.rb
git commit -m "chore: update a3s-box to ${{ steps.version.outputs.tag }}"
git push
# ── Trigger winget publishing ───────────────────────────────────
trigger-winget:
name: Trigger winget Publishing
needs: release
runs-on: ubuntu-latest
steps:
- name: Trigger winget workflow
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const tag = context.ref.replace('refs/tags/', '');
const version = tag.replace('v', '');
await github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'publish-winget.yml',
ref: 'main',
inputs: {
version: version
}
});
console.log(`Triggered winget publishing for version ${version}`);