Repository navigation
feat(parser): reusable workflow limits and prefix canonicalization #370
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: ci | |
| permissions: | |
| contents: read | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| paths-ignore: | |
| - "**.md" | |
| schedule: | |
| - cron: "0 2 * * *" | |
| workflow_dispatch: | |
| inputs: | |
| profile: | |
| description: "Property profile: fast (default) or intensive" | |
| required: false | |
| default: "fast" | |
| jobs: | |
| rust: | |
| runs-on: [self-hosted, preloop-cpane] | |
| timeout-minutes: 60 | |
| env: | |
| CARGO_BUILD_JOBS: "2" | |
| PROPTEST_CASES: "8" | |
| RUST_TEST_THREADS: "2" | |
| RUSTFLAGS: "-C link-arg=-fuse-ld=lld" | |
| steps: | |
| - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: Materialize conformance goldens | |
| run: | | |
| git lfs install --local | |
| git lfs pull --include=".runner-watch/golden/**" | |
| fixture=".runner-watch/golden/v2.335.1/06-multi-step/flows.jsonl" | |
| test -s "$fixture" | |
| if grep -q '^version https://git-lfs.github.com/spec/' "$fixture"; then | |
| echo "LFS fixture was not materialized: $fixture" >&2 | |
| exit 1 | |
| fi | |
| - uses: dtolnay/rust-toolchain@6bed0761d98439e5a578e2877258200ad565ba87 # stable | |
| with: | |
| toolchain: "1.97" | |
| components: rustfmt,clippy | |
| - name: Install lld linker | |
| run: sudo apt-get update && sudo apt-get install -y --no-install-recommends lld | |
| - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 | |
| - run: cargo fmt --all --check | |
| - run: | | |
| cargo clippy --locked -p preloop-gha-protocol -p preloop-gha-parser -p preloop-gha-expressions -p preloop-cache -p preloop-artifacts -p runner-watch -p preloop-conformance --all-targets -- -D warnings | |
| cargo clippy --locked -p preloop-runner -p preloop-runner-server -p preloop-runner-client -p preloop-dap --all-targets | |
| - run: cargo test --locked --workspace | |
| env: | |
| RUSTFLAGS: "-A warnings -C link-arg=-fuse-ld=lld" | |
| property-tests-fast: | |
| runs-on: [self-hosted, preloop-cpane] | |
| timeout-minutes: 30 | |
| if: github.event_name != 'schedule' | |
| steps: | |
| - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: dtolnay/rust-toolchain@6bed0761d98439e5a578e2877258200ad565ba87 # stable | |
| with: | |
| toolchain: "1.97" | |
| - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 | |
| - name: Verify concurrency_properties filter matches at least one test | |
| run: | | |
| count=$(PROPTEST_CASES=1 cargo test -p preloop-runner-server -- --list 2>/dev/null | grep -c 'concurrency_properties' || true) | |
| if [ "$count" -eq 0 ]; then | |
| echo "ERROR: filter 'concurrency_properties' matched zero tests in preloop-runner-server" >&2 | |
| exit 1 | |
| fi | |
| echo "concurrency_properties: $count test(s) found" | |
| - name: Verify property filters match tests | |
| run: | | |
| server=$(PROPTEST_CASES=1 cargo test -p preloop-runner-server -- --list 2>/dev/null | grep -Ec 'concurrency::properties|concurrency_properties|concurrency_http_properties' || true) | |
| runner=$(cargo test -p preloop-runner -- --list 2>/dev/null | grep -c 'timespan_tests' || true) | |
| parser=$(cargo test -p preloop-gha-parser -- --list 2>/dev/null | grep -c 'concurrency_' || true) | |
| if [ "$server" -eq 0 ] || [ "$runner" -eq 0 ] || [ "$parser" -eq 0 ]; then | |
| echo "ERROR: zero matching tests (server=$server runner=$runner parser=$parser)" >&2 | |
| exit 1 | |
| fi | |
| - name: Check no sleep() in property test files | |
| run: | | |
| files="crates/preloop-runner-server/src/concurrency_properties.rs crates/preloop-runner-server/src/concurrency_http_properties.rs" | |
| bad=0 | |
| for f in $files; do | |
| if [ -f "$f" ] && grep -q 'sleep(' "$f"; then | |
| echo "ERROR: sleep() found in $f" >&2 | |
| bad=1 | |
| fi | |
| done | |
| if [ "$bad" -ne 0 ]; then exit 1; fi | |
| echo "Sleep guard: OK" | |
| - name: Pure concurrency properties | |
| run: | | |
| PROPTEST_CASES=256 cargo test -p preloop-runner-server \ | |
| 'concurrency::properties' -- --test-threads=1 | |
| PROPTEST_CASES=256 cargo test -p preloop-runner-server \ | |
| concurrency_properties::pure -- --test-threads=1 | |
| - name: Scheduler model properties | |
| run: | | |
| PROPTEST_CASES=256 cargo test -p preloop-runner-server \ | |
| concurrency_properties::state_machine -- --test-threads=1 | |
| - name: Expression and parser properties | |
| run: | | |
| PROPTEST_CASES=256 cargo test -p preloop-gha-expressions -- --test-threads=1 | |
| cargo test -p preloop-gha-parser concurrency_ -- --test-threads=1 | |
| - name: Runner dispatcher properties | |
| run: | | |
| cargo test -p preloop-runner timespan_tests -- --test-threads=1 | |
| - name: HTTP sequence properties | |
| run: | | |
| PROPTEST_CASES=64 cargo test -p preloop-runner-server \ | |
| concurrency_http_properties -- --test-threads=1 | |
| - name: Differential harness dry-run (schema + algebraic validation) | |
| run: | | |
| python3 benchmarks/real-world/run-concurrency-property-probes.py \ | |
| --dry-run \ | |
| --corpus benchmarks/real-world/concurrency-property-cases.json | |
| - name: Differential harness rejects contaminated fixture | |
| run: | | |
| set +e | |
| python3 benchmarks/real-world/run-concurrency-property-probes.py \ | |
| --dry-run \ | |
| --corpus benchmarks/real-world/fixtures/contaminated-case.json | |
| status=$? | |
| set -e | |
| if [ "$status" -eq 0 ]; then | |
| echo "ERROR: harness did not reject contaminated fixture (expected nonzero exit)" >&2 | |
| exit 1 | |
| fi | |
| echo "Contamination rejection: OK (exit $status)" | |
| - name: Upload proptest regressions | |
| if: failure() | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: proptest-regressions-fast | |
| path: | | |
| crates/**/proptest-regressions/ | |
| if-no-files-found: ignore | |
| property-tests-intensive: | |
| runs-on: [self-hosted, preloop-cpane] | |
| timeout-minutes: 120 | |
| if: github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && github.event.inputs.profile == 'intensive') | |
| steps: | |
| - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: dtolnay/rust-toolchain@6bed0761d98439e5a578e2877258200ad565ba87 # stable | |
| with: | |
| toolchain: "1.97" | |
| - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 | |
| - name: Verify concurrency_properties filter matches at least one test | |
| run: | | |
| count=$(PROPTEST_CASES=1 cargo test -p preloop-runner-server -- --list 2>/dev/null | grep -c 'concurrency_properties' || true) | |
| if [ "$count" -eq 0 ]; then | |
| echo "ERROR: filter 'concurrency_properties' matched zero tests" >&2 | |
| exit 1 | |
| fi | |
| - name: Verify property filters match tests | |
| run: | | |
| server=$(PROPTEST_CASES=1 cargo test -p preloop-runner-server -- --list 2>/dev/null | grep -Ec 'concurrency::properties|concurrency_properties|concurrency_http_properties' || true) | |
| runner=$(cargo test -p preloop-runner -- --list 2>/dev/null | grep -c 'timespan_tests' || true) | |
| parser=$(cargo test -p preloop-gha-parser -- --list 2>/dev/null | grep -c 'concurrency_' || true) | |
| if [ "$server" -eq 0 ] || [ "$runner" -eq 0 ] || [ "$parser" -eq 0 ]; then | |
| echo "ERROR: zero matching tests (server=$server runner=$runner parser=$parser)" >&2 | |
| exit 1 | |
| fi | |
| - name: Check no sleep() in property test files | |
| run: | | |
| bad=0 | |
| for f in \ | |
| crates/preloop-runner-server/src/concurrency_properties.rs \ | |
| crates/preloop-runner-server/src/concurrency_http_properties.rs; do | |
| if [ -f "$f" ] && grep -q 'sleep(' "$f"; then | |
| echo "ERROR: sleep() found in $f" >&2 | |
| bad=1 | |
| fi | |
| done | |
| if [ "$bad" -ne 0 ]; then exit 1; fi | |
| - name: Intensive property profile (release) | |
| run: | | |
| PROPTEST_CASES=10000 PROPTEST_MAX_SHRINK_ITERS=100000 \ | |
| cargo test -p preloop-runner-server 'concurrency::properties' \ | |
| --release -- --test-threads=1 | |
| PROPTEST_CASES=10000 PROPTEST_MAX_SHRINK_ITERS=100000 \ | |
| cargo test -p preloop-runner-server concurrency_properties \ | |
| --release -- --test-threads=1 | |
| - name: Intensive runner timing profile (release) | |
| run: cargo test -p preloop-runner timespan_tests --release -- --test-threads=1 | |
| - name: Intensive expression / parser profile (release) | |
| run: | | |
| PROPTEST_CASES=10000 cargo test -p preloop-gha-expressions \ | |
| --release -- --test-threads=1 | |
| cargo test -p preloop-gha-parser concurrency_ \ | |
| --release -- --test-threads=1 | |
| - name: Intensive HTTP sequence profile (release) | |
| run: | | |
| PROPTEST_CASES=1000 PROPTEST_MAX_SHRINK_ITERS=100000 \ | |
| cargo test -p preloop-runner-server concurrency_http_properties \ | |
| --release -- --test-threads=1 | |
| - name: Differential harness dry-run | |
| run: | | |
| python3 benchmarks/real-world/run-concurrency-property-probes.py \ | |
| --dry-run \ | |
| --corpus benchmarks/real-world/concurrency-property-cases.json | |
| - name: Differential harness rejects contaminated fixture | |
| run: | | |
| set +e | |
| python3 benchmarks/real-world/run-concurrency-property-probes.py \ | |
| --dry-run \ | |
| --corpus benchmarks/real-world/fixtures/contaminated-case.json | |
| status=$? | |
| set -e | |
| if [ "$status" -eq 0 ]; then | |
| echo "ERROR: harness did not reject contaminated fixture" >&2 | |
| exit 1 | |
| fi | |
| - name: Upload proptest regressions | |
| if: failure() | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: proptest-regressions-intensive | |
| path: | | |
| crates/**/proptest-regressions/ | |
| if-no-files-found: ignore |