From 1333b74b7bd06643c55e0e83aaa536cdd69755f9 Mon Sep 17 00:00:00 2001 From: Mischa ter Smitten Date: Wed, 1 Nov 2017 16:34:05 +0100 Subject: [PATCH] Add R-update-package(s) script(s) (#20) * Add R-update-package(s) script(s) * Improved documentation [ci skip] * Add support for private bitbucket packages --- README.md | 3 +- tasks/packages.yml | 28 +++++++++-- templates/usr/local/bin/R-install-package.j2 | 10 ++-- .../usr/local/bin/R-install-requirements.j2 | 48 +++++++++++++++++++ templates/usr/local/bin/R-remove-package.j2 | 8 ++-- templates/usr/local/bin/R-update-package.j2 | 18 +++++++ templates/usr/local/bin/R-update-packages.j2 | 17 +++++++ 7 files changed, 119 insertions(+), 13 deletions(-) create mode 100644 templates/usr/local/bin/R-install-requirements.j2 create mode 100644 templates/usr/local/bin/R-update-package.j2 create mode 100644 templates/usr/local/bin/R-update-packages.j2 diff --git a/README.md b/README.md index 3227a2d..da032cd 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ Set up the latest version of R in Ubuntu systems. #### Requirements * `littler` (will be installed) +* `bash` (will not be installed) #### Variables @@ -21,7 +22,7 @@ Set up the latest version of R in Ubuntu systems. * `r_packages`: [default: `[]`]: (CRAN) Packages to install or remove * `r_packages.{n}.name`: [required]: The name of the package -* `r_packages.{n}.state`: [optional, default: `present`]: The state of the package +* `r_packages.{n}.state`: [optional, default: `present`]: The state of the package (e.g. `updated`, `absent`) * `r_packages.{n}.type`: [optional, default: `cran`]: The type of the package (e.g. `bioconductor`) * `r_packages.{n}.lib`: [optional, default: `r_packages_lib`]: The library directory to install the package to * `r_packages.{n}.repos`: [optional, default: `r_packages_repos`]: The URL to install the package from diff --git a/tasks/packages.yml b/tasks/packages.yml index 4211165..4601c0f 100644 --- a/tasks/packages.yml +++ b/tasks/packages.yml @@ -12,6 +12,14 @@ dest: R-install-package - src: R-remove-package.j2 dest: R-remove-package + - src: R-update-package.j2 + dest: R-update-package + - src: R-update-packages.j2 + dest: R-update-packages + - src: R-install-requirements.j2 + dest: R-install-requirements + tags: + - r-packages-copy-r-scripts - name: packages | install command: > @@ -20,8 +28,8 @@ {{ item.type | default(r_packages_type) }} {{ item.lib | default(r_packages_lib) }} {% if item.repos is defined %}{{ item.repos }}{% endif %} - register: r_install_package - changed_when: "r_install_package.stdout_lines[-1] is defined and r_install_package.stdout_lines[-1] == 'changed'" + register: _r_install_package + changed_when: "_r_install_package.stdout_lines[-1] is defined and _r_install_package.stdout_lines[-1] == 'changed'" with_items: "{{ r_packages_from_github | ternary(r_preset_package_remotes + r_packages, r_packages) }}" when: item.state is undefined or item.state == 'present' tags: @@ -32,9 +40,21 @@ R-remove-package {{ item.name }} {% if item.lib is defined %}{{ item.lib }}{% endif %} - register: r_remove_package - changed_when: "r_remove_package.stdout_lines[-1] is defined and r_remove_package.stdout_lines[-1] == 'changed'" + register: _r_remove_package + changed_when: "_r_remove_package.stdout_lines[-1] is defined and _r_remove_package.stdout_lines[-1] == 'changed'" with_items: "{{ r_packages }}" when: item.state is defined and item.state == 'absent' tags: - r-packages-remove + +- name: packages | update + command: > + R-update-package + {{ item.name }} + {% if item.lib is defined %}{{ item.lib }}{% endif %} + register: _r_update_package + changed_when: "_r_update_package.stdout_lines[-1] is defined and _r_update_package.stdout_lines[-1] == 'changed'" + with_items: "{{ r_packages }}" + when: item.state is defined and item.state == 'updated' + tags: + - r-packages-update diff --git a/templates/usr/local/bin/R-install-package.j2 b/templates/usr/local/bin/R-install-package.j2 index eeab242..3f01051 100644 --- a/templates/usr/local/bin/R-install-package.j2 +++ b/templates/usr/local/bin/R-install-package.j2 @@ -19,22 +19,24 @@ if (type == 'github') { if (!(package %in% installed.packages(lib.loc = lib)[, 'Package'])) { if (type == 'cran') { repos = ifelse(is.na(argv[4]), '{{ r_packages_repos }}', argv[4]); - withCallingHandlers(install.packages(package, lib, repos), warning = stop); + withCallingHandlers({ + install.packages(package, lib, repos); + cat("changed\n"); + }, warning = stop); } else if (type == 'bioconductor') { withCallingHandlers({ source('{{ r_bioclite_url }}') biocLite(package, lib = lib, suppressUpdates = TRUE, suppressAutoUpdate = TRUE, ask = FALSE) + cat("changed\n"); }, warning = stop); } else if (type == 'github') { withCallingHandlers({ library(remotes) install_github(repo, lib = lib) + cat("changed\n"); }, warning = stop); } else { cat("Unrecognised type\n"); q(status = 1); } - cat("changed\n"); -} else { - cat("unchanged\n"); } diff --git a/templates/usr/local/bin/R-install-requirements.j2 b/templates/usr/local/bin/R-install-requirements.j2 new file mode 100644 index 0000000..3882986 --- /dev/null +++ b/templates/usr/local/bin/R-install-requirements.j2 @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# +# {{ ansible_managed }} +# +# set -x; +set -e; +set -o pipefail; +# +thisFile="$(readlink -f "${0}")"; +thisFilePath="$(dirname "${thisFile}")"; + +if [ -z "${1}" ] || [ "${1}" != '-r' ] || [ -z "${2}" ]; then + echo "Usage: ${0} -r requirements.txt"; + exit 1; +fi + +if [ ! -f "${2}" ]; then + echo "Could not open requirements file for reading"; + exit 1; +fi + +requirementsFile="${2}"; +shift 2; + +while IFS= read -r requirement; do + requirementType="$(echo "${requirement}" | awk -F'::' '{ print $1}')"; + requirementName="$(echo "${requirement}" | awk -F'::' '{ print $2}' | awk -F'@' '{ print $1}')"; + requirementVersion="$(echo "${requirement}" | awk -F'::' '{ print $2}' | awk -F'@' '{ print $2}')"; + + if [ "${requirementType}" == 'github' ]; then + installCommand="devtools::install_github(\"${requirementName}\")"; + if [ -n "${requirementVersion}" ]; then + installCommand="devtools::install_github(\"${requirementName}\", ref=\"${requirementVersion}\")"; + fi + elif [ "${requirementType}" == 'bitbucket' ]; then + installCommand="devtools::install_bitbucket(\"${requirementName}\", auth_user = Sys.getenv(\"BITBUCKET_AUTH_USER\"), password = Sys.getenv(\"BITBUCKET_AUTH_PASSWORD\"))"; + if [ -n "${requirementVersion}" ]; then + installCommand="devtools::install_bitbucket(\"${requirementName}\", ref=\"${requirementVersion}\", auth_user = Sys.getenv(\"BITBUCKET_AUTH_USER\"), password = Sys.getenv(\"BITBUCKET_AUTH_PASSWORD\"))"; + fi + else + installCommand="devtools::install_cran(\"${requirementName}\")"; + if [ -n "${requirementVersion}" ]; then + installCommand="devtools::install_version(\"${requirementName}\", version=\"${requirementVersion}\")"; + fi + fi + + Rscript -e "withCallingHandlers(${installCommand}, warning = stop)"; +done < "${requirementsFile}" diff --git a/templates/usr/local/bin/R-remove-package.j2 b/templates/usr/local/bin/R-remove-package.j2 index 7a20662..be69f00 100644 --- a/templates/usr/local/bin/R-remove-package.j2 +++ b/templates/usr/local/bin/R-remove-package.j2 @@ -10,8 +10,8 @@ package = argv[1]; lib = ifelse(is.na(argv[2]), '{{ r_packages_lib }}', argv[2]); if (package %in% installed.packages(lib.loc = lib)[, 'Package']) { - withCallingHandlers(remove.packages(package, lib), warning = stop); - cat("changed\n"); -} else { - cat("unchanged\n"); + withCallingHandlers({ + remove.packages(package, lib); + cat("changed\n"); + }, warning = stop); } diff --git a/templates/usr/local/bin/R-update-package.j2 b/templates/usr/local/bin/R-update-package.j2 new file mode 100644 index 0000000..325c86c --- /dev/null +++ b/templates/usr/local/bin/R-update-package.j2 @@ -0,0 +1,18 @@ +#!/usr/bin/env Rscript + +argv = commandArgs(trailingOnly = TRUE); +if (is.null(argv) | length(argv) < 1) { + cat("Usage: R-update-package package [lib] [repos]\n"); + q(status = 1); +} + +package = argv[1]; +lib = ifelse(is.na(argv[2]), '{{ r_packages_lib }}', argv[2]); +repos = ifelse(is.na(argv[3]), '{{ r_packages_repos }}', argv[3]); + +if (package %in% old.packages(lib.loc = lib)[, 'Package']) { + withCallingHandlers({ + update.packages(package, lib, repos, ask = FALSE); + cat("changed\n"); + }, warning = stop); +} diff --git a/templates/usr/local/bin/R-update-packages.j2 b/templates/usr/local/bin/R-update-packages.j2 new file mode 100644 index 0000000..c1d8a92 --- /dev/null +++ b/templates/usr/local/bin/R-update-packages.j2 @@ -0,0 +1,17 @@ +#!/usr/bin/env Rscript + +argv = commandArgs(trailingOnly = TRUE); +if (is.null(argv) | length(argv) < 0) { + cat("Usage: R-update-packages [lib] [repos]\n"); + q(status = 1); +} + +lib = ifelse(is.na(argv[1]), '{{ r_packages_lib }}', argv[1]); +repos = ifelse(is.na(argv[2]), '{{ r_packages_repos.rstrip('/') }}', argv[2]); + +if (!is.null(old.packages(lib.loc = lib))) { + withCallingHandlers({ + update.packages(lib, repos, ask = FALSE); + cat("changed\n"); + }, warning = stop); +}