# Rebuild specific packages into a per-R-minor slot. # # The per-minor scheme only ever covered packages that passed through the build # pipeline after it existed. A package built into the flat slot before that, and # never updated on CRAN since, is never reclassified and never gets a per-minor # copy - so the union index serves its flat binary to every minor. When that # binary references a symbol the client's R no longer exports, the install fails # at dyn.load(): # # base64enc.so: undefined symbol: SETLENGTH # # base64enc calls SETLENGTH, its flat binary was built under R 4.4.3, and R 4.6 # does not export SETLENGTH. There was no way to rebuild one package into one # minor from CI, only `just rebuild` from a workstation with the S3 and Postgres # credentials to hand. This adds that path. # # `--sensitive-only` is deliberately NOT passed. That flag gates on the source # classifier, which misses Rcpp: the repair therefore skipped Rcpp entirely, # leaving its 4.5-built flat binary as the only copy and breaking every R 4.4 # client on the slot. # # Since bincraft v5.3.0 the destination is decided by the built binary's symbols # in `upload_single_binary()`, so building unconditionally is safe: a package # that needs a per-minor slot lands there, and one that does not lands in the # flat slot. Skipping before the build is what removed that decision. # # Trigger with the slot and an explicit package list: # # crow pipeline create devxy/build-cran-binaries \ # --var rebuild_abi_gap=ubuntu-2604-amd64 \ # --var ABI_PACKAGES="base64enc@0.1-6 lobstr@1.2.1" \ # --var ABI_R_MINOR=4.6 variables: # A manual pipeline creation instantiates every file in .crow/, so the # default must match no matrix row. rebuild_abi_gap: description: "Rebuild target: a specific -, 'all' for every slot, or 'none'." options: - none - all - alpine-323-amd64 - alpine-323-arm64 - alpine-324-amd64 - alpine-324-arm64 - redhat-8-amd64 - redhat-8-arm64 - redhat-9-amd64 - redhat-9-arm64 - redhat-10-amd64 - redhat-10-arm64 - ubuntu-2204-amd64 - ubuntu-2204-arm64 - ubuntu-2404-amd64 - ubuntu-2404-arm64 - ubuntu-2604-amd64 - ubuntu-2604-arm64 default: none ABI_PACKAGES: description: 'Space-separated package@version list, e.g. "base64enc@0.1-6 lobstr@1.2.1".' default: '' ABI_R_MINOR: description: 'The R minor to build into.' options: - '4.4' - '4.5' - '4.6' default: '4.6' when: - event: manual evaluate: 'rebuild_abi_gap == "all" || rebuild_abi_gap == "${OS}-${ARCH}"' skip_clone: true labels: group: rpkgs-${ARCH} matrix: include: - OS: alpine-323 ARCH: amd64 R_VERSION: 4.5.3 IMG: alpine:3.23 - OS: alpine-323 ARCH: arm64 R_VERSION: 4.5.3 IMG: alpine:3.23 - OS: alpine-324 ARCH: amd64 R_VERSION: 4.5.3 IMG: alpine:3.24 - OS: alpine-324 ARCH: arm64 R_VERSION: 4.5.3 IMG: alpine:3.24 - OS: redhat-8 ARCH: amd64 R_VERSION: 4.4.3 IMG: redhat:8 - OS: redhat-8 ARCH: arm64 R_VERSION: 4.4.3 IMG: redhat:8 - OS: redhat-9 ARCH: amd64 R_VERSION: 4.4.3 IMG: redhat:9 - OS: redhat-9 ARCH: arm64 R_VERSION: 4.4.3 IMG: redhat:9 - OS: redhat-10 ARCH: amd64 R_VERSION: 4.5.3 IMG: redhat:10 - OS: redhat-10 ARCH: arm64 R_VERSION: 4.5.3 IMG: redhat:10 - OS: ubuntu-2204 ARCH: amd64 R_VERSION: 4.4.3 IMG: ubuntu:jammy - OS: ubuntu-2204 ARCH: arm64 R_VERSION: 4.4.3 IMG: ubuntu:jammy - OS: ubuntu-2404 ARCH: amd64 R_VERSION: 4.4.3 IMG: ubuntu:noble - OS: ubuntu-2404 ARCH: arm64 R_VERSION: 4.4.3 IMG: ubuntu:noble - OS: ubuntu-2604 ARCH: amd64 R_VERSION: 4.4.3 IMG: ubuntu:resolute - OS: ubuntu-2604 ARCH: arm64 R_VERSION: 4.4.3 IMG: ubuntu:resolute steps: - name: 'Rebuild packages into the per-minor slot' image: reg.devxy.io/rpkgs/build-env-${IMG} pull: true environment: OTEL_R_TRACES_EXPORTER: none OTEL_R_LOGS_EXPORTER: none OTEL_R_METRICS_EXPORTER: none RED_HAT_DEV_PW: from_secret: RED_HAT_DEV_PW B2_S3_ACCESS_KEY: from_secret: B2_S3_ACCESS_KEY B2_S3_SECRET_KEY: from_secret: B2_S3_SECRET_KEY PGPASS: from_secret: PGPASS REPO_RO_TOKEN: from_secret: REPO_RO_TOKEN GITHUB_PAT: from_secret: GITHUB_PAT GIT_USER: pat-s # 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. ABI_PACKAGES: ${ABI_PACKAGES} ABI_R_MINOR: ${ABI_R_MINOR} UVR_CACHE_DIR: /tmp/uvr/cache UVR_PACKAGES_DIR: /tmp/uvr/packages CCACHE_DIR: /tmp/ccache NCPUS: 2 commands: - git clone -q https://pat-s:$$REPO_RO_TOKEN@git.devxy.io/devxy/build-cran-binaries.git . - mkdir -p $UVR_CACHE_DIR $UVR_PACKAGES_DIR $CCACHE_DIR - | set -eu if [ -z "$$ABI_PACKAGES" ]; then echo "ABI_PACKAGES is empty; nothing to rebuild." >&2 exit 1 fi RBIN=$(ls -d /opt/R/$${ABI_R_MINOR}*/bin 2>/dev/null | head -1) if [ -z "$$RBIN" ]; then echo "R $$ABI_R_MINOR is not installed in this image." >&2 exit 1 fi # Container-local library: this workflow mounts no shared cache volume, # so it cannot disturb the build pipeline's per-agent caches. LIB="/tmp/R-pkgs-$$ABI_R_MINOR" mkdir -p "$$LIB" export R_LIBS_USER="$$LIB" rm -rf "$$LIB"/00LOCK-* "$$RBIN/Rscript" local/install-bincraft.R rc=0 for spec in $$ABI_PACKAGES; do pkg=$${spec%@*} ver=$${spec#*@} if [ "$$pkg" = "$$ver" ]; then echo "malformed spec '$$spec'; expected package@version" >&2 rc=1 continue fi echo "=== rebuilding $$pkg $$ver into $$ABI_R_MINOR ===" "$$RBIN/Rscript" local/build-one.R "$$pkg" "$$ver" || rc=1 done exit $$rc backend_options: docker: resources: requests: memory: 5Gi cpu: 1000m