diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 20c5fac7..1e0be8b4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,6 +3,10 @@ on: branches: - main pull_request: + # `edited` included for base retargets (e.g. a stacked PR's base merging): + # paths-filter's verdict depends on the base, and without `edited` a stale + # verdict stays attached to the unchanged head sha. + types: [opened, synchronize, reopened, edited] branches: - main workflow_dispatch: @@ -90,3 +94,101 @@ jobs: retry_on: error timeout_minutes: 20 command: wasm-pack test --release --headless --\${{ matrix.browser }} ./pg-wasm + + # --------------------------------------------------------------------------- + # Wire compatibility: HEAD-sealed containers must open with published readers + # (#251 / #260). #261 adds a wire-compat-js job that downloads the artifact + # this job uploads. + # + # The path filter is a step, not an `on: paths:` key, on purpose: a job that + # is skipped by a path filter never reports, so a required check would sit + # pending forever on PRs that do not touch the wire surface. This shape always + # reports and only does the expensive work when it needs to. + # --------------------------------------------------------------------------- + wire-compat-rust: + name: Wire compat (published pg-core) + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read # paths-filter reads the PR's changed files + steps: + - uses: actions/checkout@v4 + # SHA-pinned as the one action new to this repo; the rest follow the + # file's existing floating-ref convention. + - uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2 + id: changes + with: + filters: | + wire: + - 'pg-core/**' + - 'pg-wasm/**' + - 'pg-compat/**' + # pg-core has no lockfile of its own: the bytes HEAD seals are a + # function of the ROOT lockfile (a bincode-next/ibe/serde bump + # touches only these two files). Root Cargo.toml also holds the + # exclude list that keeps pg-compat on crates.io pg-core. + - 'Cargo.lock' + - 'Cargo.toml' + - '.github/workflows/build.yml' + + - if: steps.changes.outputs.wire == 'true' + uses: dtolnay/rust-toolchain@stable + with: + components: clippy, rustfmt + + - name: Seal the sample set with HEAD + id: seal + if: steps.changes.outputs.wire == 'true' + shell: bash + run: | + cargo run --locked -p pg-core --features stream --example seal-samples \ + -- "$RUNNER_TEMP/wire-compat-artifacts" + + # Hand-off to wire-compat-js (#261). Uploaded before the reader runs so a + # red gate still leaves the bytes that broke it. + - name: Upload the sample set + if: steps.seal.outcome == 'success' + uses: actions/upload-artifact@v4 + with: + name: wire-compat-artifacts-${{ github.event.pull_request.head.sha || github.sha }} + path: ${{ runner.temp }}/wire-compat-artifacts + retention-days: 7 + + - name: Open it with published pg-core + if: steps.changes.outputs.wire == 'true' + shell: bash + env: + PG_COMPAT_ARTIFACTS: ${{ runner.temp }}/wire-compat-artifacts + run: cargo test --manifest-path pg-compat/Cargo.toml --locked + + # pg-compat is outside the workspace, so the per-crate fmt/clippy matrices do + # not cover it. Kept separate from wire-compat-rust on purpose: a new stable + # rustc lint must not red a required check named after wire compatibility, + # nor pre-empt the seal/read steps that answer it. + pg-compat-lint: + name: Lint pg-compat + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + steps: + - uses: actions/checkout@v4 + - uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2 + id: changes + with: + filters: | + wire: + - 'pg-compat/**' + - 'Cargo.lock' + - 'Cargo.toml' + - '.github/workflows/build.yml' + - if: steps.changes.outputs.wire == 'true' + uses: dtolnay/rust-toolchain@stable + with: + components: clippy, rustfmt + - name: Format pg-compat + if: steps.changes.outputs.wire == 'true' + run: cargo fmt --manifest-path pg-compat/Cargo.toml --all -- --check + - name: Clippy pg-compat + if: steps.changes.outputs.wire == 'true' + run: cargo clippy --manifest-path pg-compat/Cargo.toml --all-targets --locked -- -D warnings diff --git a/CLAUDE.md b/CLAUDE.md index 2e7a43ae..df77c61c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -5,7 +5,7 @@ Migrated from the dobby memory repo (`encryption4all/dobby`). This file is the s ## Workspace & CI - Workspace members: `pg-core` (lib), `pg-ffi` (C ABI), `pg-pkg` (PKG service), `pg-cli`. `pg-wasm` is a sibling crate the root `Cargo.toml` lists under `exclude`, so it is not part of the workspace and is built separately with wasm-pack (see Release & configuration). Sub-crates share workspace files. Build the workspace from repo root with `cargo build`. A bare `cargo test --workspace` FAILS to compile: `pg-core`'s tests are gated behind its `test` feature (also `rust`/`stream`), so the item is configured out and imports like `crate::test::TestSetup` don't resolve. CI (`.github/workflows/build.yml`) runs tests per crate: `cargo test --manifest-path pg-core/Cargo.toml --features test,rust,stream` for core, `--all-features` for `pkg`/`cli`/`ffi`. None of these cover `pg-wasm`. `pg-core` uses CGWKV + MKEM for multi-recipient encryption (production feature set `["cgwkv", "mkem"]`). -- `pg-compat` is a second excluded sibling crate (root `Cargo.toml` `exclude`), and the exclusion is load-bearing: it depends on `pg-core` from **crates.io** (`=0.6.1`), not on `../pg-core`, so it can open bytes sealed by this tree with published readers. It has its own `Cargo.lock` (run it with `--locked`) and is covered by none of the per-crate test/fmt/clippy matrices, so run `cargo fmt --manifest-path pg-compat/Cargo.toml --all -- --check` and `cargo clippy --manifest-path pg-compat/Cargo.toml --all-targets -- -D warnings` by hand. Its input comes from `cargo run -p pg-core --features stream --example seal-samples --