From cf15dd10275a52dcac38ae26e5401d74e3ed896c Mon Sep 17 00:00:00 2001 From: Steve Dekorte Date: Sat, 15 Aug 2026 16:06:01 -0700 Subject: [PATCH] Add workflow to attach build artifacts to GitHub releases Pushing a version tag now builds the WASM artifacts, runs the test suite, and attaches the results to a GitHub Release: io_static.wasm, io_component.wasm, io_browser.wasm, a browser kit with the io.js loader, and a checksum file. Tags containing alpha, beta, rc, or pre are published as prereleases. The workflow can also be run by hand against an existing tag to add artifacts to older releases. Re-running it updates the release rather than failing. Also documents the release steps in DEVELOPERS.md and ignores the dist/ directory the workflow creates. Co-Authored-By: Claude Opus 5 --- .github/workflows/release.yml | 236 ++++++++++++++++++++++++++++++++++ .gitignore | 2 + DEVELOPERS.md | 29 +++++ 3 files changed, 267 insertions(+) create mode 100644 .github/workflows/release.yml 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