Dependency floor checks #11
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Dependency floor checks | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| r_version: | |
| description: "R version to test. Use the latest patch release for the minimum supported R minor version." | |
| required: true | |
| default: "4.1.3" | |
| install_suggests: | |
| description: "Install Suggests too. Disable only for a faster import-only smoke check." | |
| required: false | |
| type: boolean | |
| default: true | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: dependency-floor-${{ github.ref }} | |
| cancel-in-progress: false | |
| env: | |
| GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} | |
| NOT_CRAN: true | |
| R_REMOTES_NO_ERRORS_FROM_WARNINGS: true | |
| _R_CHECK_FORCE_SUGGESTS_: ${{ inputs.install_suggests }} | |
| DEPENDENCY_FLOOR_CACHE_VERSION: v3 | |
| RSPM: https://packagemanager.posit.co/cran/__linux__/focal/latest | |
| R_LIBS: ${{ github.workspace }}/.cache/r-library | |
| R_LIBS_USER: ${{ github.workspace }}/.cache/r-library | |
| EUNOMIA_DATA_FOLDER: ${{ github.workspace }}/.cache/eunomia | |
| UV_CACHE_DIR: ${{ github.workspace }}/.cache/uv | |
| RETICULATE_PY_VERSION: 3.11 | |
| CDM5_POSTGRESQL_CDM_SCHEMA: ${{ secrets.CDM5_POSTGRESQL_CDM_SCHEMA }} | |
| CDM5_POSTGRESQL_OHDSI_SCHEMA: ${{ secrets.CDM5_POSTGRESQL_OHDSI_SCHEMA }} | |
| CDM5_POSTGRESQL_PASSWORD: ${{ secrets.CDM5_POSTGRESQL_PASSWORD }} | |
| CDM5_POSTGRESQL_SERVER: ${{ secrets.CDM5_POSTGRESQL_SERVER }} | |
| CDM5_POSTGRESQL_USER: ${{ secrets.CDM5_POSTGRESQL_USER }} | |
| jobs: | |
| dependency-floor: | |
| runs-on: ubuntu-latest | |
| container: rocker/r-ver:${{ inputs.r_version }} | |
| steps: | |
| - name: Checkout repo | |
| uses: actions/checkout@v5 | |
| - name: Install system requirements | |
| run: | | |
| apt-get update | |
| apt-get install -y --no-install-recommends \ | |
| build-essential \ | |
| cmake \ | |
| curl \ | |
| default-jdk \ | |
| git \ | |
| libbz2-dev \ | |
| libcurl4-openssl-dev \ | |
| libfontconfig1-dev \ | |
| libfreetype6-dev \ | |
| libfribidi-dev \ | |
| libgit2-dev \ | |
| libharfbuzz-dev \ | |
| libicu-dev \ | |
| libjpeg-dev \ | |
| liblzma-dev \ | |
| libomp-dev \ | |
| libpng-dev \ | |
| libssh-dev \ | |
| libssl-dev \ | |
| libtiff5-dev \ | |
| libwebp-dev \ | |
| libxml2-dev \ | |
| make \ | |
| pandoc \ | |
| pkg-config \ | |
| python3 \ | |
| python3-pip \ | |
| python3-venv \ | |
| zlib1g-dev | |
| R CMD javareconf | |
| - name: Prepare caches | |
| run: | | |
| mkdir -p "${R_LIBS_USER}" "${EUNOMIA_DATA_FOLDER}" "${UV_CACHE_DIR}" | |
| - name: Restore R library cache | |
| id: cache-r-library-restore | |
| uses: actions/cache/restore@v5 | |
| with: | |
| path: ${{ env.R_LIBS_USER }} | |
| key: dependency-floor-${{ env.DEPENDENCY_FLOOR_CACHE_VERSION }}-focal-r${{ inputs.r_version }}-suggests-${{ inputs.install_suggests }}-${{ hashFiles('DESCRIPTION') }} | |
| restore-keys: | | |
| dependency-floor-${{ env.DEPENDENCY_FLOOR_CACHE_VERSION }}-focal-r${{ inputs.r_version }}-suggests-${{ inputs.install_suggests }}- | |
| - name: Cache Eunomia datasets | |
| uses: actions/cache@v5 | |
| with: | |
| path: ${{ env.EUNOMIA_DATA_FOLDER }} | |
| key: eunomia-v1-${{ runner.os }}-GiBleed_5.3 | |
| - name: Cache uv | |
| uses: actions/cache@v5 | |
| with: | |
| path: ${{ env.UV_CACHE_DIR }} | |
| key: uv-v1-${{ runner.os }}-py${{ env.RETICULATE_PY_VERSION }} | |
| - name: Install dependency floor | |
| shell: Rscript {0} | |
| env: | |
| INSTALL_SUGGESTS: ${{ inputs.install_suggests }} | |
| run: | | |
| .libPaths(c(Sys.getenv("R_LIBS_USER"), .libPaths())) | |
| message("R library paths: ", paste(.libPaths(), collapse = ", ")) | |
| repos <- Sys.getenv("RSPM", unset = "https://cloud.r-project.org") | |
| install.packages(c("remotes", "rcmdcheck"), repos = repos) | |
| options(Ncpus = max(1L, parallel::detectCores())) | |
| installSuggests <- tolower(Sys.getenv("INSTALL_SUGGESTS", unset = "false")) == "true" | |
| description <- read.dcf("DESCRIPTION")[1, ] | |
| hardDependencyFields <- intersect(c("Depends", "Imports", "LinkingTo"), names(description)) | |
| dependencyFields <- hardDependencyFields | |
| suggestedPackages <- character() | |
| dependencyFields <- intersect(dependencyFields, names(description)) | |
| message("Installing dependency fields: ", paste(dependencyFields, collapse = ", ")) | |
| parseDependencies <- function(fields) { | |
| dependencyText <- paste(description[fields], collapse = ",") | |
| dependencyText <- gsub("[\r\n]", " ", dependencyText) | |
| dependencies <- trimws(unlist(strsplit(dependencyText, ","))) | |
| dependencies <- dependencies[nzchar(dependencies)] | |
| parsed <- regexec("^([A-Za-z0-9.]+)\\s*(?:\\(([^ ]+)\\s*([^)]+)\\))?$", dependencies) | |
| parsed <- regmatches(dependencies, parsed) | |
| parsed <- do.call(rbind, lapply(parsed, function(x) { | |
| length(x) <- 4 | |
| data.frame( | |
| package = x[2], | |
| operator = x[3], | |
| version = x[4], | |
| stringsAsFactors = FALSE | |
| ) | |
| })) | |
| parsed[parsed$package != "R", ] | |
| } | |
| parsed <- parseDependencies(dependencyFields) | |
| if (installSuggests && "Suggests" %in% names(description)) { | |
| suggested <- parseDependencies("Suggests") | |
| suggestedPackages <- suggested$package | |
| parsed <- rbind(parsed, suggested) | |
| } | |
| floorDependencies <- parsed[parsed$operator == ">=", ] | |
| write.csv(floorDependencies, "dependency-floor-requested.csv", row.names = FALSE) | |
| if (installSuggests) { | |
| compatibilityPins <- data.frame( | |
| package = c("Matrix", "arrow", "pbkrtest", "xgboost"), | |
| version = c("1.6-5", "17.0.0", "0.5.2", "1.7.8.1"), | |
| stringsAsFactors = FALSE | |
| ) | |
| write.csv(compatibilityPins, "dependency-floor-compatibility-pins.csv", row.names = FALSE) | |
| for (i in seq_len(nrow(compatibilityPins))) { | |
| package <- compatibilityPins$package[[i]] | |
| version <- compatibilityPins$version[[i]] | |
| message("Installing old-R compatibility pin: ", package, " ", version) | |
| remotes::install_version( | |
| package = package, | |
| version = version, | |
| repos = repos, | |
| dependencies = FALSE, | |
| upgrade = "never" | |
| ) | |
| } | |
| } else { | |
| write.csv(data.frame(package = character(), version = character()), | |
| "dependency-floor-compatibility-pins.csv", | |
| row.names = FALSE | |
| ) | |
| } | |
| remotes::install_deps( | |
| dependencies = hardDependencyFields, | |
| repos = repos, | |
| upgrade = "never" | |
| ) | |
| if (length(suggestedPackages) > 0) { | |
| installedPackages <- rownames(installed.packages()) | |
| suggestedPackages <- setdiff(suggestedPackages, installedPackages) | |
| if (length(suggestedPackages) > 0) { | |
| message("Installing direct suggested packages: ", paste(suggestedPackages, collapse = ", ")) | |
| install.packages( | |
| suggestedPackages, | |
| repos = repos, | |
| dependencies = hardDependencyFields | |
| ) | |
| } | |
| missingSuggestedPackages <- setdiff(suggestedPackages, rownames(installed.packages())) | |
| if (length(missingSuggestedPackages) > 0) { | |
| stop( | |
| "Failed to install direct suggested packages: ", | |
| paste(missingSuggestedPackages, collapse = ", ") | |
| ) | |
| } | |
| } | |
| sourceFloorPackages <- c("Andromeda", "FeatureExtraction") | |
| sourceRepos <- "https://cloud.r-project.org" | |
| for (i in seq_len(nrow(floorDependencies))) { | |
| package <- floorDependencies$package[[i]] | |
| version <- floorDependencies$version[[i]] | |
| useSource <- package %in% sourceFloorPackages | |
| message( | |
| "Installing floor dependency: ", | |
| package, | |
| " ", | |
| version, | |
| if (useSource) " from source" else "" | |
| ) | |
| remotes::install_version( | |
| package = package, | |
| version = version, | |
| repos = if (useSource) sourceRepos else repos, | |
| dependencies = FALSE, | |
| upgrade = "never", | |
| type = if (useSource) "source" else getOption("pkgType") | |
| ) | |
| } | |
| installed <- as.data.frame(installed.packages()[, c("Package", "Version")]) | |
| declared <- parsed$package | |
| installed <- installed[installed$Package %in% declared, ] | |
| installed <- installed[order(tolower(installed$Package)), ] | |
| write.csv(installed, "dependency-floor-installed.csv", row.names = FALSE) | |
| - name: Save R library cache | |
| if: steps.cache-r-library-restore.outputs.cache-hit != 'true' | |
| uses: actions/cache/save@v5 | |
| with: | |
| path: ${{ env.R_LIBS_USER }} | |
| key: ${{ steps.cache-r-library-restore.outputs.cache-primary-key }} | |
| - name: Run R CMD check | |
| shell: Rscript {0} | |
| run: | | |
| .libPaths(c(Sys.getenv("R_LIBS_USER"), .libPaths())) | |
| message("R library paths: ", paste(.libPaths(), collapse = ", ")) | |
| result <- rcmdcheck::rcmdcheck( | |
| args = c("--no-manual", "--no-build-vignettes", "--ignore-vignettes"), | |
| build_args = c("--no-manual", "--no-build-vignettes"), | |
| error_on = "warning", | |
| check_dir = "check" | |
| ) | |
| print(result) | |
| - name: Upload results | |
| if: always() | |
| uses: actions/upload-artifact@v5 | |
| with: | |
| name: dependency-floor-results | |
| path: | | |
| check | |
| dependency-floor-requested.csv | |
| dependency-floor-compatibility-pins.csv | |
| dependency-floor-installed.csv |