Skip to content

A short README

A short README #1

name: Build
on: [ push ]
env:
NODE_HEADERS: 18.0.0
V8_CONFIGURATION: release
V8_REF: 12.8.20
jobs:
# First, check to see if v8 has been built for each target. If not, then a more powerful `runs-on`
# builder is used on EC2.
# nb: Windows support w/ runs-on is beta and doesn't include the same tooling as GitHub.
# https://runs-on.com
# https://github.com/runs-on/runs-on
configure:
strategy:
matrix:
host:
- runs-on: ubuntu-latest
platform: linux-gnu
arch: x64
- runs-on: ubuntu-latest
platform: linux-musl
arch: x64
name: configure / ${{ matrix.host.platform }} ${{ matrix.host.arch }}
runs-on: ${{ matrix.host.runs-on }}
outputs:
linux-gnu-x64: ${{ steps.output.outputs.linux-gnu-x64 }}
linux-musl-x64: ${{ steps.output.outputs.linux-musl-x64 }}
steps:
- uses: actions/cache/restore@v4
id: cache
with:
key: v8/${{ env.V8_REF }}/${{ matrix.host.platform }}.${{ matrix.host.arch }}.${{ env.V8_CONFIGURATION }}
lookup-only: true
path: ./deps/v8/out
- shell: sh
id: output
env:
CACHE_HIT: ${{ steps.cache.outputs.cache-hit }}
HOST: ${{ matrix.host.platform }}-${{ matrix.host.arch }}
RUNS_ON: ${{ matrix.host.runs-on }}
run: |
if [ "$CACHE_HIT" = true ]; then
echo "$HOST=$RUNS_ON" >> "$GITHUB_OUTPUT"
else
case "$RUNS_ON" in
ubuntu-latest)
echo "$HOST=runs-on,runner=32cpu-linux-x64,run-id=$GITHUB_RUN_ID" >> "$GITHUB_OUTPUT"
;;
windows-latest)
echo "$HOST=runs-on,image=windows22-base-x64,family=m7i,run-id=$GITHUB_RUN_ID" >> "$GITHUB_OUTPUT"
;;
esac
fi
# Build isolated-vm
build:
needs: configure
strategy:
fail-fast: false
matrix:
host:
- runs-on: ${{ needs.configure.outputs.linux-gnu-x64 }}
container: debian:trixie
platform: linux-gnu
arch: x64
- runs-on: ${{ needs.configure.outputs.linux-musl-x64 }}
container: alpine:edge
platform: linux-musl
arch: x64
- runs-on: macos-latest
platform: darwin
arch: arm64
- runs-on: macos-13
platform: darwin
arch: x64
- runs-on: windows-latest
platform: win32
arch: x64
name: build / ${{ matrix.host.platform }} ${{ matrix.host.arch }}
runs-on: ${{ matrix.host.runs-on }}
container: ${{ matrix.host.container }}
concurrency: ${{ matrix.host.platform }} ${{ matrix.host.arch }}
steps:
# GitHub checkout
- uses: actions/checkout@v4
- name: Scripts
shell: sh
run: echo "$GITHUB_WORKSPACE/scripts" >> "$GITHUB_PATH"
# GNU `tar` & `zstd` is needed for `actions/cache`
- uses: laverdet/[email protected]
if: startsWith(matrix.host.platform, 'linux-')
with:
packages: tar zstd
# Restore previously built v8
- uses: actions/cache/restore@v4
id: v8-cache
with:
key: v8/${{ env.V8_REF }}/${{ matrix.host.platform }}.${{ matrix.host.arch }}.${{ env.V8_CONFIGURATION }}
path: ./deps/v8/out
# Build v8 on cache miss
- uses: ./.github/actions/v8
name: Build v8
if: steps.v8-cache.outputs.cache-hit != 'true'
with:
arch: ${{ matrix.host.arch }}
platform: ${{ matrix.host.platform }}
ref: ${{ env.V8_REF }}
# Cache v8
- uses: actions/cache/save@v4
if: steps.v8-cache.outputs.cache-hit != 'true'
with:
key: ${{ steps.v8-cache.outputs.cache-primary-key }}
path: ./deps/v8/out
# Install toolchain
- name: Toolchain [Linux]
uses: laverdet/[email protected]
if: startsWith(matrix.host.platform, 'linux-')
with:
packages: |
build-essential
clang-18
clang-tools-18
cmake
curl
libboost-all-dev
lld
ninja-build
nodejs
npm
- name: Toolchain [macOS]
if: matrix.host.platform == 'darwin'
run: brew install boost cmake llvm ninja node
# On Windows, the POSIX shell in GitHub actions is Git Bash. This runs in an isolated MSYS2
# installation under `C:/Program Files/Git`. The runner comes with another MSYS2 installation
# in `C:/msys64`. This action adds the root MSYS2 installation higher up in $PATH so we can
# use `pacman`, and consume binaries installed by `pacman`.
# nb: Do not be confused by the `/msys64` directory which exists in the default GitHub shell!
# It is not the same as `C:/msys64`.
- name: Toolchain [Windows]
if: matrix.host.platform == 'win32'
shell: sh
run: |
echo ::group::Toolchain
# You want the mingw version of ninja, not the msys version. The msys version uses
# `CMD.EXE` and does not work with the cmake Ninja generator.
/c/msys64/usr/bin/pacman -S --noconfirm \
mingw-w64-x86_64-boost \
mingw64/mingw-w64-x86_64-ninja \
;
echo "/c/msys64/mingw64/bin" >> "$GITHUB_PATH"
echo "/c/msys64/usr/bin" >> "$GITHUB_PATH"
echo ::endgroup::
echo ::group::Dependency Walker
mkdir -p "$RUNNER_TOOL_CACHE/depwalker"
cd "$RUNNER_TOOL_CACHE/depwalker"
# `--ssl-no-revoke`: curl: (35) schannel: next InitializeSecurityContext failed:
# CRYPT_E_REVOCATION_OFFLINE (0x80092013) - The revocation function was unable to check
# revocation because the revocation server was offline.
curl -fsSL --ssl-no-revoke -o depwalker.zip https://github.com/lucasg/Dependencies/releases/download/v1.11.1/Dependencies_x64_Release.zip
unzip depwalker.zip
rm depwalker.zip
echo "$PWD" >> "$GITHUB_PATH"
echo ::endgroup::
# Install npm dependencies
- uses: bahmutov/npm-install@v1
with:
install-command: npm install --no-audit --no-fund
- name: node-addon-api include path
shell: sh
id: node-addon-api
run: echo "include-dir=$(node -p 'require("node-addon-api").include_dir')" >> "$GITHUB_OUTPUT"
# Download nodejs headers
- uses: actions/cache/restore@v4
id: nodejs-headers-cache
with:
enableCrossOsArchive: true
key: nodejs-headers-${{ env.NODE_HEADERS }}
path: deps/nodejs
- name: node headers
id: nodejs-headers
if: steps.nodejs-headers-cache.outputs.cache-hit != 'true'
env:
NODE_HEADERS: ${{ env.NODE_HEADERS }}
run: nodejs_select "deps/nodejs/$NODE_HEADERS"
- uses: actions/cache/save@v4
if: steps.nodejs-headers.outcome == 'success'
with:
enableCrossOsArchive: true
key: ${{ steps.nodejs-headers-cache.outputs.cache-primary-key }}
path: deps/nodejs
# Build isolated-vm
- name: Configure
shell: sh
env:
IVM_HOST_ARCH: ${{ matrix.host.arch }}
IVM_HOST_PLATFORM: ${{ matrix.host.platform }}
NAPI_INCLUDE_DIR: ${{ steps.node-addon-api.outputs.include-dir }}
NODE_DIST_DIR: deps/nodejs/${{ env.NODE_HEADERS }}
V8_REF: ${{ env.V8_REF }}
V8_TARGET: ${{ matrix.host.platform }}.${{ matrix.host.arch }}.${{ env.V8_CONFIGURATION }}
run: |
set -u
V8_REF_PATH=$PWD/deps/v8/out/$V8_REF
CMAKE_MAKE_PROGRAM=ninja
CMAKE_PREFIX_PATH=
case "$IVM_HOST_PLATFORM" in
darwin)
CMAKE_CXX_COMPILER=$(brew --prefix llvm)/bin/clang++
;;
linux-*)
CMAKE_CXX_COMPILER=$(realpath "$(which clang-18)")
;;
win32)
CMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang++.exe"
# I do not know why cmake cannot find ninja without explicitly being told where it is.
CMAKE_MAKE_PROGRAM=$(which ninja)
CMAKE_PREFIX_PATH=C:/msys64/mingw64/lib/cmake
;;
esac
cmake \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_COMPILER="$CMAKE_CXX_COMPILER" \
-DCMAKE_MAKE_PROGRAM="$CMAKE_MAKE_PROGRAM" \
-DCMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH" \
-DIVM_HOST_ARCH="$IVM_HOST_ARCH"\
-DIVM_HOST_PLATFORM="$IVM_HOST_PLATFORM" \
-DNAPI_INCLUDE_DIR="$NAPI_INCLUDE_DIR" \
-DNODE_DIST_DIR="$NODE_DIST_DIR" \
-DV8_INCLUDE_DIR="$V8_REF_PATH/include" \
-DV8_INCLUDE_GN_FILE="$V8_REF_PATH/$V8_TARGET/include/v8-gn.h" \
-DV8_LIBRARY_TYPE=static \
-DV8_OUT_PATH="$V8_REF_PATH/$V8_TARGET" \
-B build \
-G Ninja \
;
- name: Build
shell: sh
run: ninja -C build ivm_backend_v8
- name: Sanity Check
shell: sh
env:
ARCH: ${{ matrix.host.arch }}
PLATFORM: ${{ matrix.host.platform }}
run: node -e 'require("./dist/backend_v8/${{ matrix.host.platform }}-${{ matrix.host.arch }}/backend_v8.node")'
# Diagnostics
- name: Symbols [Linux]
if: startsWith(matrix.host.platform, 'linux-')
run: |
set +x
ldd "dist/backend_v8/${{ matrix.host.platform }}-${{ matrix.host.arch }}/backend_v8.node" 2>&1 | grep -v 'Error relocating'
nm -guC "dist/backend_v8/${{ matrix.host.platform }}-${{ matrix.host.arch }}/backend_v8.node"
- name: Symbols [Windows]
shell: sh
if: matrix.host.platform == 'win32'
run: |
set +x
dependencies.exe -imports "dist/backend_v8/${{ matrix.host.platform }}-${{ matrix.host.arch }}/backend_v8.node"
# Upload build artifacts
- uses: actions/upload-artifact@v4
with:
name: ${{ matrix.host.platform }}-${{ matrix.host.arch }}
path: ./dist/backend_v8
if-no-files-found: error
# Run tests
test:
needs: build
strategy:
fail-fast: false
matrix:
host:
- runs-on: ubuntu-latest
container: debian:trixie
platform: linux-gnu
arch: x64
- runs-on: ubuntu-latest
container: alpine:edge
platform: linux-musl
arch: x64
- runs-on: macos-latest
platform: darwin
arch: arm64
- runs-on: macos-13
platform: darwin
arch: x64
- runs-on: windows-latest
platform: win32
arch: x64
node:
- 18
- 20
- 22
exclude:
- host:
platform: win32
node: 20
- host:
platform: win32
node: 22
name: test / ${{ matrix.host.platform }} ${{ matrix.host.arch }} nodejs ${{ matrix.node }}
runs-on: ${{ matrix.host.runs-on }}
container: ${{ matrix.host.container }}
steps:
# GitHub checkout
- uses: actions/checkout@v4
# Receive artifacts
- uses: actions/download-artifact@v4
with:
name: ${{ matrix.host.platform }}-${{ matrix.host.arch }}
path: ./dist/backend_v8
# Install nodejs [musl]
- shell: sh
id: configure-musl
if: matrix.host.platform == 'linux-musl'
env:
NODE_VERSION: ${{ matrix.node }}
run: |
echo https://dl-cdn.alpinelinux.org/alpine/edge/community/ >> /etc/apk/repositories
echo https://dl-cdn.alpinelinux.org/alpine/edge/testing/ >> /etc/apk/repositories
case "$NODE_VERSION" in
22) echo "package=nodejs-current" >> "$GITHUB_OUTPUT" ;;
20) echo "package=nodejs" >> "$GITHUB_OUTPUT" ;;
18) echo "package=nodejs18" >> "$GITHUB_OUTPUT" ;;
*)
echo "Unknown node version: $NODE_VERSION" 1>&2
exit 1
;;
esac
- uses: laverdet/[email protected]
if: steps.configure-musl.outcome == 'success'
with:
packages: alpine#${{ steps.configure-musl.outputs.package }} npm
# Install nodejs [others]
- uses: actions/setup-node@v4
if: matrix.host.platform != 'linux-musl'
with:
node-version: ${{ matrix.node }}
# Check linked binary sanity
- name: Sanity Check
shell: sh
env:
ARCH: ${{ matrix.host.arch }}
PLATFORM: ${{ matrix.host.platform }}
run: node -e 'require("./dist/backend_v8/${{ matrix.host.platform }}-${{ matrix.host.arch }}/backend_v8.node")'
# Install npm dependencies and build TypeScript
- uses: bahmutov/npm-install@v1
with:
install-command: npm install --no-audit --no-fund
- name: npm
shell: sh
run: |
npx tsc -b
npm config set script-shell "$SHELL"
# Run tests
- name: Test
run: npm run -S test
release:
needs: test
if: startsWith(github.ref, 'refs/tags/')
strategy:
matrix:
host:
- runs-on: ubuntu-latest
platform: linux-gnu
arch: x64
- runs-on: ubuntu-latest
platform: linux-musl
arch: x64
- runs-on: macos-latest
platform: darwin
arch: arm64
- runs-on: macos-13
platform: darwin
arch: x64
- runs-on: windows-latest
platform: win32
arch: x64
name: release / ${{ matrix.host.platform }} ${{ matrix.host.arch }}
runs-on: ${{ matrix.host.runs-on }}
permissions:
contents: write
steps:
# Receive artifacts
- uses: actions/download-artifact@v4
with:
name: ${{ matrix.host.platform }}-${{ matrix.host.arch }}
path: ./dist/backend_v8
# Save tar
- name: tar
id: tar
shell: sh
env:
PLATFORM_NAME: ${{ matrix.host.platform }}-${{ matrix.host.arch }}
run: |
TAG=${GITHUB_REF#refs/tags/}
TAR_FILE="isolated-vm-node-$TAG-$PLATFORM_NAME.tar.gz"
tar czf "$TAR_FILE" dist/backend_v8
echo "tar=$PWD/$TAR_FILE" >> "$GITHUB_OUTPUT"
# Release
- name: Release
uses: softprops/action-gh-release@v1
with:
files: ${{ steps.tar.outputs.tar }}