1

So I have a {targets} pipeline which runs on GitHub Actions. The required packages are recorded with {renv} and the whole thing runs in a docker container. Because I would prefer to have a long image build time and a short image run time, renv builds the library when the docker container is built so everything is available at runtime. The actual pipeline is not part of the image - it is checked out at runtime.

Here's the problem - if I run any R code in the GitHub workflow before using 'actions/checkout', renv works fine. But if I run anything after 'actions/checkout' renv can't find the library and instead needs to reinstall everything.

Dockerfile

FROM rocker/verse:4.3.0

ENV RENV_VERSION 0.17.3
RUN R -e "install.packages('remotes', repos = c(CRAN = 'https://cloud.r-project.org'))"
RUN R -e "remotes::install_github('rstudio/renv@${RENV_VERSION}')"

WORKDIR /project
COPY renv.lock renv.lock

ENV RENV_PATHS_LIBRARY renv/library

RUN R -e "renv::restore()"

GitHub Workflow

on:
  push:
    branches:
      - main
      - master
  pull_request:
    branches:
      - main
      - master
  schedule:
    - cron: '0 13 * * 0,2,4'

name: targets

jobs:
  targets:
    runs-on: ubuntu-latest
    container:
      image: (above image)
    env:
      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
      LANG: en_US.UTF-8 
    steps:      
      - name: Test if renv works
        shell: Rscript {0}
        run: renv::restore() # Works - up to date with lock file

      - uses: actions/checkout@v3

      - name: Test if renv works after checkout
        shell: Rscript {0}
        run: renv::restore() # Fails - reinstalls library from lockfile

My guess is that the checkout action changes the working directory and so the library that docker made isn't found. But I don't know how to fix that.

Edit: Tested it and it doesn't change the working directory - it's checked out to the same folder.

I think this might have to do with activate.R changing one of the settings. Here is a screenshot of two steps of the action that both just install dplyr (all the dependencies of which should already be installed).

GitHub Actions Screenshot

Note how the first time there's none of the bootstrapping or install renv, because activate.R does not exist until the checkout step. Could this be what is causing the problem?

Taren Sanders
  • 421
  • 2
  • 12
  • Does `- run: git config --global --add safe.directory /__w//` solve this? – Skenvy Jul 06 '23 at 03:59
  • @Skenvy no unfortunately that doesn't change anything. I do have some more info that might help though - I'll update the post. – Taren Sanders Jul 06 '23 at 04:04
  • @TarenSanders: How did you verify that `actions/checkout` was not changing the working directory or current path? – Azeem Jul 06 '23 at 04:51
  • @Azeem I just ran `pwd` before and after the checkout. – Taren Sanders Jul 06 '23 at 04:58
  • @TarenSanders: Right. Can you please add those steps and their respective workflow run steps (expanded) in your question? `actions/checkout` does change the current working directory. Not sure why it's the same in your case. Maybe, because you're running inside the container but I never observed it not changing the current directory after checkout in the container. Just want to make sure it's not changing in your case. – Azeem Jul 06 '23 at 05:01
  • @Azeem I think I've worked this out (the problem seems to be with renv/activate.R, will post when I've double checked). But just to show that the directory doesn't change: https://i.stack.imgur.com/z7Q5v.png. Must be because it's in a container? – Taren Sanders Jul 06 '23 at 05:06
  • @TarenSanders: Also, from your Dockerfile, GHA workflow, and https://github.com/rstudio/renv, IIUC you're creating the docker image with deps installed in the `project` directory i.e. already ran `renv::init()` and `renv::snapshot()` on your local machine that generated the `renv.lock` file updated with all the deps and their respective versions, and then running `renv::restore()` restores all those deps inside the container image. And, now you want to use the same deps for your project in the CI pipeline, right? – Azeem Jul 06 '23 at 05:08
  • @TarenSanders: Yes, that's the same path. You might want to add a `ls -l` after `pwd` to verify the contents as well. Sure, you may post a self-answer with all the details. – Azeem Jul 06 '23 at 05:11
  • 1
    @Azeem yes that's exactly right. The docker container should have everything it needs to run the code, except for the code itself. This is because the code changes occasionally, and I don't want to rebuild the container when the code changes. By having it in a container, I can develop in the same environment that it will eventually run in. – Taren Sanders Jul 06 '23 at 05:33

1 Answers1

1

I think I've found the solution, although I'll confess to not being 100% sure about the cause.

When the repository is checked out, it copies over the renv/ folder and the .Rprofile which sources renv/activate.R. Something in that process (possibly the settings.json) seems to override the environment variable that is set in the docker image that tells renv where to find the library.

My solution is to just not check these files out. That is:

      - uses: actions/checkout@v3
        with:
          sparse-checkout: |
            .
            /*
            !renv/
            !.Rprofile

The pipeline then runs as expected.

Taren Sanders
  • 421
  • 2
  • 12