Skip to content

Commit

Permalink
extend check_cont to include no dockerhub registries
Browse files Browse the repository at this point in the history
  • Loading branch information
bschilder committed Oct 11, 2023
1 parent c57aa8a commit 065a231
Show file tree
Hide file tree
Showing 11 changed files with 143 additions and 45 deletions.
3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ Suggests:
BiocStyle,
BiocPkgTools,
biocViews,
reticulate
reticulate,
rvest
VignetteBuilder: knitr
License: GPL-3
Config/testthat/edition: 3
Expand Down
54 changes: 23 additions & 31 deletions R/check_cont.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,34 @@
#' Check that a list of containers are valid.
#' @inheritParams construct_runners
#' @param domain Container repository API domain.
#' @returns NUll
#' @returns Null
#'
#' @keywords internal
check_cont <- function(cont,
domain = "https://hub.docker.com/v2/repositories/",
#' @keywords internal
check_cont <- function(cont,
verbose = TRUE){
# devoptera::args2vars(check_cont)
# cont <- list("ghcr.io/bioconductor/bioconductor_docker:devel" )

requireNamespace("jsonlite")
n_parts <- check_cont_general(cont)
for(co in cont){
if(is.null(co)) next()
if(isFALSE(grepl("/",co))){
stopper("Container must be specificied in the following format:",
"'owner/repo:tag'")
}
splt <- strsplit(co,":")[[1]]
URL <- paste(domain, splt[1],
"tags?page_size=1000",sep="/"
)
#### Check repo exists ####
messager("Checking public container repository exists:",shQuote(splt[1]),
v=verbose)
js <- tryCatch({
jsonlite::read_json(URL)
}, error=function(e){
stopper("Unable to find public container:",co)
}
)
#### Check tag exists ####
if(length(splt)==2){
messager("Checking tag exists:",shQuote(splt[2]),
v=verbose)
tags <- sapply(js$results ,function(x){x$name})
if(!splt[2] %in% tags){
stopper("The tag", shQuote(splt[2]),
"does not exist in the repo",shQuote(splt[1]))
}
#### Check container ####
if(grepl("ghcr.io",co)){
check_cont_ghcr(cont = co,
verbose = verbose)
} else if(grepl("docker.io",cont)){
check_cont_dockerhub(cont = co,
verbose = verbose)
} else if(n_parts==2){
messager("Assuming container is on DockerHub.",v=verbose)
check_cont_dockerhub(cont = co,
verbose = verbose)
} else {
warning(paste(
"Unable to check registry for container",co,
"Skipping check."
))
}
}

}
27 changes: 27 additions & 0 deletions R/check_cont_dockerhub.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
check_cont_dockerhub <- function(cont,
domain =
"https://hub.docker.com/v2/repositories/",
verbose = TRUE){
requireNamespace("jsonlite")
for(co in cont){
if(is.null(co)) next()
co <- gsub("docker\\.io/","",co)
splt <- strsplit(co,":")[[1]]
URL <- paste(domain, splt[1],
"tags?page_size=1000",sep="/"
)
#### Check repo exists ####
messager("Checking public container repository exists:",shQuote(splt[1]),
v=verbose)
js <- tryCatch({
jsonlite::read_json(URL)
}, error=function(e){
stopper("Unable to find public container:",co)
})
#### Check tag exists ####
tags <- sapply(js$results ,function(x){x$name})
check_tags(tags = tags,
splt = splt,
verbose = verbose)
}
}
11 changes: 11 additions & 0 deletions R/check_cont_general.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
check_cont_general <- function(cont){
lapply(cont, function(co){
if(is.null(co)) return(NULL)
if(!grepl("/",co)){
stopper("Container must be specified in the following format:",
"'registry/owner/repo:tag'")
}
n_parts <- length(strsplit(gsub("[/]+","/",co),"/")[[1]])
return(n_parts)
})
}
40 changes: 40 additions & 0 deletions R/check_cont_ghcr.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
check_cont_ghcr <- function(cont,
verbose = TRUE){
requireNamespace("rvest")

for(co in cont){
if(is.null(co)) next()
# co <- "ghcr.io/bioconductor/bioconductor_docker:devel"
co_notag <- gsub("ghcr.io/","",strsplit(co,":")[[1]][1])
##### Only works if you have permissions to the repo #####
# get_ghcr_tags <- function(container) {
# url <- paste0("https://ghcr.io/v2/", container, "/tags/list")
# response <- jsonlite::fromJSON(url)
# tags <- response$tags
# return(tags)
# }
# tags <- get_ghcr_tags("bioconductor/bioconductor_docker")
#
URL <- paste0(
"https://github.com/",
co_notag,
"/pkgs/container/",basename(co_notag),
"/versions?filters%5Bversion_type%5D=tagged"
)
#### Check if container exists ####
x <- tryCatch({
rvest::read_html(URL)
}, error=function(e){
stopper("Unable to find public container:",co)}
)
#### Check if container has tags ####
tags <- x |> rvest::html_nodes(".Label") |> rvest::html_text()
if(length(tags)==0){
stopper("Unable to find tags for container:",co)
} else {
check_tags(tags = tags,
splt = strsplit(co,":")[[1]][1],
verbose = verbose)
}
}
}
12 changes: 12 additions & 0 deletions R/check_tags.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
check_tags <- function(splt,
tags,
verbose=TRUE){
if(length(splt)==2){
messager("Checking tag exists:",shQuote(splt[2]),
v=verbose)
if(!splt[2] %in% tags){
stopper("The tag", shQuote(splt[2]),
"does not exist in the repo",shQuote(splt[1]))
}
}
}
4 changes: 3 additions & 1 deletion R/construct_cont.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#' \itemize{
#' \item{"ghcr.io/" : }{\href{https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry}{GitHub Container Registry}}
#' \item{"docker.io/" : }{\href{https://hub.docker.com/}{DockerHub}}
#' \item{"mcr.microsoft.com/" : }{\href{https://github.com/microsoft/ContainerRegistry}{Microsoft Container Registry}}
#' }
#' @param default_cont The DockerHub container to default to.
#' Used when it's detected that only the tag has been given in one or more
Expand All @@ -20,7 +21,8 @@
#' @examples
#' cont <- construct_cont()
construct_cont <- function(default_registry = c("ghcr.io/",
"docker.io/"),
"docker.io/",
"mcr.microsoft.com/"),
default_cont = "bioconductor/bioconductor_docker",
default_tag = "devel",
cont = list(
Expand Down
12 changes: 4 additions & 8 deletions man/check_cont.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/construct_cont.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions tests/testthat/test-check_cont.R
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,16 @@ test_that("check_cont works", {
testthat::expect_error(
check_cont(cont = "typooooo")
)

#### Include registry ####
testthat::expect_no_warning(
check_cont(cont = "ghcr.io/bioconductor/bioconductor_docker")
)

testthat::expect_no_warning(
check_cont(cont = "docker.io/bioconductor/bioconductor_docker:devel")
)
testthat::expect_warning(
check_cont(cont = "mcr.microsoft.com/bioconductor/bioconductor_docker:devel")
)
})
10 changes: 7 additions & 3 deletions tests/testthat/test-construct_cont.R
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
test_that("construct_cont works", {

cont1 <- construct_cont()
testthat::expect_equal(cont1[[1]], "bioconductor/bioconductor_docker:devel")
default_registry <- eval(formals(construct_cont)$default_registry)[1]
default_tag <- eval(formals(construct_cont)$default_tag)[1]
testthat::expect_equal(cont1[[1]],
paste0(opts,"bioconductor/bioconductor_docker:",default_tag))
testthat::expect_null(cont1[[2]])
testthat::expect_null(cont1[[3]])

cont2 <- construct_cont(cont = "devel")
testthat::expect_equal(cont2[[1]], "bioconductor/bioconductor_docker:devel")
testthat::expect_equal(cont2[[1]],
paste0(opts,"bioconductor/bioconductor_docker:",default_tag))

cont3 <- construct_cont(versions_explicit = TRUE)
testthat::expect_true(grepl("bioconductor/bioconductor_docker:RELEASE_*",
Expand All @@ -16,7 +20,7 @@ test_that("construct_cont works", {

cont4 <- construct_cont(default_tag = "release",
run_check_cont = TRUE)
testthat::expect_equal(cont4[[1]], "bioconductor/bioconductor_docker:latest")
testthat::expect_equal(cont4[[1]], paste0(opts,"bioconductor/bioconductor_docker:latest"))
testthat::expect_null(cont4[[2]])
testthat::expect_null(cont4[[3]])
})

0 comments on commit 065a231

Please sign in to comment.