magic/.github/workflows/main-wasm.yml

167 lines
6.5 KiB
YAML

name: CI-wasm
# Builds the Magic WebAssembly target (both the non-TCL and TCL variants)
# on every push and pull request as a CI check. **Publishing** only happens
# when a release tag of the form v<x.y.z>... is pushed — that gate is the
# manual release trigger:
#
# # bump magic/VERSION and/or npm/tcl.ref, commit, push to default branch
# git tag v8.3.638
# git push origin v8.3.638
#
# The tag name (minus the leading "v") becomes the published npm version.
# Forks publish under their own namespace via the @<owner>/ scope.
on:
push:
pull_request:
workflow_dispatch:
inputs:
emsdk_version:
description: 'emsdk version to build with (default: latest; pin a version number to bisect)'
type: string
default: 'latest'
dry_run:
description: 'Dry run: pack only, do not publish even on tag pushes'
type: boolean
default: true
# actions/upload-artifact@v5 still runs on Node.js 20. Force Node 24 to
# silence the deprecation warning until upload-artifact ships a Node-24
# release. Drop this once upgraded.
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
permissions:
contents: read
packages: write
jobs:
build-wasm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 2
- name: Set up Node.js
uses: actions/setup-node@v5
with:
node-version: '22'
registry-url: 'https://npm.pkg.github.com'
- name: Install emsdk
env:
# Defaults to latest so CI tracks emsdk HEAD and catches breakage early.
# Override via workflow_dispatch to pin a specific version when needed
# (e.g. to bisect a regression or verify a post-build.sh patch still applies).
EMSDK_VERSION: ${{ github.event.inputs.emsdk_version || 'latest' }}
run: |
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install "$EMSDK_VERSION"
./emsdk activate "$EMSDK_VERSION"
# Dump native + emscripten preprocessor defines. Useful for diagnosing
# WASM-build differences after an emsdk bump.
- name: Emscripten Diagnostic
run: |
source ./emsdk/emsdk_env.sh
echo "===== gcc -dM -E - ====="; echo | gcc -dM -E - | sort
echo "===== g++ -dM -E - ====="; echo | g++ -dM -E - | sort
echo "===== emcc -dM -E - ====="; echo | emcc -dM -E - | sort
echo "===== em++ -dM -E - ====="; echo | em++ -dM -E - | sort
# Clone intubun/tcl into a sibling directory at the pinned ref from
# npm/tcl.ref. npm/build.sh would do this on its own, but doing it as
# an explicit step makes the resolved SHA visible at the top of the
# job log and keeps the build step's output focused on the C build.
# The TCL source tree is treated as read-only — the actual WASM build
# runs inside magic (toolchains/emscripten/build-tcl-wasm.sh).
- name: Pin and clone tcltk/tcl
run: |
. npm/tcl.ref
: "${TCL_REPO_URL:=https://github.com/tcltk/tcl.git}"
: "${TCL_REF:=main}"
echo "Pinned TCL: $TCL_REF ($TCL_REPO_URL)"
# autocrlf=false: ubuntu-latest is already LF, but make it explicit.
git -c core.autocrlf=false clone "$TCL_REPO_URL" ../tcl
( cd ../tcl && git checkout --detach "$TCL_REF" )
- name: Build WASM — both variants (tcl + notcl)
run: |
source ./emsdk/emsdk_env.sh
bash npm/build.sh --variant=both
- name: Run example tests (non-TCL variant)
run: cd npm && npm test
- name: Run full test suite (TCL variant)
run: cd npm && npm run test:tcl
# Dump generated text outputs (.ext, .spice, .cif, …) into the CI log
# so a regression in extraction / netlisting / cifoutput is visible
# without having to download artifacts. The .gds output is binary —
# skip it and just record its size.
- name: Display example outputs
run: |
shopt -s nullglob
for f in npm/examples/output/*; do
name=$(basename "$f")
case "$f" in
*.gds) echo "===== $name (binary, $(wc -c < "$f") bytes — skipped) =====" ;;
*) echo "===== $name ====="; cat "$f" ;;
esac
done
# The release gate. We publish a new npm version only when a tag of the
# shape v<x.y.z>... is pushed. The tag name (minus the leading "v") is
# taken as the npm version verbatim — so `v8.3.638` → npm 8.3.638.
- name: Determine release version (tag-driven only)
id: release
run: |
if [ "${{ github.event_name }}" = "push" ] && \
echo "${{ github.ref }}" | grep -Eq '^refs/tags/v[0-9]+\.[0-9]+\.[0-9]+'; then
tag="${GITHUB_REF#refs/tags/}"
echo "publish=true" >> "$GITHUB_OUTPUT"
echo "version=${tag#v}" >> "$GITHUB_OUTPUT"
echo "Tag release: $tag → npm version ${tag#v}"
else
# For non-tag CI runs, use a dev-suffixed version so the packed
# tarball is still consumable for local inspection / artifact upload.
base=$(cat VERSION)
date=$(git show -s --format=%cs | tr -d '-')
hash=$(git show -s --format=%h)
echo "publish=false" >> "$GITHUB_OUTPUT"
echo "version=${base}-${date}.${hash}" >> "$GITHUB_OUTPUT"
echo "Non-tag build: will not publish."
fi
- name: Set package version and scope
env:
VERSION: ${{ steps.release.outputs.version }}
run: |
# Scope the package to the repo owner so it lands in the right
# GitHub Packages namespace regardless of who hosts the repo.
SCOPED_NAME="@${{ github.repository_owner }}/magic-vlsi-wasm"
cd npm
npm pkg set name="$SCOPED_NAME"
npm pkg set publishConfig.registry="https://npm.pkg.github.com"
npm version "$VERSION" --no-git-tag-version --allow-same-version
- name: Pack
run: ./npm/pack.sh
- name: Upload tarball as artifact
uses: actions/upload-artifact@v5
with:
name: magic-vlsi-wasm-npm
path: npm/*.tgz
- name: Publish to GitHub Packages
if: steps.release.outputs.publish == 'true' && github.event.inputs.dry_run != 'true'
run: cd npm && npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}