build-cran-binaries/.crow/retire-slot.yaml
pat-s bfe56ffd22
feat(slots): add a retirement workflow and a drift check
Retiring a slot means three separate things in three separate places, and
nothing tied them together.
Alpine 3.22 is what that costs: it was removed from `local.rpkgs_slots` in
`cdn.tf` at some point, so the edge stopped routing it, but it kept a matrix
row in twelve pipelines, six cron jobs on the Crow server and ~50000 objects in
the bucket.
Nightly builds kept producing binaries nobody could reach, and because an
unrouted slot serves the flat index to every client, R 4.4 and R 4.6 users got
`LOAD_FAILED` rather than nothing.

This change will:

- Add `local/check-slots.R`, which fails when any `.crow/*.yaml` still targets
  a slot missing from `local.rpkgs_slots`. Run it with `just check-slots`.
- Add `local/retire-slot.R`, which strips a slot from the pipeline matrices and
  deletes its objects from the bucket. Dry run by default, and it refuses any
  slot still listed in `cdn.tf`, so it cannot be pointed at a live slot.
- Add `.crow/retire-slot.yaml`, which runs the asset half in CI where the B2
  credentials exist.
- Document the ordering in README, including the cron jobs, which live on the
  Crow server and cannot be removed from here.

The check is one-directional on purpose.
A pipeline targeting an unpublished slot is an error; a published slot missing
from *some* pipeline is only reported, because several pipelines cover a subset
deliberately.

Verified against the tree as it stood before #213: the checker names exactly the
twelve files that PR edited by hand, and `retire-slot.R --config-only` reproduces
that commit's structural changes byte for byte across all 18 pipeline files.
The only differences are two prose lines, a usage example and a dropdown
`description:`, which the script leaves alone because rewriting free text
automatically is guesswork.
2026-09-11 08:17:21 +00:00

83 lines
2.8 KiB
YAML

# Delete a retired slot's objects from the bucket.
#
# The config half of a retirement (`.crow/*.yaml` matrices) is a commit, so it
# happens on a workstation:
#
# Rscript local/retire-slot.R <codename> --config-only --apply
#
# The asset half needs the B2 credentials, which only exist in CI, so it
# happens here. `local/retire-slot.R` refuses any slot still listed in
# `local.rpkgs_slots` in cdn.tf, so this pipeline cannot delete a live slot
# however it is invoked.
#
# Dry run unless RETIRE_APPLY is 'yes'. The dry run reports the object count,
# which is the number worth looking at before deleting a five-figure prefix.
#
# crow pipeline create devxy/build-cran-binaries --branch main \
# --var retire_slot=alpine322 --var RETIRE_APPLY=yes
#
# Retiring a distro retires both architectures: `local.rpkgs_slots` is a
# setproduct over both, so there is no way to publish one without the other,
# and the script deletes `amd64/<codename>/` and `arm64/<codename>/` together.
#
# The slot's cron jobs are not in this repository and are not removed here. The
# script prints them by name, with the API call, at the end of the run.
variables:
# A manual pipeline creation instantiates every file in .crow/, so the
# default must be a value the script never accepts.
retire_slot:
description: "Codename of the slot to retire (e.g. alpine322), or 'none'."
default: none
RETIRE_APPLY:
description: "Set to 'yes' to delete. Anything else reports and changes nothing."
options:
- 'no'
- 'yes'
default: 'no'
when:
- event: manual
evaluate: 'retire_slot != "none"'
skip_clone: true
labels:
group: rpkgs-amd64
steps:
- name: 'Delete the retired slot from the bucket'
image: reg.devxy.io/rpkgs/build-env-alpine:3.24
pull: true
environment:
OTEL_R_TRACES_EXPORTER: none
OTEL_R_LOGS_EXPORTER: none
OTEL_R_METRICS_EXPORTER: none
B2_S3_ACCESS_KEY:
from_secret: B2_S3_ACCESS_KEY
B2_S3_SECRET_KEY:
from_secret: B2_S3_SECRET_KEY
REPO_RO_TOKEN:
from_secret: REPO_RO_TOKEN
R_LIBS_USER: /tmp/R-pkgs
# Pipeline variables are substituted into the YAML, not exported, so they
# have to be bound here to be readable as env vars in the script below.
RETIRE_SLOT: ${retire_slot}
RETIRE_APPLY: ${RETIRE_APPLY}
commands:
- git clone -q https://pat-s:$$REPO_RO_TOKEN@git.devxy.io/devxy/build-cran-binaries.git .
- mkdir -p /tmp/R-pkgs
- /opt/R/4.5.3/bin/Rscript local/install-bincraft.R
- |
set -eu
APPLY=""
if [ "$$RETIRE_APPLY" = "yes" ]; then
APPLY="--apply"
fi
/opt/R/4.5.3/bin/Rscript local/retire-slot.R "$$RETIRE_SLOT" --assets-only $$APPLY
backend_options:
docker:
resources:
requests:
memory: 2Gi
cpu: 1000m