For a package containing a golem app, how to ensure dependent packages will be installed from packrat and not from CRAN

Hi,
I have a very naive question regarding package development. I developed a R package using packrat. How can I make sure that, when I share my package with community, dependent packages will also be installed through packrat ??

You can recommend that users use packrat with your package, e.g. by adding instructions in the README and/or a vingette.

The .Rprofile file added by packrat automatically activates packrat whenever a user starts R from that directory. Thus as long as you have that project-specific .Rprofile bundled with your R package, you can instruct users to use install package as follows (assuming it is available online in a Git repository):

git clone https://.../myPkg
cd myPkg
Rscript -e 'packrat::restore()'
Rscript -e 'devtools::install()'

Prior to running devtools::install(), packrat will download and install all the exact depenencies. And then to use the package, they should always start R from the myPkg/ directory.

But of course this won't work if they instead install your package via remotes::install_github() or similar.

Is there a reason you need exact versions of the dependencies to use your R package? You can specify minimum required versions in your DESCRIPTION file.

Update: Recent versions of packrat don't automatically run packrat::restore() when R is opened in a project. Thus I added the explict step of running packrat::restore() to the hypothetical installation instructions.

1 Like

Do you want to share source package for development using packrat for other developers, or share your package for use ?
In the second case, sharing your package should not involved packrat. Your dependencies will be installed from DESCRIPTION when using install.packages if on CRAN or remotes otherwise

1 Like

Thanks, Both of you. When I posted this, I was vey new to package development. I asked this question because I was converting shiny app to R package using Golem by @colin. Since beginning, I used packrat with shiny app and therefore, i thought that's the only way to keep consistency while converting it in to package. However, over the time I realised that (as both of you also mentioned) mentioning the minimum version in the DESCRIPTION file does the trick. And that has solved my problem.

Cheers,
Thanks.

1 Like

Oh this is specific ! For golem App inside package, I guess it will depend how you will share them. Usual way for a shiny app is to deploy the application on a shared server for the user to use it. The dependency mechanism will depend on how you deploy. Another option as they are in :package: is for you to build the package then share the app through a cran or something. Even if you share the source bundle, it will be enough to install the dependencies thanks to the DESCRIPTION listing them all and installation function knowing how to install dependencies.
However, I think it is important to know that this will always install the LAST version available in the configured CRAN when installing your app. This is not always a good idea. A shiny app can use very specific tools and one don't want to keep the app up to date with each package it is using.

Using packrat is a very good idea and practice to be sure specific version are installed when deploying the application. Today I would use the new renv :package: that is a replacement for packrat. There is a special migrate() to convert from a packrat project.
This will allow you golem app to have all the information so that anyone can reproduce the working state of your environment to launch the application. This allow specific versions to be installed in a project library. This is very useful for deployments. See vignettes on the website.

I would advice not to give away packrat if you switch your app to golem. You would leave a very good practice. packrat / renv can work very well with golem app too.

To answer you question with all that in mind, with a golem app using packrat (or renv), the one required to reinstall the :package: needed would just use restore() function.

3 Likes

Exactly this is what I am struggling now. I am sharing my app to users in multiple ways, which includes hoisting on shinyapps.io , install from binary(.tgz file) or source file (.tar.gz file) and also through docker image. My development environment is inside packrat (haven't tried renv yet.). When I push to shinyapps.io behaviour is exactly what I have on my local computer. However, installing from tar.gz or .tgz or building docker image takes latest version of the dependent packages and therefore app behaviour is different than what i see locally and shinyapps.io.

Do you mean I should given away installing as a package (either from tar.gz or .tgz file ) and share as a packrat bundle ? Also, preparing docker image from packrat bundle and not install from .tar.gz file ? Can we replicate the scenario to create a docker image exactly the way shinyapps.io install the app on remote server ?

1 Like

I really advice to look at renv, which packrat 2.0. You have a migrate function that should help you. I don't think you need to make a packrat bundle in the sense to include in your zip all the source package for your dependencies. Instead, you'll have a renv.lock file in you project that contains all the infos. I am seeing this scenarios

  • Develop using renv and add your dependencies, renv will lock the versions
  • when ready to deploy, make a bundle zip or a tar.gz with the necessary file for you app
  • Send the bundle for deployment, and add a step: renv::restore(). This will install exactly the same dependencies as on your development environment. I think this is what happens on shinyapps.io

that way you'll have the exact dependencies for your project to run. This restoring deployment steps can also be used in Docker. I used it with packrat and now switched to renv.

Regarding Golem, you have a add_dockerfile that can also be useful to help create a Dockerfile. I think it does lock the version too but I am not a golem expert.

If you need to get one things from me: I switched to renv and that is really great ! Locking environment ease the step for development and to help recreate R project environment for deployment.

Hope it helps

2 Likes

I followed the instructions you gave and it worked perfectly fine. Now, the app behaviour is exactly same as on local machine.

I use add_dockerfile from golem to create Dockerfile. However, the resulted Dockerfile uses "install app as a package" approach to create a Docker image. I have changed it to "restore app from packrat" approach. Once dependencies installed from renv.lock (or packrat.lock), final CMD command in the Dockerfile looks like below.

FYI : The app has been developed as a package using golem

EXPOSE 80
CMD R -e "setwd('path/to/install/location/app_package_folder/');packrat::on();options('shiny.port'=80,shiny.host='0.0.0.0');library(shinyBS);golem::document_and_reload();package_name::run_app()"

2 Likes

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