├── rechecktools ├── LICENSE ├── NAMESPACE ├── .Rbuildignore ├── DESCRIPTION ├── man │ ├── install_recheck_deps.Rd │ └── recheck.Rd ├── recheck.Rproj ├── LICENSE.md └── R │ ├── ci.R │ ├── linux-binaries.R │ └── recheck.R ├── .gitignore ├── Dockerfile ├── .github └── workflows │ ├── build.yml │ └── recheck.yml └── README.md /rechecktools/LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2024 2 | COPYRIGHT HOLDER: Jeroen Ooms 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.so 3 | *.dll 4 | .Rproj.user 5 | .Rhistory 6 | revdeps 7 | *_recheck 8 | -------------------------------------------------------------------------------- /rechecktools/NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(install_recheck_deps) 4 | export(recheck) 5 | -------------------------------------------------------------------------------- /rechecktools/.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^Dockerfile$ 4 | ^\.git$ 5 | ^\.github$ 6 | ^LICENSE.md$ 7 | ^action.yml$ 8 | ^entrypoint.sh$ 9 | ^.*_recheck$ 10 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/r-devel/rcheckserver/ubuntu 2 | 3 | COPY rechecktools /rechecktools 4 | RUN R -e 'install.packages("remotes");remotes::install_local("/rechecktools");library(rechecktools)' 5 | -------------------------------------------------------------------------------- /rechecktools/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: rechecktools 2 | Type: Package 3 | Title: Reverse Dependency Check Tools 4 | Version: 0.1.0 5 | Author: Who wrote it 6 | Maintainer: The package maintainer 7 | Description: Runs a reverse dependency check in a similar manner as CRAN incoming. 8 | License: MIT + file LICENSE 9 | Encoding: UTF-8 10 | Imports: 11 | curl 12 | RoxygenNote: 7.3.1 13 | Roxygen: list(markdown = TRUE) 14 | -------------------------------------------------------------------------------- /rechecktools/man/install_recheck_deps.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ci.R 3 | \name{install_recheck_deps} 4 | \alias{install_recheck_deps} 5 | \title{Wrappers to run in CI} 6 | \usage{ 7 | install_recheck_deps(path = ".", which = "strong") 8 | } 9 | \arguments{ 10 | \item{path}{path to source package} 11 | 12 | \item{which}{either be strong or most} 13 | } 14 | \description{ 15 | To call in CI 16 | } 17 | -------------------------------------------------------------------------------- /rechecktools/recheck.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | ProjectId: fdd81c5f-5782-426c-977c-1f8314dacc77 3 | 4 | RestoreWorkspace: Default 5 | SaveWorkspace: Default 6 | AlwaysSaveHistory: Default 7 | 8 | EnableCodeIndexing: Yes 9 | UseSpacesForTab: Yes 10 | NumSpacesForTab: 2 11 | Encoding: UTF-8 12 | 13 | RnwWeave: Sweave 14 | LaTeX: pdfLaTeX 15 | 16 | AutoAppendNewline: Yes 17 | StripTrailingWhitespace: Yes 18 | 19 | BuildType: Package 20 | PackageUseDevtools: Yes 21 | PackageInstallArgs: --no-multiarch --with-keep.source 22 | -------------------------------------------------------------------------------- /rechecktools/man/recheck.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/recheck.R 3 | \name{recheck} 4 | \alias{recheck} 5 | \title{Reverse Dependency Check} 6 | \usage{ 7 | recheck(sourcepkg, which = "strong", preinstall_dependencies = TRUE) 8 | } 9 | \arguments{ 10 | \item{sourcepkg}{path or URL to a source package tarball} 11 | 12 | \item{which}{passed to \code{tools::package_dependencies}; set to "most" to 13 | also check reverse suggests.} 14 | 15 | \item{preinstall_dependencies}{start by installing dependencies for all 16 | packages to be checked.} 17 | } 18 | \description{ 19 | Run a reverse dependency check similar to CRAN. 20 | } 21 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build Docker Image 2 | 3 | on: 4 | push: 5 | branches: 6 | - 'v1' 7 | workflow_dispatch: 8 | schedule: 9 | - cron: "0 0 * * 0" 10 | 11 | jobs: 12 | docker: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Set up QEMU 16 | uses: docker/setup-qemu-action@v3 17 | 18 | - name: Set up Docker Buildx 19 | uses: docker/setup-buildx-action@v3 20 | 21 | - name: Login to GHCR (GitHub Packages) 22 | uses: docker/login-action@v3 23 | with: 24 | registry: ghcr.io 25 | username: ${{ github.actor }} 26 | password: ${{ secrets.GITHUB_TOKEN }} 27 | 28 | - name: Build and push 29 | id: docker_build 30 | uses: docker/build-push-action@v5 31 | with: 32 | push: true 33 | tags: | 34 | ghcr.io/${{github.repository}}:latest 35 | -------------------------------------------------------------------------------- /rechecktools/LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2024 Jeroen Ooms 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /rechecktools/R/ci.R: -------------------------------------------------------------------------------- 1 | #' Wrappers to run in CI 2 | #' 3 | #' To call in CI 4 | #' 5 | #' @export 6 | #' @param path path to source package 7 | #' @param which either be strong or most 8 | install_recheck_deps <- function(path = '.', which = 'strong', check_bioc = FALSE){ 9 | desc <- as.data.frame(read.dcf(file.path(path, 'DESCRIPTION'))) 10 | pkg <- desc$Package 11 | repos <- c( 12 | CRAN = 'https://cloud.r-project.org', 13 | BIOC = if(isTRUE(check_bioc)) 'https://bioconductor.posit.co/packages/devel/bioc' 14 | ) 15 | db <- utils::available.packages(repos = repos) 16 | revdeps <- tools::package_dependencies(pkg, db = db, which = which, reverse = TRUE)[[pkg]] 17 | packages <- setdiff(unique(c(desc_deps(desc), revdeps)), basepkgs()) 18 | utils::install.packages(packages, dependencies = TRUE) 19 | #deps <- unique(unlist(unname(tools::package_dependencies(packages, recursive = TRUE)))) 20 | #update.packages(oldPkgs = deps, ask = FALSE) 21 | } 22 | 23 | desc_deps <- function(desc){ 24 | deps <- c(desc$Package, desc$Depends, desc$Imports, desc$LinkingTo, desc$Suggests, desc$Enhances) 25 | unique(trimws(sub("\\(.*\\)", "", unlist(strsplit(as.character(deps), ','))))) 26 | } 27 | 28 | # Do not try to install base packages 29 | basepkgs <- function(){ 30 | c("R", rownames(installed.packages(priority="base"))) 31 | } 32 | 33 | -------------------------------------------------------------------------------- /rechecktools/R/linux-binaries.R: -------------------------------------------------------------------------------- 1 | # The goal of this function is to speed up installation of dependencies. 2 | # This is done in two ways: 3 | # - Try to get precompiled binaries when available (mainly on ubuntu) 4 | # - Download files in parallel using curl 5 | # The latter can be removed once fixed in base-R: https://github.com/r-devel/r-svn/pull/155 6 | preinstall_linux_binaries <- function(tocheck){ 7 | rver <- getRversion() 8 | distro <- system2('lsb_release', '-sc', stdout = TRUE) 9 | options(HTTPUserAgent = sprintf("R/%s R (%s); r-universe (%s)", rver, paste(rver, R.version$platform, R.version$arch, R.version$os), distro)) 10 | bioc <- sprintf("https://bioc.r-universe.dev/bin/linux/%s/%s/", distro, substr(rver, 1, 3)) 11 | cran <- sprintf("https://p3m.dev/cran/__linux__/%s/latest", distro) 12 | repos <- c(cran, bioc) 13 | db <- utils::available.packages(repos = c(CRAN = cran, BIOC = bioc, official_bioc_repos())) 14 | checkdeps <- unique(unlist(unname(tools::package_dependencies(tocheck, db = db, which = 'most')))) 15 | alldeps <- tools::package_dependencies(checkdeps, db = db, recursive = TRUE) 16 | packages <- unlist(lapply(checkdeps, function(x){ 17 | c(rev(alldeps[[x]]), x) 18 | })) 19 | packages <- intersect(unique(packages), row.names(db)) 20 | packages <- setdiff(packages, loadedNamespaces()) 21 | versions <- db[packages, 'Version'] 22 | mirrors <- db[packages, 'Repository'] 23 | urls <- sprintf("%s/%s_%s.tar.gz", mirrors, packages, versions) 24 | destdir <- tempfile() 25 | dir.create(destdir) 26 | pwd <- setwd(destdir) 27 | on.exit(setwd(pwd), add = TRUE) 28 | on.exit(unlink(destdir, recursive = TRUE), add = TRUE) 29 | res <- curl::multi_download(urls) 30 | res$ok <- res$success & res$status_code == 200 31 | failures <- res$destfile[!res$ok] 32 | if(length(failures)){ 33 | warning("Failed downloads for: ", paste(failures, collapse = ', ')) 34 | unlink(failures) 35 | res <- res[res$ok,] 36 | } 37 | utils::install.packages(res$destfile, repos = NULL, Ncpus = parallel::detectCores()) 38 | } 39 | 40 | official_bioc_repos <- function(){ 41 | version <- utils:::.BioC_version_associated_with_R_version() 42 | sprintf(c( 43 | BioCsoft = "https://bioconductor.posit.co/packages/%s/bioc", 44 | BioCann = "https://bioconductor.posit.co/packages/%s/data/annotation", 45 | BioCexp = "https://bioconductor.posit.co/packages/%s/data/experiment" 46 | ), version) 47 | } 48 | -------------------------------------------------------------------------------- /rechecktools/R/recheck.R: -------------------------------------------------------------------------------- 1 | #' Reverse Dependency Check 2 | #' 3 | #' Run a reverse dependency check similar to CRAN. 4 | #' 5 | #' @export 6 | #' @rdname recheck 7 | #' @param sourcepkg path or URL to a source package tarball 8 | #' @param which passed to `tools::package_dependencies`; set to "most" to 9 | #' also check reverse suggests. 10 | #' @param preinstall_dependencies start by installing dependencies for all 11 | #' packages to be checked. 12 | recheck <- function(sourcepkg, which = "strong", check_bioc = FALSE, preinstall_dependencies = TRUE){ 13 | # Get the tarball 14 | if(grepl('^https:', sourcepkg)){ 15 | curl::curl_download(sourcepkg, basename(sourcepkg)) 16 | sourcepkg <- basename(sourcepkg) 17 | } 18 | if(!grepl("_", sourcepkg)){ 19 | dl <- utils::download.packages(sourcepkg, '.') 20 | sourcepkg <- basename(dl[,2]) 21 | } 22 | pkg <- sub("_.*", "", basename(sourcepkg)) 23 | checkdir <- dirname(sourcepkg) 24 | repos <- c( 25 | CRAN = 'https://cloud.r-project.org', 26 | BIOC = if(isTRUE(check_bioc)) 'https://bioconductor.posit.co/packages/devel/bioc' 27 | ) 28 | db <- utils::available.packages(repos = repos) 29 | packages <- c(pkg, tools::package_dependencies(pkg, db = db, which = which, reverse = TRUE)[[pkg]]) 30 | if(preinstall_dependencies){ 31 | group_output("Preparing dependencies", { 32 | utils::install.packages(packages, dependencies = TRUE) 33 | deps <- unique(unlist(unname(tools::package_dependencies(packages, recursive = TRUE)))) 34 | update.packages(oldPkgs = deps, ask = FALSE) 35 | }) 36 | } 37 | check_args <- character() 38 | if(nchar(Sys.which('pdflatex')) == 0){ 39 | message("No pdflatex found, skipping pdf checks") 40 | check_args <- c(check_args, '--no-manual --no-build-vignettes') 41 | } 42 | group_output("Running checks", { 43 | Sys.setenv('_R_CHECK_FORCE_SUGGESTS_' = 'false') 44 | if(.Platform$OS.type == 'windows') Sys.setenv(TAR = 'internal') 45 | tools::check_packages_in_dir(checkdir, basename(sourcepkg), 46 | reverse = list(repos = cranrepo, which = which), 47 | Ncpus = parallel::detectCores(), 48 | check_args = check_args) 49 | }) 50 | group_output("Check results details", { 51 | details <- tools::check_packages_in_dir_details(checkdir) 52 | write.csv(details, file.path(checkdir, 'check-details.csv')) 53 | writeLines(paste(format(details), collapse = "\n\n"), file.path(checkdir, 'check-details.txt')) 54 | print(details) 55 | }) 56 | tools::summarize_check_packages_in_dir_results(checkdir) 57 | } 58 | 59 | enable_all_repos <- function(){ 60 | old <- options(repos = c(CRAN = 'https://cloud.r-project.org')) 61 | utils::setRepositories(ind = 1:4) #adds bioc 62 | my_universe <- Sys.getenv('MY_UNIVERSE') 63 | if(nchar(my_universe)){ 64 | options(repos = c(my_universe = my_universe, getOption('repos'))) 65 | } 66 | return(old) 67 | } 68 | 69 | group_output<- function(title, expr){ 70 | if(Sys.getenv('CI') != ""){ 71 | cat("::group::", title, "\n", sep = "") 72 | on.exit(cat("::endgroup::\n")) 73 | } 74 | cat("===========", title, "===========\n") 75 | eval(expr) 76 | } 77 | 78 | test_recheck <- function(pkg, which = 'strong'){ 79 | checkdir <- paste(pkg, 'recheck', sep = '_') 80 | unlink(checkdir, recursive = TRUE) 81 | dir.create(checkdir) 82 | utils::download.packages(pkg, checkdir, repos = 'https://cloud.r-project.org') 83 | recheck(list.files(checkdir, pattern = 'tar.gz$', full.names = TRUE), which = which) 84 | } 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # recheck 2 | 3 | Run a reverse dependency check similar to CRAN. 4 | 5 | ## How to use with GitHub Actions 6 | 7 | We prepared a [reusable workflow](https://docs.github.com/en/actions/using-workflows/reusing-workflows) that you can easily run for free on GitHub Actions. To do this, create a new workflow file in your package git repo named `.github/workflows/recheck.yml` which contains the following: 8 | 9 | ```yml 10 | on: 11 | workflow_dispatch: 12 | inputs: 13 | which: 14 | type: choice 15 | description: Which dependents to check 16 | options: 17 | - strong 18 | - most 19 | 20 | name: Reverse dependency check 21 | 22 | jobs: 23 | revdep_check: 24 | name: Reverse check ${{ inputs.which }} dependents 25 | uses: r-devel/recheck/.github/workflows/recheck.yml@v1 26 | with: 27 | which: ${{ inputs.which }} 28 | subdirectory: '' # set if your R package is in a subdir of the git repo 29 | repository: '' # set to recheck an R package from another git repo 30 | ref: '' # set to recheck a custom tag/branch from another repo 31 | ``` 32 | 33 | After committing this file, you can trigger it using the 'run workflow' button under the actions tab. Note that you can pick a target branch in this UI, so you can perform the reverse dependency checks on a feature branch. 34 | 35 | A summary of the results can be seen in the GHA webUI. Upon completion, the full install/check logs for all packages are available in the 'artifacts' section. 36 | 37 | The `repository` and `ref` parameters are only needed if you want to recheck a package from another git repository than the one that has the workflow. 38 | 39 | ## Real world example 40 | 41 | See here for an example using the V8 package: https://github.com/jeroen/V8/actions/workflows/recheck.yaml 42 | 43 | 44 | ![example](https://github.com/user-attachments/assets/9f5f67fc-a0aa-444b-a5a6-e3afad12a354) 45 | 46 | 47 | ## Recheck goals and limitations 48 | 49 | A reverse dependency check can be a helpful diagnostic tool to identify potential regressions that may need investigation. However it is typically too volatile to use as an automatic pass/fail CI test: checks results from other packages can be influenced by all sorts of factors specific to the platform, hardware, network, system setup, or just random failures. 50 | 51 | The goal of this repo is to provide a simple tool that can run on free infrastructure to discover potential problems with reverse dependencies of your package. It is still up to you to interpret the results. We try to create a setup similar to CRAN, but we need to make trade offs to keep this practical (see below). 52 | 53 | ## Important caveats 54 | 55 | To be able check reverse dependencies, we first need to install all dependencies (including Suggests) for each of those packages. Many CRAN packages indirectly depend on 100+ other packages, so this quickly adds up. 56 | 57 | Hence even if your package only has a handful of dependents, you may need to install over a thousand other packages, before even starting the revdep check. For this reason it is only practical to do this on a platforms for which precompiled R binary packages are available. 58 | 59 | CRAN runs revdep checks on `r-devel` on a server with `debian:testing` but there are currently no R binary packages available for this platform. Instead our containers are based on `ubuntu:latest` and run `r-release`, for which public binary packages are available via https://p3m.dev and https://r-universe.dev. This is one reason results might be slighlty different from what CRAN would show, though in practice it is usually irrelevant. 60 | 61 | It is also not the goal of this repo to support every possible flag in `CMD check` 62 | 63 | ## On rcheckserver 64 | 65 | On GitHub actions we run the check inside the [rcheckserver](https://github.com/r-devel/rcheckserver) 66 | container. This container has the same system libraries installed as the CRAN Debian server. 67 | -------------------------------------------------------------------------------- /.github/workflows/recheck.yml: -------------------------------------------------------------------------------- 1 | name: Run a recheck 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | which: 7 | description: Should be 'strong' or 'most'. 8 | type: string 9 | default: strong 10 | required: false 11 | subdirectory: 12 | description: Subdirectory of R package to be checked 13 | required: false 14 | type: string 15 | default: '' 16 | repository: 17 | description: Repository to checkout (as owner/repo) 18 | required: false 19 | type: string 20 | default: '' 21 | ref: 22 | description: The branch, tag or SHA to checkout 23 | required: false 24 | type: string 25 | default: '' 26 | 27 | env: 28 | R_LIBS_USER: ${{github.workspace}}/pkglib 29 | _R_CHECK_FORCE_SUGGESTS_: 'FALSE' 30 | _R_CHECK_CRAN_INCOMING_: 'FALSE' 31 | _R_CHECK_VIGNETTES_SKIP_RUN_MAYBE_: 'TRUE' #remove for R-4.4 32 | _R_CHECK_ELAPSED_TIMEOUT_: 3600 33 | GITHUB_ACTIONS: '' 34 | CI: '' 35 | 36 | jobs: 37 | prepare: 38 | name: Prepare dependencies 39 | runs-on: ubuntu-latest 40 | container: ghcr.io/r-devel/recheck 41 | outputs: 42 | oldfile: ${{ steps.filenames.outputs.oldfile }} 43 | newfile: ${{ steps.filenames.outputs.newfile }} 44 | steps: 45 | - name: prepare 46 | run: | 47 | mkdir -p $R_LIBS_USER 48 | R -e ".libPaths()" 49 | 50 | - name: checkout 51 | uses: actions/checkout@v4 52 | with: 53 | repository: ${{ inputs.repository }} 54 | ref: ${{ inputs.ref }} 55 | path: source 56 | 57 | - name: Set package source directory 58 | run: | 59 | if [ "${{ inputs.subdirectory }}" ]; then 60 | echo "PKG_SOURCE_DIR=source/${{ inputs.subdirectory }}" >> $GITHUB_ENV 61 | else 62 | echo "PKG_SOURCE_DIR=source" >> $GITHUB_ENV 63 | fi 64 | 65 | - name: download dependencies 66 | run: rechecktools::install_recheck_deps('${{env.PKG_SOURCE_DIR}}', '${{inputs.which}}') 67 | shell: Rscript {0} 68 | 69 | - name: build source package 70 | run: | 71 | mkdir newpkg 72 | R CMD build ${{env.PKG_SOURCE_DIR}} 73 | mv *.tar.gz newpkg/ 74 | rm -Rf source 75 | 76 | - name: Get old version of package 77 | shell: Rscript {0} 78 | run: | 79 | dir.create("oldpkg") 80 | pkg <- sub("_.*", "", list.files("newpkg")) 81 | download.packages(pkg, "oldpkg", repos = "https://cran.r-project.org") 82 | 83 | - name: Get file names 84 | id: filenames 85 | run: | 86 | echo "oldfile=$(cd oldpkg; echo *.tar.gz)" >> "$GITHUB_OUTPUT" 87 | echo "newfile=$(cd newpkg; echo *.tar.gz)" >> "$GITHUB_OUTPUT" 88 | 89 | - name: Save package and library 90 | uses: actions/cache/save@v4 91 | with: 92 | path: | 93 | pkglib 94 | newpkg 95 | oldpkg 96 | key: ${{ runner.os }}-${{ github.run_id }}-${{github.run_attempt}} 97 | 98 | checks: 99 | needs: prepare 100 | runs-on: ubuntu-latest 101 | name: Recheck ${{matrix.check == 'oldpkg' && needs.prepare.outputs.oldfile || needs.prepare.outputs.newfile}} (${{matrix.check}}) 102 | container: ghcr.io/r-devel/recheck 103 | timeout-minutes: 600 104 | strategy: 105 | matrix: 106 | check: [ 'oldpkg', 'newpkg' ] 107 | steps: 108 | 109 | - name: Download package and library 110 | uses: actions/cache/restore@v4 111 | with: 112 | path: | 113 | pkglib 114 | newpkg 115 | oldpkg 116 | key: ${{ runner.os }}-${{ github.run_id }}-${{github.run_attempt}} 117 | 118 | - name: Run checks 119 | shell: Rscript {0} 120 | run: | 121 | checkdir <- "${{matrix.check}}" 122 | options(repos = c(CRAN = 'https://cloud.r-project.org')) 123 | reverse <- list(repos = 'https://cloud.r-project.org', which = "${{ inputs.which }}") 124 | Sys.setenv(R_PROFILE="nothing") # do not set binary p3m mirror in child proc 125 | tools::check_packages_in_dir(checkdir, reverse = reverse, Ncpus = parallel::detectCores()) 126 | details <- tools::check_packages_in_dir_details(checkdir) 127 | write.csv(details, file.path(checkdir, 'check-details.csv')) 128 | writeLines(paste(format(details), collapse = "\n\n"), file.path(checkdir, 'check-details.txt')) 129 | tools::summarize_check_packages_in_dir_results(checkdir) 130 | 131 | - uses: actions/upload-artifact@v4 132 | with: 133 | name: ${{matrix.check}}-checklogs 134 | path: | 135 | ${{matrix.check}}/*/*.log 136 | ${{matrix.check}}/*/*.out 137 | ${{matrix.check}}/*/*.Rout 138 | ${{matrix.check}}/*/*.fail 139 | ${{matrix.check}}/Outputs 140 | ${{matrix.check}}/check-details.* 141 | 142 | results: 143 | name: Show results 144 | needs: checks 145 | runs-on: ubuntu-latest 146 | container: ghcr.io/r-hub/r-minimal/r-minimal:latest 147 | steps: 148 | - name: Download log files 149 | uses: actions/download-artifact@v4 150 | 151 | - name: Get results 152 | shell: Rscript {0} 153 | run: | 154 | cat("\n------- Check results summary ------\n") 155 | tools::summarize_check_packages_in_dir_results("newpkg-checklogs") 156 | 157 | # Check for regressions 158 | cat("\n------- Check for regressions ------\n") 159 | changes <- tools::check_packages_in_dir_changes("newpkg-checklogs", "oldpkg-checklogs") 160 | if(nrow(changes)){ 161 | cat("Changes:\n") 162 | print(changes) 163 | stop("Found potential problems") 164 | } else { 165 | cat("No changes between old and new version\n") 166 | } 167 | --------------------------------------------------------------------------------