Advice on using maximum dependency versions

I have a package that needs to pin a maximum version for some of its dependencies. I do not plan to submit this package to CRAN, it's primarily for internal use.

Imports: 
    dplyr,
    ggplot2 (< 4.0.0)

However, pak can only install the latest version of dependencies from CRAN. (See related feature request in pak.)
Thus, using the setup-r-dependencies action fails as pak can't handle the pinned package version:

  Error: 
  ! error in pak subprocess
  Caused by error: 
  ! Could not solve package dependencies:
  * deps::.: Can't install dependency ggplot2 (< 4.0.0)
  * any::sessioninfo: dependency conflict
  * any::rcmdcheck: dependency conflict
  ---
  Backtrace:
  1. pak::lockfile_create(c(deps, extra_deps), lockfile = ".github/pkg.lock", …
  2. pak:::remote(function(...) { …
  3. err$throw(res$error)

Here's an example repo with a minimal DESCRIPTION file and github actions workflow.

A workaround is to remove any version pins from the DESCRIPTION, let pak install the dependencies from the latest versions, then downgrade the packages as needed with remotes::install_version(). See example of this strategy here.

Is this the best way to manage dependencies with maximum versions, at least for now until pak implements this feature? I'm interested in seeing other examples and solutions if anyone has found alternate strategies.

conda/mamba does a decent job at solving dependencies, but it would be ideal to not have to manually create an environment file that duplicates the package version requirements that should already be specified in the DESCRIPTION file. conda also can't handle packages outside of the conda ecosystem, while pak can handle r-universe and github repos.

I haven't tried it out, but I think I remember that you can use the extra-packages argument to pin packages to a version.

In your case ggplot2 to 3.5.2

# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
on:
  push:
    branches: [main, master]
  pull_request:

name: R-CMD-check.yaml

permissions: read-all

jobs:
  R-CMD-check:
    runs-on: ${{ matrix.config.os }}

    name: ${{ matrix.config.os }} (${{ matrix.config.r }})

    strategy:
      fail-fast: false
      matrix:
        config:
          - {os: ubuntu-latest,   r: 'release'}

    env:
      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
      R_KEEP_PKG_SOURCE: yes

    steps:
      - uses: actions/checkout@v4

      - uses: r-lib/actions/setup-pandoc@v2

      - uses: r-lib/actions/setup-r@v2
        with:
          r-version: ${{ matrix.config.r }}
          http-user-agent: ${{ matrix.config.http-user-agent }}
          use-public-rspm: true

      - uses: r-lib/actions/setup-r-dependencies@v2
        with:
          extra-packages: |
            any::rcmdcheck
            ggplot2@3.5.2
          needs: check

      - uses: r-lib/actions/check-r-package@v2
        with:
          upload-snapshots: true
          build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")'

Thanks @ryanzomorrodi! I was trying to avoid hard-coding a dependency version outside of the DESCRIPTION file, but I think this is the best way to do it currently.

In general, it's a really bad idea to depend on latest versions of packages, especially the external ones. This may (will) cause a lot of troubles. That's why tools like renv, conda, npm etc. have emerged long time and still exist. Rethink twice if you really want latest versions. Imagine you're rebuilding your package in three months. Many of the dependent libraries will change, some changes may be backward incompatibile and than your package is broken. Moreover, you won't be able to restore the previous working version because you haven't tracked the versions of dependencies.

@olibravo: I believe you've misunderstood my problem. I'm trying to depend on a package version that is older than the latest version (i.e. ggplot2 < 4.0.0). CRAN, pak, renv, etc are not set up well to handle that situation. In my experience, conda/mamba do a decent job of resolving dependencies in this situation, but it would be a duplication to also provide an environment yaml file alongside the DESCRIPTION file.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.