diff --git a/.github/scripts/check_revdeps.R b/.github/scripts/check_revdeps.R new file mode 100644 index 000000000..be3a60673 --- /dev/null +++ b/.github/scripts/check_revdeps.R @@ -0,0 +1,87 @@ +# ==================================================================== # +# TITLE: # +# AMR: An R Package for Working with Antimicrobial Resistance Data # +# # +# SOURCE CODE: # +# https://github.com/msberends/AMR # +# # +# PLEASE CITE THIS SOFTWARE AS: # +# Berends MS, Luz CF, Friedrich AW, et al. (2022). # +# AMR: An R Package for Working with Antimicrobial Resistance Data. # +# Journal of Statistical Software, 104(3), 1-31. # +# https://doi.org/10.18637/jss.v104.i03 # +# # +# Developed at the University of Groningen and the University Medical # +# Center Groningen in the Netherlands, in collaboration with many # +# colleagues from around the world, see our website. # +# # +# This R package is free software; you can freely use and distribute # +# it for both personal and commercial purposes under the terms of the # +# GNU General Public License version 2.0 (GNU GPL-2), as published by # +# the Free Software Foundation. # +# We created this package for both routine data analysis and academic # +# research and it was publicly released in the hope that it will be # +# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. # +# # +# Visit our website for the full manual and a complete tutorial about # +# how to conduct AMR data analysis: https://amr-for-r.org # +# ==================================================================== # + +# Run R CMD check on all CRAN packages that depend on AMR, against the INSTALLED development version of AMR. +# Used by .github/workflows/check-revdeps.yaml; run from the root of the repository, after installing AMR from it: +# Rscript .github/scripts/check_revdeps.R +# Fails if any reverse dependency returns an ERROR or WARNING. + +# only CRAN, also when other repositories are set, since this is about CRAN releases +repos <- c(CRAN = "https://cloud.r-project.org") +db <- utils::available.packages(repos = repos) +revdeps <- sort(tools::package_dependencies("AMR", db = db, reverse = TRUE, which = "all")[["AMR"]]) +if (length(revdeps) == 0) { + message("No reverse dependencies on CRAN") + quit(status = 0) +} +message("Reverse dependencies: ", paste(revdeps, collapse = ", ")) + +# all dependencies of the reverse dependencies, but never AMR itself, which is the development version installed from this repository +deps <- unique(unlist(tools::package_dependencies(revdeps, db = db, which = "all"), use.names = FALSE)) +base_pkgs <- rownames(utils::installed.packages(priority = "base")) +deps <- setdiff(deps, c("AMR", base_pkgs, rownames(utils::installed.packages()))) +if (length(deps) > 0) { + # pak also installs the system requirements of these packages + tryCatch(pak::pkg_install(deps, upgrade = FALSE), error = function(e) { + message("pak failed (", conditionMessage(e), "), falling back to install.packages()") + utils::install.packages(deps) + }) +} +amr_version <- read.dcf("DESCRIPTION", fields = "Version")[1, 1] +if (as.character(utils::packageVersion("AMR")) != amr_version) { + stop("installed AMR is v", utils::packageVersion("AMR"), ", expected the development version v", amr_version) +} +message("Checking against AMR v", amr_version) + +check_dir <- file.path(tempdir(), "revdeps") +dir.create(check_dir, showWarnings = FALSE) +tarballs <- utils::download.packages(revdeps, destdir = check_dir, repos = repos, type = "source")[, 2] + +results <- vapply(tarballs, FUN.VALUE = character(1), function(tarball) { + pkg <- sub("_.*", "", basename(tarball)) + message("\n=== Checking ", pkg, " ===") + out <- suppressWarnings(system2( + file.path(R.home("bin"), "R"), + c("CMD", "check", "--no-manual", "--as-cran", "-o", shQuote(check_dir), shQuote(tarball)), + stdout = TRUE, + stderr = TRUE, + # skip the incoming checks for CRAN submission, which concern the maintainers of the reverse dependencies + env = c("_R_CHECK_FORCE_SUGGESTS_=false", "_R_CHECK_CRAN_INCOMING_=false") + )) + cat(out, sep = "\n") + status <- grep("^Status:", out, value = TRUE) + if (length(status) == 0) "ERROR (check did not finish)" else trimws(sub("^Status:", "", status[length(status)])) +}, USE.NAMES = FALSE) +names(results) <- revdeps + +message("\n=== Summary against AMR v", amr_version, " ===") +message(paste0(format(names(results)), " ", results, collapse = "\n")) +if (any(grepl("ERROR|WARNING", results))) { + quit(status = 1) +} diff --git a/.github/workflows/check-revdeps.yaml b/.github/workflows/check-revdeps.yaml new file mode 100644 index 000000000..470cc23bb --- /dev/null +++ b/.github/workflows/check-revdeps.yaml @@ -0,0 +1,74 @@ +# ==================================================================== # +# TITLE: # +# AMR: An R Package for Working with Antimicrobial Resistance Data # +# # +# SOURCE CODE: # +# https://github.com/msberends/AMR # +# # +# PLEASE CITE THIS SOFTWARE AS: # +# Berends MS, Luz CF, Friedrich AW, et al. (2022). # +# AMR: An R Package for Working with Antimicrobial Resistance Data. # +# Journal of Statistical Software, 104(3), 1-31. # +# https://doi.org/10.18637/jss.v104.i03 # +# # +# Developed at the University of Groningen and the University Medical # +# Center Groningen in the Netherlands, in collaboration with many # +# colleagues from around the world, see our website. # +# # +# This R package is free software; you can freely use and distribute # +# it for both personal and commercial purposes under the terms of the # +# GNU General Public License version 2.0 (GNU GPL-2), as published by # +# the Free Software Foundation. # +# We created this package for both routine data analysis and academic # +# research and it was publicly released in the hope that it will be # +# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. # +# # +# Visit our website for the full manual and a complete tutorial about # +# how to conduct AMR data analysis: https://amr-for-r.org # +# ==================================================================== # + +# Run R CMD check on all CRAN packages that depend on AMR, against the development version of AMR installed from this repository. +# This is informative only: it is not a required check, so a failure does not block anything, but it shows which reverse dependencies break before a CRAN release. + +on: + push: + # only on main + branches: [main] + # allow manual runs from the Actions tab + workflow_dispatch: + +name: check-revdeps + +jobs: + check-revdeps: + runs-on: ubuntu-latest + + name: Reverse dependencies (R-release) + + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-pandoc@v2 + + - uses: r-lib/actions/setup-r@v2 + with: + r-version: release + # use RStudio Package Manager to quickly install packages + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + # AMR has no hard dependencies; pak is used to install the dependencies of the reverse dependencies + dependencies: '"hard"' + extra-packages: any::pak + + - name: Install AMR from this repository + shell: bash + run: R CMD INSTALL . + + - name: Check reverse dependencies against the installed AMR + shell: bash + run: Rscript .github/scripts/check_revdeps.R diff --git a/DESCRIPTION b/DESCRIPTION index 79b379575..8be709a1e 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,5 +1,5 @@ Package: AMR -Version: 3.0.1.9129 +Version: 3.0.1.9130 Date: 2026-10-13 Title: Antimicrobial Resistance Data Analysis Description: Functions to simplify and standardise antimicrobial resistance (AMR) diff --git a/NEWS.md b/NEWS.md index bfdb75dc4..f9d80c1f3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -# AMR 3.0.1.9129 +# AMR 3.0.1.9130 Planned as v3.1.0, mid October 2026. @@ -24,6 +24,7 @@ Planned as v3.1.0, mid October 2026. Previously, `mo_domain()` was an alias of `mo_kingdom()`; it is now a distinct function. Its output is therefore unchanged, while `mo_kingdom()` now returns the new formal kingdom. A one-time note per session explains this change when bacterial or archaeal records are queried. * Parallel computing in `as.sir()`, `antibiogram()`, and `wisca()` now uses the `future` and `future.apply` packages, which is faster. A non-sequential plan (e.g., `future::plan(future::multisession)`) must be active before using `parallel = TRUE` (#281). * The options of `capped_mic_handling` in `as.sir()` have been redefined as `"none"`, `"conservative"`, `"standard"` (default), and `"lenient"`. The option `"inverse"` is no longer available (#243). +* `as.sir()` now returns WT/NWT (Wildtype/Non-wildtype) instead of S/R when using ECOFF-based interpretation with `breakpoint_type = "ECOFF"`. WT/NWT results are fully supported in all resistance and susceptibility functions and in all plots (#254). ### New * **Updated clinical breakpoints** @@ -32,8 +33,6 @@ Planned as v3.1.0, mid October 2026. * `clinical_breakpoints` now contains blocking rows (`NA` breakpoints, with the reason in `note`) where EUCAST gives no breakpoint for an organism, so that `as.sir()` no longer falls back to the breakpoint of a broader taxon * Restrictions in EUCAST notes are applied, e.g., zone diameter breakpoints for *E. coli* only * EUCAST PK-PD (non-species related) breakpoints of 2019-2023 and *H. parainfluenzae* MIC breakpoints are now included -* **Wildtype/Non-wildtype interpretation** - * `as.sir()` now returns WT/NWT (Wildtype/Non-wildtype) when using ECOFF-based interpretation with `breakpoint_type = "ECOFF"`. WT/NWT results are fully supported in all resistance and susceptibility functions and in all plots (#254). * **Unified interpretive rules** * New function `interpretive_rules()` applies the interpretive rules of both EUCAST and CLSI. `eucast_rules()` is now a wrapper around this function (#235, #259). * Species named in a rule now also match all other names of the same accepted taxon (e.g., 'Clostridium ramosum' for *Thomasclavelia ramosa*). This also updated the `intrinsic_resistant` data set. diff --git a/cran-comments.md b/cran-comments.md index 82e0f4bfb..a1633c454 100644 --- a/cran-comments.md +++ b/cran-comments.md @@ -1,4 +1,13 @@ -This version is a bugfix release (v3.0.1) following the release of v3.0.0 in June 2025. +This version is a minor release (v3.1.0) following the bugfix release v3.0.1 in September 2025. It adds the EUCAST 2026 and CLSI 2026 clinical breakpoints (EUCAST 2026 is now the default), a taxonomic update of all microorganisms, unified EUCAST and CLSI interpretive rules, support for `tidymodels` pipelines, and many improvements and bug fixes, as listed in `NEWS.md`. + +This release contains four breaking changes, each documented in `NEWS.md`: + +* Following the reclassification of Bacteria and Archaea into new kingdoms (Göker and Oren, 2024), `mo_kingdom()` now returns the formal kingdom, while the new function `mo_domain()` returns the former output +* Parallel computing in `as.sir()`, `antibiogram()`, and `wisca()` now uses the suggested packages `future` and `future.apply` +* The options of the `capped_mic_handling` argument of `as.sir()` have been redefined +* `as.sir()` now returns WT/NWT (wildtype/non-wildtype) instead of S/R for interpretation based on epidemiological cut-off values (ECOFFs) + +This package has two reverse dependencies, `MIC` and `MIMER`, both checked against this version. `MIMER` passes. `MIC` is affected by the WT/NWT change, which makes some of its unit tests fail; its maintainer has been informed in advance through an issue in its GitHub repository. As with all previous >20 releases, some CHECKs on `oldrel` may return a `NOTE` for narrowly exceeding the installation size limit. This has been reduced to a minimum in prior coordination with CRAN maintainers and currently returns only an `INFO` on `release` and `devel`.