fix(build): strip the s3 scheme so per-minor objects reach their pass

`s3_dir_ls()` returns keys with the `s3://` scheme attached, but the contrib
prefix was removed as a fixed substring. That took the prefix out of the middle
of the key and left `s3://4.4/curl_1.0.tar.gz`, so the leading scheme defeated
the `^<minor>/` test in `select_cache_for_pass()`.

Every one of the 21212 per-minor objects on amd64/resolute was therefore read as
a flat-slot object: the primary pass reported "119053 of 119053 objects apply to
this pass" and each sensitive pass got an empty cache and recompiled all 10248
sensitive packages it already had.

This change will:

- anchor the contrib prefix and swallow an optional `s3://` with it
- abort when the strip leaves fewer per-minor paths than the listing held, since
  the failure is otherwise silent and only shows up as a full rebuild
- mark the cache format with a `slot_relative` attribute and read that in
  `build-all.R`, rather than sniffing for a `/`, which misreads a slot-relative
  cache holding no per-minor or Archive object as a legacy one
This commit is contained in:
Patrick Schratz 2026-09-01 22:47:24 +00:00
commit f0b76ddf94
No known key found for this signature in database
GPG key ID: 62050D5BC68AB6DC

View file

@ -201,10 +201,15 @@ s3_cache_paths <- readRDS("/mnt/cache/packages/s3_cache.rds")
# nothing; hand it nothing and it rebuilds what it already has. amd64/resolute
# recompiled 8683 packages that way.
select_cache_for_pass <- function(paths, sensitive_only, r_minor) {
# A cache written before this change holds bare basenames. Filtering those by
# path would select nothing and trigger a full rebuild, so use them as they
# are; #190's staleness check replaces it on the next pipeline anyway.
if (!any(grepl("/", paths, fixed = TRUE))) {
# A cache written before #191 holds bare basenames. Filtering those by path
# would select nothing and trigger a full rebuild, so use them as they are;
# #190's staleness check replaces it on the next pipeline anyway.
#
# The format is read from the marker `packages-to-build.R` sets, not guessed
# from the content: a slot-relative cache with no per-minor or Archive object
# holds bare names too, and treating that as legacy would hand a per-minor
# pass the flat slot's binaries and build nothing.
if (!isTRUE(attr(paths, "slot_relative"))) {
message("S3 cache is in the legacy basename format; using it unfiltered.")
return(paths)
}