archive: restore trees with read-only directories; bump to 0.2.2
DecodeDir applied each archived mode as its entry landed, so a 0555
directory became read-only the moment it was created and the first file
written into it failed with EACCES. That is not an edge case: the Go
module cache is 0555 directories and 0444 files throughout, and it is the
main thing dir download is pointed at. Build #295 died on the first cache
HIT of the new gomod key, having passed on the miss.
Directories are now created with the owner-write bit forced on and their
recorded mode applied after extraction finishes, deepest-first. Files are
written writable and chmod'ed after the copy, and a read-only file left
by an earlier restore is replaced rather than treated as an error —
re-restoring over a populated module cache is normal in CI.
Both tests fail against the previous DecodeDir with the same 'permission
denied' the build reported.
merge .builds/{unit,e2e}.yml into test.yml; cache go + garage image
Single job runs unit tests → smoke build → e2e (against a real Garage
container via testcontainers-go). Unit failure short-circuits before
paying the ~150 MB Garage image pull.
Caches via dogfooded cacher:
* Go tarball — `cacher download --url` fallback, same pattern as
publish.yml.
* Garage docker image — `cacher download` of the tar; on miss does
docker pull + save + upload to seed.
Also silences testcontainers' default logger in the garage testutil
(pull progress, container IDs, port mappings); test output now only
shows what the tests print themselves. `-v` dropped from the e2e
`go test` since per-test progress is no longer drowned out and not
worth printing on green runs.
`TESTCONTAINERS_RYUK_DISABLED=true` — VM is torn down at job end,
reaper container is just startup noise.
Verified end-to-end on job #153 (all 8 tasks ✔, cache MISS seeded).
Add end-to-end test suite against real Garage via testcontainers
* internal/testutil/garage: spins up dxflrs/garage:v2.3.0 with
--single-node --default-bucket so the bucket + access key are
auto-created from env vars at startup, no CLI bootstrap dance.
Each Start() call yields a fresh container with random creds and
registers t.Cleanup teardown.
* e2e_test.go gated by build tag e2e exercises the compiled cacher
binary against the container — covers init/doctor parity (the
regression guard for the HeadBucket+signature bugs we hit on
the real bucket), single-file round-trip, exit codes (1/2/3),
URL fallback + cache fill, --hash-from parity with sha256sum,
directory tar+zstd round-trip, and delimited list output.
* just test-e2e recipe; requires Docker on the host.
Total runtime ~30s after first image pull (~1.5s/container).
Fix Garage compat: PingBucket via ListObjects, fixed config path, delimited list
Three issues surfaced when first running doctor against the real
s3.bigb.es Garage instance:
* HeadBucket returned 403 even with valid creds. Garage doesn't
implement HeadBucket the way AWS does. Switch the doctor smoke
test to a 1-key ListObjectsV2 — matches what aws s3 ls does, which
the existing shell helper used.
* Config landed in ~/Library/Application Support/cacher on macOS
via os.UserConfigDir. cacher is a CI tool that needs the same
path on a dev mac and on a Linux build runner, so hard-code
~/.config/cacher/config.toml unconditionally.
* cacher list flat-listed every object under the configured prefix.
Add Delimiter="/" semantics by default (matches aws s3 ls), with
--recursive for the previous behaviour and --root to ignore the
configured prefix and list at the bucket root.
Initial cacher v0.0.1-dev — S3-backed CI cache helper
Replaces tarantool-protobuf/.builds/lib/ci-lib.sh (and its
two shell helpers s3_cache_or_curl + s3_cache_docker_image)
with a single static Go binary.
Commands:
init / doctor persist config + smoke-test credentials
download / upload single-file cache with URL fallback + sha256
exists / list / delete cache management
key resolve key template (for shell scripting)
docker {exists,download,upload} streamed save/load via zstd
dir {download,upload} tar+zstd directory caching (new)
Key derivation via --hash-from <path> (repeatable; file or dir),
matching the existing sha256sum | cut -c1-16 shell convention.
Garage-compatible S3 client (path-style, checksums when_required).