Skip to content

build(codegen): Pipe gen_bindings output through clang-format #7

build(codegen): Pipe gen_bindings output through clang-format

build(codegen): Pipe gen_bindings output through clang-format #7

Workflow file for this run

# Release workflow.
#
# Triggered by `v*.*.*` tag pushes. Builds and publishes everything in
# one workflow, mirroring the libsonare publish.yml shape:
#
# - publish-npm : build the embind WASM, smoke-test, publish
# `@libraz/formulon`, create the GitHub Release.
# - build-cli : matrix-build `formulon_cli` per platform-arch,
# upload tar.gz archives + sha256 sums.
# - python-wheel : build the capi WASM and a single py3-none-any
# wheel (the Python distribution is pure-Python +
# wasmtime; one wheel works on every platform).
# - publish-pypi : publish that wheel to PyPI via trusted publishing.
# - attach-cli : after the release exists, upload CLI tarballs to it.
#
# Required setup:
# - npm Trusted Publishing (OIDC) linked for `@libraz/formulon`.
# The very first publish must be performed manually so the package
# name exists on the registry; subsequent versions are published
# by this workflow via OIDC (no `NPM_TOKEN` secret required).
# - PyPI trusted publishing configured for project `formulon`,
# environment `pypi`, this workflow file.
#
# The N-API addon (`@libraz/formulon-native`) ships its prebuilds via
# `prebuild.yml` (`release-bundle` job runs on the same `v*` tag); npm
# publish for the addon is currently manual and out of scope here.
name: release
on:
push:
tags: ['v*.*.*']
permissions:
contents: write
id-token: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
jobs:
publish-npm:
name: Publish npm + create GitHub Release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Order matters: setup-emsdk@v14 prepends its bundled (non-executable)
# node / cmake to PATH. Running setup-node AFTER it re-prepends the
# real node, so `node ...` in subsequent steps hits the actions-managed
# binary, not emsdk's broken shim. cmake still needs an explicit
# CMAKE=/usr/bin/cmake override (emsdk owns its own cmake binary that
# actions/setup-node cannot displace).
- uses: mymindstorm/setup-emsdk@v14
with:
version: 3.1.74
actions-cache-folder: emsdk-cache
- uses: actions/setup-node@v4
with:
# Node 24 ships with npm >= 11.5.1 natively, which supports
# token-less OIDC publishing via Trusted Publisher. Node 22
# ships with npm 10, which can sign provenance via OIDC but
# still requires a NODE_AUTH_TOKEN for the publish PUT and
# errors with 404 against the OIDC-only registry path.
node-version: 24
registry-url: 'https://registry.npmjs.org'
- name: Install host tools
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends brotli cmake ninja-build
- name: Verify version match (npm)
run: |
set -euo pipefail
tag_version="${GITHUB_REF_NAME#v}"
pkg_version=$(node -p "require('./packages/npm/package.json').version")
if [ "${tag_version}" != "${pkg_version}" ]; then
echo "Tag ${GITHUB_REF_NAME} (version ${tag_version}) does not match packages/npm/package.json version ${pkg_version}"
exit 1
fi
- name: Build WASM
# Force apt-installed cmake; emsdk's PATH order can shadow it
# with a non-executable bundled cmake (see ci.yml WASM job).
run: make CMAKE=/usr/bin/cmake wasm
- name: Size report (advisory)
run: tools/bench/wasm_size_report.sh build-wasm/formulon.wasm
- name: Stage and smoke-test npm package
# CMAKE override mirrors the Build WASM step (emsdk's PATH order
# shadows the system cmake with a non-executable bundled copy).
# node resolves cleanly because setup-node was placed AFTER
# setup-emsdk at the top of this job.
run: |
make CMAKE=/usr/bin/cmake npm-package
make CMAKE=/usr/bin/cmake npm-test
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
name: Formulon ${{ github.ref_name }}
tag_name: ${{ github.ref_name }}
generate_release_notes: true
body_path: docs/releases/${{ github.ref_name }}.md
fail_on_unmatched_files: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish to npm
working-directory: packages/npm
run: npm publish --access public --provenance
build-cli:
name: Build CLI ${{ matrix.platform-arch }}
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- platform-arch: darwin-arm64
runner: macos-latest
archive-ext: tar.gz
- platform-arch: linux-x64
runner: ubuntu-latest
archive-ext: tar.gz
- platform-arch: linux-arm64
runner: ubuntu-24.04-arm
archive-ext: tar.gz
steps:
- uses: actions/checkout@v4
- name: Install build deps (Linux)
if: startsWith(matrix.platform-arch, 'linux-')
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends build-essential cmake ninja-build
- name: Configure
run: cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DFM_BUILD_TESTING=OFF
- name: Build CLI
run: cmake --build build --parallel --target formulon_cli
- name: Stage archive
id: stage
run: |
set -euo pipefail
version="${GITHUB_REF_NAME#v}"
dir="formulon-${version}-${{ matrix.platform-arch }}"
mkdir -p "${dir}"
cp build/bin/formulon_cli "${dir}/formulon"
cp LICENSE "${dir}/LICENSE"
[ -f NOTICE ] && cp NOTICE "${dir}/NOTICE" || true
[ -f README.md ] && cp README.md "${dir}/README.md" || true
tar -czf "${dir}.tar.gz" "${dir}"
shasum -a 256 "${dir}.tar.gz" > "${dir}.tar.gz.sha256"
echo "archive=${dir}.tar.gz" >> "$GITHUB_OUTPUT"
- uses: actions/upload-artifact@v4
with:
name: formulon-cli-${{ matrix.platform-arch }}
path: |
formulon-*.tar.gz
formulon-*.tar.gz.sha256
retention-days: 14
if-no-files-found: error
python-wheel:
name: Build py3-none-any wheel
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- uses: mymindstorm/setup-emsdk@v14
with:
# Pin to keep WASM size deterministic (matches publish-npm).
version: 3.1.74
actions-cache-folder: emsdk-cache
- name: Install host tools
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends build-essential cmake ninja-build
- name: Install Python build deps
run: python -m pip install --upgrade pip setuptools wheel
- name: Verify version match (PyPI)
shell: bash
run: |
set -euo pipefail
tag_version="${GITHUB_REF_NAME#v}"
pkg_version=$(python -c "import re; print(re.search(r'^version\s*=\s*\"([^\"]+)\"', open('packages/python/pyproject.toml').read(), re.M).group(1))")
if [ "${tag_version}" != "${pkg_version}" ]; then
echo "Tag ${GITHUB_REF_NAME} (version ${tag_version}) does not match pyproject.toml version ${pkg_version}"
exit 1
fi
- name: Build wheel
# CMAKE override mirrors publish-npm: emsdk's PATH order can
# shadow the system cmake with a non-executable bundled copy.
run: make CMAKE=/usr/bin/cmake python-wheel
- name: Smoke test wheel
# Install into the build venv, run the smoke-test suite. The
# wheel is py3-none-any so this exercises the wasmtime-driven
# WASM module exactly as a downstream user would.
run: |
set -euo pipefail
wheel=$(ls build-py/dist/formulon-*.whl | head -1)
python -m pip install "${wheel}"
python -m unittest discover -v -s packages/python/tests
- uses: actions/upload-artifact@v4
with:
name: formulon-wheel
path: build-py/dist/formulon-*.whl
retention-days: 14
if-no-files-found: error
publish-pypi:
name: Publish to PyPI
needs: [python-wheel]
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/formulon
steps:
- uses: actions/download-artifact@v4
with:
name: formulon-wheel
path: dist/
- name: List wheels
run: ls -la dist/
- uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist/
# Idempotent: if a re-run uploads the same version, skip
# instead of failing. Useful when only a sibling job (e.g.
# publish-npm) failed and the release tag has to be re-pushed.
skip-existing: true
attach-cli:
name: Attach CLI archives to GitHub Release
needs: [publish-npm, build-cli]
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
pattern: formulon-cli-*
path: cli-dist/
merge-multiple: true
- name: List CLI archives
run: ls -la cli-dist/
- name: Attach to GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
files: cli-dist/*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}