Skip to content

Commit e9d6aad

Browse files
committed
ci(core): add dependency-purity allowlist gate for gitlawb-core
gitlawb-core is embedded by gl, git-remote-gitlawb, and the node daemon, so it must stay lean. Add a CI gate that fails if its normal (non-dev, non-build) transitive dependency tree gains any crate not on an explicit allowlist. The allowlist is exhaustive-by-construction: a new heavy dependency reds CI whether or not anyone thought to ban it, which a denylist cannot do. The checker resolves like the build/test jobs (no --locked, since the committed lockfile can lag the manifests) and snapshots/restores Cargo.lock so a local run leaves no working-tree side effects. - ci/gitlawb-core-allowed-deps.txt: the 83 current normal deps, plus the regeneration command and rationale in the header - scripts/check-gitlawb-core-deps.sh: recompute and diff; hard-fail on a non-allowlisted crate, note-only on a stale (removed) allowlist entry - pr-checks.yml: new hard-fail core-deps-purity job, matching the pinned action SHAs and style of the sibling jobs
1 parent b484a24 commit e9d6aad

3 files changed

Lines changed: 211 additions & 0 deletions

File tree

‎.github/workflows/pr-checks.yml‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,3 +247,32 @@ jobs:
247247

248248
- name: cargo test (shipped Windows crates)
249249
run: cargo test -p gl -p git-remote-gitlawb
250+
251+
# gitlawb-core is embedded by every consumer (gl, git-remote-gitlawb, the node
252+
# daemon), so it must stay lean. This gate fails if gitlawb-core's normal
253+
# (non-dev, non-build) dependency tree gains any crate not on the allowlist in
254+
# ci/gitlawb-core-allowed-deps.txt. Exhaustive-by-construction: a new heavy
255+
# dependency reds CI whether or not anyone thought to ban it, which a denylist
256+
# cannot do. Regen instructions live in the allowlist header.
257+
core-deps-purity:
258+
name: gitlawb-core dependency purity
259+
runs-on: ubuntu-latest
260+
timeout-minutes: 15
261+
steps:
262+
- name: Check out repository
263+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
264+
with:
265+
persist-credentials: false
266+
267+
- name: Set up Rust toolchain
268+
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b # stable
269+
with:
270+
toolchain: stable
271+
272+
- name: Cache cargo
273+
uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
274+
with:
275+
key: core-deps-purity
276+
277+
- name: Check gitlawb-core dependency allowlist
278+
run: bash scripts/check-gitlawb-core-deps.sh

‎ci/gitlawb-core-allowed-deps.txt‎

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Dependency allowlist for the `gitlawb-core` crate.
2+
#
3+
# gitlawb-core is the shared-primitives crate every consumer embeds (the `gl`
4+
# CLI, git-remote-gitlawb, the node daemon). It must stay lean so those
5+
# consumers do not inherit daemon-weight dependencies. This file is the source
6+
# of truth for the crates gitlawb-core's NORMAL (non-dev, non-build) transitive
7+
# dependency closure is allowed to contain. CI (`scripts/check-gitlawb-core-deps.sh`,
8+
# wired into the `core-deps-purity` job in .github/workflows/pr-checks.yml)
9+
# fails if gitlawb-core's tree contains any crate not listed here.
10+
#
11+
# The allowlist is exhaustive-by-construction: a NEW dependency reds CI whether
12+
# or not anyone thought to ban it, which a denylist cannot do.
13+
#
14+
# Measured in-workspace, so feature unification across the workspace can, in
15+
# rare cases, surface a crate here that gitlawb-core would not pull standalone.
16+
# An unexpected new entry is a prompt to check what pulled it in, not noise to
17+
# rubber-stamp.
18+
#
19+
# Regenerate (from repo root, after an INTENTIONAL dependency change):
20+
# cargo tree -p gitlawb-core --edges normal --prefix none \
21+
# | sed -E 's/ v[0-9].*$//' \
22+
# | grep -v '^gitlawb-core$' \
23+
# | sort -u
24+
# then paste the result below this header block. (The checker snapshots and
25+
# restores Cargo.lock; a manual regen may refresh it — `git checkout Cargo.lock`
26+
# afterward if you did not intend that.)
27+
#
28+
# Lines starting with `#` and blank lines are ignored by the checker.
29+
aead
30+
anyhow
31+
base-x
32+
base256emoji
33+
base64
34+
base64ct
35+
block-buffer
36+
cfg-if
37+
chacha20
38+
chacha20poly1305
39+
chrono
40+
cid
41+
cipher
42+
const-oid
43+
const-str
44+
core2
45+
cpufeatures
46+
crypto-common
47+
crypto_box
48+
crypto_secretbox
49+
curve25519-dalek
50+
data-encoding
51+
data-encoding-macro
52+
data-encoding-macro-internal
53+
der
54+
digest
55+
ed25519
56+
ed25519-dalek
57+
equivalent
58+
generic-array
59+
getrandom
60+
hashbrown
61+
hex
62+
iana-time-zone
63+
indexmap
64+
inout
65+
itoa
66+
libc
67+
match-lookup
68+
memchr
69+
multibase
70+
multihash
71+
multihash-codetable
72+
multihash-derive
73+
multihash-derive-impl
74+
num-traits
75+
opaque-debug
76+
pem-rfc7468
77+
pkcs8
78+
poly1305
79+
ppv-lite86
80+
proc-macro-crate
81+
proc-macro2
82+
quote
83+
rand
84+
rand_chacha
85+
rand_core
86+
salsa20
87+
serde
88+
serde_core
89+
serde_derive
90+
serde_json
91+
sha2
92+
signature
93+
spki
94+
subtle
95+
syn
96+
synstructure
97+
thiserror
98+
thiserror-impl
99+
toml_datetime
100+
toml_edit
101+
toml_parser
102+
typenum
103+
unicode-ident
104+
universal-hash
105+
unsigned-varint
106+
uuid
107+
winnow
108+
zerocopy
109+
zeroize
110+
zeroize_derive
111+
zmij

‎scripts/check-gitlawb-core-deps.sh‎

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Dependency-purity gate for the `gitlawb-core` crate.
4+
#
5+
# gitlawb-core is embedded by every consumer (the gl CLI, git-remote-gitlawb,
6+
# the node daemon), so it must stay lean. This script recomputes gitlawb-core's
7+
# NORMAL (non-dev, non-build) transitive dependency set and fails if it contains
8+
# any crate not present in ci/gitlawb-core-allowed-deps.txt.
9+
#
10+
# Hard-fail direction: a crate present now but NOT allowlisted. That is the case
11+
# the gate exists to catch (core silently gaining a heavy dependency).
12+
# Informational only: an allowlisted crate no longer present (stale entry) — a
13+
# legitimate dependency removal should not red CI, so it is reported, not failed.
14+
#
15+
# Runnable from anywhere in the repo.
16+
set -euo pipefail
17+
18+
ROOT="$(git rev-parse --show-toplevel)"
19+
ALLOW="$ROOT/ci/gitlawb-core-allowed-deps.txt"
20+
21+
if [ ! -f "$ALLOW" ]; then
22+
echo "ERROR: allowlist not found at $ALLOW" >&2
23+
exit 1
24+
fi
25+
26+
# `cargo tree` resolves like the build/test jobs (no --locked): the committed
27+
# Cargo.lock can lag the manifests, and --locked would red this gate for
28+
# lock-staleness reasons unrelated to gitlawb-core's dependencies. Resolving can
29+
# refresh Cargo.lock as a side effect, so snapshot and restore it — this check
30+
# must never leave the working tree dirty when run locally.
31+
lock_backup="$(mktemp)"
32+
cp "$ROOT/Cargo.lock" "$lock_backup"
33+
restore_lock() { cp "$lock_backup" "$ROOT/Cargo.lock"; rm -f "$lock_backup"; }
34+
trap restore_lock EXIT
35+
36+
# Current normal-dependency closure of gitlawb-core, one crate name per line.
37+
# Must match the regen command documented in the allowlist header exactly.
38+
current="$(
39+
cargo tree -p gitlawb-core --edges normal --prefix none --manifest-path "$ROOT/Cargo.toml" \
40+
| sed -E 's/ v[0-9].*$//' \
41+
| grep -v '^gitlawb-core$' \
42+
| sort -u
43+
)"
44+
45+
# Allowlist with comments and blank lines stripped.
46+
allowed="$(grep -vE '^[[:space:]]*(#|$)' "$ALLOW" | sort -u)"
47+
48+
# comm needs sorted input; both sides are sorted above.
49+
offenders="$(comm -23 <(printf '%s\n' "$current") <(printf '%s\n' "$allowed"))"
50+
stale="$(comm -13 <(printf '%s\n' "$current") <(printf '%s\n' "$allowed"))"
51+
52+
if [ -n "$stale" ]; then
53+
echo "NOTE: allowlisted crates no longer in gitlawb-core's dependency tree"
54+
echo " (safe to prune from ci/gitlawb-core-allowed-deps.txt):"
55+
printf ' %s\n' $stale
56+
echo
57+
fi
58+
59+
if [ -n "$offenders" ]; then
60+
{
61+
echo "ERROR: gitlawb-core gained dependencies not on the allowlist:"
62+
printf ' %s\n' $offenders
63+
echo
64+
echo "gitlawb-core must stay embeddable and lean. If a new dependency is"
65+
echo "intentional, add it to ci/gitlawb-core-allowed-deps.txt (regen command"
66+
echo "is in that file's header). Otherwise, drop the dependency."
67+
} >&2
68+
exit 1
69+
fi
70+
71+
echo "gitlawb-core dependency purity: OK ($(printf '%s\n' "$current" | wc -l | tr -d ' ') normal deps, all allowlisted)."

0 commit comments

Comments
 (0)