decode: validate string fields with smoothutf8 (default-on fast-utf8 feature) #740
Workflow file for this run
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] | |
| pull_request: | |
| # Run required checks on merge queue groups so queued PRs can land. | |
| merge_group: | |
| permissions: | |
| contents: read | |
| env: | |
| CARGO_TERM_COLOR: always | |
| # protoc v27+ is required for editions 2023 support (utf8_validation.proto). | |
| # Ubuntu's apt protobuf-compiler is v21.12 — too old. Keep this in sync | |
| # with the conformance tools image (see conformance/Dockerfile.tools). | |
| PROTOC_VERSION: "33.5" | |
| jobs: | |
| # ── Fast feedback: lint + test on stable ───────────────────────────────── | |
| lint-and-test: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| # Pinned (not @stable) so rustfmt/clippy match rust-toolchain.toml and | |
| # local runs agree with CI. Bump together with that file. | |
| # | |
| # NOTE: the action only runs `rustup default`, which rust-toolchain.toml | |
| # overrides — so the file is what actually selects the toolchain for | |
| # cargo. The pin here must NAME THE SAME VERSION as the file so the | |
| # components installed by this step belong to the toolchain cargo uses. | |
| - uses: dtolnay/rust-toolchain@1.95 | |
| with: | |
| components: clippy, rustfmt | |
| - name: Install protoc | |
| run: | | |
| curl -fsSL "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-x86_64.zip" -o /tmp/protoc.zip | |
| sudo unzip -o /tmp/protoc.zip -d /usr/local | |
| protoc --version | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 (sha-pinned) | |
| - name: Rustfmt | |
| run: cargo fmt --all --check | |
| - name: Clippy | |
| run: cargo clippy --workspace --all-targets -- -D warnings | |
| - name: Tests | |
| run: cargo test --workspace | |
| # Optional features must keep compiling — #88 was a feature-flag-only | |
| # break that escaped the default-features test pass above. cargo check | |
| # is sufficient to catch compile breaks without doubling the test time. | |
| - name: Check all features | |
| run: cargo check --workspace --all-features | |
| # `gate_impls_on_crate_features` codegen output: generate the buffa-test | |
| # fixture protos with the gate on, then `cargo check` the result with | |
| # each `{json, views, text}` subset. Catches name-resolution bugs the | |
| # string-match tests cannot — a `cfg`-gated item referenced from an | |
| # ungated context survives `syn::parse_file` but fails this. Marked | |
| # `--ignored` so the default workspace test stays fast. (#113) | |
| - name: Feature-gating compile matrix | |
| run: cargo test -p buffa-codegen --test feature_gating_compile -- --ignored | |
| # ── Markdown lint ──────────────────────────────────────────────────────── | |
| # Same pinned markdownlint-cli version as `task lint-md`. Node is | |
| # preinstalled on ubuntu-latest so no setup-node step is needed. | |
| lint-markdown: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - run: npx --yes markdownlint-cli@0.47.0 '**/*.md' --ignore target --ignore .claude | |
| # ── MSRV check ─────────────────────────────────────────────────────────── | |
| msrv-check: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| # The checked-in Cargo.lock is written by the pinned dev toolchain and | |
| # may resolve transitive deps (e.g. getrandom, clap_lex) to versions | |
| # whose manifests cargo 1.75 cannot parse (edition2024). Regenerate with | |
| # stable cargo's MSRV-aware resolver so transitive deps satisfy | |
| # rust-version = 1.75; cargo writes a v3 lockfile because the workspace | |
| # rust-version is below 1.78. | |
| - name: Regenerate MSRV-compatible lockfile | |
| env: | |
| CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS: fallback | |
| run: rm -f Cargo.lock && cargo generate-lockfile | |
| - uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: '1.75' | |
| - name: Install protoc | |
| run: | | |
| curl -fsSL "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-x86_64.zip" -o /tmp/protoc.zip | |
| sudo unzip -o /tmp/protoc.zip -d /usr/local | |
| protoc --version | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 (sha-pinned) | |
| # rust-toolchain.toml pins the dev toolchain and overrides `rustup | |
| # default`, so RUSTUP_TOOLCHAIN is set explicitly to outrank the file. | |
| - name: Check (MSRV 1.75) | |
| env: | |
| RUSTUP_TOOLCHAIN: '1.75' | |
| run: cargo check --workspace --all-targets --locked | |
| # ── Miri: proves the SizeCache `unsafe` reads no uninitialized memory ───── | |
| # SizeCache stores its inline slots as `MaybeUninit<u32>` to avoid zeroing the | |
| # whole array on every encode; `consume_next` reads them via `assume_init`. | |
| # Miri tracks per-byte init state, so this job mechanically verifies the | |
| # soundness invariant (slots < len are initialized) on every reserve / set / | |
| # consume / clear / spill path the size_cache tests exercise. Scoped to that | |
| # module to keep the (interpreted, slow) run fast — ~15-30s steady state, so | |
| # it runs on every PR as a blocking gate rather than on a nightly schedule. | |
| # | |
| # The nightly is PINNED (not floating): a required check must not be broken by | |
| # an unrelated bad nightly. Bump MIRI_TOOLCHAIN occasionally; the sysroot | |
| # cache key follows it. `cargo +<toolchain>` overrides rust-toolchain.toml. | |
| miri: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| env: | |
| MIRI_TOOLCHAIN: nightly-2026-02-27 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: ${{ env.MIRI_TOOLCHAIN }} | |
| components: miri | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 (sha-pinned) | |
| # The Miri std sysroot (~100 MB) is the only slow part of a cold run | |
| # (~1-3 min to build); rust-cache does not cover it. Cache it keyed on the | |
| # pinned toolchain so steady-state runs skip the build. | |
| - name: Cache Miri sysroot | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/miri | |
| key: miri-sysroot-${{ runner.os }}-${{ env.MIRI_TOOLCHAIN }} | |
| - name: Miri setup (build/restore sysroot) | |
| run: cargo +${{ env.MIRI_TOOLCHAIN }} miri setup | |
| - name: Miri (size_cache soundness) | |
| run: cargo +${{ env.MIRI_TOOLCHAIN }} miri test -p buffa size_cache | |
| # ── no_std and 32-bit compilation checks ───────────────────────────────── | |
| check-nostd: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| # Must name the same version as rust-toolchain.toml (which selects the | |
| # toolchain cargo uses) so the cross-targets installed here belong to | |
| # that toolchain. With @stable, the targets land on a toolchain the | |
| # file then bypasses, and the bare-metal check fails with E0463. | |
| - uses: dtolnay/rust-toolchain@1.95 | |
| with: | |
| targets: i686-unknown-linux-gnu, thumbv7em-none-eabihf | |
| - name: Install protoc | |
| run: | | |
| curl -fsSL "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-x86_64.zip" -o /tmp/protoc.zip | |
| sudo unzip -o /tmp/protoc.zip -d /usr/local | |
| protoc --version | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 (sha-pinned) | |
| - name: Check buffa no_std (host) | |
| run: cargo check -p buffa --no-default-features | |
| - name: Check buffa no_std (bare-metal ARM) | |
| run: cargo check -p buffa --no-default-features --target thumbv7em-none-eabihf | |
| - name: Check buffa-types no_std | |
| run: cargo check -p buffa-types --no-default-features | |
| - name: Check buffa-types no_std + chrono | |
| run: cargo check -p buffa-types --no-default-features --features chrono | |
| - name: Check buffa-descriptor no_std | |
| run: cargo check -p buffa-descriptor --no-default-features | |
| - name: Check workspace 32-bit | |
| run: cargo check --workspace --target i686-unknown-linux-gnu | |
| # ── Verify checked-in generated code is up to date ─────────────────────── | |
| check-generated-code: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - name: Install protoc | |
| run: | | |
| curl -fsSL "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-x86_64.zip" -o /tmp/protoc.zip | |
| sudo unzip -o /tmp/protoc.zip -d /usr/local | |
| protoc --version | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 (sha-pinned) | |
| - name: Regenerate bootstrap descriptor types | |
| # Proto sources are vendored in buffa-descriptor/protos/ (pinned), | |
| # so this is independent of the installed protoc's bundled includes. | |
| run: scripts/gen-bootstrap-types.sh | |
| - name: Generate descriptor set (WKTs) | |
| run: | | |
| # WKT protos are vendored in buffa-types/protos (NOT read from | |
| # /usr/local/include) so the checked-in code is pinned to a | |
| # specific proto source, not whatever protoc version ships. | |
| protoc --descriptor_set_out=/tmp/wkt.pb --include_imports \ | |
| --include_source_info \ | |
| -I buffa-types/protos \ | |
| google/protobuf/any.proto \ | |
| google/protobuf/duration.proto \ | |
| google/protobuf/empty.proto \ | |
| google/protobuf/field_mask.proto \ | |
| google/protobuf/struct.proto \ | |
| google/protobuf/timestamp.proto \ | |
| google/protobuf/wrappers.proto | |
| - name: Regenerate WKT types | |
| run: cargo run -p buffa-codegen --bin gen_wkt_types -- /tmp/wkt.pb buffa-types/src/generated | |
| - name: Check for differences | |
| run: | | |
| if ! git diff --exit-code buffa-descriptor/src/generated/ buffa-types/src/generated/; then | |
| echo "::error::Checked-in generated code is stale. Run 'task gen-wkt-types' and/or regenerate bootstrap types, then commit." | |
| exit 1 | |
| fi | |
| # ── Conformance test suite ─────────────────────────────────────────────── | |
| # Builds conformance binaries on the runner (cached via rust-cache) and | |
| # extracts the conformance_test_runner + proto files from the tools image. | |
| conformance: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 (sha-pinned) | |
| with: | |
| workspaces: conformance | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 (sha-pinned) | |
| - name: Build tools image (cached) | |
| uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 (sha-pinned) | |
| with: | |
| context: . | |
| file: conformance/Dockerfile.tools | |
| load: true | |
| tags: buffa/tools:local | |
| cache-from: type=gha,scope=tools-image | |
| cache-to: type=gha,scope=tools-image,mode=max | |
| - name: Extract tools from image | |
| run: | | |
| CID=$(docker create buffa/tools:local /dev/null) | |
| docker cp "$CID:/conformance_test_runner" /usr/local/bin/conformance_test_runner | |
| docker cp "$CID:/protoc" /usr/local/bin/protoc | |
| docker cp "$CID:/protos/." conformance/protos/ | |
| docker rm "$CID" | |
| chmod +x /usr/local/bin/conformance_test_runner /usr/local/bin/protoc | |
| # Both builds use the same target dir so build-script artifacts | |
| # (buffa-codegen, buffa-build, syn, etc.) are compiled only once. | |
| # The std binary is copied out before the no_std build overwrites it. | |
| - name: Determine host target | |
| id: host | |
| run: echo "triple=$(rustc -vV | grep '^host:' | cut -d' ' -f2)" >> "$GITHUB_OUTPUT" | |
| - name: Build conformance binary (std) | |
| run: >- | |
| cargo build --release --manifest-path conformance/Cargo.toml | |
| --target ${{ steps.host.outputs.triple }} | |
| - name: Save std binary | |
| run: cp conformance/target/${{ steps.host.outputs.triple }}/release/conformance /tmp/buffa-conformance-std | |
| - name: Build conformance binary (no_std) | |
| run: >- | |
| cargo build --release --manifest-path conformance/Cargo.toml | |
| --no-default-features --target ${{ steps.host.outputs.triple }} | |
| - name: Run conformance tests (std) | |
| run: >- | |
| conformance_test_runner | |
| --failure_list conformance/known_failures.txt | |
| --maximum_edition 2024 | |
| /tmp/buffa-conformance-std | |
| - name: Run conformance tests (no_std) | |
| run: >- | |
| conformance_test_runner | |
| --failure_list conformance/known_failures_nostd.txt | |
| --maximum_edition 2024 | |
| conformance/target/${{ steps.host.outputs.triple }}/release/conformance | |
| - name: Run conformance tests (via-view) | |
| env: | |
| BUFFA_VIA_VIEW: "1" | |
| run: >- | |
| conformance_test_runner | |
| --failure_list conformance/known_failures_view.txt | |
| --maximum_edition 2024 | |
| /tmp/buffa-conformance-std |