From 7a0eda97b47e745064ce351f17adb81fc592f09f Mon Sep 17 00:00:00 2001 From: Frando Date: Thu, 7 May 2026 11:48:26 +0200 Subject: [PATCH 1/4] chore: check external types in CI --- .github/workflows/ci.yml | 33 +++++++++++++++++++++++++++++++-- Makefile.toml | 19 +++++++++++++++++++ external-types.toml | 30 ++++++++++++++++++++++++++++++ noq/Cargo.toml | 3 ++- 4 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 external-types.toml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cfb8d1a0e..2f5d4f57c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,7 +40,7 @@ jobs: # Go is required for FIPS builds - uses: actions/setup-go@v5 with: - go-version: 'stable' + go-version: "stable" # Prevent feature unification from selecting *ring* as the crypto provider - run: RUST_BACKTRACE=1 cargo test --locked --manifest-path noq-proto/Cargo.toml --no-default-features --features rustls,aws-lc-rs - run: RUST_BACKTRACE=1 cargo test --locked --manifest-path noq/Cargo.toml --no-default-features --features rustls,aws-lc-rs,runtime-tokio,__rustls-post-quantum-test @@ -345,6 +345,35 @@ jobs: run: | cargo +$MSRV check --workspace --exclude fuzz --all-targets + external_types: + runs-on: ubuntu-latest + env: + RUSTC_WRAPPER: "sccache" + SCCACHE_GHA_ENABLED: "on" + # The tool drives an internal rustdoc invocation that only emits JSON + # for the analyzer, so the workflow-wide `-Dwarnings` would just turn + # unrelated rustdoc lints (e.g. `private-intra-doc-links`) into hard + # failures here. Clear it for this job. + RUSTDOCFLAGS: "" + # Pin to the nightly that the pinned `cargo-check-external-types` + # release was last tested against. Update both together. + CARGO_CHECK_EXTERNAL_TYPES_VERSION: "0.4.0" + CARGO_CHECK_EXTERNAL_TYPES_NIGHTLY: "nightly-2025-10-18" + steps: + - uses: actions/checkout@v6 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ env.CARGO_CHECK_EXTERNAL_TYPES_NIGHTLY }} + - name: Install sccache + uses: mozilla-actions/sccache-action@v0.0.9 + - name: Install cargo-binstall + uses: cargo-bins/cargo-binstall@v1.18.1 + - uses: taiki-e/install-action@cargo-make + - name: Install cargo-check-external-types + run: cargo binstall cargo-check-external-types@${{ env.CARGO_CHECK_EXTERNAL_TYPES_VERSION }} --locked --no-confirm + - name: Check external types + run: cargo make check-external-types + cargo_deny: timeout-minutes: 30 name: cargo deny @@ -384,7 +413,7 @@ jobs: # Go is required for FIPS builds - uses: actions/setup-go@v5 with: - go-version: 'stable' + go-version: "stable" - name: Setup Environment (PR) if: ${{ github.event_name == 'pull_request' }} diff --git a/Makefile.toml b/Makefile.toml index 2b5d89aac..4be91ac17 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -96,3 +96,22 @@ env = { "PROPTEST_CASES" = "10000" } description = "Run proptests in regression-only mode (runs for <5 seconds)" command = "cargo" args = ["nextest", "run", "--package=noq-proto", "-P", "proptests", "--no-fail-fast", "${@}"] + +[tasks.check-external-types] +description = "Run cargo check-external-types on all workspace crates" +script = ''' +set -e +fail=0 +for crate in noq-udp noq-proto noq; do + echo "::group::$crate" + if ! cargo +nightly check-external-types \ + --manifest-path "$crate/Cargo.toml" \ + --config external-types.toml \ + --features __all_without_fips; \ + then + fail=1 + fi + echo "::endgroup::" +done +exit $fail +''' diff --git a/external-types.toml b/external-types.toml new file mode 100644 index 000000000..b946ce4ac --- /dev/null +++ b/external-types.toml @@ -0,0 +1,30 @@ +# List of types from foreign crates allowed to appear in our public APIs. +# +# This can be used with `cargo check-external-types` to ensure that no other +# items than the ones allow-listed here appear in our public APIs. A semver-breaking +# update to any crate listed here automatically becomes a semver-breaking update +# to one of our workspace crates. +# +# `cargo make check-external-types` runs this over all workspace crates, and a CI job +# `check_external_types` makes sure we don't sneak in anything unapproved. + +allowed_external_types = [ + # workspace crates + "noq_proto", + "noq_proto::*", + "noq_udp", + "noq_udp::*", + + # 1.0 crates that we deem fine to be part of the public API + "bytes::*", + "rustls_pki_types::*", + "tokio::*", + + # non-1.0 crates that we decided to accept in the public API + "rustls", + "rustls::*", + "futures_core::stream::Stream", + "identity_hash::IdentityHashable", + # gated behind the "arbitrary" feature, + "arbitrary::*", +] diff --git a/noq/Cargo.toml b/noq/Cargo.toml index e7de61bf6..a3f0a50f0 100644 --- a/noq/Cargo.toml +++ b/noq/Cargo.toml @@ -57,6 +57,7 @@ rustls-aws-lc-rs = ["rustls", "aws-lc-rs"] # Don't rely on these whatsoever. They may disappear at any time. __rustls-post-quantum-test = ["rustls/prefer-post-quantum", "rustls", "aws-lc-rs", "proto/__rustls-post-quantum-test"] +__all_without_fips = ["lock_tracking", "aws-lc-rs", "rustls", "ring", "runtime-tokio", "runtime-smol", "tracing-log", "rustls-log"] [dependencies] async-io = { workspace = true, optional = true } @@ -144,4 +145,4 @@ required-features = ["rustls", "ring"] [package.metadata.docs.rs] # all non-default features except fips (cannot build on docs.rs environment) -features = ["lock_tracking", "aws-lc-rs", "rustls", "ring", "runtime-tokio", "runtime-smol", "tracing-log", "rustls-log"] +features = ["__all_without_fips"] From 3f3dfce4ab8d0ef8451dc5f4c3b1dbd7870b4abd Mon Sep 17 00:00:00 2001 From: Frando Date: Thu, 7 May 2026 12:00:47 +0200 Subject: [PATCH 2/4] improve --- Makefile.toml | 1 - external-types.toml | 30 ------------------------------ noq-proto/Cargo.toml | 14 +++++++++++++- noq-udp/Cargo.toml | 5 +++++ noq/Cargo.toml | 12 ++++++++++++ 5 files changed, 30 insertions(+), 32 deletions(-) delete mode 100644 external-types.toml diff --git a/Makefile.toml b/Makefile.toml index 4be91ac17..4b7903972 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -106,7 +106,6 @@ for crate in noq-udp noq-proto noq; do echo "::group::$crate" if ! cargo +nightly check-external-types \ --manifest-path "$crate/Cargo.toml" \ - --config external-types.toml \ --features __all_without_fips; \ then fail=1 diff --git a/external-types.toml b/external-types.toml deleted file mode 100644 index b946ce4ac..000000000 --- a/external-types.toml +++ /dev/null @@ -1,30 +0,0 @@ -# List of types from foreign crates allowed to appear in our public APIs. -# -# This can be used with `cargo check-external-types` to ensure that no other -# items than the ones allow-listed here appear in our public APIs. A semver-breaking -# update to any crate listed here automatically becomes a semver-breaking update -# to one of our workspace crates. -# -# `cargo make check-external-types` runs this over all workspace crates, and a CI job -# `check_external_types` makes sure we don't sneak in anything unapproved. - -allowed_external_types = [ - # workspace crates - "noq_proto", - "noq_proto::*", - "noq_udp", - "noq_udp::*", - - # 1.0 crates that we deem fine to be part of the public API - "bytes::*", - "rustls_pki_types::*", - "tokio::*", - - # non-1.0 crates that we decided to accept in the public API - "rustls", - "rustls::*", - "futures_core::stream::Stream", - "identity_hash::IdentityHashable", - # gated behind the "arbitrary" feature, - "arbitrary::*", -] diff --git a/noq-proto/Cargo.toml b/noq-proto/Cargo.toml index 8e253a013..d91f5f8f3 100644 --- a/noq-proto/Cargo.toml +++ b/noq-proto/Cargo.toml @@ -50,6 +50,7 @@ rustls-aws-lc-rs = ["rustls", "aws-lc-rs"] # Don't rely on these whatsoever. They may disappear at any time. __rustls-post-quantum-test = [] +__all_without_fips = ["aws-lc-rs", "rustls", "ring", "platform-verifier", "rustls-log", "qlog", "bench"] [dependencies] aes-gcm = { workspace = true, optional = true } @@ -107,4 +108,15 @@ workspace = true [package.metadata.docs.rs] # all non-default features except fips (cannot build on docs.rs environment) -features = ["aws-lc-rs", "rustls", "ring", "platform-verifier", "rustls-log", "qlog", "bench"] +features = ["__all_without_fips"] + +[package.metadata.cargo_check_external_types] +allowed_external_types = [ + "arbitrary::Arbitrary", # gated behind `arbitrary` feature + "criterion::Criterion", # gated behind `bench` feature + "identity_hash::IdentityHashable", + "bytes::*", + "rustls", + "rustls::*", + "rustls_pki_types::*", +] diff --git a/noq-udp/Cargo.toml b/noq-udp/Cargo.toml index 306322cd2..bd01a937b 100644 --- a/noq-udp/Cargo.toml +++ b/noq-udp/Cargo.toml @@ -20,6 +20,11 @@ log = ["dep:log"] # Support private Apple APIs to send multiple packets in a single syscall. fast-apple-datapath = [] +# Internal (PRIVATE!) features used to aid testing. +# Don't rely on these whatsoever. They may disappear at any time. + +__all_without_fips = ["tracing-log", "log", "fast-apple-datapath"] + [dependencies] libc = "0.2.175" log = { workspace = true, optional = true } diff --git a/noq/Cargo.toml b/noq/Cargo.toml index a3f0a50f0..def72d15e 100644 --- a/noq/Cargo.toml +++ b/noq/Cargo.toml @@ -146,3 +146,15 @@ required-features = ["rustls", "ring"] [package.metadata.docs.rs] # all non-default features except fips (cannot build on docs.rs environment) features = ["__all_without_fips"] + +[package.metadata.cargo_check_external_types] +allowed_external_types = [ + "noq_proto::*", + "noq_udp", + "noq_udp::*", + "bytes::bytes::Bytes", + "futures_core::stream::Stream", + "rustls", + "tokio::io::async_read::AsyncRead", + "tokio::io::async_write::AsyncWrite", +] From 428d2610874ba82d607c26d94271eb9549029a98 Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 11 May 2026 11:31:37 +0200 Subject: [PATCH 3/4] fixup --- .github/workflows/ci.yml | 9 ++------- Makefile.toml | 18 +++++++++++++++--- noq-proto/Cargo.toml | 2 +- noq-udp/Cargo.toml | 2 +- noq/Cargo.toml | 2 +- 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2f5d4f57c..4468053c3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -350,20 +350,15 @@ jobs: env: RUSTC_WRAPPER: "sccache" SCCACHE_GHA_ENABLED: "on" - # The tool drives an internal rustdoc invocation that only emits JSON - # for the analyzer, so the workflow-wide `-Dwarnings` would just turn - # unrelated rustdoc lints (e.g. `private-intra-doc-links`) into hard - # failures here. Clear it for this job. - RUSTDOCFLAGS: "" # Pin to the nightly that the pinned `cargo-check-external-types` # release was last tested against. Update both together. CARGO_CHECK_EXTERNAL_TYPES_VERSION: "0.4.0" - CARGO_CHECK_EXTERNAL_TYPES_NIGHTLY: "nightly-2025-10-18" + TOOLCHAIN: "nightly-2025-10-18" steps: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@master with: - toolchain: ${{ env.CARGO_CHECK_EXTERNAL_TYPES_NIGHTLY }} + toolchain: ${{ env.TOOLCHAIN }} - name: Install sccache uses: mozilla-actions/sccache-action@v0.0.9 - name: Install cargo-binstall diff --git a/Makefile.toml b/Makefile.toml index 4b7903972..53ebf0fd1 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -101,16 +101,28 @@ args = ["nextest", "run", "--package=noq-proto", "-P", "proptests", "--no-fail-f description = "Run cargo check-external-types on all workspace crates" script = ''' set -e + +# check-external-types needs a specific nightly version +# See https://github.com/awslabs/cargo-check-external-types#how-to-use +TOOLCHAIN="${TOOLCHAIN:-nightly-2025-10-18}" + +# Disable -Dwarnings, we don't want to fail on unrelated errors here +RUSTDOCFLAGS="" + +# Install the required toolchain +rustup -q toolchain install $TOOLCHAIN -c rustc,cargo,rust-std + +# Run for each crate fail=0 for crate in noq-udp noq-proto noq; do - echo "::group::$crate" - if ! cargo +nightly check-external-types \ + echo "=== $crate ===" + if ! cargo +$TOOLCHAIN check-external-types \ --manifest-path "$crate/Cargo.toml" \ --features __all_without_fips; \ then fail=1 fi - echo "::endgroup::" done + exit $fail ''' diff --git a/noq-proto/Cargo.toml b/noq-proto/Cargo.toml index d91f5f8f3..a6e674466 100644 --- a/noq-proto/Cargo.toml +++ b/noq-proto/Cargo.toml @@ -50,7 +50,7 @@ rustls-aws-lc-rs = ["rustls", "aws-lc-rs"] # Don't rely on these whatsoever. They may disappear at any time. __rustls-post-quantum-test = [] -__all_without_fips = ["aws-lc-rs", "rustls", "ring", "platform-verifier", "rustls-log", "qlog", "bench"] +__all_without_fips = ["arbitrary", "aws-lc-rs", "rustls", "ring", "platform-verifier", "rustls-log", "qlog", "bench", "bloom", "tracing-log"] [dependencies] aes-gcm = { workspace = true, optional = true } diff --git a/noq-udp/Cargo.toml b/noq-udp/Cargo.toml index bd01a937b..6d6165793 100644 --- a/noq-udp/Cargo.toml +++ b/noq-udp/Cargo.toml @@ -23,7 +23,7 @@ fast-apple-datapath = [] # Internal (PRIVATE!) features used to aid testing. # Don't rely on these whatsoever. They may disappear at any time. -__all_without_fips = ["tracing-log", "log", "fast-apple-datapath"] +__all_without_fips = ["tracing-log", "tracing", "log", "fast-apple-datapath"] [dependencies] libc = "0.2.175" diff --git a/noq/Cargo.toml b/noq/Cargo.toml index def72d15e..56bfa6d17 100644 --- a/noq/Cargo.toml +++ b/noq/Cargo.toml @@ -57,7 +57,7 @@ rustls-aws-lc-rs = ["rustls", "aws-lc-rs"] # Don't rely on these whatsoever. They may disappear at any time. __rustls-post-quantum-test = ["rustls/prefer-post-quantum", "rustls", "aws-lc-rs", "proto/__rustls-post-quantum-test"] -__all_without_fips = ["lock_tracking", "aws-lc-rs", "rustls", "ring", "runtime-tokio", "runtime-smol", "tracing-log", "rustls-log"] +__all_without_fips = ["lock_tracking", "aws-lc-rs", "rustls", "ring", "runtime-tokio", "runtime-smol", "tracing-log", "rustls-log", "bloom", "platform-verifier", "qlog", "fast-apple-datapath"] [dependencies] async-io = { workspace = true, optional = true } From ec9ab8bfdab7cf293e25449cc1944190584adcd6 Mon Sep 17 00:00:00 2001 From: Frando Date: Mon, 11 May 2026 14:33:13 +0200 Subject: [PATCH 4/4] simplify cargo make setup --- Makefile.toml | 38 ++++++++++---------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/Makefile.toml b/Makefile.toml index 53ebf0fd1..0fafae6f5 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -7,6 +7,11 @@ default_to_workspace = false [env] RUSTFLAGS = "-Dwarnings" RUSTDOCFLAGS = "-Dwarnings" +CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true +# Workspace members to exclude when setting `workspace = true` for a task. +# Must live at global env (not task-level) so it's read before workspace iteration +# is generated. Only the `check-external-types` task uses this. +CARGO_MAKE_WORKSPACE_SKIP_MEMBERS = ["bench", "fuzz", "perf", "docs/book"] [tasks.default] alias = "dev-flow" @@ -98,31 +103,8 @@ command = "cargo" args = ["nextest", "run", "--package=noq-proto", "-P", "proptests", "--no-fail-fast", "${@}"] [tasks.check-external-types] -description = "Run cargo check-external-types on all workspace crates" -script = ''' -set -e - -# check-external-types needs a specific nightly version -# See https://github.com/awslabs/cargo-check-external-types#how-to-use -TOOLCHAIN="${TOOLCHAIN:-nightly-2025-10-18}" - -# Disable -Dwarnings, we don't want to fail on unrelated errors here -RUSTDOCFLAGS="" - -# Install the required toolchain -rustup -q toolchain install $TOOLCHAIN -c rustc,cargo,rust-std - -# Run for each crate -fail=0 -for crate in noq-udp noq-proto noq; do - echo "=== $crate ===" - if ! cargo +$TOOLCHAIN check-external-types \ - --manifest-path "$crate/Cargo.toml" \ - --features __all_without_fips; \ - then - fail=1 - fi -done - -exit $fail -''' +description = "Run cargo check-external-types on workspace crates" +workspace = true +toolchain = "${TOOLCHAIN:nightly-2025-10-18}" +command = "cargo" +args = ["check-external-types", "--features", "__all_without_fips"]