From b1455b55834d0f62ce90e2ac8fd01a50ee5eb0cd Mon Sep 17 00:00:00 2001 From: Edouard Vanbelle Date: Mon, 15 Jun 2026 15:53:43 +0200 Subject: [PATCH] chore(wasm): check, clippy, test, CI --- .github/workflows/ci.yml | 49 ++++++++++++++++++ justfile | 7 +++ scripts/build-wasm.sh | 13 +++++ .../hash-wasm/oxicloud_hash_wasm_bg.wasm | Bin 55809 -> 63589 bytes wasm/oxicloud-hash/src/lib.rs | 8 +-- 5 files changed, 73 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eeed56d8..dd793c29 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,6 +23,7 @@ jobs: outputs: frontend: ${{ steps.filter.outputs.frontend }} backend: ${{ steps.filter.outputs.backend }} + wasm: ${{ steps.filter.outputs.wasm }} steps: - uses: actions/checkout@v4 - uses: dorny/paths-filter@v3 @@ -44,6 +45,9 @@ jobs: - 'Cargo.toml' - 'Cargo.lock' - 'tests/**' + wasm: + - 'wasm/**' + - 'scripts/build-wasm.sh' frontend-check: name: Frontend — CSS and JS checks (format, lint, css-rules, types) @@ -122,6 +126,51 @@ jobs: - uses: Swatinem/rust-cache@v2 - run: cargo clippy --all-targets --all-features -- -D warnings + # Mirrors the `wasm-check` justfile recipe. The wasm crate is a + # standalone workspace under `wasm/oxicloud-hash/` and is NOT + # built by the server's `cargo build` — these checks have to run + # explicitly from inside the sub-workspace. clippy + tests run + # against the HOST target (no wasm32 target needed in CI) which + # is enough to cover the algorithmic logic; the wasm32 build is + # exercised by `scripts/build-wasm.sh` and the frontend tests. + wasm-check: + name: Wasm — fmt + clippy + needs: changes + if: needs.changes.outputs.wasm == 'true' + runs-on: ubuntu-latest + defaults: + run: + working-directory: wasm/oxicloud-hash + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt, clippy + - uses: Swatinem/rust-cache@v2 + with: + workspaces: wasm/oxicloud-hash + - run: cargo fmt --all --check + - run: cargo clippy --all-features --release -- -D warnings + + # Mirrors the `wasm-test` justfile recipe. Tests run in release + # mode because the FastCDC + BLAKE3 workload takes minutes in + # the default debug profile (no inlining / no SIMD). + wasm-test: + name: Wasm — release tests + needs: changes + if: needs.changes.outputs.wasm == 'true' + runs-on: ubuntu-latest + defaults: + run: + working-directory: wasm/oxicloud-hash + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + with: + workspaces: wasm/oxicloud-hash + - run: cargo test --release + rust-test: name: Server Unit and Functionnal Tests needs: changes diff --git a/justfile b/justfile index a0622737..5fc59258 100644 --- a/justfile +++ b/justfile @@ -69,6 +69,13 @@ frontend-check: node scripts/check-dead-tokens.mjs node scripts/check-brand-drift.mjs +wasm-check: + cd wasm/oxicloud-hash; cargo fmt --all + cd wasm/oxicloud-hash; cargo clippy --all-features --release -- -D warnings + +wasm-test: + cd wasm/oxicloud-hash; cargo test --release + # audit security (condition: cargo install cargo-audit) audit: cargo audit diff --git a/scripts/build-wasm.sh b/scripts/build-wasm.sh index 9a64cff7..55a52528 100755 --- a/scripts/build-wasm.sh +++ b/scripts/build-wasm.sh @@ -20,6 +20,19 @@ cd "$(dirname "$0")/.." CRATE=wasm/oxicloud-hash OUT=static/js/vendors/hash-wasm +if ! ( rustup target list --installed | grep -q wasm32-unknown-unknown ) +then + echo -e "install first wasm32-unknown-unknown via:\n\trustup target add wasm32-unknown-unknown" + exit 1 +fi + +if ! which wasm-bindgen >/dev/null 2>/dev/null +then + WASM_BINDGEN_VERSION=$(grep -A1 'name = "wasm-bindgen"' $CREATE/Cargo.lock | head -2 | grep version | sed 's/version = //') + echo -e "wasm-bindgen not found, install it via:\n\tcargo install wasm-bindgen-cli --version $WASM_BINDGEN_VERSION" + exit 1 +fi + # SIMD128 is baseline in every evergreen browser (Chrome 91+, Firefox 89+, # Safari 16.4+) and is worth ~3-4× in hashing throughput. Browsers without # it fail instantiation; the frontend detects that and falls back to a diff --git a/static/js/vendors/hash-wasm/oxicloud_hash_wasm_bg.wasm b/static/js/vendors/hash-wasm/oxicloud_hash_wasm_bg.wasm index 0f09d2a67647f0a5d3bed763fb86391889bf01c4..66b6097f38722b538004d7300612fba1ede80e44 100644 GIT binary patch literal 63589 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 SfK*0JUIqGNQp5Z$sre5{Ui}IH delta 22887 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 diff --git a/wasm/oxicloud-hash/src/lib.rs b/wasm/oxicloud-hash/src/lib.rs index 627c379b..b7c2955a 100644 --- a/wasm/oxicloud-hash/src/lib.rs +++ b/wasm/oxicloud-hash/src/lib.rs @@ -153,7 +153,7 @@ impl DeltaChunker { let bytes = &self.buf[chunk.offset..chunk.offset + chunk.length]; push_chunk_json( &mut out, - &blake3::hash(bytes).to_hex().to_string(), + blake3::hash(bytes).to_hex().as_ref(), chunk.length, ); consumed = chunk.offset + chunk.length; @@ -175,13 +175,13 @@ impl DeltaChunker { if !self.buf.is_empty() { push_chunk_json( &mut out, - &blake3::hash(&self.buf).to_hex().to_string(), + blake3::hash(&self.buf).to_hex().as_ref(), self.buf.len(), ); self.buf.clear(); } out.push_str("],\"file_hash\":\""); - out.push_str(&self.file_hasher.finalize().to_hex().to_string()); + out.push_str(self.file_hasher.finalize().to_hex().as_ref()); out.push_str("\",\"total\":"); out.push_str(&self.total.to_string()); out.push('}'); @@ -238,7 +238,7 @@ mod tests { fn run_chunker(data: &[u8], slice: usize) -> (Vec<(String, usize)>, String) { let mut chunker = DeltaChunker::new(); let mut chunks: Vec<(String, usize)> = Vec::new(); - let mut parse = |json: &str, into: &mut Vec<(String, usize)>| { + let parse = |json: &str, into: &mut Vec<(String, usize)>| { // items look like ["",N] — split on '[' groups. for item in json.split("[\"").skip(1) { let hash = &item[..64];