# Targeted (re)build of specific versions of a single package. # Invoked inside a build-env container (see docker/build-one.Dockerfile). # Usage: build-one.R [ ...] # Sensitivity is auto-detected per version via bincraft's ABI classifier: # risky packages go to the per-minor slot, everything else to the generic slot. sink(stdout(), type = "message") options(crayon.enabled = TRUE, future.globals.onReference = NULL) args <- commandArgs(trailingOnly = TRUE) if (length(args) < 2L) { stop("usage: build-one.R [ ...]", call. = FALSE) } package <- args[1L] versions <- args[-1L] library(bincraft, quietly = TRUE) s3 <- list( 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") ) # Clone the CRAN source for a version and ask the ABI classifier whether it # must be rebuilt per R minor. Fails safe to TRUE so a possibly-fragile binary # is never served from the cross-minor generic slot by mistake. classify <- function(pkg, ver) { dest <- file.path(tempdir(), sprintf("classify_%s_%s", pkg, ver)) on.exit(unlink(dest, recursive = TRUE, force = TRUE), add = TRUE) tryCatch( { system2( "git", c( "clone", "-q", "--branch", ver, sprintf("https://github.com/cran/%s", pkg), dest ) ) isTRUE(as.logical(bincraft::needs_per_minor_recompile(dest))) }, error = function(e) { message(sprintf( "classify failed for %s %s: %s; treating as r-minor-sensitive", pkg, ver, conditionMessage(e) )) TRUE } ) } minor <- paste( R.version$major, strsplit(R.version$minor, ".", fixed = TRUE)[[1L]][1L], sep = "." ) touched_generic <- FALSE touched_minor <- FALSE for (ver in versions) { sensitive <- classify(package, ver) cat(sprintf( "Building %s %s (r_minor_sensitive=%s, R %s)\n", package, ver, sensitive, minor )) bincraft::build_binary_package( package, tag = ver, is_r_minor_sensitive = sensitive, force = TRUE, upload = TRUE, archive = TRUE, store_build_metadata = TRUE, s3_endpoint = s3$s3_endpoint, s3_region = s3$s3_region, s3_bucket = s3$s3_bucket, s3_access_key_id = s3$s3_access_key_id, s3_secret_access_key = s3$s3_secret_access_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 ) if (sensitive) touched_minor <- TRUE else touched_generic <- TRUE } # Refresh the PACKAGES index for each slot we wrote to, so the (re)built binary # is immediately resolvable by clients. codename <- bincraft::set_codename(NULL) if (touched_generic) { cat("Refreshing generic index\n") bincraft::upload_package_index( codename = codename, s3_endpoint = s3$s3_endpoint, s3_region = s3$s3_region, s3_bucket = s3$s3_bucket, s3_access_key_id = s3$s3_access_key_id, s3_secret_access_key = s3$s3_secret_access_key ) } if (touched_minor) { cat(sprintf("Refreshing per-minor index %s\n", minor)) bincraft::upload_package_index( codename = codename, r_minor = minor, s3_endpoint = s3$s3_endpoint, s3_region = s3$s3_region, s3_bucket = s3$s3_bucket, s3_access_key_id = s3$s3_access_key_id, s3_secret_access_key = s3$s3_secret_access_key ) }