diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..79f8bb451 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,236 @@ +name: Release + +# Builds the WASM artifacts and attaches them to a GitHub Release. +# +# Triggered by pushing a version tag. Io uses date-based versioning, so tags +# look like `2026.04.20-native-final` or `2026.03.06-stackless-alpha`; the +# `v[0-9]*` pattern is accepted too in case semver tags are ever used. +# +# The workflow can also be run manually against an existing tag via +# workflow_dispatch — useful for backfilling artifacts onto older tags. + +on: + push: + tags: + - '[0-9]*' + - 'v[0-9]*' + workflow_dispatch: + inputs: + tag: + description: 'Existing tag to build and release (e.g. 2026.04.20-native-final)' + required: true + type: string + draft: + description: 'Create the release as a draft' + required: false + type: boolean + default: false + +permissions: + contents: write + +concurrency: + group: release-${{ github.event.inputs.tag || github.ref_name }} + cancel-in-progress: false + +jobs: + release: + name: Build & Publish Release + runs-on: ubuntu-latest + env: + WASI_SDK_VERSION: "24" + WASI_SDK_FULL: "24.0" + WASMTIME_VERSION: "v27.0.0" + steps: + - name: Resolve tag + id: tag + env: + # Passed through env rather than interpolated into the script body, + # so a tag name can never be spliced into the shell command. + INPUT_TAG: ${{ github.event.inputs.tag }} + run: | + if [ -n "$INPUT_TAG" ]; then + TAG="$INPUT_TAG" + else + TAG="${GITHUB_REF#refs/tags/}" + fi + echo "tag=$TAG" >> "$GITHUB_OUTPUT" + # Alpha/beta/rc tags are published as prereleases. + case "$TAG" in + *alpha*|*beta*|*rc*|*pre*) echo "prerelease=true" >> "$GITHUB_OUTPUT" ;; + *) echo "prerelease=false" >> "$GITHUB_OUTPUT" ;; + esac + echo "Releasing $TAG" + + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ steps.tag.outputs.tag }} + submodules: 'recursive' + fetch-depth: 0 # full history so we can diff against the previous tag + + - name: Install wasi-sdk + run: | + mkdir -p "$HOME/wasi-sdk" + curl -L -o /tmp/wasi-sdk.tar.gz \ + "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION}/wasi-sdk-${WASI_SDK_FULL}-x86_64-linux.tar.gz" + tar -xzf /tmp/wasi-sdk.tar.gz -C "$HOME/wasi-sdk" --strip-components=1 + "$HOME/wasi-sdk/bin/clang" --version + + - name: Install wasmtime + run: | + curl -L -o /tmp/wasmtime.tar.xz \ + "https://github.com/bytecodealliance/wasmtime/releases/download/${WASMTIME_VERSION}/wasmtime-${WASMTIME_VERSION}-x86_64-linux.tar.xz" + mkdir -p "$HOME/wasmtime" + tar -xJf /tmp/wasmtime.tar.xz -C "$HOME/wasmtime" --strip-components=1 + echo "$HOME/wasmtime" >> "$GITHUB_PATH" + "$HOME/wasmtime/wasmtime" --version + + - name: Build io_static (WASI 0.1 module) + run: make -j$(nproc) + + - name: Build test suite + run: make -j$(nproc) test + + - name: Run tests + run: make check + timeout-minutes: 10 + + - name: Build browser reactor module + run: make -j$(nproc) browser + + - name: Build WASI 0.2 component + id: component + continue-on-error: true + run: make -j$(nproc) component + + - name: Stage artifacts + id: stage + env: + TAG: ${{ steps.tag.outputs.tag }} + run: | + set -euo pipefail + mkdir -p dist + + # Core CLI VM. The Makefile emits it without an extension; it is a + # wasm module, so publish it under a name that says so. + cp build/bin/io_static dist/io_static.wasm + + # Browser reactor module, published bare for direct