Debug your package that failed on CRAN with {rhub}

Debug your package that failed on CRAN with {rhub}

If you sent packages on CRAN, you may have encountered some fails on different operating systems configurations that you never heard about before: Solaris, debian clang, fedora gcc, … Package {rhub} allows to test your package on some of them, prior to sending to CRAN. But, how to debug directly on this infrastructure to be able to reproduce and fix the errors ?

TL;DR

  • Choose the Docker image to work on
  • Run locally
    • Note the name of the container shown in the console. Something like 8f5553b1-6e87-4330-8e3a-324dbacf3394-1

In R console

# List images available
rhub::local_check_linux_images()
# Run on Debian
rhub::local_check_linux(image = "rhub/debian-clang-devel")
  • Get the Docker container ID
  • Create a new image from it
  • Enter the container
  • Find your package sources
  • Open R in the container

In Terminal

docker ps -a
CONTAINER ID   IMAGE                     COMMAND                  CREATED        STATUS                      PORTS     NAMES
d31d52e7761a   8aee372b8b95   "bash /root/sysreqs.…"   22 hours ago   Exited (0) 22 hours ago               8f5553b1-6e87-4330-8e3a-324dbacf3394-1

# Commit the stopped image
docker commit d31d52e7761a debug/debian

# create a new container from the "broken" image
docker run -it --rm --entrypoint bash debug/debian

# Find your package source
cd /tmp/artifacts

# Untar the source
tar -xvf yourpackage_x.x.x.tar.gz

# Launch R 
/opt/R-devel/bin/R
  • Change .libPaths() and you can run your checks and tests

In the R session inside the Terminal

# Change libPaths
.libPaths(c(.libPaths(), "~/R"))

# Change working directory for your package
setwd("/tmp/artifacts/yourpackage")

# Check and debug
rcmdcheck::rcmdcheck()
  • Quit R

In the R session inside the Terminal

q()
  • Clean your Docker at the end of the process

In Terminal

# Exit the container
exit
# delete the container and the image
docker image rm debug/debian

The same with a little more explanations

{rhub} Docker images are built and saved on DockerHub. There are accessible with docker pull rhub/<image-name>. When using rhub::local_check_linux(), the Docker image is downloaded on your computer. The launching script installs system dependencies, packages dependencies and your package inside the container, then run the checks. As explained in rhub vignette on local debugging, the image is still available after the checks, with the complete installation. However, the checks are finished and the container just stopped.

We will see how to re-open it and run R code inside.

{rhub} Docker images

The list of Docker images available thanks to {rhub} is available with rhub::local_check_linux_images() in your R console.
Choose the <image-name> in the list and run rhub::local_check_linux(image = "rhub/<image-name>"). This may take a long time depending on the number of dependencies required to install your package. Be patient.

Here I test {fusen} with debian-clang-devel. I should see the same warnings, errors as issued from CRAN in this case.

In R console

# Run on Debian
rhub::local_check_linux(image = "rhub/debian-clang-devel")

Note the container name a55df815-38f2-4854-a3bc-29cdcac878cc-2 that I will use in the following.

Get inside the stopped container

As you ran rhub::local_check_linux(), the image is ready with all dependencies. But the container stopped and you cannot get into it using classical docker exec. Hence, you will need to create a new image from the stopped one and run it using an entrypoint.

Let’s find the CONTAINER ID related to the container name that we kept in mind above. The docker ps -a command is run in a Terminal. If you are using RStudio, you can run the following line using CTRL + ALT + Enter, it will directly go to the Terminal.

In Terminal

docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS                      PORTS     NAMES
26515d1d9a18   5e135229a572   "/bin/bash -l /tmp/b…"   38 minutes ago   Exited (0) 21 minutes ago             a55df815-38f2-4854-a3bc-29cdcac878cc-2

Note the CONTAINER ID: 26515d1d9a18

We create a new image based on the {rhub} image in its current state with docker commit. We call this new image debug/debian-clang-devel. This means with system and R dependencies installed, and the source of your package inside. Then, we create a new container to get inside using an entrypoint. Then we will have the possibility to run code inside, even if the instructions of the original image said to stop when finished.

In Terminal

# Commit the stopped image
docker commit 26515d1d9a18 debug/debian-clang-devel

# create a new container from the "broken" image
docker run -it --rm --entrypoint bash debug/debian-clang-devel

We are now inside the container !

Find your package development sources

We will need to find where is the source of our R package so that we can run tests on it.

You may find your package source in “tmp/artifacts”

In Terminal

cd /tmp/artifacts
ls -l
-rw-r--r-- 1 docker docker   311711 Jul 29 07:46 fusen_0.2.3_R_x86_64-pc-linux-gnu.tar.gz
-rw-r--r-- 1 docker docker   303424 Jul 29 07:46 fusen_0.2.3.tar.gz
drwxr-xr-x 5 docker docker     4096 Jul 29 07:47 fusen.Rcheck

Here {fusen} appears three times:

  • fusen_0.2.3_R_x86_64-pc-linux-gnu.tar.gz is the archive ready to be installed
  • fusen_0.2.3.tar.gz is the source. The content of your package in development in which we are insterested
  • fusen.Rcheck is the output of the checks run on your package

We will need to untar our source to have access to the development directory.

In Terminal

# untar sources
tar -xvf fusen_0.2.3.tar.gz
# get inside sources
cd fusen
# list files
ls -l

Find R, run your tests and debug your code

We need to find out where R is installed inside the container, be sure that all dependencies are already installed, to avoid waiting again. Then, we’ll be able to debug our code with all tools you surely already know.

R is probably installed in the /opt/ directory.

In Terminal

# list files
ls -l /opt

Dependencies are probably installed in “/home/docker/R”.

In Terminal

# list files
ls -l /home/docker/R

Launch R

In Terminal

# Launch R
/opt/R-devel/bin/R

You are in a R session inside the stopped container!

Modify .libPaths() to have access to all installed packages.

In the R session inside the Terminal

# Change libPaths
.libPaths(c(.libPaths(), "~/R"))

Jump inside your development package directory and run the checks to verify errors can be reproduced

In the R session inside the Terminal

# Change working directory
setwd("/tmp/artifacts/fusen")
# Run checks
rcmdcheck::rcmdcheck()

The error is still there. I can debug now.

Stop the session when you are ok

In the R session inside the Terminal

# quit R
q()

Clean your Docker at the end of the process

In the Terminal

# Exit the container
exit
# delete the container and the image
docker image rm debug/debian-clang-devel

You should be good for another round !

Debug with specific flavours

Here is a list of CRAN platforms tested for {fusen}:

As of today, {rhub} proposes multiple OS versions that partially match CRAN ones.

rhub::local_check_linux_images()
## rhub/debian-clang-devel:
##   Debian Linux, R-devel, clang, ISO-8859-15 locale
## rhub/debian-gcc-devel:
##   Debian Linux, R-devel, GCC
## rhub/debian-gcc-devel-nold:
##   Debian Linux, R-devel, GCC, no long double
## rhub/debian-gcc-patched:
##   Debian Linux, R-patched, GCC
## rhub/debian-gcc-release:
##   Debian Linux, R-release, GCC
## rhub/fedora-clang-devel:
##   Fedora Linux, R-devel, clang, gfortran
## rhub/fedora-gcc-devel:
##   Fedora Linux, R-devel, GCC
## rhub/centos-epel:
##   CentOS 8, stock R from EPEL
## rhub/rocker-gcc-san:
##   Debian Linux, R-devel, GCC ASAN/UBSAN
## rhub/ubuntu-gcc-devel:
##   Ubuntu Linux 20.04.1 LTS, R-devel, GCC
## rhub/ubuntu-gcc-release:
##   Ubuntu Linux 20.04.1 LTS, R-release, GCC
## rhub/ubuntu-rchk:
##   Ubuntu Linux 20.04.1 LTS, R-devel with rchk

In some cases, there are some extra platforms tested as you can see on the list below

It seems you can use {r-debug} to partially reproduce these extra CRAN verifications following instructions here: https://github.com/wch/r-debug. I didn’t tested.

Resources

Again, unit tests helped identify problems on specific platforms. This can be painful to think and test on all these platforms, but at some point, this allows to share your work with others. Even if they are not working on the exact same conditions as your own computer.

Use Docker images:

Developing a package and send to CRAN:



Citation:

For attribution, please cite this work as:
Rochette Sébastien. (2021, Jul. 29). "Debug your package that failed on CRAN with {rhub}". Retrieved from https://statnmap.com/2021-07-29-debug-your-package-that-failed-on-solaris-and-others-on-cran-with-rhub/.


BibTex citation:
@misc{Roche2021Debug,
    author = {Rochette Sébastien},
    title = {Debug your package that failed on CRAN with {rhub}},
    url = {https://statnmap.com/2021-07-29-debug-your-package-that-failed-on-solaris-and-others-on-cran-with-rhub/},
    year = {2021}
  }