Skip to content

Bump the npm_and_yarn group across 11 directories with 8 updates #10183

Bump the npm_and_yarn group across 11 directories with 8 updates

Bump the npm_and_yarn group across 11 directories with 8 updates #10183

Workflow file for this run

name: BAML Runtime
on:
pull_request:
branches:
- canary
push:
paths:
- "engine/**"
- ".github/workflows/primary.yml"
- "typescript/**"
branches:
- canary
# need to run this periodically on the default branch to populate the build cache
schedule:
# daily at 2am PST
- cron: 0 10 * * *
merge_group:
types: [checks_requested]
workflow_dispatch: {}
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
pull-requests: read
repository-projects: read
# Common environment variables
env:
# Turbo remote caching
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: gloo
jobs:
# Determine if runtime-related files have changed
# This job enables auto-pass when only baml_language/ or typescript/apps/beps/ files are modified
determine_changes:
name: "Determine changes"
runs-on: ubuntu-latest
outputs:
# Flag that is raised when runtime-related code is changed
# If false, we can skip all runtime tests since only baml_language/ or beps/ changed
runtime: ${{ steps.check_runtime.outputs.changed }}
skip_reason: ${{ steps.check_runtime.outputs.skip_reason }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- name: Determine merge base
id: merge_base
env:
BASE_REF: ${{ github.event.pull_request.base.ref || 'canary' }}
run: |
sha=$(git merge-base HEAD "origin/${BASE_REF}" 2>/dev/null || echo "")
if [ -z "$sha" ]; then
# Fallback for workflow_dispatch or schedule
sha=$(git rev-parse HEAD~1 2>/dev/null || git rev-parse HEAD)
fi
echo "sha=${sha}" >> "$GITHUB_OUTPUT"
- name: Check if runtime code changed
id: check_runtime
env:
MERGE_BASE: ${{ steps.merge_base.outputs.sha }}
run: |
# For scheduled runs, workflow_dispatch, or pushes to canary, always run
if [[ "${{ github.event_name }}" == "schedule" ]] || \
[[ "${{ github.event_name }}" == "workflow_dispatch" ]] || \
[[ "${{ github.ref }}" == "refs/heads/canary" ]]; then
echo "changed=true" >> "$GITHUB_OUTPUT"
echo "skip_reason=" >> "$GITHUB_OUTPUT"
exit 0
fi
# Get list of all changed files
CHANGED_FILES=$(git diff --name-only "${MERGE_BASE}...HEAD" 2>/dev/null || echo "")
if [ -z "$CHANGED_FILES" ]; then
echo "No changes detected, running all tests"
echo "changed=true" >> "$GITHUB_OUTPUT"
echo "skip_reason=" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "Changed files:"
echo "$CHANGED_FILES"
# Check if ALL changed files are in baml_language/ or typescript/apps/beps/ (auto-skip paths)
# If any file is outside these paths, we need to run the tests
RUNTIME_CHANGED="false"
ONLY_BAML_LANGUAGE="true"
ONLY_BEPS="true"
while IFS= read -r file; do
# Skip empty lines
[ -z "$file" ] && continue
# Check if file is in baml_language/
if [[ ! "$file" =~ ^baml_language/ ]]; then
ONLY_BAML_LANGUAGE="false"
fi
# Check if file is in typescript/apps/beps/
if [[ ! "$file" =~ ^typescript/apps/beps/ ]]; then
ONLY_BEPS="false"
fi
# Check if file is in a path that requires runtime tests
# Runtime tests are needed for: engine/, typescript/ (except beps), integ-tests/, .github/workflows/primary.yml
if [[ "$file" =~ ^engine/ ]] || \
[[ "$file" =~ ^integ-tests/ ]] || \
[[ "$file" == ".github/workflows/primary.yml" ]] || \
[[ "$file" =~ ^\.github/actions/ ]] || \
([[ "$file" =~ ^typescript/ ]] && [[ ! "$file" =~ ^typescript/apps/beps/ ]]); then
RUNTIME_CHANGED="true"
fi
done <<< "$CHANGED_FILES"
# Determine skip reason
SKIP_REASON=""
if [[ "$RUNTIME_CHANGED" == "false" ]]; then
if [[ "$ONLY_BAML_LANGUAGE" == "true" ]]; then
SKIP_REASON="Only baml_language/ files changed - these are covered by CI - BAML Language workflow"
elif [[ "$ONLY_BEPS" == "true" ]]; then
SKIP_REASON="Only typescript/apps/beps/ files changed - these are covered by CI - BAML Language BEPs workflow"
else
SKIP_REASON="No runtime-related files changed (only baml_language/ or typescript/apps/beps/)"
fi
fi
echo "Runtime changed: $RUNTIME_CHANGED"
echo "Skip reason: $SKIP_REASON"
echo "changed=${RUNTIME_CHANGED}" >> "$GITHUB_OUTPUT"
echo "skip_reason=${SKIP_REASON}" >> "$GITHUB_OUTPUT"
# Auto-pass summary when skipping runtime tests
skip-summary:
name: "Skip Summary"
runs-on: ubuntu-latest
needs: determine_changes
if: needs.determine_changes.outputs.runtime == 'false'
steps:
- name: Report skipped tests
run: |
echo "## ⏭️ BAML Runtime Tests Skipped" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Reason:** ${{ needs.determine_changes.outputs.skip_reason }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "The BAML Runtime tests have been automatically skipped because the changes in this PR don't affect the runtime code." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### What this means:" >> $GITHUB_STEP_SUMMARY
echo "- ✅ No runtime code was modified" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Changes are covered by other CI workflows" >> $GITHUB_STEP_SUMMARY
echo "- ✅ This is an intentional optimization to reduce CI time" >> $GITHUB_STEP_SUMMARY
# Run all quality checks in parallel (lightweight setup)
lint:
runs-on: ubuntu-latest
needs: determine_changes
if: needs.determine_changes.outputs.runtime == 'true'
strategy:
matrix:
check:
[typescript-lint, rust-format, rust-lint, rust-lint-wasm, python-lint]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Tools
uses: ./.github/actions/setup-tools
# Setup Node.js for TypeScript lint
- name: Setup Node.js
if: matrix.check == 'typescript-lint'
uses: ./.github/actions/setup-node
with:
node-action-version: "v6"
# Setup Rust for Rust checks
- name: Setup Rust
if: contains(matrix.check, 'rust')
uses: ./.github/actions/setup-rust
with:
enable-wasm: ${{ matrix.check == 'rust-lint-wasm' && 'true' || 'false' }}
# Install protoc-gen-go for rust-lint (needed by baml_cffi build.rs)
- name: Setup Go
if: matrix.check == 'rust-lint'
uses: ./.github/actions/setup-go
- name: Setup Python
if: matrix.check == 'python-lint'
uses: ./.github/actions/setup-python
with:
cache: "false"
- name: Run TypeScript lint
if: matrix.check == 'typescript-lint'
run: pnpm format:ci
- name: Run Rust format check
if: matrix.check == 'rust-format'
run: |
# Ensure rustfmt is installed for the mise-managed toolchain
rustup component add rustfmt || true
cargo fmt --check -- --config imports_granularity=Crate --config group_imports=StdExternalCrate
working-directory: engine
- name: Run Rust lint (Clippy)
if: matrix.check == 'rust-lint'
run: RUSTFLAGS="-A unused -D warnings" cargo clippy --workspace -- -D clippy::print_stdout
working-directory: engine
- name: Run Rust lint WASM (Clippy)
if: matrix.check == 'rust-lint-wasm'
run: RUSTFLAGS="-A unused -D warnings" cargo clippy --target wasm32-unknown-unknown
working-directory: engine/baml-schema-wasm
- name: Run Python lint
if: matrix.check == 'python-lint'
run: |
cd integ-tests/python && uv run ruff check .
typecheck:
runs-on: ubuntu-latest
needs: determine_changes
if: needs.determine_changes.outputs.runtime == 'true'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Tools
uses: ./.github/actions/setup-tools
# Setup Node.js for TypeScript lint
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
node-action-version: "v6"
# Setup Rust for Rust checks
- name: Setup Rust
uses: ./.github/actions/setup-rust
with:
enable-wasm: true
# Install protoc-gen-go
- name: Setup Go
uses: ./.github/actions/setup-go
- name: Run typecheck for typescript and rust
run: pnpm typecheck --force
build-wasm:
runs-on: ubuntu-latest
needs: determine_changes
if: needs.determine_changes.outputs.runtime == 'true'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Tools
uses: ./.github/actions/setup-tools
- name: Setup Rust
uses: ./.github/actions/setup-rust
with:
targets: wasm32-unknown-unknown
enable-wasm: true
- name: Build rust for wasm32
run: cargo build --target=wasm32-unknown-unknown
working-directory: engine/baml-schema-wasm
# Test node generator (only needs CLI)
test-generators:
runs-on: ubuntu-latest
needs: determine_changes
if: needs.determine_changes.outputs.runtime == 'true'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Tools
uses: ./.github/actions/setup-tools
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
node-action-version: "v6"
- name: Setup Rust
uses: ./.github/actions/setup-rust
with:
enable-wasm: false
enable-cross: false
cache-on-failure: false
- name: Setup Go
uses: ./.github/actions/setup-go
with:
install-goimports: true
install-protoc-gen-go: false
- name: Test Generators (1 of 3)
run: |
pnpm build:debug && pnpm generate || (echo "::error:: merge canary and run codegen again" && exit 1)
working-directory: integ-tests/typescript
- name: Ensure No Changes (1 of 3)
run: |
git diff --exit-code || (echo "::error:: merge canary and run codegen again" && exit 1)
- name: Test Generators (2 of 3)
run: |
pnpm build:debug && pnpm generate || (echo "::error:: merge canary and run codegen again" && exit 1)
working-directory: integ-tests/typescript
- name: Ensure No Changes (2 of 3)
run: |
git diff --exit-code || (echo "::error:: merge canary and run codegen again" && exit 1)
- name: Test Generators (3 of 3)
run: |
pnpm build:debug && pnpm generate || (echo "::error:: merge canary and run codegen again" && exit 1)
working-directory: integ-tests/typescript
- name: Ensure No Changes (3 of 3)
run: |
git diff --exit-code || (echo "::error:: merge canary and run codegen again" && exit 1)
# Run tests in parallel (rebuild what's needed)
tests:
runs-on: ubuntu-latest
needs: determine_changes
if: needs.determine_changes.outputs.runtime == 'true'
strategy:
matrix:
test-suite: [rust-unit, python-integration]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Tools
uses: ./.github/actions/setup-tools
- name: Setup Rust
uses: ./.github/actions/setup-rust
- name: Setup Go
uses: ./.github/actions/setup-go
- name: Setup Node.js
if: matrix.test-suite == 'python-integration'
uses: ./.github/actions/setup-node
with:
node-action-version: "v6"
- name: Setup Python
uses: ./.github/actions/setup-python
with:
cache: "false"
- name: Setup Ruby
if: matrix.test-suite == 'rust-unit'
uses: ./.github/actions/setup-ruby
- name: Run Rust unit tests
if: matrix.test-suite == 'rust-unit'
run: |
# Find Ruby library path and add it to LD_LIBRARY_PATH
RUBY_LIB_PATH=$(ruby -e 'puts RbConfig::CONFIG["libdir"]')
export LD_LIBRARY_PATH="${RUBY_LIB_PATH}:${LD_LIBRARY_PATH}"
# Build baml_cffi shared library
cargo build --package baml_cffi
echo "Listing current directory:"
ls -la
echo "Listing release directory:"
ls -la engine/target/release/libbaml_cffi.* || true
ls -la engine/target/release/baml_cffi.* || true
echo "Listing debug directory:"
ls -la engine/target/debug/libbaml_cffi.* || true
ls -la engine/target/debug/baml_cffi.* || true
export BAML_LIBRARY_PATH=${{ github.workspace }}/engine/target/debug/libbaml_cffi.so
echo "Listing BAML_LIBRARY_PATH:"
echo $BAML_LIBRARY_PATH
# list the contents of the BAML_LIBRARY_PATH
ls -la $BAML_LIBRARY_PATH
# Copy the dylib to a stable location to prevent cargo test from rebuilding it mid-test
# This fixes "file too short" errors caused by cargo truncating the file during rebuild
STABLE_DYLIB_PATH="${{ runner.temp }}/libbaml_cffi.so"
cp $BAML_LIBRARY_PATH "$STABLE_DYLIB_PATH"
echo "Copied dylib to stable location: $STABLE_DYLIB_PATH"
ls -la "$STABLE_DYLIB_PATH"
# Run tests
echo "BAML_LIBRARY_PATH=$STABLE_DYLIB_PATH" >> $GITHUB_ENV
BAML_LIBRARY_PATH="$STABLE_DYLIB_PATH" cargo test --features skip-integ-tests --verbose -- --nocapture
working-directory: engine
- name: Run Python integration tests
if: matrix.test-suite == 'python-integration'
run: |
cd integ-tests/python && ./run_tests.sh
# Build CLI for releases only
build-cli:
needs: determine_changes
if: github.event_name == 'release' && needs.determine_changes.outputs.runtime == 'true'
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
- os: macos-latest
target: x86_64-apple-darwin
- os: windows-latest
target: x86_64-pc-windows-msvc
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Tools
uses: ./.github/actions/setup-tools
- name: Setup Rust
uses: ./.github/actions/setup-rust
with:
targets: ${{ matrix.target }}
- name: Setup Go
uses: ./.github/actions/setup-go
- name: Build CLI
run: cargo build --release --bin baml-cli --target ${{ matrix.target }}
working-directory: engine
- name: Upload CLI artifact
uses: actions/upload-artifact@v4
with:
name: baml-cli-${{ matrix.target }}
path: engine/target/release/baml-cli*
# CI Failure Alert - Required status check using "skipped = success" pattern
# See: https://devopsdirective.com/posts/2025/08/github-actions-required-checks-for-conditional-jobs/
#
# This job exploits GitHub's behavior where skipped jobs report as "Success".
# - When all tests pass (or are intentionally skipped): this job SKIPS → reports SUCCESS
# - When any test fails or is cancelled: this job RUNS and FAILS → blocks merge
#
# Configure "BAML Runtime / CI Failure Alert" as a required status check.
ci-failure-alert:
name: "CI Failure Alert"
runs-on: ubuntu-latest
needs:
- determine_changes
- lint
- typecheck
- build-wasm
- test-generators
- tests
# Only run if something failed or was cancelled (otherwise skip → success)
if: ${{ failure() || cancelled() }}
steps:
- name: Report failure
run: |
echo "## ❌ CI Failed" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "One or more required jobs failed or were cancelled." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Job | Result |" >> $GITHUB_STEP_SUMMARY
echo "|-----|--------|" >> $GITHUB_STEP_SUMMARY
echo "| lint | ${{ needs.lint.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| typecheck | ${{ needs.typecheck.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| build-wasm | ${{ needs.build-wasm.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| test-generators | ${{ needs.test-generators.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| tests | ${{ needs.tests.result }} |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "::error::One or more CI jobs failed!"
exit 1
# Sync Zed extension to separate repository
sync-zed-repository:
runs-on: ubuntu-latest
needs: determine_changes
# Only run on pushes to canary branch or manual dispatch, and only if runtime changed
if: github.ref == 'refs/heads/canary' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && needs.determine_changes.outputs.runtime == 'true'
steps:
- name: Checkout main repository
uses: actions/checkout@v4
with:
path: main-repo
- name: Checkout zed-baml repository
uses: actions/checkout@v4
with:
repository: BoundaryML/zed-baml
token: ${{ secrets.SAM_BAML_ZED_GITHUB_TOKEN }}
path: zed-baml-repo
- name: Setup rsync
run: sudo apt-get update && sudo apt-get install -y rsync
- name: Sync zed directory contents
run: |
# Change to the source directory
cd main-repo/engine/zed
# Create a temporary directory for filtered content
mkdir -p /tmp/zed-sync
# Copy files respecting gitignore
rsync -av \
--exclude-from=.gitignore \
--exclude='.git' \
--exclude='.gitignore' \
./ /tmp/zed-sync/
# Copy the gitignore file separately (we want it in the target repo)
cp .gitignore /tmp/zed-sync/
- name: Update zed-baml repository
run: |
cd zed-baml-repo
# Remove all existing content except .git
find . -mindepth 1 -maxdepth 1 ! -name '.git' -exec rm -rf {} +
# Copy new content
cp -r /tmp/zed-sync/* .
cp /tmp/zed-sync/.gitignore . 2>/dev/null || true
# Configure git
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
# Add and commit changes
git add .
# Check if there are changes to commit
if ! git diff --staged --quiet; then
git commit -m "Sync from main repository - $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
git push
echo "✅ Successfully synced zed extension to zed-baml repository"
else
echo "ℹ️ No changes to sync"
fi