Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .envrc
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ export BAML_TELEMETRY_ENV=internal

# Use nix if nix-shell is available,
# Otherwise, use mise and brew.
if command -v nix-shell >/dev/null 2>&1; then
# Never in CI: jobs pin their own toolchains (rustup +MSRV, mise) and the
# flake devshell's cargo shadowing rustup's shim breaks `cargo +1.91.1`
# (observed live on nix-capable self-hosted runners; hosted images have no
# nix so this branch never ran there).
if [ "${CI:-}" != "true" ] && command -v nix-shell >/dev/null 2>&1; then
use flake
export PATH=$(pwd)/tools:$PATH
else
Expand Down
2 changes: 2 additions & 0 deletions .github/actionlint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ self-hosted-runner:
- blacksmith-4vcpu-ubuntu-2204-arm
- blacksmith-8vcpu-windows-2025
- blacksmith-4vcpu-windows-2025
# self-hosted ix runner pool
- ix
90 changes: 90 additions & 0 deletions .github/actions/setup-ci-shell/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: "Set up CI toolchains"
description: |
One seam for how a job gets its toolchains, with two arms:

- nix on PATH (the ix runner pool, which is NixOS): enter the flake's CI
dev shell once and persist its environment into GITHUB_ENV, so every
later step runs the shell's pinned tools as plain commands. Closures
substitute from the pool's binary caches; nothing is downloaded from
tool registries.
- no nix (the Blacksmith fork-PR fallback; those images have no nix):
today's imperative path, `rustup show` + setup-mise.

Multi-toolchain jobs must not use `cargo +toolchain` on the nix arm - the
shell's cargo is not a rustup shim (see .envrc's history note). Each Rust
toolchain gets its own shell attribute instead (ci, ci-msrv).

inputs:
shell:
description: devShells attribute to enter on nix-capable runners.
required: false
default: "ci"
mise-install-args:
description: |
setup-mise install_args for the fallback arm. Empty skips mise
entirely (pass the same narrow set the job used before this action).
required: false
default: ""
rustup:
description: |
Whether the fallback arm runs `rustup show` to install the toolchain
pinned by rust-toolchain.toml. Set "false" for jobs that install a
different toolchain themselves (e.g. the MSRV job).
required: false
default: "true"
rustup-working-directory:
description: Directory whose rust-toolchain.toml `rustup show` honors.
required: false
default: "baml_language"

outputs:
nix:
description: |
"true" when the job entered the flake shell; jobs gate their
fallback-only steps (rustup target add, musl cross setup) on this.
value: ${{ steps.detect.outputs.nix }}

runs:
using: "composite"
steps:
- name: Detect nix
id: detect
shell: bash
run: |
if command -v nix >/dev/null 2>&1; then
echo "nix=true" >>"$GITHUB_OUTPUT"
else
echo "nix=false" >>"$GITHUB_OUTPUT"
fi

- name: Enter the flake CI shell
if: steps.detect.outputs.nix == 'true'
shell: bash
# Retried: the first entry on a freshly rolled VM downloads the shell
# closure, and a transient substituter failure should not fail the job
# (same shape as ix-cross.yml's retry). `ci-env` appends the current
# PATH so runner-provided tools stay reachable for unconverted steps.
run: |
for attempt in 1 2 3; do
if BAML_CI_BASE_PATH="$PATH" \
nix develop "$GITHUB_WORKSPACE#${{ inputs.shell }}" -c ci-env >"$RUNNER_TEMP/ci-shell.env"; then
cat "$RUNNER_TEMP/ci-shell.env" >>"$GITHUB_ENV"
exit 0
fi
echo "nix develop failed (attempt $attempt), retrying" >&2
sleep $((attempt * 10))
done
echo "could not enter devShells.${{ inputs.shell }} after 3 attempts" >&2
exit 1

- name: Install Rust toolchain (no-nix fallback)
if: steps.detect.outputs.nix == 'false' && inputs.rustup == 'true'
shell: bash
working-directory: ${{ inputs.rustup-working-directory }}
run: rustup show

- name: Install tools with mise (no-nix fallback)
if: steps.detect.outputs.nix == 'false' && inputs.mise-install-args != ''
uses: ./.github/actions/setup-mise
with:
install_args: ${{ inputs.mise-install-args }}
8 changes: 6 additions & 2 deletions .github/actions/setup-musl-cross/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ runs:
# The cc/cargo env var names are the target triple with dashes as
# underscores (CC lower-cased, the cargo linker var upper-cased).
# Derived from the target so the platform contract stays shell-free.
sudo apt-get update
sudo apt-get install -y musl-tools
# Self-hosted ix runners ship musl-gcc on the unit PATH (NixOS: no
# apt); only install on GitHub-hosted Ubuntu images.
if ! command -v musl-gcc >/dev/null 2>&1; then
sudo apt-get update
sudo apt-get install -y musl-tools
fi
target="${{ inputs.target }}"
up="$(printf '%s' "$target" | tr '[:lower:]' '[:upper:]')"
echo "CC_${target//-/_}=musl-gcc" >> "$GITHUB_ENV"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-cli-release.reusable.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ jobs:
# Download protoc directly to avoid rate limiting
PROTOC_VERSION="27.1"
curl -LO "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-win64.zip"
unzip -q protoc-${PROTOC_VERSION}-win64.zip -d $HOME/.local
unzip -oq protoc-${PROTOC_VERSION}-win64.zip -d $HOME/.local
echo "$HOME/.local/bin" >> $GITHUB_PATH
rm protoc-${PROTOC_VERSION}-win64.zip

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/build2-bridge-cffi.reusable.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ defaults:

jobs:
# The cffi build matrix is generated from the repository's platform contract
# (`release/platforms.json`) so the target set + per-target build config live
# (`baml_language/crates/baml_release/platforms.json`) so the target set + per-target build config live
# in one machine-readable place, not a hand-copied YAML list. Any future
# experimental target carries that tier in the contract, which drives
# `continue-on-error` on the build job below.
Expand Down Expand Up @@ -103,7 +103,7 @@ jobs:
| .artifacts.cffi as $c
| {target: .triple, os: $c.runner}
+ ({use_cross: $c.use_cross, smoke: $c.smoke, experimental: $c.experimental}
| with_entries(select(.value == true)))]' release/platforms.json)"
| with_entries(select(.value == true)))]' baml_language/crates/baml_release/platforms.json)"
echo "include=$include" >> "$GITHUB_OUTPUT"
jq . <<<"$include"

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/build2-java-sdk.reusable.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ name: BAML SDK Release - Build Java
# canary → `0.15.0`, nightly → `0.15.0-nightly.YYYYMMDD.a`), injected via
# `-PbamlVersion`.
# - the 8-target build matrix is generated from the repository platform
# contract (`release/platforms.json`) `java` artifact key, not a hand-copied
# contract (`baml_language/crates/baml_release/platforms.json`) `java` artifact key, not a hand-copied
# list. Experimental targets (musl, windows-arm64) carry `experimental: true`
# there, which drives `continue-on-error` so they never block the release.
#
Expand Down Expand Up @@ -63,7 +63,7 @@ defaults:

jobs:
# The java build matrix is generated from the platform contract
# (`release/platforms.json`) so the target set + per-target runner live in one
# (`baml_language/crates/baml_release/platforms.json`) so the target set + per-target runner live in one
# machine-readable place. `libc` rides along so the musl setup step can key on
# it; `experimental` is emitted only when true (drives continue-on-error).
matrix:
Expand All @@ -90,7 +90,7 @@ jobs:
| select(.artifacts.java != null)
| .artifacts.java as $j
| {target: .triple, os: $j.runner, platform: $j.platform, libc: .libc}
+ ({experimental: $j.experimental} | with_entries(select(.value == true)))]' release/platforms.json)"
+ ({experimental: $j.experimental} | with_entries(select(.value == true)))]' baml_language/crates/baml_release/platforms.json)"
echo "include=$include" >> "$GITHUB_OUTPUT"
jq . <<<"$include"

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/build2-python-sdk.reusable.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ defaults:

jobs:
# Target set + per-target runner/manylinux/architecture come from the platform
# contract (`release/platforms.json`), not a hand-copied matrix list.
# contract (`baml_language/crates/baml_release/platforms.json`), not a hand-copied matrix list.
matrix:
name: Compute target matrix
runs-on: ubuntu-latest
Expand All @@ -52,7 +52,7 @@ jobs:
| .artifacts.python as $p
| {target: .triple, runs_on: $p.runner}
+ (if $p.manylinux then {manylinux: $p.manylinux} else {} end)
+ (if $p.architecture then {architecture: $p.architecture} else {} end)]' release/platforms.json)"
+ (if $p.architecture then {architecture: $p.architecture} else {} end)]' baml_language/crates/baml_release/platforms.json)"
echo "include=$include" >> "$GITHUB_OUTPUT"
jq . <<<"$include"

Expand Down
Loading