Skip to content

Simplify release: single JS file, no side module #4

Simplify release: single JS file, no side module

Simplify release: single JS file, no side module #4

Workflow file for this run

name: Build SymEngine WASM
on:
schedule:
- cron: '0 0 * * 0' # Every Sunday at midnight UTC
workflow_dispatch:
inputs:
force_rebuild:
description: 'Force rebuild even if release exists'
required: false
default: 'false'
type: boolean
specific_version:
description: 'Build specific version (e.g., 0.12.0)'
required: false
type: string
push:
branches: [main]
paths:
- 'build_wasm.sh'
- 'src/**'
- 'cmake/**'
- '.github/workflows/build.yml'
permissions:
contents: write
concurrency:
group: "build"
cancel-in-progress: false
jobs:
check-versions:
runs-on: ubuntu-latest
outputs:
versions_to_build: ${{ steps.check.outputs.versions }}
has_new_versions: ${{ steps.check.outputs.has_new }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Check for new SymEngine versions
id: check
env:
GH_TOKEN: ${{ github.token }}
run: |
# Get existing releases in this repo
EXISTING=$(gh release list --json tagName -q '.[].tagName' 2>/dev/null | tr '\n' ' ' || echo "")
echo "Existing releases: $EXISTING"
# Get available SymEngine releases (exclude known broken versions)
AVAILABLE=$(curl -s https://api.github.com/repos/symengine/symengine/releases | \
jq -r '.[].tag_name' | sed 's/^v//' | grep -v '^0\.8\.1$' | head -10)
echo "Available SymEngine versions: $AVAILABLE"
# Find versions not yet built
TO_BUILD=""
for version in $AVAILABLE; do
TAG="v${version}"
if ! echo "$EXISTING" | grep -q "$TAG"; then
TO_BUILD="$TO_BUILD $version"
fi
done
# Handle specific version request
if [ -n "${{ inputs.specific_version }}" ]; then
TO_BUILD="${{ inputs.specific_version }}"
fi
# Handle force rebuild - rebuild latest
if [ "${{ inputs.force_rebuild }}" = "true" ]; then
TO_BUILD=$(echo "$AVAILABLE" | head -1)
fi
TO_BUILD=$(echo "$TO_BUILD" | xargs)
if [ -z "$TO_BUILD" ]; then
echo "No new versions to build"
echo "has_new=false" >> $GITHUB_OUTPUT
echo "versions=[]" >> $GITHUB_OUTPUT
else
echo "Versions to build: $TO_BUILD"
echo "has_new=true" >> $GITHUB_OUTPUT
JSON_ARRAY=$(echo "$TO_BUILD" | tr ' ' '\n' | jq -R . | jq -sc .)
echo "versions=$JSON_ARRAY" >> $GITHUB_OUTPUT
fi
build:
needs: check-versions
if: needs.check-versions.outputs.has_new_versions == 'true'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
version: ${{ fromJson(needs.check-versions.outputs.versions_to_build) }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Emscripten
uses: mymindstorm/setup-emsdk@v14
with:
version: '3.1.51'
actions-cache-folder: 'emsdk-cache'
- name: Verify Emscripten
run: emcc --version
- name: Cache Boost
uses: actions/cache@v4
with:
path: deps/boost
key: boost-1.84.0
- name: Download dependencies
run: |
VERSION="${{ matrix.version }}"
# Download SymEngine
mkdir -p symengine
echo "Downloading SymEngine v$VERSION"
curl -fsSL "https://github.com/symengine/symengine/archive/refs/tags/v${VERSION}.tar.gz" | \
tar xz --strip-components=1 -C symengine
# Download Boost if not cached
if [ ! -d "deps/boost" ]; then
mkdir -p deps
curl -fsSL "https://archives.boost.io/release/1.84.0/source/boost_1_84_0.tar.gz" | \
tar xz -C deps
mv deps/boost_1_84_0 deps/boost
fi
- name: Build WASM with embind
run: ./build_wasm.sh --mode=standalone --with-embind --single-file
- name: Prepare release artifacts
run: |
VERSION="${{ matrix.version }}"
VERSION_SAFE=$(echo "$VERSION" | tr '.' '-')
mkdir -p release
mv dist/symengine.js "release/symengine.${VERSION_SAFE}.js"
mv dist/symengine.d.ts "release/symengine.${VERSION_SAFE}.d.ts"
- name: Create GitHub Release
env:
GH_TOKEN: ${{ github.token }}
run: |
VERSION="${{ matrix.version }}"
VERSION_SAFE=$(echo "$VERSION" | tr '.' '-')
# Check if release already exists
if gh release view "v${VERSION}" >/dev/null 2>&1; then
if [ "${{ inputs.force_rebuild }}" = "true" ]; then
echo "Deleting existing release for rebuild"
gh release delete "v${VERSION}" --yes
else
echo "Release v${VERSION} already exists, skipping"
exit 0
fi
fi
# Create release
gh release create "v${VERSION}" \
--title "SymEngine.js v${VERSION}" \
--notes "WebAssembly build of SymEngine v${VERSION}
## Files
| File | Description |
|------|-------------|
| symengine.${VERSION_SAFE}.js | JavaScript ES6 module (WASM bundled) |
| symengine.${VERSION_SAFE}.d.ts | TypeScript declarations |
## Usage
\`\`\`javascript
import SymEngine from './symengine.${VERSION_SAFE}.js';
const se = await SymEngine();
const expr = se.parse('(x + 1)^2');
console.log(expr.expand().toString());
// Output: 1 + 2*x + x**2
\`\`\`
## Build Info
- Integer Class: boostmp (no GMP dependency)
- Emscripten: $(emcc --version | head -1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')
- Build Date: $(date -u +%Y-%m-%d)
" \
release/*
echo "Created release v${VERSION}"
update-latest:
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Update latest symlink release
env:
GH_TOKEN: ${{ github.token }}
run: |
# Get the latest version
LATEST=$(gh release list --json tagName,isLatest -q 'sort_by(.tagName) | reverse | .[0].tagName')
echo "Latest release: $LATEST"
# Download latest release assets
mkdir -p latest
gh release download "$LATEST" --dir latest
# Rename to generic names
VERSION=$(echo "$LATEST" | sed 's/^v//')
VERSION_SAFE=$(echo "$VERSION" | tr '.' '-')
cp "latest/symengine.${VERSION_SAFE}.js" latest/symengine.latest.js
cp "latest/symengine.${VERSION_SAFE}.d.ts" latest/symengine.latest.d.ts
# Delete old 'latest' release if exists
gh release delete "latest" --yes 2>/dev/null || true
# Create 'latest' release
gh release create "latest" \
--title "Latest SymEngine.js (v${VERSION})" \
--notes "Always points to the latest stable build.
Current version: ${VERSION}
Use versioned releases for production to avoid breaking changes.
## Quick Start
\`\`\`javascript
import SymEngine from './symengine.latest.js';
const se = await SymEngine();
\`\`\`
" \
--prerelease \
latest/symengine.latest.*
echo "Updated latest release to point to $LATEST"