diff --git a/.github/versions.env b/.github/versions.env new file mode 100644 index 0000000..4670418 --- /dev/null +++ b/.github/versions.env @@ -0,0 +1,4 @@ +# Centralized version pins for GitHub Actions and local tooling checks. +# Keep these values in sync with rust-toolchain.toml and scripts/check-tools.sh. +RUST_VERSION=1.95.0 +STELLAR_CLI_VERSION=22.8.2 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d312d29..09171ae 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,7 +6,6 @@ on: env: CARGO_TERM_COLOR: always - STELLAR_CLI_VERSION: "22.8.2" jobs: wasm-build: @@ -14,10 +13,19 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Load version pins + shell: bash + run: | + set -a + source .github/versions.env + set +a + echo "RUST_VERSION=$RUST_VERSION" >> "$GITHUB_ENV" + echo "STELLAR_CLI_VERSION=$STELLAR_CLI_VERSION" >> "$GITHUB_ENV" + - name: Install Rust toolchain uses: dtolnay/rust-toolchain@master with: - toolchain: "1.95.0" + toolchain: ${{ env.RUST_VERSION }} targets: wasm32-unknown-unknown - name: Install stellar-cli build dependencies diff --git a/.github/workflows/contract-size.yml b/.github/workflows/contract-size.yml index 7dcc926..02ddc0f 100644 --- a/.github/workflows/contract-size.yml +++ b/.github/workflows/contract-size.yml @@ -24,10 +24,18 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Load version pins + shell: bash + run: | + set -a + source .github/versions.env + set +a + echo "RUST_VERSION=$RUST_VERSION" >> "$GITHUB_ENV" + - name: Install Rust toolchain uses: dtolnay/rust-toolchain@master with: - toolchain: "1.95.0" + toolchain: ${{ env.RUST_VERSION }} targets: wasm32-unknown-unknown - name: Cache cargo build diff --git a/.github/workflows/fmt.yml b/.github/workflows/fmt.yml index 2815c59..11a1bcd 100644 --- a/.github/workflows/fmt.yml +++ b/.github/workflows/fmt.yml @@ -13,10 +13,18 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Load version pins + shell: bash + run: | + set -a + source .github/versions.env + set +a + echo "RUST_VERSION=$RUST_VERSION" >> "$GITHUB_ENV" + - name: Install Rust toolchain uses: dtolnay/rust-toolchain@master with: - toolchain: "1.95.0" + toolchain: ${{ env.RUST_VERSION }} components: rustfmt - name: Check formatting diff --git a/.github/workflows/init-smoke-test.yml b/.github/workflows/init-smoke-test.yml index b6f89b3..2ba0ef8 100644 --- a/.github/workflows/init-smoke-test.yml +++ b/.github/workflows/init-smoke-test.yml @@ -14,7 +14,6 @@ on: env: CARGO_TERM_COLOR: always - STELLAR_CLI_VERSION: "22.8.2" jobs: init-smoke-test: @@ -37,10 +36,19 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Load version pins + shell: bash + run: | + set -a + source .github/versions.env + set +a + echo "RUST_VERSION=$RUST_VERSION" >> "$GITHUB_ENV" + echo "STELLAR_CLI_VERSION=$STELLAR_CLI_VERSION" >> "$GITHUB_ENV" + - name: Install Rust toolchain uses: dtolnay/rust-toolchain@master with: - toolchain: "1.95.0" + toolchain: ${{ env.RUST_VERSION }} targets: wasm32-unknown-unknown - name: Install stellar-cli build dependencies diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 18b2add..4c940dc 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -13,12 +13,23 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Load version pins + shell: bash + run: | + set -a + source .github/versions.env + set +a + echo "RUST_VERSION=$RUST_VERSION" >> "$GITHUB_ENV" + - name: Install Rust toolchain uses: dtolnay/rust-toolchain@master with: - toolchain: "1.95.0" + toolchain: ${{ env.RUST_VERSION }} components: clippy + - name: Check workflow version pins + run: bash scripts/check-workflow-version-pins.sh + - name: Cache Rust dependencies uses: Swatinem/rust-cache@v2 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f560880..b65015a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,10 +20,18 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Load version pins + shell: bash + run: | + set -a + source .github/versions.env + set +a + echo "RUST_VERSION=$RUST_VERSION" >> "$GITHUB_ENV" + - name: Install Rust toolchain uses: dtolnay/rust-toolchain@master with: - toolchain: "1.95.0" + toolchain: ${{ env.RUST_VERSION }} targets: wasm32-unknown-unknown - name: Cache Rust dependencies @@ -49,10 +57,18 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Load version pins + shell: bash + run: | + set -a + source .github/versions.env + set +a + echo "RUST_VERSION=$RUST_VERSION" >> "$GITHUB_ENV" + - name: Install Rust toolchain uses: dtolnay/rust-toolchain@master with: - toolchain: "1.95.0" + toolchain: ${{ env.RUST_VERSION }} targets: wasm32-unknown-unknown - name: Install cargo-mutants diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f3bae89..6fafa31 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,3 +16,15 @@ repos: entry: scripts/check-enum-ordering.sh language: script pass_filenames: false + - id: check-workflow-version-pins + name: Check centralized workflow version pins + entry: scripts/check-workflow-version-pins.sh + language: system + pass_filenames: false + - id: slow-local-ci + name: slow local CI equivalent + entry: > + bash -c 'set -euo pipefail; if [ "${SKIP_SLOW_CHECKS:-0}" = "1" ]; then echo "Skipping slow pre-push checks because SKIP_SLOW_CHECKS=1"; exit 0; fi; echo "Running slow pre-push checks (cargo test --all + wasm size gate)..."; cargo test --all; cargo build --target wasm32-unknown-unknown --release; MAX_CONTRACT_SIZE=${MAX_CONTRACT_SIZE:-65536}; shopt -s nullglob; for wasm in target/wasm32-unknown-unknown/release/*.wasm; do size=$(stat --format=%s "$wasm"); if [ "$size" -gt "$MAX_CONTRACT_SIZE" ]; then echo "Contract WASM exceeds ${MAX_CONTRACT_SIZE} bytes: ${wasm##*/} (${size} bytes)"; exit 1; fi; done; echo "Slow pre-push checks passed."' + language: system + pass_filenames: false + stages: [pre-push] diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 455ce13..31d7f88 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -97,12 +97,37 @@ pip install pre-commit pre-commit install ``` -Hooks run on each commit and enforce: +The default hooks run on each commit and enforce: - `cargo fmt --all -- --check` - `cargo clippy -- -D warnings` +- the enum-ordering check in `scripts/check-enum-ordering.sh` -Run all hooks manually: +There is also a separate, intentionally slower pre-push hook that mirrors the full local CI-equivalent pass before you push: + +```sh +pre-commit install --hook-type pre-push +``` + +This pre-push hook runs: + +- `cargo test --all` +- `cargo build --target wasm32-unknown-unknown --release` +- a local WASM size gate for every compiled contract (`64 KiB` limit) + +This is intentionally not the default commit hook because `cargo test --all` takes longer than the fast commit checks and is meant to be a one-time, deliberate full verification step before pushing. If you need to bypass it for a temporary local push, set: + +```sh +SKIP_SLOW_CHECKS=1 git push +``` + +You can also run the slow hook manually without a push: + +```sh +SKIP_SLOW_CHECKS=1 pre-commit run --hook-stage pre-push +``` + +Run all commit hooks manually: ```sh pre-commit run --all-files diff --git a/contracts/settlement-workflow/src/lib.rs b/contracts/settlement-workflow/src/lib.rs index 1760719..5968674 100644 --- a/contracts/settlement-workflow/src/lib.rs +++ b/contracts/settlement-workflow/src/lib.rs @@ -126,9 +126,9 @@ impl SettlementWorkflowContract { settlement_ids: Vec, token_contract: Address, merchant: Address, - ) -> Vec { + ) -> Result, TreasuryError> { let compliance = ComplianceClient::new(&env, &Self::compliance_id(&env)); - compliance.require_allowed_for_treasury(&merchant).unwrap(); + compliance.require_allowed_for_treasury(&merchant)?; let treasury = TreasuryOnlyClient::new(&env, &Self::treasury_id(&env)); let mut executed = Vec::new(&env); for id in settlement_ids.iter() { @@ -146,6 +146,6 @@ impl SettlementWorkflowContract { } // Invalid / already-executed / threshold-failed IDs are silently skipped. } - executed + Ok(executed) } } diff --git a/scripts/check-workflow-version-pins.sh b/scripts/check-workflow-version-pins.sh new file mode 100755 index 0000000..eb21ca0 --- /dev/null +++ b/scripts/check-workflow-version-pins.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +VERSIONS_FILE="$ROOT_DIR/.github/versions.env" +WORKFLOWS_DIR="$ROOT_DIR/.github/workflows" + +if [[ ! -f "$VERSIONS_FILE" ]]; then + echo "Missing central version pins file: $VERSIONS_FILE" >&2 + exit 1 +fi + +# shellcheck disable=SC1090 +set -a +source "$VERSIONS_FILE" +set +a + +if [[ -z "${RUST_VERSION:-}" || -z "${STELLAR_CLI_VERSION:-}" ]]; then + echo "Central version pins file is missing RUST_VERSION or STELLAR_CLI_VERSION" >&2 + exit 1 +fi + +matches=$(grep -RInE '1\.95\.0|22\.8\.2' "$WORKFLOWS_DIR"/*.yml 2>/dev/null || true) +if [[ -z "$matches" ]]; then + echo "Workflow version pins are centralized in .github/versions.env." + exit 0 +fi + +violations=() +while IFS= read -r line; do + file="${line%%:*}" + rest="${line#*: }" + if [[ "$rest" =~ ^[[:space:]]*# ]]; then + continue + fi + if [[ "$rest" =~ \.github/versions\.env|env\.RUST_VERSION|env\.STELLAR_CLI_VERSION|\$\{\{[[:space:]]*env\.[A-Z_]+[[:space:]]*\}\}|\$RUST_VERSION|\$STELLAR_CLI_VERSION ]]; then + continue + fi + violations+=("$line") +done <<< "$matches" + +if (( ${#violations[@]} > 0 )); then + echo "Hardcoded workflow version pins detected. Use .github/versions.env instead:" >&2 + printf '%s\n' "${violations[@]}" >&2 + exit 1 +fi + +echo "Workflow version pins are centralized in .github/versions.env."