Skip to content

Commit

Permalink
build: add build args generate script and args json files [slip ci]
Browse files Browse the repository at this point in the history
  • Loading branch information
eitsupi committed Apr 21, 2024
1 parent 1c255df commit 410a3b2
Show file tree
Hide file tree
Showing 4 changed files with 295 additions and 0 deletions.
11 changes: 11 additions & 0 deletions build/args/4.2.3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"r_version": "4.2.3",
"r_release_date": "2023-03-15",
"r_freeze_date": "2023-04-20",
"ubuntu_series": "jammy",
"cran": "https://p3m.dev/cran/__linux__/jammy/2023-04-20",
"rstudio_version": "2023.03.0+386",
"ctan": "https://www.texlive.info/tlnet-archive/2023/04/20/tlnet",
"r_major_latest": false,
"r_minor_latest": true
}
11 changes: 11 additions & 0 deletions build/args/4.3.2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"r_version": "4.3.2",
"r_release_date": "2023-10-31",
"r_freeze_date": "2024-02-28",
"ubuntu_series": "jammy",
"cran": "https://p3m.dev/cran/__linux__/jammy/2024-02-28",
"rstudio_version": "2023.12.0+369",
"ctan": "https://www.texlive.info/tlnet-archive/2024/02/28/tlnet",
"r_major_latest": false,
"r_minor_latest": false
}
11 changes: 11 additions & 0 deletions build/args/4.3.3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"r_version": "4.3.3",
"r_release_date": "2024-02-29",
"r_freeze_date": null,
"ubuntu_series": "jammy",
"cran": "https://p3m.dev/cran/__linux__/jammy/latest",
"rstudio_version": "2023.12.0+369",
"ctan": "https://mirror.ctan.org/systems/texlive/tlnet",
"r_major_latest": true,
"r_minor_latest": true
}
262 changes: 262 additions & 0 deletions build/scripts/generate-args.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
library(rversions)
library(jsonlite)
library(pak)
library(dplyr, warn.conflicts = FALSE)
library(readr)
library(tibble)
library(httr2)
library(purrr, warn.conflicts = FALSE)
library(glue, warn.conflicts = FALSE)
library(tidyr)
library(stringr)
library(gert)


#' Search the latest P3M CRAN mirror URL for Linux at a given date
#' @param date A single character of date like `"2023-10-30"` or `NA`.
#' If `NA`, the "latest" URL will be returned.
#' @param distro_version_name A character of distro version name like `"focal"`.
#' @param r_version A character of R version like `"4.3.0"`.
#' @return A character of P3M CRAN mirror URL.
#' @examples
#' latest_p3m_cran_url_linux("2023-10-30", "focal", "4.3.0")
#' latest_p3m_cran_url_linux(NA, "focal", "4.3.0")
latest_p3m_cran_url_linux <- function(date, distro_version_name, r_version) {
n_retry_max <- 6

dates_try <- if (is.na(date)) {
NA_real_
} else {
seq(as.Date(date), as.Date(date) - n_retry_max, by = -1)
}

fallback_distro <- if (distro_version_name == "jammy") {
"focal"
} else {
NULL
}

urls_try <- tidyr::expand_grid(
date = dates_try,
distro_version_name = c(distro_version_name, fallback_distro),
type = c("binary")
) |>
purrr::pmap_chr(make_p3m_cran_url_linux) |>
unique()

for (i in seq_along(urls_try)) {
.url <- urls_try[i]
if (is_cran_url_available(.url, r_version)) break
.url <- NA_character_
}

if (is.na(.url)) rlang::abort("\nCRAN mirrors are not available!\n")

.url
}


#' A funtion to make P3M CRAN mirror URL for Linux
#' @param date A character vector of dates like `"2023-10-30"`.
#' If `NA`, the "latest" URL will be returned.
#' @param distro_version_name A character of distro version name like `"focal"`.
#' @param type A character of package type, `"source"` (default) or `"binary"`.
#' @return A character of P3M CRAN mirror URL.
#' @examples
#' make_p3m_cran_url_linux(c("2023-10-30", NA), "focal", "binary")
make_p3m_cran_url_linux <- function(date, distro_version_name, type = "source") {
base_url <- "https://p3m.dev/cran"

dplyr::case_when(
type == "source" & is.na(date) ~ glue::glue("{base_url}/latest"),
type == "binary" & is.na(date) ~ glue::glue("{base_url}/__linux__/{distro_version_name}/latest"),
type == "source" ~ glue::glue("{base_url}/{date}"),
type == "binary" ~ glue::glue("{base_url}/__linux__/{distro_version_name}/{date}")
)
}


#' Check if a CRAN URL is available via [pak::repo_ping()]
#' @param url A single character of CRAN URL.
#' @param r_version A character of R version like `"4.3.0"`.
is_cran_url_available <- function(url, r_version) {
glue::glue("\n\nfor R {r_version}, repo_ping to {url}\n\n") |>
cat()

is_available <- pak::repo_ping(cran_mirror = url, r_version = r_version, bioc = FALSE) |>
dplyr::filter(name == "CRAN") |>
dplyr::pull(ok)

is_available
}


#' Check if an RStudio deb package (amd64) is available
#' @param rstudio_version A single character of RStudio version like `"2023.12.0+369"`.
#' @param ubuntu_series A character of Ubuntu series like `"jammy"`.
#' @return A logical value.
#' @examples
#' is_rstudio_deb_available("2023.12.0+369", "jammy")
is_rstudio_deb_available <- function(rstudio_version, ubuntu_series) {
os_ver <- dplyr::case_match(
ubuntu_series,
"focal" ~ "bionic",
.default = ubuntu_series
)

glue::glue("\n\nChecking RStudio Sever {rstudio_version} deb package for {os_ver}\n\n") |>
cat()

is_available <- glue::glue(
"https://download2.rstudio.org/server/{os_ver}/amd64/rstudio-server-{rstudio_version}-amd64.deb"
) |>
stringr::str_replace_all("\\+", "-") |>
httr2::request() |>
httr2::req_error(is_error = \(...) FALSE) |>
httr2::req_perform() |>
httr2::resp_is_error() |>
isFALSE()

is_available
}


#' Get the latest CTAN URL for a given date
#' @param date A [Date] class vector.
#' If `NA`, the "latest" URL will be returned.
#' @return A character of CTAN URL.
#' @examples
#' latest_ctan_url(as.Date(c("2023-10-30", NA)))
latest_ctan_url <- function(date) {
.url <- dplyr::if_else(
is.na(date), "https://mirror.ctan.org/systems/texlive/tlnet",
stringr::str_c("https://www.texlive.info/tlnet-archive/", format(date, "%Y/%m/%d"), "/tlnet")
)

.url
}


#' Get the latest version from Git remote tags
#' @param remote_repo A single character of Git remote repository URL.
#' @return A character of the latest version.
#' @examples
#' latest_version_of_git_repo("https://github.com/OSGeo/PROJ.git")
latest_version_of_git_repo <- function(remote_repo) {
gert::git_remote_ls(remote = remote_repo) |>
dplyr::pull(ref) |>
stringr::str_subset(r"(^refs/tags/v?(\d+\.){2}\d+$)") |>
stringr::str_extract(r"((\d+\.)*\d+$)") |>
package_version() |>
sort() |>
utils::tail(1) |>
as.character()
}


#' Paste each element of vectors in a cartesian product
#' @param ... Dynamic dots. Character vectors to paste.
#' @return A character vector.
#' @examples
#' outer_paste(c("a", "b"), "-", c("c", "d", "e"))
outer_paste <- function(...) {
.paste <- function(x, y) {
outer(x, y, stringr::str_c) |>
c()
}

out <- rlang::list2(...) |>
purrr::reduce(.paste)

out
}


rocker_versioned_args <- function(
...,
r_versions_file = "build/variables/r-versions.tsv",
ubuntu_lts_versions_file = "build/variables/ubuntu-lts-versions.tsv",
rstudio_versions_file = "build/variables/rstudio-versions.tsv") {
df_all <- readr::read_tsv(r_versions_file, show_col_types = FALSE) |>
dplyr::arrange(as.numeric_version(r_version)) |>
dplyr::mutate(
r_minor_version = stringr::str_extract(r_version, r"(^\d+\.\d+)") |>
as.numeric_version(),
r_major_version = stringr::str_extract(r_version, r"(^\d+)") |>
as.numeric_version(),
) |>
dplyr::mutate(
r_minor_latest = dplyr::if_else(dplyr::row_number() == dplyr::n(), TRUE, FALSE),
.by = r_minor_version
) |>
dplyr::mutate(
r_major_latest = dplyr::if_else(dplyr::row_number() == dplyr::n(), TRUE, FALSE),
.by = r_major_version
) |>
dplyr::select(!c(r_minor_version, r_major_version)) |>
# Supports the latest two patch versions and the latest two minor versions.
dplyr::filter(
r_minor_latest | dplyr::lead(r_major_latest, default = FALSE)
) |>
dplyr::slice_tail(n = 3) |>
tidyr::expand_grid(
readr::read_tsv(
ubuntu_lts_versions_file,
show_col_types = FALSE,
col_types = list(ubuntu_version = readr::col_character())
)
) |>
dplyr::filter(r_release_date >= ubuntu_release_date + 90) |>
dplyr::slice_max(ubuntu_release_date, with_ties = FALSE, by = r_version) |>
tidyr::expand_grid(
readr::read_tsv(
rstudio_versions_file,
show_col_types = FALSE
)
) |>
dplyr::filter(
r_freeze_date > rstudio_commit_date | is.na(r_freeze_date)
)

df_available_rstudio <- df_all |>
dplyr::distinct(ubuntu_series, rstudio_version) |>
dplyr::filter(
purrr::map2_lgl(rstudio_version, ubuntu_series, is_rstudio_deb_available)
)

df_all |>
dplyr::semi_join(df_available_rstudio, by = c("ubuntu_series", "rstudio_version")) |>
dplyr::slice_max(rstudio_version, with_ties = FALSE, by = c(r_version, ubuntu_series)) |>
dplyr::mutate(
ctan = latest_ctan_url(r_freeze_date),
cran = purrr::pmap_chr(
list(r_freeze_date, ubuntu_series, r_version),
\(...) latest_p3m_cran_url_linux(...)
)
) |>
dplyr::select(
r_version,
r_release_date,
r_freeze_date,
ubuntu_series,
cran,
rstudio_version,
ctan,
r_major_latest,
r_minor_latest
)
}


rocker_versioned_args() |>
purrr::pwalk(
\(...) {
dots <- rlang::list2(...)
dots |>
jsonlite::write_json(
glue::glue("build/args/{dots$r_version}.json"),
auto_unbox = TRUE,
pretty = TRUE
)
}
)

0 comments on commit 410a3b2

Please sign in to comment.