build-cran-binaries/.crow
Repository files (latest commit first)
Filename Latest commit message Latest commit date
pat-s af4cc6f414
Some checks failed
ci/crow/manual/verify-repo-routing/15 Pipeline was successful
ci/crow/manual/verify-repo-routing/3 Pipeline failed
ci/crow/manual/prune-stale-flat-binaries/15 Pipeline was successful
ci/crow/manual/reindex/7 Pipeline was successful
ci/crow/cron/process-updates/1 Pipeline failed
ci/crow/cron/process-updates/7 Pipeline was successful
ci/crow/manual/verify-repo-routing/16 Pipeline was successful
ci/crow/cron/process-updates/9 Pipeline was successful
ci/crow/manual/repair-unsafe-flat-objects/7 Pipeline was successful
ci/crow/cron/process-updates/8 Pipeline was successful
ci/crow/cron/process-updates/2 Pipeline was successful
feat(ci): verify what clients actually receive from every published slot (#209)
## Why

Everything built so far reasons about the *binaries*: `abi_flat_safety` records what an object's symbols say it can load under, and the index writer drops records on that verdict.
None of it proves what a **client** actually receives, which is the product of the CDN rewrite, the per-minor indexes and the `Path:` field acting together.

The reprex that found the `base64enc` failure ran on a workstation, could only reach amd64, and did not survive the session.
This makes it a pipeline.

## What it does

For every slot, under every R minor the image carries, it installs a fixed package set through each URL form the website documents and checks that each one loads in a fresh subprocess.

| form | repository | user agent |
| --- | --- | --- |
| `arch` | `https://cran.rpkgs.com/<arch>/<codename>/latest` | R's own |
| `generic` | `https://cran.rpkgs.com/` | the string the website's snippet builds |
| `flat` | the arch URL | `curl/8.5.0`, so the edge cannot read an R minor |

`arch` and `generic` are contractual, so a failure there fails the run.
`flat` measures what a client hiding its R minor is exposed to: it is reported and never fatal, because pruning the flat slot is a separate decision.

Two details that matter:

- **CRAN is deliberately absent from `repos`.** A package missing from our index must fail loudly rather than be quietly compiled from source, which would hide exactly the gap this exists to find.
- **One process per form.** `available.packages()` caches its index in `tempdir()` keyed by repository URL, and `arch` and `flat` share a URL. In a single process the second form would read the first form's index and prove nothing.

## Verification

Run against the live repository in `build-env-ubuntu:noble` under R 4.6.0, mid-repair:

```
amd64/noble R 4.6 via arch:    11 of 11 packages usable
amd64/noble R 4.6 via generic: 11 of 11 packages usable
amd64/noble R 4.6 via flat:     8 of 11 packages usable
```

The three `flat` failures are `Rcpp`, `data.table` and `yaml`, each `Built: R 4.4.3` and each failing `dyn.load()` under 4.6.
That is the unrouted-client exposure, measured rather than estimated.

The rows also show the routed forms serving a mix of per-minor and flat objects (`Rcpp` at `R 4.6.0`, `stringi` at `R 4.4.3`), which is the intended behaviour: only objects that cannot load cross-minor get a per-minor copy.

Reviewed-on: #209
2026-09-09 12:52:16 +00:00
..
archive-missed-packages.yaml fix(index): add a slot repair for a broken Built stamp and retire alpine 3.21 (#150) 2026-08-07 09:15:04 +00:00
auto-apply-patches.yaml fix(ci): install RPostgres for audit workflows (#172) 2026-08-30 07:31:28 +00:00
backfill-abi-classification.yaml feat(abi): backfill classifier verdicts for pre-per-minor packages (#199) 2026-09-04 10:34:49 +00:00
backfill-flat-safety.yaml fix(ci): authenticate uvr's GitHub resolution in the index workflows (#204) 2026-09-05 15:59:16 +00:00
build-all-versions-install-deps.yaml fix(ci): make every manual gate default to a value that matches nothing (#158) 2026-08-09 15:31:14 +00:00
build-all-versions.yaml fix(ci): install RPostgres in build shards (#195) 2026-09-03 20:09:20 +00:00
process-updates.yaml fix(ci): install RPostgres for metadata updates 2026-08-28 08:48:58 +00:00
prune-stale-flat-binaries.yaml fix(abi): prune flat-slot binaries of ABI-risky packages (#200) 2026-09-04 10:54:09 +00:00
rebuild-abi-gap.yaml fix(ci): do not gate the targeted repair on the source classifier (#205) 2026-09-07 06:20:04 +00:00
reindex.yaml fix(ci): authenticate uvr's GitHub resolution in the index workflows (#204) 2026-09-05 15:59:16 +00:00
repair-built-stamp.yaml fix(ci): make every manual gate default to a value that matches nothing (#158) 2026-08-09 15:31:14 +00:00
repair-unsafe-flat-objects.yaml feat(abi): repair from the recorded verdicts rather than an ad-hoc scan (#206) 2026-09-07 18:46:50 +00:00
trial-build-registry.yaml fix(ci): gate the three ungated pipelines on their own variable (#155) 2026-08-09 10:02:05 +00:00
verify-repo-routing.yaml feat(ci): verify what clients actually receive from every published slot (#209) 2026-09-09 12:52:16 +00:00
weekly-audit-missing.yaml fix(ci): install RPostgres for audit workflows (#172) 2026-08-30 07:31:28 +00:00
weekly-patch-proposals.yaml fix(ci): install RPostgres for audit workflows (#172) 2026-08-30 07:31:28 +00:00
weekly-rebuild-missing.yaml Revert "fix(ci): split oversized weekly rebuild matrix" 2026-08-14 07:01:56 +00:00
weekly-rebuild-reindex.yaml fix(ci): authenticate uvr's GitHub resolution in the index workflows (#204) 2026-09-05 15:59:16 +00:00