Skip to content

Instantly share code, notes, and snippets.

@nbenn
Last active May 19, 2016 20:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save nbenn/7ce01f52f6cdd5277441d487eb066946 to your computer and use it in GitHub Desktop.
Save nbenn/7ce01f52f6cdd5277441d487eb066946 to your computer and use it in GitHub Desktop.
Fetch latest build artifact from gitlab and install as R package.
#' Install an R package hosted as a build artifact on gitlab
#'
#' Gitlab supports the storage of build artifacts which may be utilized as
#' distribution mechanism for code binaries. Applying this to scheme to R, a
#' build task may be defined (for example for each tagged commit), yielding a
#' .zip file of the tar.gz package produced by R CMD build. This function
#' fetches the most recent build artifact and installs it as a package.
#'
#' @param gitlab A string representing the base url of the gitlab host
#' @param name The name of the package repository
#' @param token The user token, required for accessing the gitlab REST api
#' @param ... All further arguments are passed to install.packages
#'
#' @return NULL
#'
install.gitlab <- function(gitlab, name, token, ...) {
library(httr)
base <- paste0(gitlab, "/api/v3/")
resp <- GET(paste0(base, "projects"), add_headers("PRIVATE-TOKEN"=token))
json <- content(resp)
id.project <- lapply(json, function(project, name) {
if(project$name == name) return(project$id)
else return(NULL)
}, name=name)
id.project <- unlist(id.project)
if(length(id.project) != 1) warning("expecting to find exactly 1 repo match.")
resp <- GET(paste0(base, "projects/", id.project, "/builds"),
add_headers("PRIVATE-TOKEN"=token))
json <- content(resp)
build <- lapply(json, function(build) {
if(!is.null(build$artifacts_file$filename)) {
id <- build$id
date <- build$started_at
date <- gsub(paste0("^([0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:",
"[0-9]{2}\\.[0-9]+[+-][0-9]{2}):([0-9]{2})$"),
"\\1\\2", date)
date <- as.POSIXct(strptime(date, "%Y-%m-%dT%H:%M:%OS%z"))
return(list(id, date))
}
else return(NULL)
})
build <- lapply(build, data.frame)
build <- do.call(rbind.data.frame, build)
colnames(build) <- c("build_id", "build_date")
latest <- build$build_id[tail(order(build$build_date), n=1)]
resp <- GET(paste0(base, "projects/", id.project, "/builds/", latest,
"/artifacts"),
add_headers("PRIVATE-TOKEN"=token))
tempdir <- paste0(tempdir(), "/build_", name)
tmpexis <- dir.exists(tempdir)
if(!tmpexis) dir.create(tempdir)
tempzip <- paste0(tempdir, "/", name, ".zip")
if(file.exists(tempzip)) stop(".zip already exists in temp dir.")
temptar <- list.files(tempdir, pattern="*.tar.gz", full.names=T)
if(length(temptar) != 0) stop("some .tar.gz already exists in temp dir.")
writeBin(content(resp, "raw"), tempzip)
unzip(tempzip, exdir=tempdir)
temptar <- list.files(tempdir, pattern="*.tar.gz", full.names=T)
if(length(temptar) != 1) stop("expecting exactly 1 .tar.gz file in temp dir.")
install.packages(pkgs=temptar, repos=NULL, type="source", ...)
if(tmpexis) unlink(c(tempzip, temptar))
else unlink(tempdir, recursive=T)
return(invisible(NULL))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment