Skip to content

Commit 065a231

Browse files
committed
extend check_cont to include no dockerhub registries
1 parent c57aa8a commit 065a231

11 files changed

+143
-45
lines changed

DESCRIPTION

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ Suggests:
5858
BiocStyle,
5959
BiocPkgTools,
6060
biocViews,
61-
reticulate
61+
reticulate,
62+
rvest
6263
VignetteBuilder: knitr
6364
License: GPL-3
6465
Config/testthat/edition: 3

R/check_cont.R

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,34 @@
33
#' Check that a list of containers are valid.
44
#' @inheritParams construct_runners
55
#' @param domain Container repository API domain.
6-
#' @returns NUll
6+
#' @returns Null
77
#'
8-
#' @keywords internal
9-
check_cont <- function(cont,
10-
domain = "https://hub.docker.com/v2/repositories/",
8+
#' @keywords internal
9+
check_cont <- function(cont,
1110
verbose = TRUE){
11+
# devoptera::args2vars(check_cont)
12+
# cont <- list("ghcr.io/bioconductor/bioconductor_docker:devel" )
1213

13-
requireNamespace("jsonlite")
14+
n_parts <- check_cont_general(cont)
1415
for(co in cont){
1516
if(is.null(co)) next()
16-
if(isFALSE(grepl("/",co))){
17-
stopper("Container must be specificied in the following format:",
18-
"'owner/repo:tag'")
19-
}
20-
splt <- strsplit(co,":")[[1]]
21-
URL <- paste(domain, splt[1],
22-
"tags?page_size=1000",sep="/"
23-
)
24-
#### Check repo exists ####
25-
messager("Checking public container repository exists:",shQuote(splt[1]),
26-
v=verbose)
27-
js <- tryCatch({
28-
jsonlite::read_json(URL)
29-
}, error=function(e){
30-
stopper("Unable to find public container:",co)
31-
}
32-
)
33-
#### Check tag exists ####
34-
if(length(splt)==2){
35-
messager("Checking tag exists:",shQuote(splt[2]),
36-
v=verbose)
37-
tags <- sapply(js$results ,function(x){x$name})
38-
if(!splt[2] %in% tags){
39-
stopper("The tag", shQuote(splt[2]),
40-
"does not exist in the repo",shQuote(splt[1]))
41-
}
17+
#### Check container ####
18+
if(grepl("ghcr.io",co)){
19+
check_cont_ghcr(cont = co,
20+
verbose = verbose)
21+
} else if(grepl("docker.io",cont)){
22+
check_cont_dockerhub(cont = co,
23+
verbose = verbose)
24+
} else if(n_parts==2){
25+
messager("Assuming container is on DockerHub.",v=verbose)
26+
check_cont_dockerhub(cont = co,
27+
verbose = verbose)
28+
} else {
29+
warning(paste(
30+
"Unable to check registry for container",co,
31+
"Skipping check."
32+
))
4233
}
4334
}
35+
4436
}

R/check_cont_dockerhub.R

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
check_cont_dockerhub <- function(cont,
2+
domain =
3+
"https://hub.docker.com/v2/repositories/",
4+
verbose = TRUE){
5+
requireNamespace("jsonlite")
6+
for(co in cont){
7+
if(is.null(co)) next()
8+
co <- gsub("docker\\.io/","",co)
9+
splt <- strsplit(co,":")[[1]]
10+
URL <- paste(domain, splt[1],
11+
"tags?page_size=1000",sep="/"
12+
)
13+
#### Check repo exists ####
14+
messager("Checking public container repository exists:",shQuote(splt[1]),
15+
v=verbose)
16+
js <- tryCatch({
17+
jsonlite::read_json(URL)
18+
}, error=function(e){
19+
stopper("Unable to find public container:",co)
20+
})
21+
#### Check tag exists ####
22+
tags <- sapply(js$results ,function(x){x$name})
23+
check_tags(tags = tags,
24+
splt = splt,
25+
verbose = verbose)
26+
}
27+
}

R/check_cont_general.R

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
check_cont_general <- function(cont){
2+
lapply(cont, function(co){
3+
if(is.null(co)) return(NULL)
4+
if(!grepl("/",co)){
5+
stopper("Container must be specified in the following format:",
6+
"'registry/owner/repo:tag'")
7+
}
8+
n_parts <- length(strsplit(gsub("[/]+","/",co),"/")[[1]])
9+
return(n_parts)
10+
})
11+
}

R/check_cont_ghcr.R

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
check_cont_ghcr <- function(cont,
2+
verbose = TRUE){
3+
requireNamespace("rvest")
4+
5+
for(co in cont){
6+
if(is.null(co)) next()
7+
# co <- "ghcr.io/bioconductor/bioconductor_docker:devel"
8+
co_notag <- gsub("ghcr.io/","",strsplit(co,":")[[1]][1])
9+
##### Only works if you have permissions to the repo #####
10+
# get_ghcr_tags <- function(container) {
11+
# url <- paste0("https://ghcr.io/v2/", container, "/tags/list")
12+
# response <- jsonlite::fromJSON(url)
13+
# tags <- response$tags
14+
# return(tags)
15+
# }
16+
# tags <- get_ghcr_tags("bioconductor/bioconductor_docker")
17+
#
18+
URL <- paste0(
19+
"https://github.com/",
20+
co_notag,
21+
"/pkgs/container/",basename(co_notag),
22+
"/versions?filters%5Bversion_type%5D=tagged"
23+
)
24+
#### Check if container exists ####
25+
x <- tryCatch({
26+
rvest::read_html(URL)
27+
}, error=function(e){
28+
stopper("Unable to find public container:",co)}
29+
)
30+
#### Check if container has tags ####
31+
tags <- x |> rvest::html_nodes(".Label") |> rvest::html_text()
32+
if(length(tags)==0){
33+
stopper("Unable to find tags for container:",co)
34+
} else {
35+
check_tags(tags = tags,
36+
splt = strsplit(co,":")[[1]][1],
37+
verbose = verbose)
38+
}
39+
}
40+
}

R/check_tags.R

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
check_tags <- function(splt,
2+
tags,
3+
verbose=TRUE){
4+
if(length(splt)==2){
5+
messager("Checking tag exists:",shQuote(splt[2]),
6+
v=verbose)
7+
if(!splt[2] %in% tags){
8+
stopper("The tag", shQuote(splt[2]),
9+
"does not exist in the repo",shQuote(splt[1]))
10+
}
11+
}
12+
}

R/construct_cont.R

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#' \itemize{
88
#' \item{"ghcr.io/" : }{\href{https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry}{GitHub Container Registry}}
99
#' \item{"docker.io/" : }{\href{https://hub.docker.com/}{DockerHub}}
10+
#' \item{"mcr.microsoft.com/" : }{\href{https://github.com/microsoft/ContainerRegistry}{Microsoft Container Registry}}
1011
#' }
1112
#' @param default_cont The DockerHub container to default to.
1213
#' Used when it's detected that only the tag has been given in one or more
@@ -20,7 +21,8 @@
2021
#' @examples
2122
#' cont <- construct_cont()
2223
construct_cont <- function(default_registry = c("ghcr.io/",
23-
"docker.io/"),
24+
"docker.io/",
25+
"mcr.microsoft.com/"),
2426
default_cont = "bioconductor/bioconductor_docker",
2527
default_tag = "devel",
2628
cont = list(

man/check_cont.Rd

Lines changed: 4 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/construct_cont.Rd

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-check_cont.R

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,16 @@ test_that("check_cont works", {
1717
testthat::expect_error(
1818
check_cont(cont = "typooooo")
1919
)
20+
21+
#### Include registry ####
22+
testthat::expect_no_warning(
23+
check_cont(cont = "ghcr.io/bioconductor/bioconductor_docker")
24+
)
25+
26+
testthat::expect_no_warning(
27+
check_cont(cont = "docker.io/bioconductor/bioconductor_docker:devel")
28+
)
29+
testthat::expect_warning(
30+
check_cont(cont = "mcr.microsoft.com/bioconductor/bioconductor_docker:devel")
31+
)
2032
})

0 commit comments

Comments
 (0)