alef 0.64.0

Opinionated polyglot binding generator for Rust libraries
Documentation
name: CI

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

permissions:
  contents: read

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1

jobs:
  validate:
    name: Validate
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: xberg-io/actions/setup-rust@v1
        with:
          components: "rustfmt, clippy"
          install-llvm-cov: "false"
          macos-dynamic-lookup: "false"
      - uses: taiki-e/install-action@v2
        with:
          tool: cargo-deny,cargo-machete,cargo-sort
      - name: Check formatting
        run: cargo fmt --all -- --check
      - name: Clippy
        run: cargo clippy --workspace --all-targets -- -D warnings -A clippy::needless_update
      - name: Check unused dependencies
        run: cargo machete
      - name: Security and license audit
        run: cargo deny check
      - name: Check Cargo.toml sorting
        run: cargo sort --check --workspace

  poly-validate:
    uses: xberg-io/actions/.github/workflows/reusable-validate.yml@v1
    with:
      setup-rust: true
      setup-python: true

  test:
    name: Test (${{ matrix.os }})
    needs: validate
    strategy:
      fail-fast: false
      matrix:
        os:
          - ubuntu-latest
          - macos-latest
          - windows-latest
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v7
      - uses: xberg-io/actions/setup-rust@v1
        with:
          install-llvm-cov: "false"
          cache-key-prefix: ci-test
      # Several `#[test]`s compile alef's own generated output with the real per-language
      # toolchain rather than mocking it (that is the point of them), so those toolchains
      # have to actually be on PATH here, not just in the `generated-output-gate` job.
      # `poly` is deliberately not installed in this job: the tests that exercise it
      # already tolerate its absence (see `e2e::format::format_language`'s non-`--strict`
      # deferral), so it is not required for this job to pass, only for the
      # `generated-output-gate` job's lanes, which install it themselves.
      - name: Set up JDK
        uses: actions/setup-java@v5
        with:
          distribution: temurin
          # Matches `template_versions::toolchain::JAVA_JVM_TARGET`: alef's generated Java
          # service bindings use the `java.lang.foreign` FFM API, stable only from JDK 22.
          java-version: "25"
      - uses: xberg-io/actions/setup-maven@v1
      - uses: xberg-io/actions/setup-zig@v1
      - name: Run tests
        run: cargo test --workspace

  # Runs the consumer's own toolchain gate over a tree alef emits, in a scratch directory.
  # The `validate` job above lints alef; this one lints alef's *output*, which nothing
  # else in this workflow looks at. Kept a separate job because it needs poly and
  # cargo-sort — which the three-OS `test` matrix does not install — and because it
  # compiles the emitted crates.
  generated-output-gate:
    name: Generated output gate
    needs: validate
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: xberg-io/actions/setup-rust@v1
        with:
          components: "clippy"
          install-llvm-cov: "false"
          cache-key-prefix: ci-generated-output-gate
      - uses: taiki-e/install-action@v2
        with:
          tool: cargo-sort
      - uses: xberg-io/actions/install-homebrew-linux@v1
      # Homebrew 6.x refuses to load formulae from a third-party tap until the tap is
      # explicitly trusted; `brew install` on an untrusted tap fails rather than skipping.
      # `brew trust` is a real subcommand as of 6.x (verified locally); see
      # https://docs.brew.sh/Tap-Trust.
      - name: Trust goldziher/tap
        run: |
          brew tap goldziher/tap
          brew trust goldziher/tap
      - name: Install poly
        run: brew install goldziher/tap/poly
      # Both tools must be present *before* the lanes run. The lanes fail on a missing
      # tool rather than skipping, so this step exists to fail earlier and more legibly,
      # not to decide whether the gate runs.
      - name: Verify downstream tooling is present
        run: |
          cargo sort --version
          poly --version
      # Not ignored, needs no tooling: the isolation guard and the wiring check. Run as
      # its own step so "the gate refuses to lint alef itself" is a named, visible result
      # in the CI log rather than an assertion buried inside a long run.
      - name: Prove the gate refuses to lint alef itself
        run: cargo test --test generated_output_downstream_gate -- --nocapture
      # The lanes and their sabotage proofs. Every test here is #[ignore]d, so dropping
      # `--ignored` would run none of them and still exit 0 — which is why
      # `ci_workflow_runs_the_generated_output_gate` asserts this flag is still here.
      - name: Run downstream gate over the emitted tree
        run: cargo test --test generated_output_downstream_gate -- --ignored --nocapture

  build:
    name: Build release
    needs: validate
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: xberg-io/actions/setup-rust@v1
        with:
          install-llvm-cov: "false"
          cache-key-prefix: ci-build
      - uses: xberg-io/actions/build-rust-cli@v1
        id: build-cli
        with:
          package-name: alef
          binary-name: alef
      - name: Verify binary
        run: ${{ steps.build-cli.outputs.binary-path }} --help