fabro/.github/workflows/rust.yml
Scott Werner 00984ce241 build: track Lithos git dependencies on branch main
Every lithoscomputer git dependency (sandbox-driver, pebble, petri,
lithos-llm, twins) now uses `branch = "main"` instead of an exact rev,
matching the libraries, so the workspace resolves one Cargo source per
repository. Cargo.lock is the single place the commits are chosen; move
one with `cargo update -p <crate>`.

The lockfile keeps every commit except sandbox-driver, which moves from
583a164 to b30203c: Daytona removed its paginated sandbox listing, and
b30203c lists through cursors instead (it also moves the driver's
daytona-sdk-rust dependency to 0e69058). The Daytona auth-probe test
mocks now serve the cursor endpoint the driver calls.

CI reads the sandbox-driver commit for the plugin install from the
lockfile through cargo metadata instead of from Cargo.toml.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-23 12:40:52 -04:00

295 lines
13 KiB
YAML

name: Rust
on:
push:
branches: [main]
paths:
- "lib/apps/**"
- "lib/components/**"
- "lib/foundation/**"
- "test/**"
- "Cargo.toml"
- "Cargo.lock"
- ".cargo/**"
- ".config/**"
- "bin/dev/**"
- "docs/public/reference/cli.mdx"
- "docs/public/reference/user-configuration.mdx"
- "openapi/**"
- ".github/workflows/rust.yml"
pull_request:
branches: [main]
paths:
- "lib/apps/**"
- "lib/components/**"
- "lib/foundation/**"
- "test/**"
- "Cargo.toml"
- "Cargo.lock"
- ".cargo/**"
- ".config/**"
- "bin/dev/**"
- "docs/public/reference/cli.mdx"
- "docs/public/reference/user-configuration.mdx"
- "openapi/**"
- ".github/workflows/rust.yml"
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: {}
env:
CARGO_TERM_COLOR: always
CARGO_NET_RETRY: "10"
jobs:
fmt:
name: Format
runs-on: ubuntu-24.04-x86-32-cores
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
with:
toolchain: nightly-2026-04-14
components: rustfmt
- run: cargo +nightly-2026-04-14 fmt --check --all
clippy:
name: Clippy
runs-on: ubuntu-24.04-x86-32-cores
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
with:
toolchain: nightly-2026-04-14
components: clippy
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2
with:
cache-on-failure: true
- name: Verify legacy auth identity removal
run: |
if git grep -nE 'AuthMode::Disabled|RunAuthMethod|RunSubjectProvenance|\bActorRef\b|\bActorKind\b|AuthenticatedSubject|AuthenticatedService|AuthorizeRunScoped|AuthorizeRunBlob|AuthorizeStageArtifact|AuthorizeCommandLog|auth_method\s*==\s*"disabled"' \
-- lib/apps lib/components lib/foundation apps lib/packages docs/public/api-reference/fabro-api.yaml; then
echo "::error::Legacy auth identities remain in the repository"
exit 1
else
status=$?
if [ "$status" -ne 1 ]; then
exit "$status"
fi
fi
- run: cargo +nightly-2026-04-14 clippy --locked --workspace --all-targets -- -D warnings
rustdoc:
name: Rustdoc
runs-on: ubuntu-24.04-x86-32-cores
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
with:
toolchain: 1.97.1
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2
with:
cache-on-failure: true
# Broken intra-doc links and the other rustdoc lints fail the build.
- run: cargo doc --locked --workspace --no-deps
env:
RUSTDOCFLAGS: -D warnings
generated-docs:
name: Generated Docs
runs-on: ubuntu-24.04-x86-32-cores
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
with:
toolchain: 1.97.1
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2
with:
cache-on-failure: true
- run: cargo --locked dev docs check
test:
name: Test (Linux)
runs-on: ubuntu-24.04-x86-32-cores
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
with:
toolchain: 1.97.1
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2
with:
cache-on-failure: true
- uses: taiki-e/install-action@773334c0e05d7e699e4d78234494308223f3a2cf # nextest
# Every Petri run takes its scope through a sandbox-driver plugin
# executable that Petri finds on PATH: `sandbox-driver-host` for the
# `local` provider, `sandbox-driver-docker` for `docker`. Installed
# at the commit Cargo.lock resolves sandbox-driver to, so the plugins
# and the in-process driver are one build; a from-source build, so the
# two executables are cached by OS and commit and only rebuilt when the
# lockfile moves the driver.
- name: Read the sandbox-driver commit Cargo.lock resolves
id: sandbox-driver
run: |
rev="$(cargo metadata --locked --format-version 1 | jq -r '.packages[] | select(.name == "sandbox-driver") | .source' | sed 's/.*#//' | sort -u)"
[[ "$rev" =~ ^[0-9a-f]{40}$ ]]
echo "rev=$rev" >> "$GITHUB_OUTPUT"
- name: Restore the sandbox-driver plugin executables
id: sandbox-driver-cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: |
~/.cargo/bin/sandbox-driver-host
~/.cargo/bin/sandbox-driver-docker
key: sandbox-driver-plugins-${{ runner.os }}-${{ steps.sandbox-driver.outputs.rev }}
- name: Install the sandbox-driver plugin executables
if: steps.sandbox-driver-cache.outputs.cache-hit != 'true'
run: cargo install --locked --git https://github.com/lithoscomputer/sandbox-driver --rev "${{ steps.sandbox-driver.outputs.rev }}" sandbox-driver-host sandbox-driver-docker
# The images the suite's Docker tests run. The plugin pulls a missing
# image on first use, but a 1 GiB pull inside a run's wait is a flake,
# so pull them here, where a registry problem reads as one. Most tests
# leave the image to Petri, whose Docker scope runs on its default
# runner image at the pin the checked-out Petri names; the
# fabro-server catalog scenarios name CATALOG_IMAGE in
# lib/apps/fabro-server/tests/it/scenario/petri.rs.
- name: Pull the images the Docker tests run
run: |
backend="$(dirname "$(cargo metadata --locked --format-version 1 | jq -r '.packages[] | select(.name == "petri-executor-sandbox") | .manifest_path')")/src/backend.rs"
pin="$(sed -n 's/^const RUNNER_PIN: &str = "\([0-9a-f]*\)";$/\1/p' "$backend")"
test -n "$pin"
docker pull "ghcr.io/lithoscomputer/ubuntu-24.04:slim-$pin"
docker pull ghcr.io/lithoscomputer/ubuntu-22.04:slim
- run: cargo nextest run --locked --workspace --status-level slow --profile ci
# The twin-mode ignored suites this job once ran belonged to fabro-agent,
# which pebble's coding agent replaced; the agent loop's workflow-level
# tests run in the suite above, and pebble's own suite covers the loop.
# Re-add a `--run-ignored only -E 'package(...)'` step here when a
# package has ignored suites that are fully green in twin mode.
sandbox-docker:
name: Sandbox providers (Docker)
runs-on: ubuntu-24.04-x86-32-cores
permissions:
contents: read
env:
# The Docker scenarios skip when the executable, the daemon or the
# image is missing; in CI a skip is a failure.
FABRO_REQUIRE_SANDBOX_PLUGINS: "1"
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
with:
toolchain: 1.97.1
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2
with:
cache-on-failure: true
- uses: taiki-e/install-action@773334c0e05d7e699e4d78234494308223f3a2cf # nextest
# The image the Docker scenarios' environment names, and Petri's
# default runner image, which the fabro-petri Docker test runs.
- run: docker pull buildpack-deps:noble
- name: Pull Petri's default runner image
run: |
backend="$(dirname "$(cargo metadata --locked --format-version 1 | jq -r '.packages[] | select(.name == "petri-executor-sandbox") | .manifest_path')")/src/backend.rs"
pin="$(sed -n 's/^const RUNNER_PIN: &str = "\([0-9a-f]*\)";$/\1/p' "$backend")"
test -n "$pin"
docker pull "ghcr.io/lithoscomputer/ubuntu-24.04:slim-$pin"
# Every Petri run takes its scope through a sandbox-driver plugin
# executable that Petri finds on PATH: `sandbox-driver-host` for the
# `local` provider, `sandbox-driver-docker` for `docker`. Installed
# at the commit Cargo.lock resolves sandbox-driver to, so the plugins
# and the in-process driver are one build; a from-source build, so the
# two executables are cached by OS and commit and only rebuilt when the
# lockfile moves the driver.
- name: Read the sandbox-driver commit Cargo.lock resolves
id: sandbox-driver
run: |
rev="$(cargo metadata --locked --format-version 1 | jq -r '.packages[] | select(.name == "sandbox-driver") | .source' | sed 's/.*#//' | sort -u)"
[[ "$rev" =~ ^[0-9a-f]{40}$ ]]
echo "rev=$rev" >> "$GITHUB_OUTPUT"
- name: Restore the sandbox-driver plugin executables
id: sandbox-driver-cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: |
~/.cargo/bin/sandbox-driver-host
~/.cargo/bin/sandbox-driver-docker
key: sandbox-driver-plugins-${{ runner.os }}-${{ steps.sandbox-driver.outputs.rev }}
- name: Install the sandbox-driver plugin executables
if: steps.sandbox-driver-cache.outputs.cache-hit != 'true'
run: cargo install --locked --git https://github.com/lithoscomputer/sandbox-driver --rev "${{ steps.sandbox-driver.outputs.rev }}" sandbox-driver-host sandbox-driver-docker
# The workflow scenarios on the Docker provider. The scenarios are e2e
# tests (ignored by default); the key-free ones run here, the
# LLM-backed ones self-skip without credentials.
- run: cargo nextest run --locked --profile ci --status-level slow --run-ignored only -p fabro-cli --test it -E 'test(/::docker_/)'
# The Petri runs (not ignored: they skip without the host plugin, which
# the environment above forbids).
- run: cargo nextest run --locked --profile ci --status-level slow -p fabro-petri
test-macos:
name: Test (macOS)
if: github.event_name == 'workflow_dispatch'
runs-on: macos-15
permissions:
contents: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
with:
toolchain: 1.97.1
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2
with:
cache-on-failure: true
- uses: taiki-e/install-action@773334c0e05d7e699e4d78234494308223f3a2cf # nextest
# Every Petri run takes its scope through a sandbox-driver plugin
# executable that Petri finds on PATH: `sandbox-driver-host` for the
# `local` provider, `sandbox-driver-docker` for `docker`. Installed
# at the commit Cargo.lock resolves sandbox-driver to, so the plugins
# and the in-process driver are one build; a from-source build, so the
# two executables are cached by OS and commit and only rebuilt when the
# lockfile moves the driver.
- name: Read the sandbox-driver commit Cargo.lock resolves
id: sandbox-driver
run: |
rev="$(cargo metadata --locked --format-version 1 | jq -r '.packages[] | select(.name == "sandbox-driver") | .source' | sed 's/.*#//' | sort -u)"
[[ "$rev" =~ ^[0-9a-f]{40}$ ]]
echo "rev=$rev" >> "$GITHUB_OUTPUT"
- name: Restore the sandbox-driver plugin executables
id: sandbox-driver-cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: |
~/.cargo/bin/sandbox-driver-host
~/.cargo/bin/sandbox-driver-docker
key: sandbox-driver-plugins-${{ runner.os }}-${{ steps.sandbox-driver.outputs.rev }}
- name: Install the sandbox-driver plugin executables
if: steps.sandbox-driver-cache.outputs.cache-hit != 'true'
run: cargo install --locked --git https://github.com/lithoscomputer/sandbox-driver --rev "${{ steps.sandbox-driver.outputs.rev }}" sandbox-driver-host sandbox-driver-docker
# No Docker daemon on the macOS runner: the Docker tests skip there.
- run: cargo nextest run --locked --workspace --status-level slow --profile ci