Ansible role that installs R itself, R packages (from CRAN, archived and remote repos) and associated tools.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
6.4 KiB

- name: Include R_CRAN_packages variable
file: packages-CRAN.yml
- name: Include R_archived_packages variable
file: packages-archived.yml
- name: Include R_dev_packages variable
file: packages-dev.yml
# we do this to avoid "NO DISPLAY" warnings/errors when installing some R packages
- name: Install virtual framebuffer X server
- xvfb
- xfonts-base
state: present
# temporarily disable any ~/.Rprofile before installing R packages
# (because its output pollutes the playbook output/log)
- name: Temporarily disable ~/.Rprofile by renaming the file
ansible.builtin.command: "mv {{ ansible_env.HOME }}/.Rprofile {{ ansible_env.HOME }}/.Rprofile.moved"
ignore_errors: true
# ignore_errors in case the playbook is interrupted at this point and then restarted, file already moved
# I added xvfb-run to fix "NO DISPLAY" warnings/errors when installating certain packages
# Note: when rerunning xvfb-run, it fails to start with "Server is already active for display 99"
# This is because the already running xvfb-instance and the new instance you are trying to start
# will both try to connect to server number 99.
# The flag --auto-servernum allows the new instance to get a new number instead.
# Based on this task below, I could probably improve the following CRAN Ansible module:
- name: Install R CRAN packages
# RPYTHON_PYTHON_VERSION=3: otherwise rPython fails with "could not locate python-config"
ansible.builtin.command: >
xvfb-run --auto-servernum Rscript --slave --no-save --no-restore-history -e
if (! ('{{ item }}' %in% installed.packages()[, 'Package'])) {
install.packages(pkgs='{{ item }}', lib='{{ RLIBS_SYSTEM }}');
print('Added {{ item }}');
} else {
print('Already installed {{ item }}');
register: r_cran_package
failed_when: "r_cran_package.rc != 0 or 'had non-zero exit status' in r_cran_package.stderr"
changed_when: "'Added' in r_cran_package.stdout"
with_items: "{{ R_CRAN_packages }}"
# The diffractometry package has been archived on CRAN, and does not have any git repo
- name: Install R CRAN archived packages
ansible.builtin.command: >
xvfb-run --auto-servernum Rscript --slave --no-save --no-restore-history -e
"if (! ('{{ }}' %in% installed.packages()[, 'Package'])) {
new='{{ RLIBS_SYSTEM }}',
remotes::install_version(package='{{ }}', version='{{ item.version }}'));
print('Added {{ }}');
} else {
print('Already installed {{ }}');
register: r_archive_package
failed_when: "r_archive_package.rc != 0 or 'had non-zero exit status' in r_archive_package.stderr"
changed_when: "'Added' in r_archive_package.stdout"
with_items: "{{ R_archived_packages }}"
# Install R packages from Github using remotes::install_github()
# together with withr::with_libpaths() to specify our main R library path
# For the first time ever, I hit Github's API rate limiter...
# > Unauthenticated requests only get 60/hour.
# withr::with_libpaths(new='/opt/R/4.0.5/lib/R/library', remotes::install_github('solarchemist/renishaw')
# Error: Failed to install 'renishaw' from GitHub:
# HTTP error 403. API rate limit exceeded for
# (But here's the good news: Authenticated requests get a higher rate limit.
# Check out the documentation for more details.)
# Rate limit remaining: 0/60
# Rate limit reset at: 2022-01-27 20:16:13 UTC
# To increase your GitHub API rate limit - Use `usethis::create_github_token()` to create a
# Personal Access Token. Use `usethis::edit_r_environ()` and add the token as `GITHUB_PAT`.
# It seems remotes:: hits the Github API more than my other Ansible tasks. So suggested fix is probably the best.
- name: Install R dev packages
ansible.builtin.command: >
xvfb-run --auto-servernum Rscript --slave --no-save --no-restore-history -e
"withr::with_libpaths(new='{{ RLIBS_SYSTEM }}', remotes::install_github('{{ item.repo }}'));
print('Added {{ }}');"
register: r_dev_package
failed_when: "r_dev_package.rc != 0 or 'had non-zero exit status' in r_dev_package.stderr"
changed_when: "'Added' in r_dev_package.stdout"
with_items: "{{ R_dev_packages }}"
- name: Import fonts into the extrafont database and register the fonts with the PDF output device
ansible.builtin.command: >
xvfb-run --auto-servernum Rscript --slave --no-save --no-restore-history -e
"library(extrafont); font_import(prompt=FALSE); loadfonts()"
# you can view the resulting table of font information with
# > fonts()
# [1] "DejaVu Math TeX Gyre" "DejaVu Sans" "DejaVu Sans Light"
# [4] "DejaVu Sans Condensed" "DejaVu Sans Mono" "DejaVu Serif"
# [7] "DejaVu Serif Condensed" "Droid Sans Fallback" "Liberation Mono"
# [10] "Liberation Sans" "Liberation Sans Narrow" "Liberation Serif"
# [13] "Noto Mono"
# move ~/.Rprofile back
- name: Enable our ~/.Rprofile again
ansible.builtin.command: "mv {{ ansible_env.HOME }}/.Rprofile.moved {{ ansible_env.HOME }}/.Rprofile"
ignore_errors: true