Files
OpenShell/.github/workflows/branch-checks.yml
Evan Lezar b10ab39f9a refactor(e2e): align suite layout with testing strategy
Move behavioral suites under e2e/suites and extract shared Rust tooling into e2e/support/rust. Organize conformance tests into one Cargo target per area with story modules containing the tests and assertions. Remove the separate scenario crate and registry, and split lifecycle coverage into independent stop/start and stopped-deletion stories.

Reuse shared helpers from the existing Rust harness, preserve artifact packaging and focused test selection, and include tooling and pure assertion tests in test:rust and branch checks. Update authoring guidance for required behavior and retained failures with explicit waivers.

Closes #4119

Signed-off-by: Evan Lezar <elezar@nvidia.com>
2026-10-06 16:56:51 +02:00

493 lines
18 KiB
YAML

name: Branch Checks
on:
merge_group:
types: [checks_requested]
push:
branches:
- "pull-request/[0-9]+"
workflow_dispatch:
env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: "0"
MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
permissions:
contents: read
packages: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
pr_metadata:
name: Resolve PR metadata
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
should_run: ${{ steps.gate.outputs.should_run }}
base_sha: ${{ steps.gate.outputs.base_sha }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- id: gate
uses: ./.github/actions/pr-gate
protobuf-compatibility:
name: Protobuf Compatibility
needs: pr_metadata
if: needs.pr_metadata.outputs.should_run == 'true'
runs-on: linux-amd64-cpu8
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- uses: ./.github/actions/check-protobuf-compatibility
with:
ref: >-
${{ github.event_name == 'workflow_dispatch'
&& format('refs/remotes/origin/{0}', github.event.repository.default_branch)
|| github.event.merge_group.base_sha
|| needs.pr_metadata.outputs.base_sha }}
mise-lockfile:
name: mise Lockfile
needs: pr_metadata
if: needs.pr_metadata.outputs.should_run == 'true'
runs-on: linux-amd64-cpu8
timeout-minutes: 30
container:
image: ghcr.io/nvidia/openshell/ci:9cb72baa2e61a1b5f12407e6e82da7fdba0aa722@sha256:67a9a0c32cb99825e6d3e9d9eec45d67149ea1ff7c11a1b1e1b3480d2d3df684
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Mark workspace as safe for git
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: Verify mise.lock is in sync with mise.toml
run: |
mise lock
if ! git diff --exit-code mise.lock; then
echo "::error::mise.lock is out of sync with mise.toml. Run 'mise lock' locally and commit the result." >&2
exit 1
fi
license-headers:
name: License Headers
needs: pr_metadata
if: needs.pr_metadata.outputs.should_run == 'true'
runs-on: linux-amd64-cpu8
timeout-minutes: 30
container:
image: ghcr.io/nvidia/openshell/ci:9cb72baa2e61a1b5f12407e6e82da7fdba0aa722@sha256:67a9a0c32cb99825e6d3e9d9eec45d67149ea1ff7c11a1b1e1b3480d2d3df684
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Install tools
run: mise install --locked
- name: Check license headers
run: mise run license:check
cargo-deny:
name: Cargo Deny
needs: pr_metadata
if: needs.pr_metadata.outputs.should_run == 'true'
runs-on: linux-amd64-cpu8
timeout-minutes: 30
defaults:
run:
shell: nix develop .#devShells.x86_64-linux.default -c bash -euo pipefail {0}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: ./.github/actions/setup-nix
with:
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
prepare-shell: "true"
shell-installable: .#devShells.x86_64-linux.default
- name: Check dependencies
run: cargo deny check licenses bans sources
rust-format:
name: Rust format
needs: pr_metadata
if: needs.pr_metadata.outputs.should_run == 'true'
runs-on: linux-amd64-cpu8
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: ./.github/actions/setup-nix
with:
prepare-shell: "true"
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
- name: Format
shell: nix develop -c bash -euo pipefail {0}
run: |
cargo fmt --all -- --check
cargo fmt --manifest-path e2e/support/rust/Cargo.toml --all -- --check
cargo fmt --manifest-path e2e/suites/conformance/Cargo.toml --all -- --check
cargo fmt --manifest-path e2e/rust/Cargo.toml --all -- --check
cargo fmt --manifest-path examples/governance-interceptor/Cargo.toml --all -- --check
cargo fmt --manifest-path examples/supervisor-middleware-content-guard/Cargo.toml --all -- --check
cargo-lockfiles:
name: Cargo lockfiles
needs: pr_metadata
if: needs.pr_metadata.outputs.should_run == 'true'
runs-on: linux-amd64-cpu8
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: ./.github/actions/setup-nix
with:
prepare-shell: "true"
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
- name: Verify Cargo lockfiles
shell: nix develop -c bash -euo pipefail {0}
run: tasks/scripts/check-cargo-lockfiles.sh
rust-lint:
name: Rust lint (${{ matrix.system }})
needs: pr_metadata
if: needs.pr_metadata.outputs.should_run == 'true'
strategy:
fail-fast: false
matrix:
include:
- runner: linux-amd64-cpu8
system: x86_64-linux
- runner: linux-arm64-cpu8
system: aarch64-linux
- runner: macos-15-xlarge
system: aarch64-darwin
runs-on: ${{ matrix.runner }}
timeout-minutes: 45
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: ./.github/actions/setup-nix
with:
prepare-shell: "true"
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
- uses: ./.github/actions/setup-rust
with:
cache-key: rust-checks-v2
save-cache: "false"
- name: Lint
shell: nix develop -c bash -euo pipefail {0}
run: |
cargo clippy --locked --workspace --all-targets -- -D warnings
cargo clippy --locked --manifest-path e2e/support/rust/Cargo.toml --workspace --all-targets -- -D warnings
cargo clippy --locked --manifest-path e2e/suites/conformance/Cargo.toml --workspace --all-targets -- -D warnings
cargo clippy --locked --manifest-path e2e/rust/Cargo.toml --all-targets -- -D warnings
cargo clippy --locked --manifest-path examples/governance-interceptor/Cargo.toml --all-targets -- -D warnings
cargo clippy --locked --manifest-path examples/supervisor-middleware-content-guard/Cargo.toml --all-targets -- -D warnings
rust-test:
name: Rust test (${{ matrix.system }})
needs: pr_metadata
if: needs.pr_metadata.outputs.should_run == 'true'
strategy:
fail-fast: false
matrix:
include:
- runner: linux-amd64-cpu8
system: x86_64-linux
- runner: linux-arm64-cpu8
system: aarch64-linux
- runner: macos-15-xlarge
system: aarch64-darwin
runs-on: ${{ matrix.runner }}
timeout-minutes: 45
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: ./.github/actions/setup-nix
with:
prepare-shell: "true"
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
- uses: ./.github/actions/setup-rust
with:
cache-key: rust-checks-v2
save-cache: "true"
- name: Test
shell: nix develop -c bash -euo pipefail {0}
env:
OPENSHELL_TELEMETRY_ENABLED: "false"
run: |
cargo nextest run --locked --profile ci --workspace --features openshell-server/test-support
cargo nextest run --locked --config-file .config/nextest.toml --profile ci --manifest-path e2e/support/rust/Cargo.toml
cargo nextest run --locked --config-file .config/nextest.toml --profile ci --manifest-path e2e/suites/conformance/Cargo.toml --package openshell-test-conformance-cli -E 'binary(policy_advisor) & test(draft_assertion::tests::)'
cargo nextest run --locked --config-file .config/nextest.toml --profile ci --manifest-path examples/supervisor-middleware-content-guard/Cargo.toml
rust-build-modes:
name: Rust build modes (${{ matrix.system }})
needs: pr_metadata
if: needs.pr_metadata.outputs.should_run == 'true'
strategy:
fail-fast: false
matrix:
include:
- runner: linux-amd64-cpu8
system: x86_64-linux
- runner: linux-arm64-cpu8
system: aarch64-linux
- runner: macos-15-xlarge
system: aarch64-darwin
runs-on: ${{ matrix.runner }}
timeout-minutes: 45
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: ./.github/actions/setup-nix
with:
prepare-shell: "true"
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
- uses: ./.github/actions/setup-rust
with:
cache-key: rust-checks-v2
save-cache: "false"
- name: Verify build modes
shell: nix develop -c bash -euo pipefail {0}
run: |
cargo build --locked -p openshell-gateway --bin openshell-gateway
tasks/scripts/verify-telemetry-compiled-out.sh present target/debug/openshell-gateway
cargo build --locked -p openshell-gateway --bin openshell-gateway --no-default-features --features defaults-without-telemetry
tasks/scripts/verify-telemetry-compiled-out.sh absent target/debug/openshell-gateway
cargo build --locked -p openshell-supervisor --bin openshell-supervisor --no-default-features --features defaults-without-telemetry
tasks/scripts/verify-telemetry-compiled-out.sh absent target/debug/openshell-supervisor
cargo check --locked -p openshell-supervisor --all-targets --no-default-features --features system-ca-roots
- name: Verify system CA roots dependency boundary
shell: nix develop -c bash -euo pipefail {0}
run: |
cargo tree --locked -p openshell-supervisor --prefix none --no-default-features --features system-ca-roots > /tmp/openshell-supervisor-dependencies.txt
if grep -Eq '^(webpki-roots|webpki-root-certs) v' /tmp/openshell-supervisor-dependencies.txt; then
echo "ERROR: bundled Mozilla roots found in system CA roots build" >&2
cat /tmp/openshell-supervisor-dependencies.txt >&2
exit 1
fi
- name: Verify standalone prover dependency boundary
shell: nix develop -c bash -euo pipefail {0}
run: |
cargo tree --locked -p openshell-prover-cli --edges normal --prefix none > /tmp/openshell-prover-dependencies.txt
if grep -Eq '^(openshell-(cli|server|sdk|bootstrap|tui|providers|core|policy)) v' /tmp/openshell-prover-dependencies.txt; then
echo "ERROR: standalone prover includes an OpenShell control-plane dependency" >&2
cat /tmp/openshell-prover-dependencies.txt >&2
exit 1
fi
rust-feature-alias:
name: Rust feature alias
needs: pr_metadata
if: needs.pr_metadata.outputs.should_run == 'true'
runs-on: linux-amd64-cpu8
timeout-minutes: 30
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: ./.github/actions/setup-nix
with:
prepare-shell: "true"
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
- uses: ./.github/actions/setup-rust
with:
cache-key: rust-checks-v2
save-cache: "false"
- name: Verify defaults-without-telemetry feature alias
shell: nix develop -c bash -euo pipefail {0}
run: |
tasks/scripts/verify-defaults-without-telemetry.sh
git diff --exit-code HEAD -- ':(glob)**/Cargo.lock'
rust-gateway-core-features:
name: Rust gateway core features
needs: pr_metadata
if: needs.pr_metadata.outputs.should_run == 'true'
runs-on: linux-amd64-cpu8
timeout-minutes: 30
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: ./.github/actions/setup-nix
with:
prepare-shell: "true"
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
- uses: ./.github/actions/setup-rust
with:
cache-key: rust-checks-v2
save-cache: "false"
- name: Verify core gateway compute-driver feature sets
shell: nix develop -c bash -euo pipefail {0}
run: |
cargo nextest run --locked --profile ci -p openshell-gateway --all-targets --no-default-features
cargo nextest run --locked --profile ci -p openshell-gateway --all-targets --no-default-features --features compute-driver-docker
cargo nextest run --locked --profile ci -p openshell-gateway --all-targets --no-default-features --features compute-driver-kubernetes
cargo nextest run --locked --profile ci -p openshell-gateway --all-targets --no-default-features --features compute-driver-podman
rust-gateway-extended-features:
name: Rust gateway extended features
needs: pr_metadata
if: needs.pr_metadata.outputs.should_run == 'true'
runs-on: linux-amd64-cpu8
timeout-minutes: 30
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: ./.github/actions/setup-nix
with:
prepare-shell: "true"
cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }}
- uses: ./.github/actions/setup-rust
with:
cache-key: rust-checks-v2
save-cache: "false"
- name: Verify extended gateway compute-driver feature sets
shell: nix develop -c bash -euo pipefail {0}
run: |
cargo nextest run --locked --profile ci -p openshell-gateway --all-targets --no-default-features --features compute-driver-vm
cargo nextest run --locked --profile ci -p openshell-gateway --all-targets --no-default-features --features compute-driver-mxc
cargo nextest run --locked --profile ci -p openshell-gateway --all-targets --no-default-features --features compute-driver-docker,compute-driver-vm
python:
name: Python (${{ matrix.runner }})
needs: pr_metadata
if: needs.pr_metadata.outputs.should_run == 'true'
strategy:
fail-fast: false
matrix:
runner: [linux-amd64-cpu8, linux-arm64-cpu8]
runs-on: ${{ matrix.runner }}
timeout-minutes: 30
container:
image: ghcr.io/nvidia/openshell/ci:9cb72baa2e61a1b5f12407e6e82da7fdba0aa722@sha256:67a9a0c32cb99825e6d3e9d9eec45d67149ea1ff7c11a1b1e1b3480d2d3df684
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Install tools
run: mise install --locked
- name: Install dependencies
run: uv sync --frozen
- name: Format
run: mise run python:format:check
- name: Lint
run: mise run python:lint
- name: Typecheck
run: mise run python:typecheck
- name: Test
run: mise run test:python
- name: Test local gateway configuration helpers
run: |
bash tasks/scripts/test-gateway-pull-policy.sh
bash tasks/scripts/test-gateway-config.sh
go:
name: Go SDK
needs: pr_metadata
if: needs.pr_metadata.outputs.should_run == 'true'
runs-on: linux-amd64-cpu8
timeout-minutes: 30
container:
image: ghcr.io/nvidia/openshell/ci:9cb72baa2e61a1b5f12407e6e82da7fdba0aa722@sha256:67a9a0c32cb99825e6d3e9d9eec45d67149ea1ff7c11a1b1e1b3480d2d3df684
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Install tools
run: mise install --locked
- name: Lint, build, test, proto-check
run: mise run go:ci
markdown:
name: Markdown
needs: pr_metadata
if: needs.pr_metadata.outputs.should_run == 'true'
runs-on: linux-amd64-cpu8
timeout-minutes: 30
container:
image: ghcr.io/nvidia/openshell/ci:9cb72baa2e61a1b5f12407e6e82da7fdba0aa722@sha256:67a9a0c32cb99825e6d3e9d9eec45d67149ea1ff7c11a1b1e1b3480d2d3df684
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Install tools
run: mise install --locked
- name: Lint
run: mise run markdown:lint
sdk-typescript:
name: TypeScript SDK
needs: pr_metadata
if: needs.pr_metadata.outputs.should_run == 'true'
runs-on: linux-amd64-cpu8
timeout-minutes: 30
container:
image: ghcr.io/nvidia/openshell/ci:9cb72baa2e61a1b5f12407e6e82da7fdba0aa722@sha256:67a9a0c32cb99825e6d3e9d9eec45d67149ea1ff7c11a1b1e1b3480d2d3df684
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Install tools
run: mise install --locked
- name: Check TypeScript SDK
run: mise run sdk:ts:ci
# Exercise the full release publish path (version stamp, dist-tag,
# prepublishOnly, tarball) without uploading. Uses the off-tag dev
# version, which validates the prerelease dist-tag branch too.
- name: Verify publishable artifact (dry-run)
env:
OPENSHELL_NPM_PUBLISH_ARGS: --dry-run
run: |
OPENSHELL_NPM_VERSION="$(uv run python tasks/scripts/release.py get-version --npm)" \
mise run sdk:ts:publish