OverviewFilesCommitsIssuesDocsReleasesPeers

hardops commits / 27fbc2e

ci: make the zip reproducible so both backends agree
Forge build artifacts do not replicate — each backend builds its own copy from the same commit. A plain `zip -r` stores checkout mtimes and readdir order, so those copies came out the same SIZE but a different HASH. Behind the load balancer that means /releases/<repo>/<version>/<file> serves different bytes depending on which backend answers, and a checksum a user records is only valid for whichever one they happened to hit. Pinning mtimes to the commit timestamp, sorting entries and passing -X makes independent builds of a commit byte-identical, which restores the URL as a stable identifier. Verified locally first: two simulated checkouts produced two hashes with the old recipe and one with this. This does not make divergence impossible in general — a recipe embedding timestamps or using non-deterministic tooling will still differ per backend, so a puller still must not treat a hash mismatch as corruption. It does mean a repo can opt into being verifiable. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
27fbc2e6c2ea3b0f8878fffa3a8c4b088b5df6ca
by plankatron <fleeky@gmail.com> · 2026-08-07T23:57:05.000Z

Changed files (1) +18 -1

.pear-git/ci.yaml +18 -1
……@@ -23,8 +23,25 @@ steps:
2323 # copy the tree minus VCS, bytecode and the build dir itself
2424 tar cf - --exclude=./.git --exclude=__pycache__ --exclude=./build . \
2525 | (cd build/hardops && tar xf -)
26 (cd build && zip -qr ../hardops.zip hardops)
26
27 # Reproducible zip. Artifacts do NOT replicate between forge backends —
28 # each daemon builds its own from the same commit — so a naive `zip -r`
29 # yields the same SIZE but a different HASH on each backend, because it
30 # stores checkout mtimes and readdir order. Behind the load balancer that
31 # makes /releases/<repo>/<version>/<file> return different bytes depending
32 # on which backend answers, and any checksum a user records is
33 # backend-specific.
34 #
35 # Pinning mtimes to the commit timestamp, sorting entries, and -X
36 # (drop extra file attributes) makes independent builds of one commit
37 # byte-identical, so the URL is a stable identifier again.
38 TS=$(git log -1 --format=%ct 2>/dev/null || echo 0)
39 cd build
40 find hardops -exec touch -h -d "@$TS" {} +
41 find hardops -print | LC_ALL=C sort | zip -X -q ../hardops.zip -@
42 cd ..
2743 ls -l hardops.zip
44 sha256sum hardops.zip
2845 timeout: 300
2946
3047artifacts: