diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eabf4db..65f49bd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,5 +12,26 @@ jobs: steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt - name: Check formatting run: cargo fmt --all -- --check + + clippy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy + targets: wasm32-unknown-unknown + - name: Clippy (deny warnings) + run: cargo clippy --all-targets -- -D warnings + + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - name: Run tests + run: cargo test diff --git a/README.md b/README.md index a0da63a..1882ef5 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,30 @@ The release artifact is written to: target/wasm32-unknown-unknown/release/streampay_contract.wasm ``` +## CI + +Every push and pull request runs three CI checks: + +- **Format**: `cargo fmt --all -- --check` enforces consistent code style. +- **Clippy**: `cargo clippy --all-targets -- -D warnings` denies all clippy + warnings, including pedantic lints. Known-safe casts are allowed at the + crate level. +- **Test**: `cargo test` runs the full unit test suite. + +All three checks must pass before a PR can be merged. Run them locally with: + +```bash +make fmt-check # or `make fmt` to auto-fix formatting +make clippy +make test +``` + +Or run all three in one command: + +```bash +make lint +``` + ## Deploy ```bash diff --git a/src/lib.rs b/src/lib.rs index cf1ddfd..73efff8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,16 @@ #![no_std] +#![deny(clippy::all)] +#![warn(clippy::pedantic)] +// Intentional numeric casts that are safe by construction: +// - u64 subtractions cast to i128/u128 for vesting math (values bounded by window) +// - i128 bps values cast to u32 (bounded to 0..=10_000) +// - usize/u32 loop counters cast to u64 for stream IDs +#![allow(clippy::cast_possible_truncation)] +#![allow(clippy::cast_possible_wrap)] +#![allow(clippy::cast_precision_loss)] +#![allow(clippy::cast_sign_loss)] +// Type names intentionally repeat the module name (e.g. `error::Error`). +#![allow(clippy::module_name_repetitions)] //! StreamPay: a real-time payment-streaming smart contract for Stellar. //! //! StreamPay lets a sender escrow a fixed amount of a token and stream it diff --git a/src/test.rs b/src/test.rs index 96111d5..feb155e 100644 --- a/src/test.rs +++ b/src/test.rs @@ -893,6 +893,8 @@ fn test_create_stream_zero_start_rejects_end_before_now() { .contract .try_create_stream(&s.sender, &s.recipient, &1_000, &0, &500); assert_eq!(res, Err(Ok(Error::InvalidTimeRange))); +} + // --- Supply cap tests ------------------------------------------------------- #[test] @@ -1082,6 +1084,8 @@ fn test_supply_recovers_after_full_withdraw_allowing_new_stream() { .create_stream(&s.sender, &s.recipient, &500, &400, &500); assert_eq!(new_id, 1); assert_eq!(s.contract.get_total_supply(), 500); +} + // --- README content contract ----------------------------------------------- /// Verify that the README contains a "Resource Costs" section.