From 8fac2da4ed45d8c4c9548f4831d31d8d0b3dbab1 Mon Sep 17 00:00:00 2001 From: Jeroen Ooms Date: Mon, 15 Apr 2024 14:49:14 +0200 Subject: [PATCH] merge with old stuff --- .github/workflows/build.yml | 32 +++++++++ .github/workflows/recheck.yml | 4 +- .gitignore | 7 ++ Dockerfile | 4 ++ rechecktools/.Rbuildignore | 9 +++ rechecktools/DESCRIPTION | 13 ++++ rechecktools/LICENSE | 2 + rechecktools/LICENSE.md | 21 ++++++ rechecktools/NAMESPACE | 4 ++ rechecktools/R/ci.R | 24 +++++++ rechecktools/R/linux-binaries.R | 47 +++++++++++++ rechecktools/R/recheck.R | 90 ++++++++++++++++++++++++ rechecktools/man/install_recheck_deps.Rd | 16 +++++ rechecktools/man/recheck.Rd | 20 ++++++ rechecktools/recheck.Rproj | 20 ++++++ 15 files changed, 311 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/build.yml create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 rechecktools/.Rbuildignore create mode 100644 rechecktools/DESCRIPTION create mode 100644 rechecktools/LICENSE create mode 100644 rechecktools/LICENSE.md create mode 100644 rechecktools/NAMESPACE create mode 100644 rechecktools/R/ci.R create mode 100644 rechecktools/R/linux-binaries.R create mode 100644 rechecktools/R/recheck.R create mode 100644 rechecktools/man/install_recheck_deps.Rd create mode 100644 rechecktools/man/recheck.Rd create mode 100644 rechecktools/recheck.Rproj diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..4d80140 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,32 @@ +name: Build Docker Image + +on: + push: + branches: + - 'v1' + workflow_dispatch: + +jobs: + docker: + runs-on: ubuntu-latest + steps: + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to GHCR (GitHub Packages) + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push + id: docker_build + uses: docker/build-push-action@v5 + with: + push: true + tags: | + ghcr.io/${{github.repository}}:latest diff --git a/.github/workflows/recheck.yml b/.github/workflows/recheck.yml index f48c3eb..060355f 100644 --- a/.github/workflows/recheck.yml +++ b/.github/workflows/recheck.yml @@ -16,7 +16,7 @@ jobs: prepare: name: Prepare dependencies runs-on: ubuntu-latest - container: ghcr.io/r-universe-org/recheck + container: ghcr.io/r-devel/recheck outputs: oldfile: ${{ steps.filenames.outputs.oldfile }} newfile: ${{ steps.filenames.outputs.newfile }} @@ -66,7 +66,7 @@ jobs: needs: prepare runs-on: ubuntu-latest name: Recheck ${{matrix.check == 'oldpkg' && needs.prepare.outputs.oldfile || needs.prepare.outputs.newfile}} (${{matrix.check}}) - container: ghcr.io/r-universe-org/recheck + container: ghcr.io/r-devel/recheck timeout-minutes: 600 strategy: matrix: diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b5054f8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.o +*.so +*.dll +.Rproj.user +.Rhistory +revdeps +*_recheck diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a6fdf00 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,4 @@ +FROM ghcr.io/r-devel/rcheckserver/ubuntu + +COPY rechecktools /rechecktools +RUN R -e 'install.packages("remotes");remotes::install_local("/rechecktools");library(rechecktools)' diff --git a/rechecktools/.Rbuildignore b/rechecktools/.Rbuildignore new file mode 100644 index 0000000..41dc725 --- /dev/null +++ b/rechecktools/.Rbuildignore @@ -0,0 +1,9 @@ +^.*\.Rproj$ +^\.Rproj\.user$ +^Dockerfile$ +^\.git$ +^\.github$ +^LICENSE.md$ +^action.yml$ +^entrypoint.sh$ +^.*_recheck$ diff --git a/rechecktools/DESCRIPTION b/rechecktools/DESCRIPTION new file mode 100644 index 0000000..94ce1ff --- /dev/null +++ b/rechecktools/DESCRIPTION @@ -0,0 +1,13 @@ +Package: rechecktools +Type: Package +Title: Reverse Dependency Check Tools +Version: 0.1.0 +Author: Who wrote it +Maintainer: The package maintainer +Description: Runs a reverse dependency check in a similar manner as CRAN incoming. +License: MIT + file LICENSE +Encoding: UTF-8 +Imports: + curl +RoxygenNote: 7.3.1 +Roxygen: list(markdown = TRUE) diff --git a/rechecktools/LICENSE b/rechecktools/LICENSE new file mode 100644 index 0000000..76824f2 --- /dev/null +++ b/rechecktools/LICENSE @@ -0,0 +1,2 @@ +YEAR: 2024 +COPYRIGHT HOLDER: Jeroen Ooms diff --git a/rechecktools/LICENSE.md b/rechecktools/LICENSE.md new file mode 100644 index 0000000..a572aef --- /dev/null +++ b/rechecktools/LICENSE.md @@ -0,0 +1,21 @@ +# MIT License + +Copyright (c) 2024 Jeroen Ooms + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/rechecktools/NAMESPACE b/rechecktools/NAMESPACE new file mode 100644 index 0000000..5aa028a --- /dev/null +++ b/rechecktools/NAMESPACE @@ -0,0 +1,4 @@ +# Generated by roxygen2: do not edit by hand + +export(install_recheck_deps) +export(recheck) diff --git a/rechecktools/R/ci.R b/rechecktools/R/ci.R new file mode 100644 index 0000000..3579216 --- /dev/null +++ b/rechecktools/R/ci.R @@ -0,0 +1,24 @@ +#' Wrappers to run in CI +#' +#' To call in CI +#' +#' @export +#' @param path path to source package +#' @param which either be strong or most +install_recheck_deps <- function(path = '.', which = 'strong'){ + oldrepos <- enable_all_repos() + oldtimeout <- options(timeout = 600) + on.exit(options(c(oldrepos, oldtimeout)), add = TRUE) + desc <- read.dcf(file.path(path, 'DESCRIPTION')) + pkg <- desc[[1, 'Package']] + cranrepo <- getOption('repos')['CRAN'] + cran <- utils::available.packages(repos = cranrepo) + packages <- c(pkg, tools::package_dependencies(pkg, db = cran, which = which, reverse = TRUE)[[pkg]]) + if(grepl("Linux", Sys.info()[['sysname']])){ + preinstall_linux_binaries(packages) + } else { + utils::install.packages(packages, dependencies = TRUE) + deps <- unique(unlist(unname(tools::package_dependencies(packages, recursive = TRUE)))) + update.packages(oldPkgs = deps, ask = FALSE) + } +} diff --git a/rechecktools/R/linux-binaries.R b/rechecktools/R/linux-binaries.R new file mode 100644 index 0000000..f8f6044 --- /dev/null +++ b/rechecktools/R/linux-binaries.R @@ -0,0 +1,47 @@ +# The goal of this function is to speed up installation of dependencies. +# This is done in two ways: +# - Try to get precompiled binaries when available (mainly on ubuntu) +# - Download files in parallel using curl +# The latter can be removed once fixed in base-R: https://github.com/r-devel/r-svn/pull/155 +preinstall_linux_binaries <- function(tocheck){ + rver <- getRversion() + distro <- system2('lsb_release', '-sc', stdout = TRUE) + options(HTTPUserAgent = sprintf("R/%s R (%s); r-universe (%s)", rver, paste(rver, R.version$platform, R.version$arch, R.version$os), distro)) + bioc <- sprintf("https://bioc.r-universe.dev/bin/linux/%s/4/", distro) + cran <- sprintf("https://p3m.dev/cran/__linux__/%s/latest", distro) + repos <- c(cran, bioc) + db <- utils::available.packages(repos = c(CRAN = cran, BIOC = bioc, official_bioc_repos())) + checkdeps <- unique(unlist(unname(tools::package_dependencies(tocheck, db = db, which = 'most')))) + alldeps <- tools::package_dependencies(checkdeps, db = db, recursive = TRUE) + packages <- unlist(lapply(checkdeps, function(x){ + c(rev(alldeps[[x]]), x) + })) + packages <- intersect(unique(packages), row.names(db)) + packages <- setdiff(packages, loadedNamespaces()) + versions <- db[packages, 'Version'] + mirrors <- db[packages, 'Repository'] + urls <- sprintf("%s/%s_%s.tar.gz", mirrors, packages, versions) + destdir <- tempfile() + dir.create(destdir) + pwd <- setwd(destdir) + on.exit(setwd(pwd), add = TRUE) + on.exit(unlink(destdir, recursive = TRUE), add = TRUE) + res <- curl::multi_download(urls) + res$ok <- res$success & res$status_code == 200 + failures <- res$destfile[!res$ok] + if(length(failures)){ + warning("Failed downloads for: ", paste(failures, collapse = ', ')) + unlink(failures) + res <- res[res$ok,] + } + utils::install.packages(res$destfile, repos = NULL, Ncpus = parallel::detectCores()) +} + +official_bioc_repos <- function(){ + version <- utils:::.BioC_version_associated_with_R_version() + sprintf(c( + BioCsoft = "https://bioconductor.org/packages/%s/bioc", + BioCann = "https://bioconductor.org/packages/%s/data/annotation", + BioCexp = "https://bioconductor.org/packages/%s/data/experiment" + ), version) +} diff --git a/rechecktools/R/recheck.R b/rechecktools/R/recheck.R new file mode 100644 index 0000000..7453968 --- /dev/null +++ b/rechecktools/R/recheck.R @@ -0,0 +1,90 @@ +#' Reverse Dependency Check +#' +#' Run a reverse dependency check similar to CRAN. +#' +#' @export +#' @rdname recheck +#' @param sourcepkg path or URL to a source package tarball +#' @param which passed to `tools::package_dependencies`; set to "most" to +#' also check reverse suggests. +#' @param preinstall_dependencies start by installing dependencies for all +#' packages to be checked. +recheck <- function(sourcepkg, which = "strong", preinstall_dependencies = TRUE){ + # Some temporary settings + oldrepos <- enable_all_repos() + oldtimeout <- options(timeout = 600) + on.exit(options(c(oldrepos, oldtimeout)), add = TRUE) + + # Get the tarball + if(grepl('^https:', sourcepkg)){ + curl::curl_download(sourcepkg, basename(sourcepkg)) + sourcepkg <- basename(sourcepkg) + } + if(!grepl("_", sourcepkg)){ + dl <- utils::download.packages(sourcepkg, '.') + sourcepkg <- basename(dl[,2]) + } + pkg <- sub("_.*", "", basename(sourcepkg)) + checkdir <- dirname(sourcepkg) + cranrepo <- getOption('repos')['CRAN'] # + cran <- utils::available.packages(repos = cranrepo) + packages <- c(pkg, tools::package_dependencies(pkg, db = cran, which = which, reverse = TRUE)[[pkg]]) + if(preinstall_dependencies){ + group_output("Preparing dependencies", { + if(grepl("Linux", Sys.info()[['sysname']])){ + preinstall_linux_binaries(packages) + } else { + utils::install.packages(packages, dependencies = TRUE) + deps <- unique(unlist(unname(tools::package_dependencies(packages, recursive = TRUE)))) + update.packages(oldPkgs = deps, ask = FALSE) + } + }) + } + check_args <- character() + if(nchar(Sys.which('pdflatex')) == 0){ + message("No pdflatex found, skipping pdf checks") + check_args <- c(check_args, '--no-manual --no-build-vignettes') + } + group_output("Running checks", { + Sys.setenv('_R_CHECK_FORCE_SUGGESTS_' = 'false') + if(.Platform$OS.type == 'windows') Sys.setenv(TAR = 'internal') + tools::check_packages_in_dir(checkdir, basename(sourcepkg), + reverse = list(repos = cranrepo, which = which), + Ncpus = parallel::detectCores(), + check_args = check_args) + }) + group_output("Check results details", { + details <- tools::check_packages_in_dir_details(checkdir) + write.csv(details, file.path(checkdir, 'check-details.csv')) + writeLines(paste(format(details), collapse = "\n\n"), file.path(checkdir, 'check-details.txt')) + print(details) + }) + tools::summarize_check_packages_in_dir_results(checkdir) +} + +enable_all_repos <- function(){ + old <- options(repos = c(CRAN = 'https://cloud.r-project.org')) + utils::setRepositories(ind = 1:4) #adds bioc + my_universe <- Sys.getenv('MY_UNIVERSE') + if(nchar(my_universe)){ + options(repos = c(my_universe = my_universe, getOption('repos'))) + } + return(old) +} + +group_output<- function(title, expr){ + if(Sys.getenv('CI') != ""){ + cat("::group::", title, "\n", sep = "") + on.exit(cat("::endgroup::\n")) + } + cat("===========", title, "===========\n") + eval(expr) +} + +test_recheck <- function(pkg, which = 'strong'){ + checkdir <- paste(pkg, 'recheck', sep = '_') + unlink(checkdir, recursive = TRUE) + dir.create(checkdir) + utils::download.packages(pkg, checkdir, repos = 'https://cloud.r-project.org') + recheck(list.files(checkdir, pattern = 'tar.gz$', full.names = TRUE), which = which) +} diff --git a/rechecktools/man/install_recheck_deps.Rd b/rechecktools/man/install_recheck_deps.Rd new file mode 100644 index 0000000..7d42b7a --- /dev/null +++ b/rechecktools/man/install_recheck_deps.Rd @@ -0,0 +1,16 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ci.R +\name{install_recheck_deps} +\alias{install_recheck_deps} +\title{Wrappers to run in CI} +\usage{ +install_recheck_deps(path = ".", which = "strong") +} +\arguments{ +\item{path}{path to source package} + +\item{which}{either be strong or most} +} +\description{ +To call in CI +} diff --git a/rechecktools/man/recheck.Rd b/rechecktools/man/recheck.Rd new file mode 100644 index 0000000..3278304 --- /dev/null +++ b/rechecktools/man/recheck.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/recheck.R +\name{recheck} +\alias{recheck} +\title{Reverse Dependency Check} +\usage{ +recheck(sourcepkg, which = "strong", preinstall_dependencies = TRUE) +} +\arguments{ +\item{sourcepkg}{path or URL to a source package tarball} + +\item{which}{passed to \code{tools::package_dependencies}; set to "most" to +also check reverse suggests.} + +\item{preinstall_dependencies}{start by installing dependencies for all +packages to be checked.} +} +\description{ +Run a reverse dependency check similar to CRAN. +} diff --git a/rechecktools/recheck.Rproj b/rechecktools/recheck.Rproj new file mode 100644 index 0000000..497f8bf --- /dev/null +++ b/rechecktools/recheck.Rproj @@ -0,0 +1,20 @@ +Version: 1.0 + +RestoreWorkspace: Default +SaveWorkspace: Default +AlwaysSaveHistory: Default + +EnableCodeIndexing: Yes +UseSpacesForTab: Yes +NumSpacesForTab: 2 +Encoding: UTF-8 + +RnwWeave: Sweave +LaTeX: pdfLaTeX + +AutoAppendNewline: Yes +StripTrailingWhitespace: Yes + +BuildType: Package +PackageUseDevtools: Yes +PackageInstallArgs: --no-multiarch --with-keep.source