Skip to content

Commit 3e0c25f

Browse files
authored
chore(ci): enforce external type allow-list in public API (#4204)
## Description Foreign types in our public API block semver-breaking updates of those crates during 1.0. #3177 tracks reducing that surface to a curated allow list. This adds a `check_external_types` CI job that runs [`cargo-check-external-types`] against all workspace crates against a shared `external-types.toml` at the workspace root. Closes #3177. [`cargo-check-external-types`]: https://github.com/awslabs/cargo-check-external-types ## Change checklist <!-- Remove any that are not relevant. --> - [x] Self-review. - [ ] Documentation updates following the [style guide](https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html#appendix-a-full-conventions-text), if relevant. - [ ] Tests if relevant. - [ ] All breaking changes documented.
1 parent c953d9b commit 3e0c25f

2 files changed

Lines changed: 95 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,56 @@ jobs:
271271
baseline-rev: ${{ env.HEAD_COMMIT_SHA }}
272272
use-cache: false
273273

274+
check_external_types:
275+
timeout-minutes: 30
276+
name: Check external types in public API
277+
if: "github.event_name != 'pull_request' || ! contains(github.event.pull_request.labels.*.name, 'flaky-test')"
278+
needs: pick-runner
279+
runs-on: ${{ fromJSON(needs.pick-runner.outputs.overflow_9) }}
280+
# runs-on: [self-hosted, linux, X64]
281+
env:
282+
RUSTC_WRAPPER: "sccache"
283+
SCCACHE_GHA_ENABLED: "on"
284+
# The tool drives an internal rustdoc invocation that only emits JSON
285+
# for the analyzer, so the workflow-wide `-Dwarnings` would just turn
286+
# unrelated rustdoc lints (e.g. `private-intra-doc-links`) into hard
287+
# failures here. Clear it for this job.
288+
RUSTDOCFLAGS: ""
289+
# Pin to the nightly that the pinned `cargo-check-external-types`
290+
# release was last tested against. Update both together.
291+
CARGO_CHECK_EXTERNAL_TYPES_VERSION: "0.4.0"
292+
CARGO_CHECK_EXTERNAL_TYPES_NIGHTLY: "nightly-2025-10-18"
293+
steps:
294+
- uses: actions/checkout@v6
295+
- uses: dtolnay/rust-toolchain@master
296+
with:
297+
toolchain: ${{ env.CARGO_CHECK_EXTERNAL_TYPES_NIGHTLY }}
298+
- name: Install sccache
299+
uses: mozilla-actions/sccache-action@v0.0.9
300+
301+
- name: Install cargo-binstall
302+
uses: cargo-bins/cargo-binstall@v1.18.1
303+
304+
- name: Install cargo-check-external-types
305+
# Match the version of wasm-bindgen used in Cargo.lock
306+
run: cargo binstall cargo-check-external-types@${{ env.CARGO_CHECK_EXTERNAL_TYPES_VERSION }} --locked --no-confirm
307+
308+
- name: Check external types
309+
run: |
310+
set -e
311+
fail=0
312+
for crate in iroh-base iroh-dns iroh-relay iroh iroh-dns-server; do
313+
echo "::group::$crate"
314+
if ! cargo check-external-types \
315+
--manifest-path "$crate/Cargo.toml" \
316+
--config external-types.toml \
317+
--all-features; then
318+
fail=1
319+
fi
320+
echo "::endgroup::"
321+
done
322+
exit $fail
323+
274324
check_fmt:
275325
timeout-minutes: 30
276326
name: Checking fmt

external-types.toml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# List of types from foreign crates allowed to appear in our public APIs.
2+
#
3+
# This can be used with `cargo check-external-types` to ensure that no other
4+
# items than the ones allow-listed here appear in our public APIs. A semver-breaking
5+
# update to any crate listed here automatically becomes a semver-breaking update
6+
# to one of our workspace crates.
7+
#
8+
# There's a `check_external_types` CI job that fails when any foreign item not listed
9+
# here appears in the public API of a workspace crate.
10+
11+
allowed_external_types = [
12+
# workspace crates
13+
"iroh_base::*",
14+
"iroh_dns::*",
15+
"iroh_relay::*",
16+
17+
# 1.0 crates that we deem fine to be part of the public API
18+
"bytes::*",
19+
"http::*",
20+
"http_body::*",
21+
"hyper::*",
22+
"rustls_pki_types::*",
23+
"serde::*",
24+
"serde_core::*",
25+
"tokio::*",
26+
"url::*",
27+
28+
# crates owned by us that will move to 1.0 as well
29+
"iroh_metrics::*",
30+
"n0_error::*",
31+
"n0_watcher::*",
32+
"noq::*",
33+
"noq_proto::*",
34+
"noq_udp::*",
35+
"portmapper::metrics::Metrics",
36+
37+
# non-1.0 crates that we decided to accept in the public API
38+
"rustls::*",
39+
"tokio_rustls::*",
40+
"futures_core::stream::Stream",
41+
"futures_sink::Sink",
42+
# these are only type aliases
43+
"futures_lite::future::Boxed",
44+
"futures_lite::stream::Boxed",
45+
]

0 commit comments

Comments
 (0)