Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 77a2f1f04a | |||
|
e9782bb529 |
|||
|
|
d2333c6cbe | ||
|
|
f4ab6f9dc5 | ||
|
|
d1da0c6cb4 | ||
|
|
c7b4dca6e2 | ||
|
50495f5c3b |
|||
|
b75fd2f1c4 |
|||
|
132d1d2d3c |
|||
|
|
706fd10d79 | ||
| 9bded261ee | |||
| a1c1f5e78f | |||
| aa4c95457f | |||
| 4b7dc28cc8 |
14 changed files with 255 additions and 126 deletions
|
|
@ -58,7 +58,7 @@ steps:
|
|||
- git clone -q https://pat-s:$$REPO_RO_TOKEN@git.devxy.io/devxy/build-cran-binaries.git .
|
||||
- mkdir -p /mnt/cache/R-pkgs
|
||||
- rm -rf /mnt/cache/R-pkgs/00LOCK-*
|
||||
- UVR_R_BIN=/opt/R/$R_VERSION/bin/R local/uvr-install.sh httr2 jsonlite
|
||||
- UVR_R_BIN=/opt/R/$R_VERSION/bin/R local/uvr-install.sh RPostgres httr2 jsonlite
|
||||
- /opt/R/$R_VERSION/bin/Rscript local/propose-patches.R --open-pr --limit $PATCH_LIMIT
|
||||
backend_options:
|
||||
kubernetes:
|
||||
|
|
|
|||
|
|
@ -3,15 +3,15 @@
|
|||
# Routing is preserved 1:1:
|
||||
# - cron: each existing `process-cran-updates-<os>-<arch>` cron fires only
|
||||
# its matching matrix row (via the per-row `cron:` name filter).
|
||||
# - manual: pick a target from the `process_cran_updates` dropdown
|
||||
# ("all" = every os/arch).
|
||||
# - manual: pick a target from the `process_cran_updates` dropdown;
|
||||
# "all" fans out every os/arch as parallel matrix workflows.
|
||||
# Arch placement is handled by the group label (rpkgs-amd64, rpkgs-arm64).
|
||||
variables:
|
||||
# Gates this pipeline. A manual pipeline creation instantiates every file in
|
||||
# .crow/, and a declared default is applied even when the run never passed
|
||||
# this variable, so the default must be a value that matches no matrix row.
|
||||
process_cran_updates:
|
||||
description: "Manual run target: a specific <os>-<arch>, 'all' for every os/arch, or 'none' to run nothing."
|
||||
description: "Manual run target: a specific <os>-<arch>, 'all' to run every os/arch in parallel, or 'none' to run nothing."
|
||||
options:
|
||||
- none
|
||||
- all
|
||||
|
|
@ -203,6 +203,7 @@ steps:
|
|||
- rm -rf /mnt/cache/R-pkgs/00LOCK-* /mnt/cache/R-pkgs/bincraft
|
||||
- mkdir -p /mnt/cache/uvr/cache /mnt/cache/uvr/packages /mnt/cache/R-pkgs /mnt/cache/ccache /mnt/cache/packages
|
||||
- /opt/R/$R_VERSION/bin/Rscript local/install-bincraft.R
|
||||
- UVR_R_BIN=/opt/R/$R_VERSION/bin/R local/uvr-install.sh RPostgres
|
||||
- /opt/R/$R_VERSION/bin/R -q -e 'packageVersion("bincraft")'
|
||||
# rhel-10 ships xwfb-run (Xwayland) instead of xvfb-run; prefer it and start weston, else fall back to xvfb-run
|
||||
- XVFB=$(command -v xwfb-run 2>/dev/null || command -v xvfb-run); XVFB_ARGS=""; if command -v xwfb-run >/dev/null 2>&1; then dnf install -y -q weston 2>/dev/null; XVFB_ARGS="-c weston"; fi
|
||||
|
|
@ -218,6 +219,7 @@ steps:
|
|||
LIB="/mnt/cache/R-pkgs-$RMINOR"
|
||||
mkdir -p "$LIB"
|
||||
R_LIBS_USER="$LIB" "$(dirname "$RBIN")/Rscript" local/install-bincraft.R || true
|
||||
R_LIBS_USER="$LIB" UVR_R_BIN="$RBIN" local/uvr-install.sh RPostgres || true
|
||||
R_LIBS_USER="$LIB" $XVFB $XVFB_ARGS -- "$(dirname "$RBIN")/R" -q -e "options(crayon.enabled = TRUE, Ncpus = 4, future.globals.onReference = NULL); bincraft::process_cran_updates(interval = $INTERVAL, platform = '${OS}', process_updated = TRUE, process_new = FALSE, process_removed = FALSE, patches = 'local/patches', r_minor_detection = 'classifier',r_minor_sensitive_only = TRUE, s3_endpoint = 'https://s3.eu-central-003.backblazeb2.com', s3_region = 'eu-central-003', s3_bucket = 'devxy-rpkgs-binaries', s3_access_key_id = Sys.getenv('B2_S3_ACCESS_KEY'), s3_secret_access_key = Sys.getenv('B2_S3_SECRET_KEY'), metadata_db_host = 'r-binaries.devxy.io', metadata_db_name = 'build_metadata', metadata_db_table = 'single_builds', metadata_db_user = 'rpkgs', metadata_db_password = Sys.getenv('PGPASS'), metadata_db_sslmode = 'require', metadata_db_port = 15432, archive = TRUE, upload = TRUE, store_build_metadata = TRUE)" || true
|
||||
done
|
||||
- /opt/R/$R_VERSION/bin/R -q -e 'library(bincraft); upload_package_index(codename = "${OS_ID}", s3_endpoint = "https://s3.eu-central-003.backblazeb2.com", s3_region = "eu-central-003", s3_bucket = "devxy-rpkgs-binaries", s3_access_key_id = Sys.getenv("B2_S3_ACCESS_KEY"), s3_secret_access_key = Sys.getenv("B2_S3_SECRET_KEY"))'
|
||||
|
|
|
|||
|
|
@ -3,15 +3,15 @@
|
|||
# Routing is preserved 1:1:
|
||||
# - cron: each existing `weekly-audit-missing-<os>-<arch>` cron fires only
|
||||
# its matching matrix row (via the per-row `cron:` name filter).
|
||||
# - manual: pick a target from the `weekly_audit_missing` dropdown
|
||||
# ("all" = every os/arch).
|
||||
# - manual: pick a target from the `weekly_audit_missing` dropdown;
|
||||
# "all" fans out every os/arch as parallel matrix workflows.
|
||||
# Arch placement is via the group label (rpkgs-amd64, rpkgs-arm64).
|
||||
variables:
|
||||
# Gates this pipeline. A manual pipeline creation instantiates every file in
|
||||
# .crow/, and a declared default is applied even when the run never passed
|
||||
# this variable, so the default must be a value that matches no matrix row.
|
||||
weekly_audit_missing:
|
||||
description: "Manual run target: a specific <os>-<arch>, 'all' for every os/arch, or 'none' to run nothing."
|
||||
description: "Manual run target: a specific <os>-<arch>, 'all' to run every os/arch in parallel, or 'none' to run nothing."
|
||||
options:
|
||||
- none
|
||||
- all
|
||||
|
|
@ -147,7 +147,7 @@ steps:
|
|||
- mkdir -p /mnt/cache/packages /mnt/cache/R-pkgs
|
||||
- rm -rf /mnt/cache/R-pkgs/00LOCK-*
|
||||
- /opt/R/$R_VERSION/bin/Rscript local/install-bincraft.R
|
||||
- UVR_R_BIN=/opt/R/$R_VERSION/bin/R local/uvr-install.sh httr2 jsonlite
|
||||
- UVR_R_BIN=/opt/R/$R_VERSION/bin/R local/uvr-install.sh RPostgres httr2 jsonlite
|
||||
- /opt/R/$R_VERSION/bin/R -q -e 'source("local/weekly-missing-binaries-audit.R")'
|
||||
backend_options:
|
||||
docker:
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ steps:
|
|||
- git clone -q https://pat-s:$$REPO_RO_TOKEN@git.devxy.io/devxy/build-cran-binaries.git .
|
||||
- mkdir -p /mnt/cache/R-pkgs
|
||||
- rm -rf /mnt/cache/R-pkgs/00LOCK-*
|
||||
- UVR_R_BIN=/opt/R/$R_VERSION/bin/R local/uvr-install.sh httr2 jsonlite
|
||||
- UVR_R_BIN=/opt/R/$R_VERSION/bin/R local/uvr-install.sh RPostgres httr2 jsonlite
|
||||
- /opt/R/$R_VERSION/bin/Rscript local/propose-patches.R --open-issue
|
||||
- /opt/R/$R_VERSION/bin/Rscript local/proposal-tracking.R --open-issue
|
||||
backend_options:
|
||||
|
|
|
|||
|
|
@ -4,17 +4,11 @@
|
|||
# - cron: each existing `weekly-rebuild-missing-<os>-<arch>` cron fires only
|
||||
# its matching matrix rows (via the per-row `cron:` name filter),
|
||||
# which is now all three shards of that slot.
|
||||
# - manual: `weekly_rebuild_missing` dropdown, default "all" (matches the
|
||||
# previous bare manual trigger that ran every os/arch); pick a
|
||||
# single <os>-<arch> to run just one.
|
||||
# - manual: pick a target from the `weekly_rebuild_missing` dropdown;
|
||||
# "all" fans out every os/arch and shard as parallel matrix
|
||||
# workflows, while a single <os>-<arch> runs its three shards.
|
||||
# Arch placement is handled by the group label (rpkgs-amd64, rpkgs-arm64).
|
||||
#
|
||||
# 9 OS versions x 2 arches x 3 shards = 54 rows. Crow counts the *declared*
|
||||
# matrix against CROW_MAX_MATRIX_SIZE before any `when:` gate is applied, so a
|
||||
# single-slot manual run expands all 54 too. The server default is 50 and was
|
||||
# raised for this; `crow lint` does not check the limit, so adding an OS
|
||||
# version here is only caught when a pipeline is triggered.
|
||||
#
|
||||
# The shard picks up its own slice and re-derives what is still outstanding
|
||||
# from the bucket, so a restart resumes rather than replaying; see
|
||||
# local/rebuild-missing.R.
|
||||
|
|
@ -27,7 +21,7 @@ variables:
|
|||
# .crow/, and a declared default is applied even when the run never passed
|
||||
# this variable, so the default must be a value that matches no matrix row.
|
||||
weekly_rebuild_missing:
|
||||
description: "Manual run target: a specific <os>-<arch>, 'all' for every os/arch, or 'none' to run nothing."
|
||||
description: "Manual run target: a specific <os>-<arch>, 'all' to run every os/arch in parallel, or 'none' to run nothing."
|
||||
options:
|
||||
- none
|
||||
- all
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ variables:
|
|||
# exactly the slots it rebuilt. A manual pipeline creation instantiates every
|
||||
# file in .crow/, so the default must match no matrix row.
|
||||
weekly_rebuild_missing:
|
||||
description: "Manual run target: a specific <os>-<arch>, 'all' for every os/arch, or 'none' to run nothing."
|
||||
description: "Manual run target: a specific <os>-<arch>, 'all' to run every os/arch in parallel, or 'none' to run nothing."
|
||||
options:
|
||||
- none
|
||||
- all
|
||||
|
|
@ -173,15 +173,13 @@ steps:
|
|||
OTEL_R_METRICS_EXPORTER: none
|
||||
BUNNYNET_API_KEY:
|
||||
from_secret: BUNNYNET_API_KEY
|
||||
REPO_RO_TOKEN:
|
||||
from_secret: REPO_RO_TOKEN
|
||||
# All hostnames on the zone share this id, so one purge covers
|
||||
# cran.devxy.io, cran.allianceswisspass.devxy.io and cran.rpkgs.com.
|
||||
BUNNY_PULLZONE: '3857050'
|
||||
# cran.rpkgs.com and cran.allianceswisspass.devxy.io are on separate
|
||||
# Bunny pull zones, so both must be purged after the shared origin changes.
|
||||
BUNNY_PULLZONES: '3857050 cran.allianceswisspass.devxy.io'
|
||||
commands:
|
||||
- apk add --no-cache -q bash curl git
|
||||
- git clone -q https://pat-s:$$REPO_RO_TOKEN@git.devxy.io/devxy/build-cran-binaries.git .
|
||||
- bash scripts/purge_cdn_zone.sh "$BUNNYNET_API_KEY" "$BUNNY_PULLZONE"
|
||||
- apk add --no-cache -q bash curl jq
|
||||
# Crow carries the checkout from the re-index step into this step.
|
||||
- bash scripts/purge_cdn_zone.sh "$BUNNYNET_API_KEY" $BUNNY_PULLZONES
|
||||
# Runs on every row rather than on one designated slot: a cron fires only
|
||||
# its own slot's row, so gating on a named slot would leave every other
|
||||
# slot unpurged. A manual "all" run therefore purges the zone 18 times,
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ repos:
|
|||
hooks:
|
||||
- id: air-format
|
||||
- repo: https://github.com/editorconfig-checker/editorconfig-checker
|
||||
rev: v3.11.1
|
||||
rev: v3.11.2
|
||||
hooks:
|
||||
- id: editorconfig-checker
|
||||
exclude: ^local/patches/.*\.patch$
|
||||
|
|
|
|||
134
.terraform.lock.hcl
generated
134
.terraform.lock.hcl
generated
|
|
@ -2,79 +2,79 @@
|
|||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.opentofu.org/hashicorp/http" {
|
||||
version = "3.6.0"
|
||||
version = "3.6.1"
|
||||
hashes = [
|
||||
"h1:0n4RBz9zNw6TTddh5+x7E8L2+qzPXNwKhK4uoZ/DUwE=",
|
||||
"h1:22Ob7lpzMBSqdrCvoFN5EgmhGPHPBovV/9qo0c/Cd+A=",
|
||||
"h1:2IRBvmWOYrq/ooaYYn2i86jZb7iIUvlg0KlmOMfDHoQ=",
|
||||
"h1:5mucXikk4OcW3un3u94QnMx4AB4Wfih+sXeMd5QxSNk=",
|
||||
"h1:5oU7Zm+2gAVGmxqtJ9E8uTudUkYy/DEn/y3IWphdv4k=",
|
||||
"h1:5w0R4b1/VSzpqQF1tXXPr/qmaQLPVRXamOmPKWFcTk4=",
|
||||
"h1:AEVeJr8xGmwad+JUUQ833C3x5d4W+W2szF5DfwxYppw=",
|
||||
"h1:CPHJ+0zQbS/cX1m55Y90jIOgf1jV3ocUUnqsXAh+9Eg=",
|
||||
"h1:JPewnGDOJudNer5+ghqwXoaJkfot3QRq9uiEYvo+JHU=",
|
||||
"h1:QzbluV2vQLxsJYxjpziQCmPndIoJ/UGS4/UHH/GpwUM=",
|
||||
"h1:TjUNbUdqweRBq/ycQ4ixpNkx5qaYwpXEOn9QCpqNZP8=",
|
||||
"h1:XNbcODP60ajj21N/OO7af8bBg1ltIsYkq9egn7BYbiY=",
|
||||
"h1:tgrbgmX7WYQz9G9ncgu7TkpVB+RlLjJA/Rvp9KPlZH8=",
|
||||
"h1:vLxthX/ZWsOZ+aHKbAMqmNKqD0K5f4nJ8ppy0Ioyup0=",
|
||||
"h1:wZOdGBAZkY8OKEPjKz82j1HloAKOmmvtjWyTxM+I110=",
|
||||
"zh:0f719fa5426bc883e9fa6abf7f6498e48025edafbc29015e2f5c028f1cca3b9d",
|
||||
"zh:1b4d7dafefd6c61764b2f9ed6943ceb9a200dee3590d18747e3a5f6b20ce85e0",
|
||||
"zh:1d23a712984866d29f7b07028a4e99c783c71f1a5dddf08bc3d4e7da9d91a1fa",
|
||||
"zh:257d23d58c3bb024b6bc8eb88736eaf912e934ad47c639d0c3c742bddda849a1",
|
||||
"zh:479860e1a5468f5e04013b9364c9496d7ed0804bf9a1acd8e07558d57609993d",
|
||||
"zh:4cb5e681bf599b411b27c4a2c4066a5fb2ed79aaa3a1a3cb5a30002fec062ce9",
|
||||
"zh:4fb35c3f643dae9f3670d719397a415f815a0b95f8ed7bd8a72f27a94ba78092",
|
||||
"zh:59ba40825ab38db5b4a0989a2db0df35cc15d8984f898176011ba352f27d77b7",
|
||||
"zh:61fc1252eb88088638f4c69ea4e2171cde2e5089fa632ac1e943b13787348f73",
|
||||
"zh:7c5d6dd5f7cbc460e95d368be35c29b4e0402069b8912dbd5d1cd7fa9acef216",
|
||||
"zh:7f76d756240d4284642f359ad470226e5378670239aadc366ef54d9d914d4d2e",
|
||||
"zh:8133ad0814098177e0d067c816ccf1bf48bbadacd18f6f2c808c90447505723b",
|
||||
"zh:c93be06269bb728f1968f8c50506de56c887017ac1d6e4be1f925651d8437eb6",
|
||||
"zh:ef47b78a10a82e6cf53344a6a85a94041c28286c10a70541c564d762f1cfede0",
|
||||
"zh:f5796a53a74999135bd9087aff50fddda59129d09b2f9b1902ff8c0c1e047e48",
|
||||
"h1:7fra+jbUXbG5wMaz5L6RKMBv6gIuenJcBiIww87GoXo=",
|
||||
"h1:BzSV3Ie9XMXF7sZHKAS54CzV95v5GBZNhQ4nrprUgfQ=",
|
||||
"h1:CkrbSKS+pNVgvP3bMe2WoYHaFCIWJUkCtlC5vyTAdLI=",
|
||||
"h1:FboJEwgVIRmqUJkjEoSRpfavVCJotUTe1zzT+pBzcV0=",
|
||||
"h1:GlXELDLSZrdV3Svx1jjEBAXiJFkkdF/Hgx1qrmRK5hE=",
|
||||
"h1:VuXFI2IcnZ6t4sDqtvkuIzbPK1CJQa0CkaM0MBuOlSU=",
|
||||
"h1:WmL2nFQbSzRiDsDiwUbZbBp/cxGQrXrZnB7A4LGSvJU=",
|
||||
"h1:Zdj26awWJ+m8kMoAMhItsIDcDFg81PWgKKJrvNi3WOI=",
|
||||
"h1:lHvYYIumeZ+KJgCrmhCLnRGzrvNMjSHBTdV24coyMEc=",
|
||||
"h1:pAOYMwA6Zki3ujAbG20b49u1IYXdBz56pW1JHqKdX5U=",
|
||||
"h1:qi9GUp2+g69C8zY6Z68u4fWPwcZlDTa/CtdhvPgWbMA=",
|
||||
"h1:w5A3xJ2mowj2wgiE3oNfOI0lFJf5X9IgxOJ6SErMczA=",
|
||||
"h1:xAO03iJyuNGSOqolIcXcofH8cocgUb6Cnzq6yivbWcI=",
|
||||
"h1:xXigGPwW8MlrB6Br2ce+Bf35BbdzdPKa97T/q/xrrcA=",
|
||||
"h1:yDYzQ2ncNE9q1288xAgflIPq98bOOYsAb9tq6vkbFzw=",
|
||||
"zh:129d7d5944b31f40916b1ca86b31cef65a6b02fd36008809d13c561894bfedb9",
|
||||
"zh:24631608288b0bcd35c1fc63dc5839572254d881c0589ebba036be52b2fc04d6",
|
||||
"zh:5a0f100d7eb256463fe5a2aa1a7128391147b2c5fc895ff1b1ef54fc5b8f15ab",
|
||||
"zh:6a8a1126ab9ca61be3b62ec184f6b2e7cbf01cde810acc548cee27d71277b09b",
|
||||
"zh:6fffef54fd3aada85c074e34d41386aa09c79a308a4679132da31c7272733c6c",
|
||||
"zh:899c992d2aa290ebe1304da0289c5104a630bca421cc6a88ce55bf0960aab1b4",
|
||||
"zh:960fd6c2847859a843dd9dbfc95a0037a470aa744094d155a38a057175cf1502",
|
||||
"zh:9b032b685a644634158ace5529e260dfc4447a280056f02858d205ea26753f69",
|
||||
"zh:bba5477c97020c28ed12d4f5b36be2c1bf14d946d7e44b3690e5c23cd7ddf5e6",
|
||||
"zh:c2ff6c33efef52441fa3485137972792031626dcabca2b1d8b6527d45f185279",
|
||||
"zh:cd492b3dfd150de6bef8ad505293d3d53c6c907706f36d0e497b4fc027d8edb6",
|
||||
"zh:d1f832bc33c42781454dc020c6937e7d0133155a5a9f64335309d64a34b36bb7",
|
||||
"zh:d42e9cbebc77643556853b1ebbec14cefe70c57ee86cd3b8c71fbe7f523f07df",
|
||||
"zh:d4c0466f578d7f990646bb0847e31ba3797f2100b6380ee1ca736887546c7621",
|
||||
"zh:d9d81ecebfe6edabdd4c527f3f4debde3e052ff87c5ef4c67497ab3d7539e424",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/bunnyway/bunnynet" {
|
||||
version = "0.17.0"
|
||||
constraints = "~> 0.17"
|
||||
version = "0.18.2"
|
||||
constraints = "~> 0.18"
|
||||
hashes = [
|
||||
"h1:+qDt35lVSK7acw6a1xHuPYrqmZEcHSmtd+6n1TxNuYw=",
|
||||
"h1:1dCu2l4DhPBjizVAH/WwAjT1Xbo52K4PMvHoD5zUhuU=",
|
||||
"h1:Dvn46Auwuel4jqrqZXs2D7kdujNhs17LEmqhuY0k4/4=",
|
||||
"h1:M5eDL3m2uSEr1XATJW0foHzKl8pFhCtgKuOM24bJRwU=",
|
||||
"h1:PddaC7nM/gY4x9i3xy6TxOs9MAu2/6g58Xs/gv4DRV8=",
|
||||
"h1:QVIKiZluI+NQAKu8NpFBl3Nvyx+d81vW9btEUdIQREc=",
|
||||
"h1:S6TnzXHsRoGYvC1vJBkDiVEc0spceksY4n6x5WN5iYw=",
|
||||
"h1:VcxZDWqCWMSjcUsC1K4sB6uYEoeoou+BC0ePoJXmf3A=",
|
||||
"h1:W0y/agBVqls1cJlFGFYMu2VnqoPXFzxVHPIYe3OqfYQ=",
|
||||
"h1:XmNd5fP9a0O77ve5BMQP2vARExgIa7rYl6KvyUYXPSs=",
|
||||
"h1:e0EFKrWSQwaa/kGhnha4DXk4T68Av8QxP84mRSdWC9M=",
|
||||
"h1:eM+/lUiU0pNSgQKoqKPgE3xJrJ0MHIpKG+yhaGB/P0M=",
|
||||
"h1:fPWWA4T0/y7GX+tCGN23l1jODhZ3uCdR/MKgZDXYpAE=",
|
||||
"h1:g+r2GVi4gVC4DuQg3PL70gW9BDskgWUzCBIMXTUq63A=",
|
||||
"h1:gaZ8eALDtVHqykVDHav8004gHiMGaYR/3KwET0FUgao=",
|
||||
"h1:kbqW25eaiv4N/N/z+sxLdJZ15yh5cgnRD/q6RclPMLc=",
|
||||
"h1:rGjxue3mXRyQQqpywTXC4zK//JAtf0Cz7RP+uPMMJjw=",
|
||||
"zh:05943fef14c2028f4722bf078aa1889229e94302f7678cc6f63adb669d8ea612",
|
||||
"zh:26a163930a92a7408f7bbd0130064b84df8a232b500d8c6c3989952986308539",
|
||||
"zh:41305feaaade55391447521ec309f3c038b631ca542907ad95132fab71a7e116",
|
||||
"zh:606919a930f0299948504adbdcd0f239a8af5c418f85741c48f8add370a3d038",
|
||||
"zh:66963d5b445639511939fc508513fd31da3ee1d4ee1a565ee396c9532897a349",
|
||||
"zh:6c981ec0c8545556395c43e2511861ab65ee9ecf2a960480e7889c3af0d23af3",
|
||||
"zh:7334a1bdb726ce1f1bf0a3155f30f84f65206980c229c832ff5f0b0718c44e0b",
|
||||
"zh:75f6c86bf74511e605423332d113711c76c8028361a32282fb3359d6c7ecae9e",
|
||||
"zh:7aebb1a01cfe8be54903853202ae06eba14ad99c37d230ed93ce7d6633e05e9b",
|
||||
"h1:3rZl+Co3WMpwj8SciPaCNXoGA31aSoqp6iweLarr5m4=",
|
||||
"h1:6d9cKLhz8QOZ4R5yVX1G0TsWL+K1Abtfbm3xngndxto=",
|
||||
"h1:EBjjkfp5Gx7nXP1DVO+tLhsow6fEUvaIjsCEFRT2fY8=",
|
||||
"h1:Nu2DoHGOv2YN7ag4kFGpfnPeRDh6bzWqY5anW+ETGpM=",
|
||||
"h1:OnvZxg28m4/UJeEhHVLU4kM2MZ704sxRzYfLWlLxnhA=",
|
||||
"h1:PiCse2/UcB7nkPxosveHsJN/jKdBC8AH6tKTxcHSYKw=",
|
||||
"h1:QAahdtlDBUon7eMwNN0D2V6CxgasOXIi+9/UExik6Sg=",
|
||||
"h1:Su5z0A7/UaSm/E7FJnFjpDVQaa1Ju5+fZ8Mirf8E+k8=",
|
||||
"h1:UA3a78FJAPAGqCCvlIg9ekPltpVsrmEhwFLalWCFnew=",
|
||||
"h1:XAlCTNHRtgUkNjdUItkiak6ajjT7wFJzJN8frXKD5Ms=",
|
||||
"h1:ZgLBOPebYxH059z1cGHmjYO8CTf+tbWPb3VbO97S2YM=",
|
||||
"h1:anR91C2F6NDJoQQQIy6KHChodnTaSKnApSWSGM4jSX0=",
|
||||
"h1:gVmaNmIu4gEiITM+CAb66e+zncAqzNBYkniTZfvxZ5Y=",
|
||||
"h1:pODlGrkPqHV4yhXiO7LLLu11HtcuxOAB2zUx3B8w1vI=",
|
||||
"h1:qEYeHEKVRcc78q5xiRGJSY8DGQpLj40KafEXUxFfaQc=",
|
||||
"h1:qdVz+O0lLHhyf5YX3ujmoVvAGlKqvi+YOPUzVTqpKzY=",
|
||||
"h1:yTrPkdc9eQkxfPLBYydFf0fpcjarP5w0sdLPzekD9RQ=",
|
||||
"zh:0fe3987c927d81196c97504470ce4d26c3ad0014f8ee3d0c1be422d08cfcf49c",
|
||||
"zh:15c36dc69e058876921ac887213e1716217d159b7ee7f0f233e21fb35be85178",
|
||||
"zh:29d58d7b76dcb142a06d4edd15b8500fe6c1afb7f7c056ada17e2d42bb999fbd",
|
||||
"zh:33d313836c0e985186b3456c0946e062b27cacfcb08611d0a394f36db9ee1aef",
|
||||
"zh:47e085e52e9b24ad85fa2988dbb8604256a970a6f53f7fa6aab04d8ae756a738",
|
||||
"zh:4ba4f87571ca72fbc6c24ab71f2f7b5a086938262e2d8e5c0b39701ed52f8bbc",
|
||||
"zh:4c6bae97b543c5b328e1ecbcf7c976351b4b381654e9d3e569270dcab3ba816c",
|
||||
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
||||
"zh:9041d0e20c9ceea532de6eebf5cb3a27dad0bb49d3f5b5154be2a08d68fbbf1f",
|
||||
"zh:a6bbf65431a02be4df0ebb1cbe01185ad357ff6e33c01bd0558f59bed90c8f36",
|
||||
"zh:c6d075a31096f080c388dfe46036f451c0cc114c3311a4f46ab8dbe1938a202f",
|
||||
"zh:dd8703f7b55b8bc8e10f8718bea889781100b18e932b04898995b63178c3d36e",
|
||||
"zh:dd92a5cd4e133a4000e7e5bc8cce876ae0ed803543cedd2f3d590661ba244d04",
|
||||
"zh:e024fdf121bebc48c1e6debea344c6d4f174117f3ae605fca6e13b9705d92d22",
|
||||
"zh:ee0e80c31b438e35fa1608f6a2f5824d2806db1e5e8b9f7a90986585c7bcb895",
|
||||
"zh:fc2d4b705411b48f8c045981f9368a3ea2f74969dd6302008c31ff0bedd51f0a",
|
||||
"zh:9ba7ab56537963db2449d217528a751469c9dc4e413dec3e3d63fd7daf3db4ef",
|
||||
"zh:a3c48eda7e11b03b831f2a639797524bb335f155f0dff0e999cf3496994da8b3",
|
||||
"zh:aab8f4814d55ef8c6c285d2496ae412437017d0fd1be70106f7b3a4a6e764feb",
|
||||
"zh:b92b9beacf71ae894717c2036ceb68db52c9c43af4a01b8209eceae9f91a2c8e",
|
||||
"zh:da389285938e22e1249e6a00cebf12a9f67334743f0b3f66399e6881028bda11",
|
||||
"zh:dadcc33d06e6f64a17d1965478af5e8bbdc971e92ec9b14e384c5d43861d63f7",
|
||||
"zh:e090c916e6da685125194af4f0a1fd772494a0c63f3f16ab3741782e17f4a8f9",
|
||||
"zh:e5881e00fa970c08e66e8079b47d69b76def6e7ff3bdc35b68d7811e5ece55d1",
|
||||
"zh:eeebb25a066a6287d545c91c0fc264acee5b28174d0979faeebdac3bd14f0fff",
|
||||
"zh:f368195116c9ce0181aa7527c51ae5e7ab23d42fb966acf4eddca344621ae339",
|
||||
]
|
||||
}
|
||||
|
|
|
|||
63
cdn.tf
63
cdn.tf
|
|
@ -32,7 +32,7 @@
|
|||
# cache_stale = ["offline", "updating"]
|
||||
# use_background_update = true
|
||||
|
||||
# block_ips = var.cdn_block_ips
|
||||
# block_ips = var.cdn_block_ips
|
||||
|
||||
# # 50 TB
|
||||
# limit_bandwidth = 50000000000000
|
||||
|
|
@ -82,7 +82,7 @@ resource "bunnynet_pullzone" "cran_rpkgs_com" {
|
|||
|
||||
cache_expiration_time = 31919000
|
||||
websockets_enabled = false
|
||||
errorpage_whitelabel = true
|
||||
errorpage_whitelabel = true
|
||||
|
||||
origin {
|
||||
type = "OriginUrl"
|
||||
|
|
@ -147,6 +147,65 @@ resource "bunnynet_pullzone_hostname" "cran_rpkgs_com" {
|
|||
tls_enabled = true
|
||||
}
|
||||
|
||||
# Alliance SwissPass historically used a separate, manually configured pull
|
||||
# zone. Adopt it so both public repositories use the same B2 origin, middleware
|
||||
# release and cache behavior.
|
||||
import {
|
||||
to = bunnynet_pullzone.cran_allianceswisspass
|
||||
id = "3265648"
|
||||
}
|
||||
|
||||
resource "bunnynet_pullzone" "cran_allianceswisspass" {
|
||||
name = "cran-allianceswisspass"
|
||||
|
||||
cache_errors = false
|
||||
cache_expiration_time = 31919000
|
||||
websockets_enabled = false
|
||||
errorpage_whitelabel = true
|
||||
|
||||
origin {
|
||||
type = "OriginUrl"
|
||||
url = "https://devxy-rpkgs-binaries.s3.eu-central-003.backblazeb2.com"
|
||||
middleware_script = bunnynet_compute_script.rpkgs_router.id
|
||||
}
|
||||
|
||||
routing {
|
||||
filters = [
|
||||
"scripting",
|
||||
]
|
||||
}
|
||||
|
||||
s3_auth_enabled = true
|
||||
s3_auth_key = var.B2_S3_ACCESS_KEY
|
||||
s3_auth_secret = var.B2_S3_SECRET_KEY
|
||||
s3_auth_region = "eu-central-003"
|
||||
|
||||
cache_enabled = true
|
||||
request_coalescing_enabled = true
|
||||
block_post_requests = true
|
||||
cache_vary_headers = ["User-Agent"]
|
||||
|
||||
limit_requests = 5000
|
||||
limit_connections = 1000
|
||||
|
||||
safehop_enabled = true
|
||||
add_canonical_header = true
|
||||
cache_stale = ["offline", "updating"]
|
||||
block_ips = var.cdn_block_ips
|
||||
|
||||
# 50 TB
|
||||
limit_bandwidth = 50000000000000
|
||||
|
||||
block_root_path = true
|
||||
}
|
||||
|
||||
resource "bunnynet_pullzone_hostname" "cran_allianceswisspass" {
|
||||
pullzone = bunnynet_pullzone.cran_allianceswisspass.id
|
||||
name = "cran.allianceswisspass.devxy.io"
|
||||
force_ssl = true
|
||||
tls_enabled = true
|
||||
}
|
||||
|
||||
# resource "bunnynet_storage_zone" "devxy-r-binaries" {
|
||||
# name = "devxy-r-binaries-storage"
|
||||
# region = "DE"
|
||||
|
|
|
|||
|
|
@ -117,6 +117,13 @@ Deno.test('rpkgs-router', async (t) => {
|
|||
assertEquals(res.status, 200);
|
||||
});
|
||||
|
||||
await t.step('serves an archived binary when it exists', async () => {
|
||||
const path = `${SLOT}/Archive/xml2/xml2_1.5.2.tar.gz`;
|
||||
const res = await probe(path, UA_R45_MUSL);
|
||||
assertEquals(res.status, 200);
|
||||
assertEquals(res.location, null);
|
||||
});
|
||||
|
||||
await t.step('does not redirect a path already under a minor', async () => {
|
||||
const res = await probe(`${SLOT}/4.5/PACKAGES.gz`, UA_R45_MUSL);
|
||||
assertEquals(res.location, null);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import * as BunnySDK from 'https://esm.sh/@bunny.net/edgescript-sdk@0.12';
|
|||
|
||||
const PUBLIC_CDN_ORIGIN = 'https://cran.rpkgs.com';
|
||||
const CRAN_ORIGIN = 'https://cran.r-project.org';
|
||||
const PUBLIC_CDN_HOSTS = new Set(['cran.rpkgs.com', 'cran.allianceswisspass.devxy.io']);
|
||||
|
||||
/** Slots ("<arch>/<os>", comma separated) whose per-minor index is a union. */
|
||||
const UNION_SLOTS = new Set(
|
||||
|
|
@ -47,6 +48,10 @@ const INDEX_FILE_REGEX = /^PACKAGES(\.gz|\.rds)?$/;
|
|||
|
||||
const SRC_CONTRIB_REGEX = /^\/src\/contrib\/(.+)$/;
|
||||
|
||||
/** A binary archive URL whose upstream source counterpart CRAN can serve. */
|
||||
const ARCHIVE_TARBALL_REGEX =
|
||||
/^\/(?:amd64|arm64)\/[a-z0-9._-]+\/latest\/src\/contrib\/Archive\/([^/]+)\/([^/]+\.tar\.gz)$/;
|
||||
|
||||
const MACOS_BIN_REGEX =
|
||||
/^\/bin\/macosx\/(big-sur-arm64|big-sur-x86_64|monterey-arm64|monterey-x86_64)\/contrib\/([0-9.]+)\/(.+)$/;
|
||||
|
||||
|
|
@ -85,6 +90,10 @@ function redirectTo(location: string, status = 302): Response {
|
|||
});
|
||||
}
|
||||
|
||||
function publicCdnOrigin(url: URL): string {
|
||||
return PUBLIC_CDN_HOSTS.has(url.hostname) ? url.origin : PUBLIC_CDN_ORIGIN;
|
||||
}
|
||||
|
||||
function extractRMinor(userAgent: string): string | null {
|
||||
for (const regex of R_MINOR_REGEXES) {
|
||||
const match = userAgent.match(regex);
|
||||
|
|
@ -181,15 +190,14 @@ BunnySDK.net.http
|
|||
const url = new URL(ctx.request.url);
|
||||
const path = normalizePathname(url.pathname);
|
||||
const userAgent = ctx.request.headers.get('User-Agent') || '';
|
||||
const publicOrigin = publicCdnOrigin(url);
|
||||
|
||||
// macOS clients are served from CRAN's own binary tree.
|
||||
const srcContrib = path.match(SRC_CONTRIB_REGEX);
|
||||
if (srcContrib && /darwin/.test(userAgent)) {
|
||||
const mac = parseMacUserAgent(userAgent);
|
||||
if (mac) {
|
||||
return Promise.resolve(
|
||||
redirectTo(`${PUBLIC_CDN_ORIGIN}/bin/macosx/${mac.os}/contrib/${mac.rver}/${srcContrib[1]}`),
|
||||
);
|
||||
return Promise.resolve(redirectTo(`${publicOrigin}/bin/macosx/${mac.os}/contrib/${mac.rver}/${srcContrib[1]}`));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -213,7 +221,7 @@ BunnySDK.net.http
|
|||
if (target === path) {
|
||||
return Promise.resolve(ctx.request);
|
||||
}
|
||||
return Promise.resolve(redirectTo(`${PUBLIC_CDN_ORIGIN}${target}`));
|
||||
return Promise.resolve(redirectTo(`${publicOrigin}${target}`));
|
||||
}
|
||||
|
||||
// The bare `https://cran.rpkgs.com` form, resolved from the User-Agent.
|
||||
|
|
@ -224,12 +232,27 @@ BunnySDK.net.http
|
|||
}
|
||||
|
||||
const rest = srcContrib ? srcContrib[1] : '';
|
||||
return Promise.resolve(redirectTo(`${PUBLIC_CDN_ORIGIN}${contribPath(slot, rest, userAgent)}`));
|
||||
return Promise.resolve(redirectTo(`${publicOrigin}${contribPath(slot, rest, userAgent)}`));
|
||||
}
|
||||
|
||||
return Promise.resolve(ctx.request);
|
||||
})
|
||||
.onOriginResponse((ctx) => {
|
||||
.onOriginResponse(async (ctx) => {
|
||||
const path = normalizePathname(new URL(ctx.request.url).pathname);
|
||||
const archive = path.match(ARCHIVE_TARBALL_REGEX);
|
||||
|
||||
// Binary archives can be incomplete when an older build never succeeded.
|
||||
// Preserve renv/remotes version restores by falling back to CRAN's source
|
||||
// package only for an absent archived tarball. A requested version can be
|
||||
// either archived upstream or still current, so probe the archive first.
|
||||
// Other 404s remain visible.
|
||||
if (ctx.response.status === 404 && archive) {
|
||||
const archiveUrl = `${CRAN_ORIGIN}/src/contrib/Archive/${archive[1]}/${archive[2]}`;
|
||||
const archiveResponse = await fetch(archiveUrl, { method: 'HEAD' });
|
||||
const sourceUrl = archiveResponse.ok ? archiveUrl : `${CRAN_ORIGIN}/src/contrib/${archive[2]}`;
|
||||
return redirectTo(sourceUrl);
|
||||
}
|
||||
|
||||
ctx.response.headers.append('X-Via', 'MyMiddleware');
|
||||
return Promise.resolve(ctx.response);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -84,9 +84,20 @@ trap 'rm -rf "$project_dir"' EXIT
|
|||
cd "$project_dir"
|
||||
|
||||
"$uvr_bin" init --here --r-version "$r_full"
|
||||
# --no-install: resolve and lock only. The install happens in the sync below,
|
||||
# which is the only command that honours --library.
|
||||
"$uvr_bin" add --no-install "$@"
|
||||
# --no-install resolves and locks only; retry because concurrent shards can
|
||||
# expose short-lived DNS or CRAN-index failures and uvr rolls the manifest back
|
||||
# cleanly after an unsuccessful resolution.
|
||||
add_attempt=1
|
||||
while ! "$uvr_bin" add --no-install "$@"; do
|
||||
if [ "$add_attempt" -ge 4 ]; then
|
||||
echo "error: uvr add failed after ${add_attempt} attempts" >&2
|
||||
exit 1
|
||||
fi
|
||||
add_delay=$((add_attempt * 10))
|
||||
echo "warning: uvr add attempt ${add_attempt} failed; retrying in ${add_delay}s" >&2
|
||||
sleep "$add_delay"
|
||||
add_attempt=$((add_attempt + 1))
|
||||
done
|
||||
|
||||
# TEMPORARY (drop once the images ship a uvr above v0.4.5): the sync below runs
|
||||
# `apt-get install` for every resolved system dependency without refreshing the
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ terraform {
|
|||
required_providers {
|
||||
bunnynet = {
|
||||
source = "registry.terraform.io/BunnyWay/bunnynet"
|
||||
version = "~> 0.17"
|
||||
version = "~> 0.18"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,35 +18,70 @@
|
|||
# objects were replaced. The cost is a cold cache for everything else, which is
|
||||
# why this is not used by the daily update path.
|
||||
#
|
||||
# All hostnames on the zone (cran.devxy.io, cran.allianceswisspass.devxy.io,
|
||||
# cran.rpkgs.com) share pull zone 3857050, so one purge covers all of them.
|
||||
# The public hostnames currently use separate pull zones, so callers must pass
|
||||
# every zone that serves the repository. A zone can be identified by its
|
||||
# numeric ID or by one of its hostnames; hostname lookup avoids persisting IDs
|
||||
# that change when a zone is recreated.
|
||||
#
|
||||
# Usage:
|
||||
# purge_cdn_zone.sh <BUNNYNET_API_KEY> <pull_zone_id>
|
||||
# purge_cdn_zone.sh <BUNNYNET_API_KEY> <pull_zone> [<pull_zone>...]
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
if (($# < 2)); then
|
||||
echo "usage: $0 <api_key> <pull_zone_id>" >&2
|
||||
echo "usage: $0 <api_key> <pull_zone> [<pull_zone>...]" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
api_key="$1"
|
||||
zone_id="$2"
|
||||
shift
|
||||
|
||||
echo "Purging BunnyCDN pull zone ${zone_id}"
|
||||
resolve_zone_id() {
|
||||
local zone="$1"
|
||||
local response_file
|
||||
local zone_id
|
||||
|
||||
status=$(
|
||||
curl -sS -o /tmp/purge_zone_response.txt -w '%{http_code}' -X POST \
|
||||
if [[ "${zone}" =~ ^[0-9]+$ ]]; then
|
||||
echo "${zone}"
|
||||
return
|
||||
fi
|
||||
|
||||
response_file=$(mktemp)
|
||||
curl -sS -o "${response_file}" \
|
||||
-H "AccessKey: ${api_key}" \
|
||||
-H "Content-Length: 0" \
|
||||
"https://api.bunny.net/pullzone/${zone_id}/purgeCache"
|
||||
)
|
||||
"https://api.bunny.net/pullzone"
|
||||
zone_id=$(
|
||||
jq -r --arg hostname "${zone}" \
|
||||
'(.Items // .)[] | select(any(.Hostnames[]?; .Value == $hostname)) | .Id' \
|
||||
"${response_file}"
|
||||
)
|
||||
rm -f "${response_file}"
|
||||
|
||||
if [[ "${status}" != "200" && "${status}" != "204" ]]; then
|
||||
echo "Purge of pull zone ${zone_id} failed with HTTP ${status}:" >&2
|
||||
cat /tmp/purge_zone_response.txt >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -z "${zone_id}" ]]; then
|
||||
echo "Could not find BunnyCDN pull zone for hostname ${zone}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Purged pull zone ${zone_id} (HTTP ${status})"
|
||||
echo "${zone_id}"
|
||||
}
|
||||
|
||||
for zone in "$@"; do
|
||||
zone_id=$(resolve_zone_id "${zone}")
|
||||
echo "Purging BunnyCDN pull zone ${zone_id}"
|
||||
|
||||
response_file="/tmp/purge_zone_response_${zone_id}.txt"
|
||||
status=$(
|
||||
curl -sS -o "${response_file}" -w '%{http_code}' -X POST \
|
||||
-H "AccessKey: ${api_key}" \
|
||||
-H "Content-Length: 0" \
|
||||
"https://api.bunny.net/pullzone/${zone_id}/purgeCache"
|
||||
)
|
||||
|
||||
if [[ "${status}" != "200" && "${status}" != "204" ]]; then
|
||||
echo "Purge of pull zone ${zone_id} failed with HTTP ${status}:" >&2
|
||||
cat "${response_file}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Purged pull zone ${zone_id} (HTTP ${status})"
|
||||
done
|
||||
|
|
|
|||
Loading…
Reference in a new issue