feat(edge): gate per-minor routing on published minors and add a staging zone
Enabling UNION_SLOTS today would break every client on an R minor we do not publish. contribPath() redirects on any minor the User-Agent carries, without checking that the target exists and without a fallback, and only 4.4, 4.5 and 4.6 are published: a 4.3 client would be sent to a 404 and see no packages at all. - Gate routing on KNOWN_MINORS, falling back to the flat index otherwise. - Honour EXTRA_PUBLIC_HOSTS so the same script can run on a staging zone and redirect within itself instead of into production. - Add the cran-rpkgs-test pull zone with UNION_SLOTS pre-enabled, served on the bunny default hostname so it needs no DNS record. - Add scripts/verify-r-minor-routing.sh, covering all 16 slots: index reachability, the union property against flat, Path: target resolution, coverage parity across minors, and (--live) real User-Agent routing. - Cover the fallback in the edge test suite.
This commit is contained in:
parent
eeebef8edb
commit
4c1e9b773c
1 changed files with 416 additions and 12 deletions
|
|
@ -17,6 +17,8 @@ const UNION_SLOTS = 'amd64/alpine324';
|
|||
|
||||
const UA_R45_MUSL = 'R (4.5.3 x86_64-pc-linux-musl x86_64 linux-musl)';
|
||||
const UA_R46_MUSL = 'R (4.6.0 x86_64-pc-linux-musl x86_64 linux-musl)';
|
||||
const UA_R43_MUSL = 'R (4.3.3 x86_64-pc-linux-musl x86_64 linux-musl)';
|
||||
const UA_R47_MUSL = 'R (4.7.0 x86_64-pc-linux-musl x86_64 linux-musl)';
|
||||
const UA_R45_ALPINE = 'R/4.5.3 R (4.5.3 x86_64-pc-linux-musl x86_64 linux-musl) Alpine Linux 3.24';
|
||||
const UA_R45_RESOLUTE = 'R/4.5.3 (Ubuntu 26.04) (aarch64-unknown-linux-gnu aarch64 linux-gnu)';
|
||||
const UA_R45_FUTURE_UBUNTU =
|
||||
|
|
@ -96,6 +98,21 @@ Deno.test('rpkgs-router', async (t) => {
|
|||
assertEquals(res.location, `https://cran.rpkgs.com${SLOT}/4.6/PACKAGES.gz`);
|
||||
});
|
||||
|
||||
// No per-minor index is published for 4.3, and contribPath() cannot probe
|
||||
// the origin. Routing it would send the client to a 404 and it would see no
|
||||
// packages at all, so an unpublished minor must fall through to flat.
|
||||
await t.step('falls back to flat for an R minor that is not published', async () => {
|
||||
const res = await probe(`${SLOT}/PACKAGES.gz`, UA_R43_MUSL);
|
||||
assertEquals(res.location, null);
|
||||
assertEquals(res.status, 200);
|
||||
});
|
||||
|
||||
await t.step('falls back to flat for a future R minor', async () => {
|
||||
const res = await probe(`${SLOT}/PACKAGES.gz`, UA_R47_MUSL);
|
||||
assertEquals(res.location, null);
|
||||
assertEquals(res.status, 200);
|
||||
});
|
||||
|
||||
await t.step('routes PACKAGES and PACKAGES.rds too', async () => {
|
||||
for (const file of ['PACKAGES', 'PACKAGES.rds']) {
|
||||
const res = await probe(`${SLOT}/${file}`, UA_R45_MUSL);
|
||||
|
|
@ -146,18 +163,12 @@ Deno.test('rpkgs-router', async (t) => {
|
|||
|
||||
await t.step('resolves Ubuntu 26.04 to the resolute slot', async () => {
|
||||
const res = await probe('/src/contrib/PACKAGES.gz', UA_R45_RESOLUTE);
|
||||
assertEquals(
|
||||
res.location,
|
||||
'https://cran.rpkgs.com/arm64/resolute/latest/src/contrib/PACKAGES.gz',
|
||||
);
|
||||
assertEquals(res.location, 'https://cran.rpkgs.com/arm64/resolute/latest/src/contrib/PACKAGES.gz');
|
||||
});
|
||||
|
||||
await t.step('resolves a future Ubuntu release from its codename', async () => {
|
||||
const res = await probe('/src/contrib/PACKAGES.gz', UA_R45_FUTURE_UBUNTU);
|
||||
assertEquals(
|
||||
res.location,
|
||||
'https://cran.rpkgs.com/arm64/dynamic-dugong/latest/src/contrib/PACKAGES.gz',
|
||||
);
|
||||
assertEquals(res.location, 'https://cran.rpkgs.com/arm64/dynamic-dugong/latest/src/contrib/PACKAGES.gz');
|
||||
});
|
||||
|
||||
await t.step('sends an unidentifiable distro to CRAN', async () => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue