Merge remote-tracking branch 'origin/main' into t3code/smarter-disk-pruning-macmini
# Conflicts: # .crow/build-all-versions-install-deps.yaml # .crow/build-all-versions.yaml
This commit is contained in:
commit
6afa4e2405
25 changed files with 2119 additions and 69 deletions
|
|
@ -62,9 +62,9 @@ steps:
|
|||
GIT_USER: pat-s
|
||||
R_VERSION: 4.5.3
|
||||
commands:
|
||||
- /opt/R/$R_VERSION/bin/R -q -e 'if (!requireNamespace("bincraft", quietly = TRUE) || packageVersion("bincraft") != "4.2.2") pak::pak("git::https://codefloe.com/rpkgs/bincraft.git@v4.2.2", dependencies = TRUE)'
|
||||
- /opt/R/$R_VERSION/bin/Rscript local/install-bincraft.R
|
||||
- /opt/R/$R_VERSION/bin/R -q -e 'packageVersion("bincraft")'
|
||||
- /opt/R/$R_VERSION/bin/R -q -e 'bincraft::process_unarchived_pkgs(Sys.getenv("CODENAME"), Sys.getenv("ARCH"), workers = 2L)'
|
||||
- /opt/R/$R_VERSION/bin/R -q -e 'bincraft::process_unarchived_pkgs(Sys.getenv("CODENAME"), Sys.getenv("ARCH"), 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"), workers = 2L)'
|
||||
backend_options:
|
||||
kubernetes:
|
||||
resources:
|
||||
|
|
|
|||
|
|
@ -10,11 +10,22 @@ variables:
|
|||
- arm64
|
||||
default: amd64
|
||||
OS:
|
||||
description: 'Base OS image name (e.g. alpine, redhat, ubuntu).'
|
||||
description: "Base OS image name."
|
||||
options:
|
||||
- alpine
|
||||
- redhat
|
||||
- ubuntu
|
||||
default: alpine
|
||||
OS_VERSION:
|
||||
description: 'OS version / image tag (e.g. 3.24, 9, jammy, noble).'
|
||||
default: '3.24'
|
||||
description: "OS image tag. Must match OS (alpine: 3.24; redhat: 8/9/10; ubuntu: jammy/noble)."
|
||||
options:
|
||||
- "3.24"
|
||||
- "8"
|
||||
- "9"
|
||||
- "10"
|
||||
- "jammy"
|
||||
- "noble"
|
||||
default: "3.24"
|
||||
R_VERSION:
|
||||
description: 'Primary R version under /opt/R.'
|
||||
options:
|
||||
|
|
@ -42,6 +53,9 @@ steps:
|
|||
image: 'reg.devxy.io/rpkgs/build-env-${OS}:${OS_VERSION}'
|
||||
pull: true
|
||||
environment:
|
||||
OTEL_R_TRACES_EXPORTER: none
|
||||
OTEL_R_LOGS_EXPORTER: none
|
||||
OTEL_R_METRICS_EXPORTER: none
|
||||
REPO_RO_TOKEN:
|
||||
from_secret: REPO_RO_TOKEN
|
||||
GITHUB_PAT:
|
||||
|
|
@ -66,8 +80,9 @@ steps:
|
|||
- rm -rf /mnt/cache/pkgcache/R/pkgcache/_metadata/patched-* /mnt/cache/pkgcache/R/pkgcache/_metadata/pkgs-*.rds || true
|
||||
- mkdir -p /mnt/cache/pkgcache /mnt/cache/R-pkgs /mnt/cache/ccache /mnt/cache/packages
|
||||
- git clone -q https://pat-s:$$REPO_RO_TOKEN@git.devxy.io/devxy/build-cran-binaries.git .
|
||||
- git clone -q https://codefloe.com/rpkgs/bincraft.git /tmp/bincraft
|
||||
- /opt/R/$R_VERSION/bin/R -q -e 'pak::sysreqs_db_update(); pak::local_install("/tmp/bincraft"); pak::pak(c("RPostgres", "s3fs", "data.table", "future", "jsonlite")); packageVersion("bincraft")'
|
||||
# Pin the same bincraft version the build steps use, so the precomputed
|
||||
# snapshot and the per-agent library stay consistent across the pipeline.
|
||||
- /opt/R/$R_VERSION/bin/R -q -e 'pak::sysreqs_db_update(); source("local/install-bincraft.R"); pak::pak(c("RPostgres", "s3fs", "data.table", "future", "jsonlite")); packageVersion("bincraft")'
|
||||
- /opt/R/$R_VERSION/bin/R -q -e "source('local/packages-to-build.R'); saveRDS(pkgs, '/mnt/cache/packages/pkgs_to_build.rds'); saveRDS(pkgs[r_minor_sensitive == TRUE], '/mnt/cache/packages/r_minor_sensitive_pkgs.rds'); sprintf('Precomputed %s package versions (%s r-minor-sensitive)', nrow(pkgs), nrow(pkgs[r_minor_sensitive == TRUE]))"
|
||||
backend_options:
|
||||
docker:
|
||||
|
|
|
|||
|
|
@ -11,11 +11,25 @@ variables:
|
|||
- arm64
|
||||
default: amd64
|
||||
OS:
|
||||
description: 'Base OS image name (e.g. alpine, redhat, ubuntu).'
|
||||
description: "Base OS image name."
|
||||
options:
|
||||
- alpine
|
||||
- redhat
|
||||
- ubuntu
|
||||
default: alpine
|
||||
OS_VERSION:
|
||||
description: 'OS version / image tag (e.g. 3.24, 9, jammy, noble).'
|
||||
default: '3.24'
|
||||
description: "OS image tag. Must match OS (alpine: 3.24; redhat: 8/9/10; ubuntu: jammy/noble)."
|
||||
options:
|
||||
- "3.22"
|
||||
- "3.23"
|
||||
- "3.24"
|
||||
- "8"
|
||||
- "9"
|
||||
- "10"
|
||||
- "jammy"
|
||||
- "noble"
|
||||
- "resolute"
|
||||
default: "3.24"
|
||||
R_VERSION:
|
||||
description: 'Primary R version under /opt/R.'
|
||||
options:
|
||||
|
|
@ -76,6 +90,9 @@ steps:
|
|||
image: 'reg.devxy.io/rpkgs/build-env-${OS}:${OS_VERSION}'
|
||||
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:
|
||||
|
|
@ -105,6 +122,14 @@ steps:
|
|||
# growth is bounded separately by trim_pkgcache_metadata() in build-all.R.
|
||||
- rm -rf /mnt/cache/pkgcache/R/pkgcache/_metadata/patched-* /mnt/cache/pkgcache/R/pkgcache/_metadata/pkgs-*.rds || true
|
||||
- mkdir -p /mnt/cache/pkgcache /mnt/cache/R-pkgs /mnt/cache/ccache /mnt/cache/packages
|
||||
# The primary pass must not rely on build-all-versions-install-deps having
|
||||
# run on *this* agent: depends_on only orders the steps, but the cache
|
||||
# volume is per-agent, so a job landing on an agent where install-deps did
|
||||
# not run would otherwise use a stale bincraft (which resolves `platform`
|
||||
# to a zero-length value and breaks every metadata query and the sysdeps
|
||||
# install). Pin bincraft here, exactly like the R-minor pass below.
|
||||
- rm -rf /mnt/cache/R-pkgs/00LOCK-*
|
||||
- /opt/R/$R_VERSION/bin/Rscript local/install-bincraft.R
|
||||
- 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
|
||||
- $XVFB $XVFB_ARGS -n $SPLIT_INDEX -- /opt/R/$R_VERSION/bin/Rscript local/build-all.R $SPLIT_INTO $SPLIT_INDEX $NCPUS 2>&1
|
||||
- |
|
||||
|
|
@ -116,11 +141,12 @@ steps:
|
|||
echo "=== R-minor-sensitive pass under R $RV ==="
|
||||
LIB="/mnt/cache/R-pkgs-$RMINOR"
|
||||
mkdir -p "$LIB"
|
||||
R_LIBS_USER="$LIB" "$(dirname "$RBIN")/R" -q -e 'if (!requireNamespace("bincraft", quietly = TRUE) || packageVersion("bincraft") != "4.2.2") pak::pak("git::https://codefloe.com/rpkgs/bincraft.git@v4.2.2")' || true
|
||||
R_LIBS_USER="$LIB" "$(dirname "$RBIN")/Rscript" local/install-bincraft.R || true
|
||||
R_LIBS_USER="$LIB" $XVFB $XVFB_ARGS -n $SPLIT_INDEX -- "$(dirname "$RBIN")/Rscript" local/build-all.R --sensitive-only $SPLIT_INTO $SPLIT_INDEX $NCPUS 2>&1 || true
|
||||
done
|
||||
# archive missed packages
|
||||
- /opt/R/$R_VERSION/bin/R -q -e "bincraft::process_unarchived_pkgs(paste(Sys.getenv('OS'), Sys.getenv('OS_VERSION')), Sys.getenv('ARCH'), workers = $NCPUS)"
|
||||
# archive missed packages; first arg is the codename (e.g. "alpine324"),
|
||||
# derived via bincraft like the upload step, not paste(OS, OS_VERSION).
|
||||
- /opt/R/$R_VERSION/bin/R -q -e "bincraft::process_unarchived_pkgs(bincraft::set_codename(NULL), Sys.getenv('ARCH'), 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'), workers = $NCPUS)"
|
||||
backend_options:
|
||||
docker:
|
||||
resources:
|
||||
|
|
@ -134,6 +160,9 @@ steps:
|
|||
image: 'reg.devxy.io/rpkgs/build-env-${OS}:${OS_VERSION}'
|
||||
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:
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ variables:
|
|||
- alpine-322-arm64
|
||||
- alpine-323-amd64
|
||||
- alpine-323-arm64
|
||||
- alpine-324-amd64
|
||||
- alpine-324-arm64
|
||||
- redhat-8-amd64
|
||||
- redhat-8-arm64
|
||||
- redhat-9-amd64
|
||||
|
|
@ -25,6 +27,8 @@ variables:
|
|||
- ubuntu-2204-arm64
|
||||
- ubuntu-2404-amd64
|
||||
- ubuntu-2404-arm64
|
||||
- ubuntu-2604-amd64
|
||||
- ubuntu-2604-arm64
|
||||
default: all
|
||||
|
||||
when:
|
||||
|
|
@ -64,6 +68,18 @@ matrix:
|
|||
IMG: alpine:3.24
|
||||
OS_ID: alpine323
|
||||
PROCESS_NEW: "FALSE"
|
||||
- OS: alpine-324
|
||||
ARCH: amd64
|
||||
R_VERSION: 4.5.3
|
||||
IMG: alpine:3.24
|
||||
OS_ID: alpine324
|
||||
PROCESS_NEW: "FALSE"
|
||||
- OS: alpine-324
|
||||
ARCH: arm64
|
||||
R_VERSION: 4.5.3
|
||||
IMG: alpine:3.24
|
||||
OS_ID: alpine324
|
||||
PROCESS_NEW: "FALSE"
|
||||
- OS: redhat-8
|
||||
ARCH: amd64
|
||||
R_VERSION: 4.4.3
|
||||
|
|
@ -124,12 +140,27 @@ matrix:
|
|||
IMG: ubuntu:noble
|
||||
OS_ID: noble
|
||||
PROCESS_NEW: "TRUE"
|
||||
- OS: ubuntu-2604
|
||||
ARCH: amd64
|
||||
R_VERSION: 4.5.3
|
||||
IMG: ubuntu:resolute
|
||||
OS_ID: resolute
|
||||
PROCESS_NEW: "TRUE"
|
||||
- OS: ubuntu-2604
|
||||
ARCH: arm64
|
||||
R_VERSION: 4.5.3
|
||||
IMG: ubuntu:resolute
|
||||
OS_ID: resolute
|
||||
PROCESS_NEW: "TRUE"
|
||||
|
||||
steps:
|
||||
- name: 'Processing Updates'
|
||||
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:
|
||||
|
|
@ -164,13 +195,13 @@ steps:
|
|||
commands:
|
||||
- git clone -q https://pat-s:$$REPO_RO_TOKEN@git.devxy.io/devxy/build-cran-binaries.git .
|
||||
- rm -rf /mnt/cache/R-pkgs/00LOCK-* /mnt/cache/R-pkgs/bincraft /mnt/cache/R-pkgs/pkgcache /mnt/cache/pkgcache/R/pkgcache
|
||||
- /opt/R/$R_VERSION/bin/R -q -e 'if (!requireNamespace("bincraft", quietly = TRUE) || packageVersion("bincraft") != "4.2.2") pak::pak("git::https://codefloe.com/rpkgs/bincraft.git@v4.2.2")'
|
||||
- /opt/R/$R_VERSION/bin/Rscript local/install-bincraft.R
|
||||
- /opt/R/$R_VERSION/bin/R -q -e 'packageVersion("bincraft")'
|
||||
- mkdir -p /mnt/cache/pkgcache /mnt/cache/R-pkgs /mnt/cache/ccache /mnt/cache/packages
|
||||
# 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
|
||||
# options(future.globals.onReference = NULL): for some reason s3fs::file_delete() throws 'Error: Detected a non-exportable reference ('externalptr') in one of the globals ('FUN' of class 'function') used in the future expression' otherwise
|
||||
- $XVFB $XVFB_ARGS -- /opt/R/$R_VERSION/bin/R -q -e "options(crayon.enabled = TRUE, Ncpus = 4, future.globals.onReference = 'error', repos = structure(c(getOption('repos'),INLA='https://inla.r-inla-download.org/R/stable'))); progressr::handlers('cli'); progressr::handlers(global = TRUE); options(future.globals.onReference = NULL); bincraft::process_cran_updates(interval = $INTERVAL, platform = '${OS}', process_updated = TRUE, process_new = ${PROCESS_NEW}, process_removed = TRUE, r_minor_detection = 'classifier', 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)"
|
||||
- $XVFB $XVFB_ARGS -- /opt/R/$R_VERSION/bin/R -q -e "options(crayon.enabled = TRUE, Ncpus = 4, future.globals.onReference = 'error', repos = structure(c(getOption('repos'),INLA='https://inla.r-inla-download.org/R/stable'))); progressr::handlers('cli'); progressr::handlers(global = TRUE); options(future.globals.onReference = NULL); bincraft::process_cran_updates(interval = $INTERVAL, platform = '${OS}', process_updated = TRUE, process_new = ${PROCESS_NEW}, process_removed = TRUE, patches = 'local/patches', r_minor_detection = 'classifier',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)"
|
||||
- |
|
||||
PRIMARY_MINOR=$(echo "$R_VERSION" | cut -d. -f1-2)
|
||||
for RBIN in /opt/R/[0-9]*/bin/R; do
|
||||
|
|
@ -180,8 +211,8 @@ steps:
|
|||
echo "=== R-minor-sensitive update pass under R $RV ==="
|
||||
LIB="/mnt/cache/R-pkgs-$RMINOR"
|
||||
mkdir -p "$LIB"
|
||||
R_LIBS_USER="$LIB" "$(dirname "$RBIN")/R" -q -e 'if (!requireNamespace("bincraft", quietly = TRUE) || packageVersion("bincraft") != "4.2.2") pak::pak("git::https://codefloe.com/rpkgs/bincraft.git@v4.2.2")' || 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, 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
|
||||
R_LIBS_USER="$LIB" "$(dirname "$RBIN")/Rscript" local/install-bincraft.R || 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"))'
|
||||
- |
|
||||
|
|
@ -202,6 +233,9 @@ steps:
|
|||
- name: Purge CDN cache
|
||||
image: reg.devxy.io/docker.io/library/alpine:3.24
|
||||
environment:
|
||||
OTEL_R_TRACES_EXPORTER: none
|
||||
OTEL_R_LOGS_EXPORTER: none
|
||||
OTEL_R_METRICS_EXPORTER: none
|
||||
BUNNYNET_API_KEY:
|
||||
from_secret: BUNNYNET_API_KEY
|
||||
SUBDOMAIN1: 'cran.devxy.io'
|
||||
|
|
|
|||
|
|
@ -103,6 +103,9 @@ steps:
|
|||
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:
|
||||
|
|
@ -129,12 +132,12 @@ steps:
|
|||
- git clone -q https://pat-s:$$REPO_RO_TOKEN@git.devxy.io/devxy/build-cran-binaries.git .
|
||||
- mkdir -p /mnt/cache/pkgcache /mnt/cache/R-pkgs /mnt/cache/ccache /mnt/cache/packages
|
||||
- rm -rf /mnt/cache/R-pkgs/00LOCK-*
|
||||
- /opt/R/$R_VERSION/bin/R -q -e 'if (!requireNamespace("bincraft", quietly = TRUE) || packageVersion("bincraft") != "4.2.2") pak::pak("git::https://codefloe.com/rpkgs/bincraft.git@v4.2.2")'
|
||||
- /opt/R/$R_VERSION/bin/Rscript local/install-bincraft.R
|
||||
- /opt/R/$R_VERSION/bin/R -q -e 'packageVersion("bincraft")'
|
||||
- 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
|
||||
- /opt/R/$R_VERSION/bin/R -q -e 'pak::pak("httr2")'
|
||||
- /opt/R/$R_VERSION/bin/R -q -e 'source("local/fetch-rebuild-packages-from-issue.R")'
|
||||
- $XVFB $XVFB_ARGS -- /opt/R/$R_VERSION/bin/R -q -e "sink(stdout(), type = 'message'); options(crayon.enabled = TRUE, Ncpus = $NCPUS, future.globals.onReference = NULL); pkgs <- readLines('/tmp/rebuild_pkgs.txt'); if (length(pkgs) == 0) { cat('Nothing to rebuild\n'); q('no') }; excluded <- jsonlite::fromJSON('local/excluded-packages.json')[['package']]; pkgs <- setdiff(pkgs, excluded); cat(sprintf('Rebuilding %d packages\n', length(pkgs))); n <- length(pkgs); for (i in seq_along(pkgs)) { x <- pkgs[i]; cat(sprintf('[%d/%d] %s\n', i, n, x)); tryCatch(bincraft::build_binary_package(x, tag_limit = 1L, 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), error = function(e) cat(sprintf('ERROR building %s - %s\n', x, conditionMessage(e)))) }" 2>&1
|
||||
- $XVFB $XVFB_ARGS -- /opt/R/$R_VERSION/bin/R -q -e "sink(stdout(), type = 'message'); options(crayon.enabled = TRUE, Ncpus = $NCPUS, future.globals.onReference = NULL); pkgs <- readLines('/tmp/rebuild_pkgs.txt'); if (length(pkgs) == 0) { cat('Nothing to rebuild\n'); q('no') }; excluded <- jsonlite::fromJSON('local/excluded-packages.json')[['package']]; pkgs <- setdiff(pkgs, excluded); cat(sprintf('Rebuilding %d packages\n', length(pkgs))); n <- length(pkgs); for (i in seq_along(pkgs)) { x <- pkgs[i]; cat(sprintf('[%d/%d] %s\n', i, n, x)); tryCatch(bincraft::build_binary_package(x, tag_limit = 1L, patches = 'local/patches', 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), error = function(e) cat(sprintf('ERROR building %s - %s\n', x, conditionMessage(e)))) }" 2>&1
|
||||
backend_options:
|
||||
docker:
|
||||
resources:
|
||||
|
|
|
|||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -99,3 +99,6 @@ docs/
|
|||
local/test.R
|
||||
.DS_Store
|
||||
docs/
|
||||
|
||||
# Superpowers SDD scratch (briefs, reports, ledger)
|
||||
.superpowers/
|
||||
|
|
|
|||
|
|
@ -2,3 +2,6 @@
|
|||
ignores:
|
||||
- LICENSE.md
|
||||
- docs/superpowers/**
|
||||
# Internal design docs (specs/plans) are not user-facing reference material.
|
||||
- specs/**
|
||||
- plans/**
|
||||
|
|
|
|||
|
|
@ -16,19 +16,19 @@ repos:
|
|||
args:
|
||||
- --markdown-linebreak-ext=md
|
||||
- repo: https://github.com/DavidAnson/markdownlint-cli2
|
||||
rev: v0.22.1
|
||||
rev: v0.23.0
|
||||
hooks:
|
||||
- id: markdownlint-cli2
|
||||
- repo: https://github.com/rbubley/mirrors-prettier
|
||||
rev: v3.8.4
|
||||
rev: v3.9.4
|
||||
hooks:
|
||||
- id: prettier
|
||||
- repo: https://github.com/posit-dev/air-pre-commit
|
||||
rev: 0.9.0
|
||||
rev: 0.10.0
|
||||
hooks:
|
||||
- id: air-format
|
||||
- repo: https://github.com/editorconfig-checker/editorconfig-checker
|
||||
rev: v3.7.0
|
||||
rev: v3.8.0
|
||||
hooks:
|
||||
- id: editorconfig-checker
|
||||
- repo: https://github.com/adrienverge/yamllint.git
|
||||
|
|
@ -43,3 +43,9 @@ repos:
|
|||
entry: YAML filenames must have .yaml extension.
|
||||
language: fail
|
||||
files: .yml$
|
||||
- id: validate-patches
|
||||
name: validate patch registry
|
||||
entry: Rscript local/validate-patches.R
|
||||
language: system
|
||||
files: ^local/(patches/|validate-patches\.R$)
|
||||
pass_filenames: false
|
||||
|
|
|
|||
72
.terraform.lock.hcl
generated
72
.terraform.lock.hcl
generated
|
|
@ -38,43 +38,43 @@ provider "registry.opentofu.org/hashicorp/http" {
|
|||
}
|
||||
|
||||
provider "registry.terraform.io/bunnyway/bunnynet" {
|
||||
version = "0.14.3"
|
||||
constraints = "~> 0.14"
|
||||
version = "0.15.1"
|
||||
constraints = "~> 0.15"
|
||||
hashes = [
|
||||
"h1:2VmbbvV/3fVb/dHZ5m3CxSPoptpn/PuhvSgV/RA9Ae8=",
|
||||
"h1:4MANuttWPyJGZlfbx5P4i2Jpbmvda1tfWgd3olK2nhY=",
|
||||
"h1:AsSfDvm6flYQgjFnFVaRPv7v1/P5pj36dQ4N103Nw+A=",
|
||||
"h1:D2AK5psWQmZqrOHsbeV70OP/zcG92i++AmGKBz/HVMA=",
|
||||
"h1:DpJWi/bhHoZa/ccy2YB/c7HJjTlR6CuZBxGFCxU2uJk=",
|
||||
"h1:Iz47FCzHBOZC1RrTxKwJwKsH6bdEvdYtO0+RBpbmz8I=",
|
||||
"h1:RJQm4qEfljAmcJaFf45uXwUhtbRTwfDuiUWZ6Q7X+Cw=",
|
||||
"h1:YQBi0MRW+dOfkxQYbjKkzDm7UIcc2FeFm8Cck+W3kgs=",
|
||||
"h1:bWq/zJ2Chr5TNuz9y3eaGmzrmXsX30pl5HkGpxE1kVM=",
|
||||
"h1:hwzEskDnFHaJFvKNAGv/wIxRT2SHcXLfwmBb8XNspq4=",
|
||||
"h1:jGggry0lZmG0S0inM7Odae3275na9Gp3O97ZlvBiA2s=",
|
||||
"h1:mJdpVc9qOpqXcPpptWfAET8qloo6qFMb+NzHesazybk=",
|
||||
"h1:nbpkaopSGlmxkKLtNe9sKx9IqojoicD1+hNRdaYd5ok=",
|
||||
"h1:pwuoUqikuVOut3RtPTnu6pNoDnyeXlEX7Rfb2Hr1Ch0=",
|
||||
"h1:u0naFiWGrBVhI3AsUb/ZfS5N/GeiRk0ZkxjHtA10lF0=",
|
||||
"h1:uozoSPzZ7MJIHj5O62W8n86NIfH4JtF7GvMNI6rKlrM=",
|
||||
"h1:vDS308OeXVVgjojMCAAEQ1VshmOLjwra7obliKB5fv8=",
|
||||
"zh:23200ad919df4c44a720c667c536d3a0ae0c235e1f7b53b9e56f88005bf01891",
|
||||
"zh:2fe5445f578c6a244995538fde6dd7ef0dd5f3969686cba3d91fcf28ea31278d",
|
||||
"zh:3a5a8139ed177ccbee74feb4d19c881e18723e4bf3a64b6d35931420402a2a1a",
|
||||
"zh:5189bd6c03ec3c428185992f519f3bf520d4e9eba8771c240814adbecdf60140",
|
||||
"zh:532ac8eb94a84ccf046d4cb4eded825269effdbb7597f392f848fbfad5dcae1d",
|
||||
"zh:5f100279d73ce998c7bf4ffa2bbcd617ee307bf51c4a94146f210aeec268c4d0",
|
||||
"zh:80cb58abd2e431386ab1b6ad186a6e6e5347448993bacc831c0251b9016445b9",
|
||||
"h1:/2NUpbtjkc+w6n5V3kGP0rSzGjN0K2Wdfe2K+CZdmhU=",
|
||||
"h1:1TOrpmCR0aT5xX1sjt70zqlYkMJnVe6r0nx2B0DS/mE=",
|
||||
"h1:4uC8r8ILr+vZJ230uGqIUaWQ7uORCrIzoEuYrAq2JuE=",
|
||||
"h1:6b+2osJUfwcaYZ6mathLPf/58sr/4XkLXQrcSufnkMk=",
|
||||
"h1:CPldfjf79QS8mIP+GWoS0FVhrFlyjvN2+39zfyP76Ik=",
|
||||
"h1:EvXICHyGIKpoYlDeKHOPzfmpvdRdhgsOMcR2nb6+tKY=",
|
||||
"h1:GZLq+nDxS1CyBH0ELGTSQj9X7ozemJ1jpPA4KwbtR+c=",
|
||||
"h1:ISNFqL745IQgZ6yMLy8ofV8ixbYqZYa9JKdi2W3pmNk=",
|
||||
"h1:IrNrEuvFd0nYDGQefwmT8d1CSJb9e8LN5w9vw1ODp7E=",
|
||||
"h1:Ms79slY9bZ94+n4cwIHvI9+/cvbucwo6S1+z5KAiznw=",
|
||||
"h1:NWA9XSEBcpSkgwwIvl6tHrxGQY3uYhqNS4Vnb9RLyLQ=",
|
||||
"h1:UjvxxxggicLtiE3yTe1Gx0oLUTeZpWmgIfXuHzWHn1c=",
|
||||
"h1:VgJjo14DGkU4Jwo4D3GT4/5sq1tdjiZscKS5l3cb890=",
|
||||
"h1:dBu3AW5YNLIvbBIMNk3wUHKw4TW+BDbj34a+mCqYhWE=",
|
||||
"h1:i5oGD06nQ3JRsBIa2u4wCej+ETgp970CFl75dOKkHno=",
|
||||
"h1:mTqR+vD1AWPx+mu7S0/pzBy71z7WOrjH7arOP77PXh4=",
|
||||
"h1:nmTM61G8vYjpofeEqspMORpsNvTGCNZySGfjdXardL0=",
|
||||
"zh:0f9bf5aaa47164a4d6ae4433d5e285a9456a5053401b2bad4ed68622f574ddee",
|
||||
"zh:3039bee421fb8855a919f449fc731d145254371f5f0c39cc4660f3aeed6a8b10",
|
||||
"zh:36664b08186e0c194747b18dee24ed97327c6e704133d4cf0df27abef1652f86",
|
||||
"zh:3c7eae99d8c5ff65dfb99c8b9c1980147282d68971e1ef1ff0f126a6bff59d8f",
|
||||
"zh:5293cc21abf54f4e5745437ca2d40d206aae323b2e1d41cf45dcc63a8868cbb3",
|
||||
"zh:5994e5145e616e7e881010717e4c7def2945eb6d933f62db4ec3167732ccac84",
|
||||
"zh:7994db9ed3fdb6cbf21f2154ea962cf82f04e425988bedc6657de2497d6cb6c3",
|
||||
"zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f",
|
||||
"zh:9ac734c6aae19ea0832269f1f1dc3c3e100855c09b6168eecd8693958515b228",
|
||||
"zh:a0e3b75176c71e5f41a6552cef57ad67d11778cb59fd2eb792e69f662b67ae01",
|
||||
"zh:b4d0e1dd9a80d1ac9a3f1beaefb58d4b944cb0a30bdc672b9037a69b4dc20ec3",
|
||||
"zh:b8309337e966528991cc2dd61ff0247864e4c3c7bef7dcf225f066edb6171050",
|
||||
"zh:c34ce5fcdd481214697505bceb616a7dfcda7702f1afefa7dc5459965b8e01ca",
|
||||
"zh:cb3f662ad06bb86aa763a5644ba318bc3db0ed30b04eb810c478e81f4b012d55",
|
||||
"zh:cf0f0a459e2b6b1e014af9f53f32b5f555a249b61a0dcaccd3e4fe89178d8aa5",
|
||||
"zh:d4dfb653a0295bfbbebcb4bb022b490f2c24ca31287ebf77fe9dcaee2e5ea658",
|
||||
"zh:e49ba31aa092a30ea8a1091f7b26dbe41c3998f924f5b0d82810f27fc2f63501",
|
||||
"zh:ea4d7d5688caf2f9cda3a1721779b61a051db6b43ca7267ae2712bd1262cfcfd",
|
||||
"zh:93aa863e536ba9376ccf9e614e9edc9b214a2ce8c4316d416a8e249b436f52d2",
|
||||
"zh:ab5cb4baeda57559686a0ccf0e09158aa64624ee6ba0ef32b769f13b11a43068",
|
||||
"zh:ae9388b62eede8fd9272407bf75f8241a965bd489d45ec9dd3f9fac696d500e1",
|
||||
"zh:caa5befd16960e2f69c7ec483e228e5ff43ab0979c17f1b874c9ffaa1c7c0e43",
|
||||
"zh:cddd3e1067defa06a4e4ad5cb3940c7943e29c42417de57236aa7d3e2aeaae13",
|
||||
"zh:cdfa44d591d0805116159556947904d70f534c6816188c45cf3a7544d2722ac9",
|
||||
"zh:d607e9f1f3e09f13404f219e1893e3b3c77aece4afb54e999f934c021f41f576",
|
||||
"zh:d8a397aca95125c6a0c0c78d2ded5843b9204effa9f5cf7419f017b500ad9228",
|
||||
"zh:f5499eaff0d221725ad209d27d87c5b46d5c554caad7dc42947c760377abe3b0",
|
||||
"zh:fc5f5cf433abc83e5169fa222992ec521c0c802075970251e3dd2c1d50c4f5c1",
|
||||
]
|
||||
}
|
||||
|
|
|
|||
14
CLAUDE.md
Normal file
14
CLAUDE.md
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# CLAUDE.md
|
||||
|
||||
Crow CI pipelines (`.crow/`) and local tooling (`local/`) that build CRAN binary packages (incl. Alpine/musl) and upload them to Backblaze B2.
|
||||
|
||||
## Conventions
|
||||
|
||||
- **PRs:** the remote is Forgejo on `codefloe.com`; use `fj -H codefloe.com` (not `gh`).
|
||||
- **Storage:** Backblaze B2 bucket `devxy-r-builds` (endpoints configured in the `.crow/` pipelines).
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **B2 requires authentication for the list-bucket API.** Anonymous GET only works for individual public-read objects — an empty listing means missing credentials, not an empty bucket.
|
||||
- Weekly-rebuild pipelines run for hours; watch them as background tasks and fetch Crow logs yourself instead of having the user paste progress.
|
||||
- musl builds of packages with bundled native deps (e.g. RcppParallel/TBB) recur as failures; check for an existing patch before re-deriving a fix.
|
||||
24
README.md
24
README.md
|
|
@ -53,6 +53,28 @@ For every package+tag combination:
|
|||
1. Archive old package versions and keep the latest one in the root
|
||||
1. Delete local binaries after successful upload
|
||||
|
||||
## Patching packages
|
||||
|
||||
Some CRAN packages fail to compile on specific platforms due to compiler- or OS-specific issues unrelated to the package itself.
|
||||
The canonical example is `RcppParallel`, whose bundled TBB sources fail on musl (Alpine) and newer compiler/OS combinations.
|
||||
Because such packages are often transitive dependencies of many others, a single failure cascades: all dependents fail even though nothing is wrong with the dependent itself.
|
||||
|
||||
To address this, frequently-failing packages can be "patched" before they are installed — whether as a direct build target or a transitive dependency pulled in by `pak`.
|
||||
|
||||
The patch registry lives in `local/patches/registry.json`.
|
||||
Each entry specifies a package and the platforms/versions it applies to, along with either lightweight build-time overrides (environment variables, configure arguments, Makevars) or a source diff (for deeper fixes).
|
||||
See `local/patches/README.md` for the complete schema.
|
||||
|
||||
Patching uses a two-tier approach:
|
||||
|
||||
1. **Lightweight overrides:** environment variables, configure arguments, or Makevars settings applied during build — typically version-independent and fast.
|
||||
2. **Source diffs:** unified diff patches applied to the unpacked source before building — more powerful but version-pinned.
|
||||
|
||||
The system is implemented in `bincraft`: when a package needs patching, `bincraft` pre-builds it with the patch and serves the patched binary to `pak`, ensuring transitive dependents receive the fixed package.
|
||||
This way, the fix cascades to all packages that depend on it.
|
||||
|
||||
For the design rationale and architecture, see `specs/2026-06-30-package-patching-design.md`.
|
||||
|
||||
## Build Environment
|
||||
|
||||
Binaries are built on a mixed-architecture Kubernetes cluster using CI.
|
||||
|
|
@ -199,7 +221,7 @@ Tag does not have a NAMESPACE file and hence cannot be built.
|
|||
Dependency not available: Either because the dependency was not declared or errored itself during installation.
|
||||
|
||||
```text
|
||||
In function '\033[01m\033[KRcpp::List solveRRBLUP(const mat&, const mat&, const mat&)\033[m\033[K':\n\033[01m\033[KMME.cpp:162:61:\033[m\033[K \033[01;31m\033[Kerror: \033[m\033[K'\033[01m\033[KPI\033[m\033[K' was not declared in this scope\n 162 | double ll = -0.5*(double(optRes[\"objective\"])+df+df*log(2*\033[01;31m\033[KPI\033[m\033[K/df));\n | \033[01;31m\033[K^~\033[m\033[K\n\033[01m\033[KMME.cpp:\033[m\033[K In function '\033[01m\033[KRcpp::List solveRRBLUPMV(const mat&, const mat&, const mat&, int, double)\033[m\033[K':\n\033[01m\033[KMME.cpp:277:31:\033[m\033[K \033[01;31m\033[Kerror: \033[m\033[K'\033[01m\033[KPI\033[m\033[K' was not declared in this scope; did you mean '\033[01m\033[KHI\033[m\033[K'?\n 277 | ll -= double(n*m)/2.0*log(2*\033[01;31m\033[KPI\033[m\033[K);\n | \033[01;31m\033[K^~\033[m\033[K\n | \033[32m\033[KHI\033[m\033[K\nmake: *** [/opt/R/4.4.1/lib/R/etc/Makeconf:204: MME.o] Error 1\nERROR: compilation failed for package 'AlphaSimR'\n* removing '/tmp/RtmpclI5CE/temp_libpath11135d215d5/AlphaSimR'\n
|
||||
In function '\033[01m\033[KRcpp::List solveRRBLUP(const mat&, const mat&, const mat&)\033[m\033[K':\n\033[01m\033[KMME.cpp:162:61:\033[m\033[K \033[01;31m\033[Kerror: \033[m\033[K'\033[01m\033[KPI\033[m\033[K' was not declared in this scope\n 162 | double ll = -0.5*(double(optRes[\"objective\"])+df+df*log(2*\033[01;31m\033[KPI\033[m\033[K/df));\n | \033[01;31m\033[K^~\033[m\033[K\n\033[01m\033[KMME.cpp:\033[m\033[K In function '\033[01m\033[KRcpp::List solveRRBLUPMV(const mat&, const mat&, const mat&, int, double)\033[m\033[K':\n\033[01m\033[KMME.cpp:277:31:\033[m\033[K \033[01;31m\033[Kerror: \033[m\033[K'\033[01m\033[KPI\033[m\033[K' was not declared in this scope; did you mean '\033[01m\033[KHI\033[m\033[K'?\n 277 | ll -= double(n*m)/2.0*log(2*\033[01;31m\033[KPI\033[m\033[K);\n | \033[01;31m\033[K^~\033[m\033[K\n | \033[32m\033[KHI\033[m\033[K\nmake: *** [/opt/R/4.4.2/lib/R/etc/Makeconf:204: MME.o] Error 1\nERROR: compilation failed for package 'AlphaSimR'\n* removing '/tmp/RtmpclI5CE/temp_libpath11135d215d5/AlphaSimR'\n
|
||||
```
|
||||
|
||||
Compiler error: Possible reasons: too old CXX code which cannot be compiled anymore with CXX14 or CXX17.
|
||||
|
|
|
|||
|
|
@ -16,6 +16,11 @@ ARG CACHEBUST
|
|||
|
||||
WORKDIR /work
|
||||
COPY build-one.R /work/build-one.R
|
||||
# Resolve and install the latest bincraft release dynamically (no hardcoded pin).
|
||||
COPY install-bincraft.R /work/install-bincraft.R
|
||||
# Ship the patch registry so build-one.R's `patches = "local/patches"` resolves
|
||||
# (build context is `local/`, CWD is /work).
|
||||
COPY patches /work/local/patches
|
||||
|
||||
RUN --mount=type=secret,id=b2_access,required=true \
|
||||
--mount=type=secret,id=b2_secret,required=true \
|
||||
|
|
@ -27,6 +32,9 @@ RUN --mount=type=secret,id=b2_access,required=true \
|
|||
export GITHUB_PAT="$(cat /run/secrets/github_pat 2>/dev/null || true)" && \
|
||||
export GIT_TERMINAL_PROMPT=0 && \
|
||||
export OTEL_SDK_DISABLED=true && \
|
||||
export OTEL_R_TRACES_EXPORTER=none && \
|
||||
export OTEL_R_LOGS_EXPORTER=none && \
|
||||
export OTEL_R_METRICS_EXPORTER=none && \
|
||||
XVFB=$(command -v xwfb-run 2>/dev/null || command -v xvfb-run || true); \
|
||||
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; \
|
||||
|
|
@ -37,7 +45,7 @@ RUN --mount=type=secret,id=b2_access,required=true \
|
|||
echo "No working virtual display; building without xvfb" >&2; \
|
||||
fi; \
|
||||
run_build() { if [ "$USE_XVFB" = 1 ]; then $XVFB -a $XVFB_ARGS -- "$@"; else "$@"; fi; }; \
|
||||
ensure_bincraft() { "$1" -q -e 'if (!requireNamespace("bincraft", quietly = TRUE) || packageVersion("bincraft") != "4.2.1") pak::pak("git::https://codefloe.com/rpkgs/bincraft.git@v4.2.1")'; }; \
|
||||
ensure_bincraft() { "$1" -q -e 'source("/work/install-bincraft.R")'; }; \
|
||||
PRIMARY_MINOR=$(echo "$R_VERSION" | cut -d. -f1-2); \
|
||||
seen=" $PRIMARY_MINOR "; \
|
||||
prc=0; failed=""; \
|
||||
|
|
|
|||
41
docker/buildkitd.toml
Normal file
41
docker/buildkitd.toml
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# BuildKit GC config for the remote buildx builders (artemis/amd64, gaia/arm64).
|
||||
#
|
||||
# Apply when creating the docker-container builders:
|
||||
# docker buildx create --name artemis --driver docker-container \
|
||||
# --config docker/buildkitd.toml ssh://<user@host-amd64>
|
||||
# docker buildx create --name gaia --driver docker-container \
|
||||
# --config docker/buildkitd.toml ssh://<user@host-arm64>
|
||||
#
|
||||
# Why: BuildKit's default GC caps the ephemeral cache tier — RUN
|
||||
# --mount=type=cache mounts, local build context, git checkouts — at a
|
||||
# hardcoded 512 MB (shown as "488.3 MiB" in `buildx inspect`). Across our
|
||||
# 7-distro build matrix that fills instantly and forces re-downloads of
|
||||
# system + R packages every rebuild. The first rule below raises that tier.
|
||||
#
|
||||
# Limits are absolute (not %) on purpose: artemis and gaia have very
|
||||
# different free space (Hetzner ~42 GiB free vs Mac mini ~279 GiB), so a
|
||||
# percentage would mean wildly different real budgets. minFreeSpace = 20 GB
|
||||
# keeps the tight Hetzner host safe while staying modest on the Mac mini.
|
||||
|
||||
[worker.oci]
|
||||
gc = true
|
||||
|
||||
# Tier 1 — ephemeral caches (cache mounts, local context, git checkouts).
|
||||
# Raised from the 512 MB default to 8 GB, retained for 7 days so weekly
|
||||
# rebuilds reuse downloaded packages instead of re-fetching them.
|
||||
[[worker.oci.gcpolicy]]
|
||||
filters = [
|
||||
"type==source.local",
|
||||
"type==exec.cachemount",
|
||||
"type==source.git.checkout",
|
||||
]
|
||||
keepDuration = "168h"
|
||||
maxUsedSpace = "8GB"
|
||||
|
||||
# Tier 2 — everything else (image layers, RUN exec results). Bounds the
|
||||
# whole buildkit cache and always leaves 20 GB free on the host disk.
|
||||
[[worker.oci.gcpolicy]]
|
||||
all = true
|
||||
reservedSpace = "2GB"
|
||||
maxUsedSpace = "40GB"
|
||||
minFreeSpace = "20GB"
|
||||
6
justfile
6
justfile
|
|
@ -10,8 +10,10 @@
|
|||
# - buildx builders named `artemis` (amd64) and `gaia` (arm64), created with the
|
||||
# docker-container driver (runs BuildKit on the remote host's docker daemon over
|
||||
# SSH). The default `remote` driver does NOT work with an ssh:// docker host.
|
||||
# docker buildx create --name artemis --driver docker-container ssh://<user@host-amd64>
|
||||
# docker buildx create --name gaia --driver docker-container ssh://<user@host-arm64>
|
||||
# Pass --config docker/buildkitd.toml so BuildKit's GC keeps a usable cache
|
||||
# (the default caps the cache-mount tier at 512 MB, forcing re-downloads).
|
||||
# docker buildx create --name artemis --driver docker-container --config docker/buildkitd.toml ssh://<user@host-amd64>
|
||||
# docker buildx create --name gaia --driver docker-container --config docker/buildkitd.toml ssh://<user@host-arm64>
|
||||
# - exported secrets: B2_S3_ACCESS_KEY, B2_S3_SECRET_KEY, PGPASS (GITHUB_PAT optional)
|
||||
#
|
||||
# Overridable (env or `just VAR=… rebuild …`):
|
||||
|
|
|
|||
|
|
@ -64,12 +64,38 @@ sprintf("# of package versions for this job: %s", nrow(chunk))
|
|||
exclude <- jsonlite::fromJSON("local/excluded-packages.json")[["package"]]
|
||||
chunk <- chunk[!chunk$Package %in% exclude, ]
|
||||
|
||||
# Skip package versions already built in a previous run.
|
||||
# Skip package versions already attempted in a previous run (built or errored).
|
||||
# pkgs_to_build.rds is a static snapshot from the install-deps step, so on a
|
||||
# restart it still lists everything an interrupted run already produced. The
|
||||
# metadata DB reflects that progress, so we re-derive the remaining set here.
|
||||
platform <- paste(Sys.getenv("OS"), gsub("[.]", "", Sys.getenv("OS_VERSION")), sep = "-")
|
||||
arch <- Sys.getenv("ARCH")
|
||||
# We exclude *all* attempted versions, not just successful ones: a previously
|
||||
# errored version is skipped by build_binary_package() anyway, so leaving it in
|
||||
# the chunk only makes the job cycle through it one-by-one for no benefit.
|
||||
# Derive platform + arch from the running container, mirroring the codename ->
|
||||
# platform mapping bincraft uses internally. The OS/OS_VERSION selectors are
|
||||
# workflow-level CI variables that are not injected into the container
|
||||
# environment, so Sys.getenv() would return "" and this pre-filter would query
|
||||
# platform "-" and skip nothing.
|
||||
codename <- bincraft::set_codename(NULL)
|
||||
platform <- switch(
|
||||
codename,
|
||||
jammy = "ubuntu-2204",
|
||||
noble = "ubuntu-2404",
|
||||
resolute = "ubuntu-2604",
|
||||
rhel10 = "redhat-10",
|
||||
rhel9 = "redhat-9",
|
||||
rhel8 = "redhat-8",
|
||||
alpine320 = "alpine-320",
|
||||
alpine321 = "alpine-321",
|
||||
alpine322 = "alpine-322",
|
||||
alpine323 = "alpine-323",
|
||||
alpine324 = "alpine-324",
|
||||
alpine325 = "alpine-325",
|
||||
alpine326 = "alpine-326",
|
||||
NA_character_
|
||||
)
|
||||
local_machine <- Sys.info()[["machine"]]
|
||||
arch <- if (grepl("arm64|aarch64", local_machine)) "arm64" else "amd64"
|
||||
con <- DBI::dbConnect(
|
||||
RPostgres::Postgres(),
|
||||
dbname = "build_metadata",
|
||||
|
|
@ -81,13 +107,13 @@ con <- DBI::dbConnect(
|
|||
)
|
||||
built <- DBI::dbGetQuery(
|
||||
con,
|
||||
"SELECT name, tag FROM single_builds WHERE platform = $1 AND arch = $2 AND error_occurred = FALSE",
|
||||
"SELECT name, tag FROM single_builds WHERE platform = $1 AND arch = $2",
|
||||
params = list(platform, arch)
|
||||
)
|
||||
DBI::dbDisconnect(con)
|
||||
before <- nrow(chunk)
|
||||
chunk <- chunk[!paste(chunk$Package, chunk$Version) %in% paste(built$name, built$tag), ]
|
||||
sprintf("Skipped %d already-built package versions; %d remaining for this job", before - nrow(chunk), nrow(chunk))
|
||||
sprintf("Skipped %d already-attempted package versions; %d remaining for this job", before - nrow(chunk), nrow(chunk))
|
||||
|
||||
# Read pre-computed S3 listing from install-deps step
|
||||
# This avoids loading s3fs/reticulate/Python in the build container,
|
||||
|
|
@ -121,6 +147,7 @@ mapply(
|
|||
metadata_db_sslmode = "require",
|
||||
metadata_db_port = 15432,
|
||||
archive = TRUE,
|
||||
patches = "local/patches",
|
||||
upload = TRUE,
|
||||
store_build_metadata = TRUE
|
||||
)
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ for (ver in versions) {
|
|||
force = TRUE,
|
||||
upload = TRUE,
|
||||
archive = TRUE,
|
||||
patches = "local/patches",
|
||||
store_build_metadata = TRUE,
|
||||
s3_endpoint = s3$s3_endpoint,
|
||||
s3_region = s3$s3_region,
|
||||
|
|
|
|||
52
local/install-bincraft.R
Normal file
52
local/install-bincraft.R
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#!/usr/bin/env Rscript
|
||||
|
||||
# Install the latest tagged bincraft release, resolved dynamically, so the CI
|
||||
# workflows and the build-one image never pin a hardcoded version (no more
|
||||
# editing `@vX.Y.Z` in many places on every release).
|
||||
#
|
||||
# Run with the R whose library should receive bincraft:
|
||||
# Rscript local/install-bincraft.R
|
||||
# or, to target a specific R from a shell loop:
|
||||
# "$RBIN" -q -e 'source("local/install-bincraft.R")'
|
||||
#
|
||||
# How it works: list the remote tags with `git ls-remote` (no token needed for
|
||||
# the public repo), keep the `vX.Y.Z` release tags, pick the highest version,
|
||||
# and install it with pak. pak is idempotent on the git ref, so re-running keeps
|
||||
# the package when it is already current and only updates when a newer tag ships.
|
||||
# Filtering/sorting is done in R (not via git's `--sort`/refspec) so behaviour is
|
||||
# identical across git versions and `system2()` argument handling.
|
||||
|
||||
repo_url <- Sys.getenv(
|
||||
"BINCRAFT_GIT_URL",
|
||||
unset = "https://codefloe.com/rpkgs/bincraft.git"
|
||||
)
|
||||
|
||||
# GIT_TERMINAL_PROMPT=0 keeps a non-interactive run from hanging on auth.
|
||||
refs <- system2(
|
||||
"git",
|
||||
c("ls-remote", "--tags", repo_url),
|
||||
stdout = TRUE,
|
||||
stderr = FALSE,
|
||||
env = "GIT_TERMINAL_PROMPT=0"
|
||||
)
|
||||
tags <- sub(".*refs/tags/", "", refs)
|
||||
tags <- tags[!grepl("\\^\\{\\}$", tags)] # drop dereferenced "...^{}" lines
|
||||
tags <- grep("^v[0-9]", tags, value = TRUE) # only vX.Y.Z release tags
|
||||
if (length(tags) == 0L) {
|
||||
stop(
|
||||
"Could not resolve any bincraft release tag from ",
|
||||
repo_url,
|
||||
call. = FALSE
|
||||
)
|
||||
}
|
||||
latest <- tags[order(package_version(sub("^v", "", tags)), decreasing = TRUE)][
|
||||
1L
|
||||
]
|
||||
|
||||
message(sprintf("Installing latest bincraft release: %s", latest))
|
||||
pak::pak(sprintf("git::%s@%s", repo_url, latest))
|
||||
message(sprintf(
|
||||
"bincraft %s installed (%s)",
|
||||
as.character(utils::packageVersion("bincraft")),
|
||||
latest
|
||||
))
|
||||
43
local/patches/README.md
Normal file
43
local/patches/README.md
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# Patch Registry
|
||||
|
||||
This directory contains the curated registry of per-package build-time patches consumed by bincraft's `patches` argument.
|
||||
|
||||
## Schema
|
||||
|
||||
The registry is defined in `registry.json` as an array of patch entries. Each entry specifies lightweight build-time overrides (environment variables, configure arguments, Makevars) and optionally a source diff to apply before building.
|
||||
|
||||
### Field semantics
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `package` | string | yes | CRAN package name. |
|
||||
| `versions` | string | yes | `"*"` for any, a constraint such as `">=5.1.0"`, or an exact version `"5.1.11-2"`. Env-tier fixes are typically `"*"`; source diffs are normally exact or lower-bounded because a diff is pinned to the source it was generated against. |
|
||||
| `platforms` | array of strings | yes | Matched against the running build's platform tokens — distro family (`alpine`, `ubuntu`, `redhat`), codename (`ubuntu-2604`, `alpine-324`), and arch (`amd64`, `arm64`). An entry matches if any listed token matches any build token. `["*"]` matches all platforms. |
|
||||
| `env` | object | no | Environment variables exported only for this package's isolated build. |
|
||||
| `configure_args` | array | no | Arguments passed as `--configure-args` to the isolated build. |
|
||||
| `makevars` | object | no | Key/value pairs written into a package-local Makevars for the isolated build. |
|
||||
| `patch` | string or null | no | Path (relative to `local/patches/`) to a unified diff applied to the unpacked CRAN source before building. |
|
||||
| `reason` | string | yes | Human explanation, surfaced in logs and metadata. |
|
||||
|
||||
## Adding an entry
|
||||
|
||||
To add a new patch entry:
|
||||
|
||||
1. Add an object to the array in `registry.json` with the fields documented above.
|
||||
Start with lightweight overrides (environment variables, configure arguments, Makevars) before resorting to source diffs.
|
||||
|
||||
2. If a source diff is needed, place it in `local/patches/<package>/<file>.patch` and reference its path in the `patch` field.
|
||||
For example, a diff for `RcppParallel` would go in `local/patches/RcppParallel/fix.patch` and be referenced as `"patch": "RcppParallel/fix.patch"`.
|
||||
|
||||
3. The `reason` field should clearly explain why the patch is needed and what problem it solves.
|
||||
|
||||
## Validation
|
||||
|
||||
The registry is validated and applied by bincraft during the build process.
|
||||
For manual validation, run the validator from the repo root:
|
||||
|
||||
```bash
|
||||
Rscript local/validate-patches.R
|
||||
```
|
||||
|
||||
This validates the schema, referenced patch-file existence, and checks for duplicate entries across platforms and versions.
|
||||
16
local/patches/RcppParallel/disable-tbb.patch
Normal file
16
local/patches/RcppParallel/disable-tbb.patch
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
diff --git a/src/Makevars.in b/src/Makevars.in
|
||||
index be8445f..faee771 100644
|
||||
--- a/src/Makevars.in
|
||||
+++ b/src/Makevars.in
|
||||
@@ -60,7 +60,10 @@ else
|
||||
endif
|
||||
|
||||
ifeq ($(UNAME), Linux)
|
||||
- USE_TBB=Linux
|
||||
+ # bincraft patch: the bundled Intel TBB build hangs/fails on musl (Alpine)
|
||||
+ # and newer toolchains (g++ 15). Skip it (leave USE_TBB unset) and force the
|
||||
+ # TinyThread backend so RcppParallel still builds.
|
||||
+ PKG_CXXFLAGS += -DRCPP_PARALLEL_USE_TBB=0
|
||||
endif
|
||||
|
||||
ifeq ($(UNAME), SunOS)
|
||||
19
local/patches/fs/force-vendored-libuv.patch
Normal file
19
local/patches/fs/force-vendored-libuv.patch
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
diff --git a/configure b/configure
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -11,6 +11,15 @@
|
||||
PKG_TEST_HEADER="<uv.h>"
|
||||
PKG_LIBS="-luv"
|
||||
|
||||
+# bincraft patch: force the vendored static libuv so the resulting binary
|
||||
+# is self-contained. fs configure otherwise links system libuv whenever
|
||||
+# pkg-config finds libuv-devel (installed as a build-time sysreq), yielding
|
||||
+# an fs.so with NEEDED libuv.so.1 that fails to dyn.load on machines lacking
|
||||
+# runtime libuv (install.packages/renv do not install SystemRequirements).
|
||||
+echo "Building static libuv (bincraft: forced vendored)" 1>&2
|
||||
+cp -f src/Makevars.vendor src/Makevars
|
||||
+exit 0
|
||||
+
|
||||
# Use pkg-config if available
|
||||
if [ `command -v pkg-config` ]; then
|
||||
PKGCONFIG_CFLAGS=`pkg-config --cflags --silence-errors ${PKG_CONFIG_NAME}`
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue