Merge pull request #721 from soma-enyi/feature/issues-663-664-665-666 #191
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 | |
| on: | |
| push: | |
| branches: ["main", "feature/**", "fix/**", "docs/**"] | |
| pull_request: | |
| branches: ["main"] | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: 1 | |
| jobs: | |
| # ── Type-check all contracts ────────────────────────────────────────────── | |
| check: | |
| name: cargo check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: "1.75" | |
| targets: wasm32-unknown-unknown | |
| - name: Cache cargo registry | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml') }} | |
| restore-keys: ${{ runner.os }}-cargo- | |
| - name: cargo check (native) | |
| run: cargo check --workspace | |
| - name: cargo check (wasm32) | |
| run: cargo check --workspace --target wasm32-unknown-unknown --exclude kora-tests | |
| # ── Lint ────────────────────────────────────────────────────────────────── | |
| clippy: | |
| name: clippy | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: "1.75" | |
| components: clippy | |
| - name: Cache cargo registry | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-clippy-${{ hashFiles('**/Cargo.toml') }} | |
| restore-keys: ${{ runner.os }}-clippy- | |
| - name: cargo clippy (warnings as errors) | |
| run: cargo clippy --workspace -- -D warnings | |
| # ── Formatting ──────────────────────────────────────────────────────────── | |
| fmt: | |
| name: rustfmt | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: "1.75" | |
| components: rustfmt | |
| - name: cargo fmt --check | |
| run: cargo fmt --all -- --check | |
| # ── Unbounded loop guard ────────────────────────────────────────────────── | |
| # | |
| # Flags loops over ledger-sourced collections (Map/Vec loaded from | |
| # persistent/instance storage) that make a cross-contract call per | |
| # iteration with no visible bound — cost scales with on-chain state size | |
| # and can exceed Soroban's CPU instruction limit at scale. | |
| # financing_pool::distribute_yield is a known, baselined instance; new | |
| # occurrences fail this check. See scripts/check_unbounded_loops.py. | |
| unbounded-loop-guard: | |
| name: unbounded loop guard | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Check for unbounded loops with cross-contract calls | |
| run: python3 scripts/check_unbounded_loops.py | |
| # ── Dependency cycle guard (issue #275) ────────────────────────────────── | |
| # | |
| # Runs `cargo tree` and fails if any cycle is detected. | |
| # Cargo itself rejects cyclic Cargo.toml graphs, so this step | |
| # catches the error and surfaces it clearly in the CI log. | |
| # | |
| # If a cycle is ever introduced, cargo tree will exit non-zero and | |
| # print the cycle path. Fix by removing the circular dependency. | |
| cycle-guard: | |
| name: dependency cycle guard | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: "1.75" | |
| - name: Cache cargo registry | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| key: ${{ runner.os }}-tree-${{ hashFiles('**/Cargo.toml') }} | |
| restore-keys: ${{ runner.os }}-tree- | |
| - name: Install cargo-tree (bundled with cargo, verify it works) | |
| run: cargo tree --version | |
| - name: Check for dependency cycles | |
| run: | | |
| echo "=== Kora workspace dependency graph ===" | |
| cargo tree --workspace --depth 3 | |
| echo "" | |
| echo "=== Cycle check ===" | |
| # cargo tree exits non-zero if it encounters a cycle. | |
| # An explicit check with --no-dedupe surfaces all paths. | |
| if cargo tree --workspace --no-dedupe 2>&1 | grep -i "cycle detected"; then | |
| echo "ERROR: Circular dependency detected in workspace." | |
| echo "Fix: remove the cycle shown above before merging." | |
| exit 1 | |
| fi | |
| echo "No dependency cycles detected." | |
| # ── KoraError variant consistency guard (issue #421) ───────────────────── | |
| # | |
| # Fails the build if any contract crate references a `KoraError::Variant` | |
| # that isn't actually declared on the `KoraError` enum in | |
| # contracts/shared/src/errors.rs — the recurring bug class behind issues | |
| # #188, #244, #245, #346, #347. Runs independently of `cargo check` so it | |
| # still gives a signal even when the workspace itself fails to compile. | |
| error-variant-guard: | |
| name: KoraError variant consistency | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: "1.75" | |
| - name: Cache cargo registry | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-xtask-${{ hashFiles('**/Cargo.toml') }} | |
| restore-keys: ${{ runner.os }}-xtask- | |
| - name: cargo run -p kora-xtask --bin check-error-variants | |
| run: cargo run -p kora-xtask --bin check-error-variants | |
| # ── Unit & integration tests ────────────────────────────────────────────── | |
| test: | |
| name: cargo test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: "1.75" | |
| - name: Cache cargo registry | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-test-${{ hashFiles('**/Cargo.toml') }} | |
| restore-keys: ${{ runner.os }}-test- | |
| - name: cargo test | |
| run: cargo test --workspace | |
| # ── Code coverage gate (issue #643) ────────────────────────────────────── | |
| # | |
| # Measures code coverage using cargo-tarpaulin with a minimum threshold | |
| # to ensure adequate test coverage across the workspace. | |
| coverage: | |
| name: code coverage | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: "1.75" | |
| - name: Cache cargo registry | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-coverage-${{ hashFiles('**/Cargo.toml') }} | |
| restore-keys: ${{ runner.os }}-coverage- | |
| - name: Install cargo-tarpaulin | |
| run: cargo install cargo-tarpaulin --locked --version 0.21.0 | |
| - name: Run coverage analysis | |
| run: make coverage COVERAGE_MIN=95 | |
| # ── TTL Keeper validation (issue #644) ─────────────────────────────────── | |
| # | |
| # Validates that the TTL keeper script is properly configured for | |
| # scheduled execution with proper error handling and network validation. | |
| ttl-keeper-validation: | |
| name: TTL Keeper validation | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Validate TTL keeper script | |
| run: ./scripts/test-ttl-keeper.sh | |
| # ── Reproducible build verification (issue #645) ───────────────────────── | |
| # | |
| # Validates that WASM binaries are built reproducibly. This ensures that | |
| # the compiled output is deterministic, which is critical for proving that | |
| # deployed contracts match their source code. | |
| reproducible-build-check: | |
| name: Reproducible build verification | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Validate reproducible build structure | |
| run: ./scripts/test-reproducible-build.sh | |
| # ── WASM size regression gate test (issue #646) ────────────────────────── | |
| # | |
| # Validates that the WASM size regression gate is properly configured to: | |
| # - Track all contract sizes | |
| # - Compare against baseline | |
| # - Fail on regressions exceeding threshold | |
| # - Report results clearly | |
| wasm-size-gate-test: | |
| name: WASM size regression gate validation | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Validate WASM size gate configuration | |
| run: ./scripts/test-wasm-size-gate.sh | |
| # ── Supply-chain audit gate (issue #609) ───────────────────────────────── | |
| # | |
| # Runs cargo-deny (license / banned-crate / source checks against deny.toml) | |
| # and cargo-audit (vulnerability advisories against RustSec database) as a | |
| # blocking CI gate. Both tools are installed at pinned versions so results | |
| # are reproducible. | |
| # | |
| # Exception process: | |
| # - For a known advisory that is accepted-risk: add an `[advisories.ignore]` | |
| # entry in deny.toml with a comment explaining the rationale and a | |
| # tracking issue. | |
| # - For a disallowed license or source: add an explicit `[licenses.allow]` | |
| # or `[sources.allow-git]` entry in deny.toml. | |
| # | |
| # Retry policy: the step retries once on non-zero exit to absorb transient | |
| # registry/network failures (GitHub Actions native retry via a shell loop). | |
| supply-chain-audit: | |
| name: supply-chain audit (cargo-deny + cargo-audit) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: "1.75" | |
| - name: Cache cargo registry | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| key: ${{ runner.os }}-audit-${{ hashFiles('**/Cargo.toml', 'deny.toml') }} | |
| restore-keys: ${{ runner.os }}-audit- | |
| - name: Install cargo-deny (pinned) | |
| run: | | |
| # Retry once on transient network failure | |
| cargo install cargo-deny --locked --version 0.14.24 \ | |
| || cargo install cargo-deny --locked --version 0.14.24 | |
| - name: Install cargo-audit (pinned) | |
| run: | | |
| cargo install cargo-audit --locked --version 0.21.0 \ | |
| || cargo install cargo-audit --locked --version 0.21.0 | |
| - name: cargo deny check | |
| # Fail on vulnerabilities, disallowed licenses, banned crates, and | |
| # disallowed registries/sources. Retry once on transient registry | |
| # network failures (exit code 1 can also mean a real deny failure, | |
| # but a second attempt distinguishes the two in most cases). | |
| run: | | |
| cargo deny check \ | |
| || cargo deny check | |
| - name: cargo audit | |
| # Fetch the advisory database and check for known CVEs. | |
| # --deny warnings escalates unmaintained/unsound to a failure. | |
| # Retry once for network resilience. | |
| run: | | |
| cargo audit --deny warnings \ | |
| || cargo audit --deny warnings |