Skip to content

Commit

Permalink
feat: allow installing the TS library on node-alpine (#1029)
Browse files Browse the repository at this point in the history
<!-- ELLIPSIS_HIDDEN -->


> [!IMPORTANT]
> Modularizes TypeScript build process with a reusable GitHub Actions
workflow and updates Cargo and Node.js configurations for musl support.
> 
>   - **GitHub Actions**:
> - Adds `build-typescript-release.reusable.yaml` for TypeScript builds
supporting targets like `x86_64-unknown-linux-gnu` and
`x86_64-unknown-linux-musl`.
> - Updates `release.yml` to use the new reusable workflow for
TypeScript builds.
>   - **Cargo Configuration**:
> - Updates `Cargo.toml` to specify linkers for
`x86_64-unknown-linux-musl` and `aarch64-unknown-linux-musl` targets.
>   - **Misc**:
>     - Updates Node.js version in `.mise.toml` to `20.14`.
> - Adds `setup-cross-compile-env.sh` script for setting up
cross-compilation environment in Docker.
> 
> <sup>This description was created by </sup>[<img alt="Ellipsis"
src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=BoundaryML%2Fbaml&utm_source=github&utm_medium=referral)<sup>
for aa50754. It will automatically
update as commits are pushed.</sup>


<!-- ELLIPSIS_HIDDEN -->
  • Loading branch information
sxlijin authored Oct 11, 2024
1 parent 9e7431f commit 1c37a0d
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 115 deletions.
123 changes: 123 additions & 0 deletions .github/workflows/build-typescript-release.reusable.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
name: Release language_client_typescript

on:
workflow_call: {}
push:
branches: [sam/alpine-builds]

concurrency:
# suffix is important to prevent a concurrency deadlock with the calling workflow
group: ${{ github.workflow }}-${{ github.ref }}-build-typescript
cancel-in-progress: true

env:
DEBUG: napi:*
APP_NAME: baml
MACOSX_DEPLOYMENT_TARGET: "10.13"

jobs:
build:
strategy:
fail-fast: false
matrix:
_:
- target: aarch64-apple-darwin
host: macos-14
node_build: pnpm build:napi-release --target aarch64-apple-darwin

- target: aarch64-unknown-linux-gnu
host: ubuntu-latest
# from https://github.com/PyO3/maturin-action?tab=readme-ov-file#manylinux-docker-container
# need a new version of manylinux to build crates on arm64-linux
container: ghcr.io/rust-cross/manylinux_2_28-cross:aarch64
node_build: pnpm build:napi-release --target aarch64-unknown-linux-gnu --use-napi-cross
cargo_args: -p baml-typescript-ffi -p baml-python-ffi

- target: x86_64-apple-darwin
host: macos-latest
node_build: pnpm build:napi-release --target x86_64-apple-darwin

- target: x86_64-pc-windows-msvc
host: windows-latest
node_build: pnpm build:napi-release --target x86_64-pc-windows-msvc
cargo_args: -p baml-typescript-ffi -p baml-python-ffi

- target: x86_64-unknown-linux-gnu
host: ubuntu-latest
node_build: pnpm build:napi-release --target x86_64-unknown-linux-gnu --use-napi-cross

- target: x86_64-unknown-linux-musl
host: ubuntu-latest
before: |
curl -LO https://musl.cc/x86_64-linux-musl-cross.tgz
tar -xzf x86_64-linux-musl-cross.tgz
echo "$PWD/x86_64-linux-musl-cross/bin" >> $GITHUB_PATH
cat >>$GITHUB_ENV <<EOF
CC_x86_64_unknown_linux_musl=x86_64-linux-musl-gcc
CXX_x86_64_unknown_linux_musl=x86_64-linux-musl-g++
AR_x86_64_unknown_linux_musl=x86_64-linux-musl-ar
EOF
node_build: pnpm build:napi-release --target x86_64-unknown-linux-musl --use-napi-cross

- target: aarch64-unknown-linux-musl
host: ubuntu-latest
before: |
curl -LO https://musl.cc/aarch64-linux-musl-cross.tgz
tar -xzf aarch64-linux-musl-cross.tgz
echo "$PWD/aarch64-linux-musl-cross/bin" >> $GITHUB_PATH
node_build: pnpm build:napi-release --target aarch64-unknown-linux-musl --use-napi-cross

name: Build ${{ matrix._.target }}
runs-on: ${{ matrix._.host }}
container: ${{ matrix._.container }}
steps:
- uses: actions/checkout@v4

# Install common toolchain dependencies
# NOTE: we can't use mise here because it doesn't support Windows
- uses: pnpm/action-setup@v3
with:
version: 9.0.6
run_install: false
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
cache-dependency-path: |
engine/language_client_typescript/pnpm-lock.yaml
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
targets: ${{ matrix._.target }}

# Set up build cache and dependencies
- uses: Swatinem/rust-cache@v2
with:
workspaces: engine
shared-key: engine-${{ github.job }}-${{ matrix._.target }}
cache-on-failure: true

- name: PNPM Install
run: pnpm install --frozen-lockfile
working-directory: engine/language_client_typescript

# per-matrix-entry dependency setup
- name: Build tools setup
run: ${{ matrix._.before }}

# Build the NAPI library and bindings
- name: PNPM Build
run: ${{ matrix._.node_build }}
working-directory: engine/language_client_typescript

- name: Build TS
run: pnpm build:ts_build
working-directory: engine/language_client_typescript

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: bindings-${{ matrix._.target }}
path: engine/language_client_typescript/*.node
if-no-files-found: error
117 changes: 3 additions & 114 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ name: BAML Release

on:
workflow_dispatch: {}
push:
branches: [sam/alpine-builds]
# need to run this periodically on the default branch to populate the build cache
schedule:
# daily at 2am PST
Expand All @@ -14,13 +16,6 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: write
id-token: write
env:
DEBUG: napi:*
APP_NAME: baml
MACOSX_DEPLOYMENT_TARGET: "10.13"
jobs:
build-wasm:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -99,114 +94,8 @@ jobs:
build-ruby-release:
uses: ./.github/workflows/build-ruby-release.reusable.yaml

# NB(sam): we should bring back release_language_client_typescript.yaml and make it another reusable workflow
build-typescript-release:
strategy:
fail-fast: false
matrix:
_:
- target: aarch64-apple-darwin
host: macos-14
node_build: pnpm build:napi-release --target aarch64-apple-darwin
baml_build_help: "off"
# mise: true

# Disabled as python is not supported on aarch64 windows
# - target: aarch64-pc-windows-msvc
# host: windows-latest
# node_build: pnpm build --target aarch64-pc-windows-msvc

- target: aarch64-unknown-linux-gnu
host: ubuntu-latest
# from https://github.com/PyO3/maturin-action?tab=readme-ov-file#manylinux-docker-container
# need a new version of manylinux to build crates on arm64-linux
container: ghcr.io/rust-cross/manylinux_2_28-cross:aarch64
node_build: pnpm build:napi-release --target aarch64-unknown-linux-gnu --use-napi-cross
cargo_args: -p baml-typescript-ffi -p baml-python-ffi
baml_build_help: "off"

- target: x86_64-apple-darwin
host: macos-latest
node_build: pnpm build:napi-release --target x86_64-apple-darwin
baml_build_help: "off"
# mise: true

- target: x86_64-pc-windows-msvc
host: windows-latest
node_build: pnpm build:napi-release --target x86_64-pc-windows-msvc
setup-python-architecture: x64
cargo_args: -p baml-typescript-ffi -p baml-python-ffi
baml_build_help: "off"

- target: x86_64-unknown-linux-gnu
host: ubuntu-latest
# Using any of the manylinux containers breaks a bunch of stuff: actions/checkout here, pnpm build there - not worth it.
container: null
node_build: pnpm build:napi-release --target x86_64-unknown-linux-gnu --use-napi-cross
mise: true

name: Build ${{ matrix._.target }}
runs-on: ${{ matrix._.host }}
container: ${{ matrix._.container }}
env:
BAML_BUILD_HELP: ${{ matrix._.baml_build_help }}
steps:
- uses: actions/checkout@v4

- uses: jdx/mise-action@v2
if: ${{ matrix._.mise }}

- uses: pnpm/action-setup@v3
with:
version: 9.0.6
run_install: false

- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
cache-dependency-path: |
engine/language_client_typescript/pnpm-lock.yaml
# Install rust
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
targets: ${{ matrix._.target }}

# Install steps
- name: PNPM Install
run: pnpm install --frozen-lockfile
working-directory: engine/language_client_typescript

# Rust caching
- uses: Swatinem/rust-cache@v2
with:
workspaces: engine
shared-key: engine-${{ github.job }}-${{ matrix._.target }}
cache-on-failure: true

- name: Build Rust
run: cargo build --release --target ${{ matrix._.target }} ${{ matrix._.cargo_args }}
working-directory: engine

# Build NAPI release
- name: PNPM Build
run: ${{ matrix._.node_build }}
working-directory: engine/language_client_typescript

# Build TS wrapper code and helpers as well
- name: Build TS
run: pnpm build:ts_build
working-directory: engine/language_client_typescript


- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: bindings-${{ matrix._.target }}
path: engine/language_client_typescript/*.node
if-no-files-found: error
uses: ./.github/workflows/build-typescript-release.reusable.yaml

# placeholder fan-in step
assert-all-builds-passed:
Expand Down
2 changes: 1 addition & 1 deletion .mise.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[tools]
node = "latest"
node = "20.14"
ruby = "3.1"
pnpm = "9.9"
6 changes: 6 additions & 0 deletions engine/language_client_typescript/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ version = "0.0.1"
name = "baml"
crate-type = ["cdylib"]

[target.x86_64-unknown-linux-musl]
linker = "x86_64-linux-musl-gcc"

[target.aarch64-unknown-linux-musl]
linker = "aarch64-linux-musl-gcc"

[dependencies]
anyhow.workspace = true
baml-types = { path = "../baml-lib/baml-types" }
Expand Down
60 changes: 60 additions & 0 deletions tools/setup-cross-compile-env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env sh

set -euxo pipefail

cat <<EOF
This script is meant for usage inside a Docker image, with boundaryml/baml
mounted into the image as a volume; it installs necessary dependencies for
cross-compiling BAML.
To start such a Docker image with BAML mounted directly:
docker run -v ~/baml2:/baml2 -it node bash
docker run -v ~/baml3:/baml3 -it node:alpine sh
Note that we do _not_ suggest running this script against ~/baml - it will require you
to nuke your node_modules
EOF

# Install curl based on the detected operating system
if [ -f /etc/os-release ]; then
case "$(grep '^ID=' /etc/os-release | cut -d= -f2)" in
amzn|amazonlinux)
yum install -y curl
;;
alpine)
apk add --no-cache curl bash
;;
ubuntu|debian)
# apt-get update && apt-get install -y curl
apt install -y curl
;;
*)
echo "Unsupported operating system. Please install curl manually."
exit 1
;;
esac
else
echo "Unable to detect operating system. Please install curl manually."
exit 1
fi

# set up mise
curl https://mise.run | sh
~/.local/bin/mise install -y pnpm

# set up rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y

# set up bashrc startup
cat >~/.bashrc <<'EOF'
eval "$(~/.local/bin/mise activate bash)"
. ~/.cargo/env
export PS1="[mise][rust] $PS1"
EOF

echo "Starting bash shell - run 'exit' or press Ctrl-D to close session"

bash

0 comments on commit 1c37a0d

Please sign in to comment.