Skip to content

don't treat biocViews as proof of bioconductor origin#2306

Merged
kevinushey merged 4 commits into
mainfrom
bugfix/bioc-views-not-proof
Jun 8, 2026
Merged

don't treat biocViews as proof of bioconductor origin#2306
kevinushey merged 4 commits into
mainfrom
bugfix/bioc-views-not-proof

Conversation

@kevinushey

Copy link
Copy Markdown
Collaborator

Problem

renv used the presence of a biocViews field in a package's DESCRIPTION as "proof" that the package came from Bioconductor (#2128, problem 1). But some CRAN packages legitimately declare biocViews, and Posit Package Manager can serve Bioconductor packages from a CRAN-like "R repository". In those cases renv misclassified the package: it recorded Source: Bioconductor, activated the Bioconductor repositories, and injected a Bioconductor/BiocVersion block into the lockfile -- pulling the package from bioconductor.org instead of the repository it actually came from.

Approach

The key insight is that what matters for restore is where a package was obtained (the Repository field) rather than where it originally came from (its git provenance). A genuine Bioconductor package's DESCRIPTION carries Repository: Bioconductor <ver> (and git_url: https://git.bioconductor.org/...); a CRAN/PPM package carries Repository: CRAN (or a repo name).

  • New helper renv_description_bioconductor(dcf) (R/bioconductor.R) decides origin by precedence:

    1. no biocViews -> not Bioconductor;
    2. Repository contains "Bioconductor" (matched anywhere, case-insensitive, so custom-named PPM Bioconductor repositories are recognized) -> Bioconductor;
    3. Repository is CRAN / a known mirror / one of the active repos -> not Bioconductor (covers CRAN packages and PPM CRAN-like "R repositories", even when they retain Bioconductor git provenance);
    4. otherwise fall back to git_url provenance, then to the historical behaviour of trusting biocViews.
  • The snapshot classification, _source_custom, field-strip blocks, retrieve.R repo activation, graph.R resolution, install.R, and lockfile.R call sites are rewired to use this (and the new setting below) instead of a bare nzchar(biocViews) check. Because the lockfile Bioconductor block is driven by Source == "Bioconductor", correcting classification also resolves the unwanted BiocVersion/repo injection (problem 2) for the misclassified case.

  • New bioconductor.enabled project setting (logical, default TRUE, persisted in renv/settings.json). When FALSE, renv never infers a Bioconductor source, activates the Bioconductor repositories, or writes a Bioconductor entry into the lockfile -- a first-class opt-out for repository-only projects, replacing the options(renv.bioconductor.repos = ...) workaround.

Notes on PPM / mirrors

renv does not hard-code Bioconductor URLs: it asks BiocManager (which honors BioC_mirror) for the repositories, or uses the renv.bioconductor.repos override verbatim. So a PPM Bioconductor mirror is used automatically when configured, and needs no special handling here. The vignette is updated to explain the BioC_mirror vs renv.bioconductor.repos distinction and the reproducibility options. Capturing the mirror in the lockfile was considered and deliberately left out of scope.

Testing

Added snapshot tests covering: CRAN + biocViews -> Repository; a CRAN-like (PPM) repo + biocViews + bioc git provenance -> Repository; genuine Repository: Bioconductor and custom-named PPM bioc repos -> Bioconductor; and bioconductor.enabled = FALSE disabling inference and the lockfile entry.

All passing locally: snapshot, bioconductor, settings, lockfile, install, graph, retrieve, restore (0 failures).

Closes #2128.

renv used the presence of a biocViews field in a package's DESCRIPTION as
proof that the package came from Bioconductor. Some CRAN packages declare
biocViews, and Posit Package Manager can serve Bioconductor packages from a
CRAN-like "R repository", so renv misclassified such packages as Bioconductor.

Introduce renv_description_bioconductor(), which decides a package's origin
from where it was obtained (the Repository field, and Bioconductor git
provenance) rather than from biocViews alone, and rewire the snapshot,
retrieve, graph, install, and lockfile call sites to use it.

Also add a bioconductor.enabled project setting (default TRUE) so a project
can opt out of Bioconductor entirely.

#2128
On R-devel, Bioconductor often has no usable release yet (BiocManager maps
the R version only to a 'future' Bioconductor release with no installable
packages), so the live bioc install tests fail with "failed to install".

Add renv_bioconductor_supported(), which consults BiocManager's R-to-
Bioconductor version map and reports whether the running R maps to a
Bioconductor release with a usable status, and a skip_if_no_bioconductor()
test helper built on it. Guard the tests that perform real Bioconductor
installs or resolution.
R CMD build in R-devel (r90095, PR#17549) fails to build a package whose
source tree contains only top-level files, because the build directory is
created solely from the package's subdirectories; the test-r.R fixture was
a DESCRIPTION-only package and hit this.

Add renv_package_skeleton() to utils.R, which writes a minimal but complete
package (DESCRIPTION, NAMESPACE, and an R/ directory), and use it in
test-r.R so the package both builds and installs.
@kevinushey kevinushey merged commit b1fd8fa into main Jun 8, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

disabling bioconductor

1 participant