1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# HOOK PARITY: the cargo fmt/clippy/test/doc jobs AND the `leaf-deps` job are
# mirrored by .githooks/pre-push. When editing those, update the push hook to
# match. The
# build/test/clippy jobs run with `--all-features` so the default-OFF `unstable-merkle`
# feature (src/merkle.rs / MerkleNode) is actually compiled and tested; the
# `test` job additionally runs a plain `cargo test` to keep the default-feature
# surface green and to prove `unstable-merkle` stays off by default. The `doc` job runs
# rustdoc with `-D warnings` (`--all-features`) so a broken intra-doc link fails
# CI — API-surface hygiene (issue #9); it is mirrored in the hook (rustdoc is
# cheap). The `leaf-deps` job runs scripts/check-leaf-deps.sh, which asserts the
# published core crate's dependency closure is registry-only (no path/git deps),
# keeping it a true leaf (issue #13); it reads only `cargo metadata` (no build),
# so it is fast and offline and is mirrored in the hook (true parity).
#
# CI-ONLY jobs (documented exceptions, NOT in the hook):
# - `msrv` pins `dtolnay/rust-toolchain` to 1.85 and runs build+test so a
# transitive dep can't silently raise the real MSRV floor above the declared
# `rust-version = "1.85"` (issue #9, gate item #10). Installing a second
# toolchain on every push is too heavy for a fast hook, so it is CI-only —
# the same rationale as the `python` job. The declared floor still lives in
# Cargo.toml, which the hook respects implicitly.
# - `python` (maturin + pytest for the PyO3 face) — building the extension
# module is too heavy for a fast pre-push hook (the pattern kyln uses to keep
# its p4d suite out of the hook).
# The pre-push hook records both exceptions in its header.
#
# ACTION PINNING: every third-party action is pinned to a full commit SHA with a
# human-readable version tag in a trailing comment. `.github/dependabot.yml`
# opens reviewable PRs to move these pins forward. When bumping a pin, update the
# trailing `# vX.Y.Z` comment to match — the SHA is authoritative, the comment is
# for humans. The release workflow (.github/workflows/release.yml) pins the same
# actions to the same SHAs; keep them in lockstep.
#
# LEAST PRIVILEGE: the default GITHUB_TOKEN is dropped to nothing at the workflow
# level (`permissions: {}`) and each job re-grants only `contents: read`. No CI
# job writes to the repo, publishes packages, or needs an OIDC token.
name: CI
on:
push:
branches:
pull_request:
branches:
permissions:
env:
CARGO_TERM_COLOR: always
RUSTFLAGS: "-D warnings"
jobs:
build:
name: build
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # stable
with:
toolchain: stable
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
- name: cargo build
run: cargo build --all-targets --all-features
test:
name: test
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # stable
with:
toolchain: stable
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
- name: cargo test (default features — proves unstable-merkle stays off)
run: cargo test
- name: cargo test --all-features (exercises the unstable-merkle feature)
run: cargo test --all-features
msrv:
name: msrv (1.85)
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
# Pin the declared MSRV floor. If a transitive dependency starts requiring
# a newer Rust, THIS job fails — surfacing an MSRV bump as an intentional,
# SemVer-relevant change instead of a silent drift (issue #9, gate #10).
# These commands resolve to `default-members = ["."]` (the published core
# crate only); the PyO3 `content-addressable-py` member is NOT built here.
# Its PyO3/pythonize stack (pyo3 0.29) needs ~1.83, below this 1.85 floor,
# and it is a maturin-built wheel — not the crates.io LIBRARY whose contract
# this 1.85 floor is. Keep this job scoped to the core crate.
- uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # 1.85
with:
toolchain: "1.85"
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
- name: cargo build (MSRV 1.85, core crate)
run: cargo build --all-targets --all-features
- name: cargo test (MSRV 1.85, core crate)
run: cargo test --all-features
clippy:
name: clippy
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # stable
with:
toolchain: stable
components: clippy
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
- name: cargo clippy
run: cargo clippy --all-targets --all-features -- -D warnings
doc:
name: doc (intra-doc links)
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # stable
with:
toolchain: stable
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
# `-D warnings` turns broken intra-doc links into a hard CI failure so doc
# rot can't return (issue #9 — public API surface hygiene).
- name: cargo doc (deny warnings)
run: cargo doc --no-deps --all-features
env:
RUSTDOCFLAGS: "-D warnings"
fmt:
name: fmt
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # stable
with:
toolchain: stable
components: rustfmt
- name: cargo fmt --check
run: cargo fmt -- --check
leaf-deps:
name: leaf-deps (published core is a true leaf)
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # stable
with:
toolchain: stable
# No build cache and no compilation: the guard only reads `cargo
# metadata`, asserting the `content-addressable` core's resolved
# dependency closure is registry-only (no path/git/workspace edges) so it
# stays a publishable leaf (issue #13). The legitimate
# `content-addressable-py -> content-addressable` path edge is a REVERSE
# dep of the core and is never inside the core's forward closure, so the
# guard tolerates it by construction.
- name: check published core is a true leaf
run: ./scripts/check-leaf-deps.sh
python:
name: python (PyO3 face)
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # stable
with:
toolchain: stable
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
- name: build the extension and run pytest
run: |
python -m venv .venv
. .venv/bin/activate
pip install --upgrade pip maturin pytest blake3
maturin develop -m content-addressable-py/Cargo.toml
pytest -q