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
- Note the name of the container shown in the console. Something like
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 installedfusen_0.2.3.tar.gz
is the source. The content of your package in development in which we are insterestedfusen.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:
- rhub vignette on local debugging
- Checking your R package on Solaris on rhub blog
- Use “How To Run Commands In Stopped Docker Containers”
- Dockerfile with several builds of R for memory/thread debugging
Developing a package and send to CRAN:
- {fusen}: Inflate your package from a simple flat Rmd
- ThinkR guide with all steps “Prepare your package for a CRAN submission”.
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}
}