name: WAI operation catalogue # WAI's toolchain has one catalogue of operations, `noun.verb` (wai/wai-rs/src/catalogue.rs), # and every door names them by it. This workflow fails on drift: # # - the export, wai/catalogue/ops.json, is the table (`wai ops export --check`); # - the table keeps its naming rules (the library's catalogue tests); # - the command line reaches operations through the catalogue alone, and every operation # keeps the agent rules: its help, the exit codes, the JSON envelope, --dry-run on every # operation that is not read-only, --yes (tests/cli_ops.rs, and the binary's own tests); # - the other doors name operations as the catalogue does: MCP tool names, the services' # OpenAPI operationIds, the C header, and the Swift and Kotlin sinks # (scripts/check-wai-ops-doors.py, with its selftest). # # - wai-rs passes clippy with warnings denied in the quickstart and full builds, and with # `http` or `live_egress` alone. # # Push filters match the push's delta, so every path a door or a test reads is listed. concurrency: group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.sha || github.ref }} cancel-in-progress: true on: push: branches: [main] paths: - 'wai/wai-rs/**' - 'wai/catalogue/**' - 'wai/examples/**' # The project file's reader (dx/project.rs, in the binary's tests) holds wai.json's schema to it. - 'wai/schema/**' - 'wai/http-conformance/**' - 'wai/score-conformance/**' - 'wai/live-conformance/fleet/**' # tests/cli_ops.rs builds the revenue share's --dry-run sample from this corpus. - 'wai/live-conformance/share/**' - 'wai/live-conformance/channels/**' # tests/cli_key.rs signs a conformance record against this corpus and an upscale with this prior. - 'wai/jwp-conformance/**' # Read by tests/cli_folds.rs: the corpora each fold is held to. - 'wai/telemetry-conformance/**' - 'wai/claim-conformance/**' - 'wai/live-conformance/rooms/**' - 'wai/live-conformance/audit/**' - 'wai/live-conformance/upscale/**' # tests/cli_toolchain.rs holds wai --version and the deprecations to these, and searches the text. - 'wai/CHANGELOG.md' - 'wai/VERSIONING.md' - 'wai/DEPRECATIONS.md' - 'wai/SPEC.md' - 'wai/registry/**' - 'wai/REGISTRY.md' - 'wai/LICENSE' - 'wai/wai-quantum/**' - 'wai/wai-ops/**' - 'wai/wai-app/**' - 'wai/wai-sink-swift/**' - 'wai/wai-sink-android/**' - 'joule-code/joule-code-rs/crates/*/openapi.json' # tests/cli_deploy.rs holds the deployment API's OpenAPI document and its text to the # reference target and to wai deploy. - 'wai/extensions/deployment.md' - 'wai/extensions/deployment.openapi.json' - 'scripts/check-wai-ops-doors.py' - 'scripts/check-wai-ops-doors-selftest.sh' - 'rust-toolchain.toml' - '.github/workflows/wai-catalogue.yml' pull_request: paths: - 'wai/wai-rs/**' - 'wai/catalogue/**' - 'wai/examples/**' # The project file's reader (dx/project.rs, in the binary's tests) holds wai.json's schema to it. - 'wai/schema/**' - 'wai/http-conformance/**' - 'wai/score-conformance/**' - 'wai/live-conformance/fleet/**' # tests/cli_ops.rs builds the revenue share's --dry-run sample from this corpus. - 'wai/live-conformance/share/**' - 'wai/live-conformance/channels/**' # tests/cli_key.rs signs a conformance record against this corpus and an upscale with this prior. - 'wai/jwp-conformance/**' # Read by tests/cli_folds.rs: the corpora each fold is held to. - 'wai/telemetry-conformance/**' - 'wai/claim-conformance/**' - 'wai/live-conformance/rooms/**' - 'wai/live-conformance/audit/**' - 'wai/live-conformance/upscale/**' # tests/cli_toolchain.rs holds wai --version and the deprecations to these, and searches the text. - 'wai/CHANGELOG.md' - 'wai/VERSIONING.md' - 'wai/DEPRECATIONS.md' - 'wai/SPEC.md' - 'wai/registry/**' - 'wai/REGISTRY.md' - 'wai/LICENSE' - 'wai/wai-quantum/**' - 'wai/wai-ops/**' - 'wai/wai-app/**' - 'wai/wai-sink-swift/**' - 'wai/wai-sink-android/**' - 'joule-code/joule-code-rs/crates/*/openapi.json' # tests/cli_deploy.rs holds the deployment API's OpenAPI document and its text to the # reference target and to wai deploy. - 'wai/extensions/deployment.md' - 'wai/extensions/deployment.openapi.json' - 'scripts/check-wai-ops-doors.py' - 'scripts/check-wai-ops-doors-selftest.sh' - 'rust-toolchain.toml' - '.github/workflows/wai-catalogue.yml' jobs: # The path filters gate the trigger; this job gates the work from the pull request's own # diff (scripts/pr-touches-paths.py, reading the list above), as wai-pack.yml explains. relevant: name: does this change touch it runs-on: gate outputs: run: ${{ steps.gate.outputs.run }} steps: - uses: actions/checkout@v5 with: fetch-depth: 0 - id: gate run: | set -euo pipefail r=$(python3 scripts/pr-touches-paths.py .github/workflows/wai-catalogue.yml \ "${{ github.event.pull_request.base.sha }}" \ "${{ github.event.pull_request.head.sha }}") echo "this change touches the operation catalogue: $r" echo "run=$r" >> "$GITHUB_OUTPUT" catalogue: name: the catalogue and every door ยท linux needs: relevant if: needs.relevant.outputs.run == 'true' runs-on: linux timeout-minutes: 60 steps: - uses: actions/checkout@v5 - name: Install Rust 1.99.1 shell: bash run: | export PATH="$HOME/.cargo/bin:$PATH" command -v rustup >/dev/null 2>&1 || \ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.99.1 rustup toolchain install 1.99.1 --profile minimal --component clippy rustup default 1.99.1 SUDO=""; [ "$(id -u)" -ne 0 ] && SUDO="sudo" command -v python3 >/dev/null || { $SUDO apt-get update -qq; $SUDO apt-get install -y -qq python3; } echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" # The export other tools and this workflow's door check read is the table, byte for # byte; the message says how to regenerate it. - name: The catalogue's export is up to date working-directory: wai/wai-rs run: cargo run -q --locked --no-default-features --bin wai -- ops export --check ../catalogue/ops.json - name: Every door names its operations as the catalogue does shell: bash run: | set -euo pipefail bash scripts/check-wai-ops-doors-selftest.sh python3 -I scripts/check-wai-ops-doors.py # The library's catalogue tests: the naming rules, each broken in a copy of the table # and refused. The binary's own tests: every implementation names an operation of the # catalogue and every operation with a command line has one; help is the catalogue's. # tests/cli_ops.rs: wai ops, help, the exit codes, the envelope, --dry-run and --yes (and # --confirm, its deprecated spelling), # first in the archive's build (quickstart), then with the feature full (wai-rs/Cargo.toml: # every feature an operation of the catalogue needs, none that needs a system library, which # the library's catalogue tests hold to the table), so --dry-run is held on generate, score, # stage, the development room's doors and prior fetch too, and a full build holds every # operation (cli_ops' a_full_build_holds_every_operation), with # Create's (app), so it is held on wai app export, with the revenue share's # (revenue_share), so it is held on wai contract create|accept and wai statement create, and # with the opportunity report's (opportunity_report), so it is held on wai opportunity # create and wai statement check. tests/cli_key.rs: wai key, its keystore, and --key on # the operations that sign, first in the archive's build, then with the features whose # operations read --key apart (the revenue share, the exact derivations) and with # key_discovery, whose wai-keys reads what wai key exports. tests/cli_toolchain.rs: wai --version # and the one version it names, wai docs search and wai registry show, the deprecation notice, # and wai/DEPRECATIONS.md held to the catalogue. tests/cli_target.rs: wai target, wai auth, # --target on the fleet's operations and on every operation of a service's API, and wai mcp # --target, against a stand-in service: a key never written, printed or logged, a read-only # target refusing every change, an unknown target exit 5. tests/cli_folds.rs: each fold against # the tool it folds, on the same input: wai cmcd and wai_telemetry over the whole corpus, wai # receipt create and the receipt wai wrap leaves, wai verify on every record kind of the claim, # JWP, room and audit corpora and a sealed playlist (with video_manifest), a file of no kind # refused; and wai audit|serve|quantum against stand-ins that record what they were given, a # verb the quantum toolset does not list never reaching wai-quantum. tests/cli_deploy.rs: wai # deploy and wai deployment list|promote|rollback against the reference deployment target # (wai_deploy_target), each target a process on a port it picked: a project deployed, # promoted, rolled back and served; planted faults each refused (a file of dist/ changed after # its build, bytes put under another SHA-256, a promotion of a digest the target does not hold, # a rollback with none before, a receipt answering another request or edited, a kept receipt # changed); a rollback making live exactly the one before; --dry-run leaving the target as it # was; and the OpenAPI document held to the implementation. - name: The catalogue's rules, and the command line through it shell: bash working-directory: wai/wai-rs run: | set -euo pipefail ran() { grep -qE '^test result: ok\. [1-9][0-9]* passed; 0 failed' "$1" || { echo "::error::no test ran in $1"; exit 1; }; } cargo test --locked --no-default-features --lib catalogue 2>&1 | tee "$RUNNER_TEMP/lib.log" ran "$RUNNER_TEMP/lib.log" cargo test --locked --no-default-features --features quickstart --bin wai --test cli_ops --test cli_key --test cli_toolchain --test cli_target --test cli_deploy 2>&1 | tee "$RUNNER_TEMP/cli.log" ran "$RUNNER_TEMP/cli.log" cargo test --locked --no-default-features --features quickstart,key_discovery,revenue_share,exact_upscale,exact_tonemap --test cli_key 2>&1 | tee "$RUNNER_TEMP/cli-key.log" ran "$RUNNER_TEMP/cli-key.log" cargo test --locked --no-default-features --features full --test cli_ops 2>&1 | tee "$RUNNER_TEMP/cli-full.log" ran "$RUNNER_TEMP/cli-full.log" grep -q '^test a_full_build_holds_every_operation \.\.\. ok$' "$RUNNER_TEMP/cli-full.log" \ || { echo "::error::a build with --features full did not run a_full_build_holds_every_operation"; exit 1; } cargo test --locked --no-default-features --features quickstart,telemetry,video_manifest --test cli_folds 2>&1 | tee "$RUNNER_TEMP/cli-folds.log" ran "$RUNNER_TEMP/cli-folds.log" cargo test --locked --no-default-features --features quickstart,app --test cli_ops 2>&1 | tee "$RUNNER_TEMP/cli-app.log" ran "$RUNNER_TEMP/cli-app.log" cargo test --locked --no-default-features --features quickstart,revenue_share --test cli_ops 2>&1 | tee "$RUNNER_TEMP/cli-share.log" ran "$RUNNER_TEMP/cli-share.log" cargo test --locked --no-default-features --features quickstart,opportunity_report --test cli_ops 2>&1 | tee "$RUNNER_TEMP/cli-opportunity.log" ran "$RUNNER_TEMP/cli-opportunity.log" # wai-rs is clippy-clean, warnings denied, in the two builds a user installs: the # archive's (quickstart) and the one that holds every operation (full), every target of # each (the library, the programs, the tests). This is the check every push to main that # touches wai-rs runs; wai-conformance.yml holds the conformance builds to the same on # pull requests and nightly. A finding is fixed, or allowed on the one item it names # with the reason beside it; nothing is allowed for the crate. Last, and run whatever the # steps before it found, so a lint never hides a catalogue finding nor one of those a lint. # Two builds more, each a feature alone: `http`, the build `wai http` and the HTTP corpus's # generator are made in (wai-http.yml), and `live_egress`, the one a live egress builds on # (joule-moq-http). Neither is the full build less something a lint would not see: code # that only `video_manifest` or `key_discovery` calls is unused in them, and the full and # the conformance builds, which have both, cannot show it. - name: wai-rs is clippy-clean in the quickstart and full builds, and with http or live_egress alone if: ${{ !cancelled() }} shell: bash working-directory: wai/wai-rs run: | set -euo pipefail cargo clippy --locked --all-targets --no-default-features --features quickstart -- -D warnings cargo clippy --locked --all-targets --no-default-features --features full -- -D warnings cargo clippy --locked --all-targets --no-default-features --features http -- -D warnings cargo clippy --locked --all-targets --no-default-features --features live_egress -- -D warnings