knitr::opts_chunk$set(echo = FALSE, warning = FALSE)
When working on the package, development tasks - such as building, documenting,
or testing - require other packages to execute. These packages are available in
the packrat
environment (see below). Any new development dependencies should
be installed in the packrat environment and a new snapshot taken. Please update
the below list with any additional development dependencies:
devtools
knitr
lintr
pkgdown
rmarkdown
shiny
styler
testthat
testthis
The packrat
package manages all R
package dependencies that this project uses. packrat
provides a local
repository of packages, based upon a sweep of all R/
code for any library()
or required()
calls. It stores versioned TARs of those packages, retrieved
from CRAN or other defined repositories in the packrat/src/
directory, along
with a packrat.lock
file that specifies the packages and their versions.
To improve the operational speed of Packrat tasks, especially in our CI
processes, some of these necessary development dependencies are not included in
the Packrat library. They are referenced in the Packrat configuration file,
packrat/packrat.opts
, as external.packages
. As a developer of the pfsrsdk
package, please ensure that the following packages are installed in your system
library:
devtools
knitr
lintr
pkgdown
shiny
styler
testthat
testthis
packrat::init()
These files are generated on a new project by calling:
install.packages("packrat") packrat::init()
and are part of source control. Git ignores all installed instances of packages
in the packrat/lib*/
directories.
packrat::restore()
In a new clone of this project, initialize your environment into the packrat
repository by calling:
packrat::restore()
This will put all calls to dependencies in your source files towards the
packrat
context.
packrat::snapshot()
If you are adding any new package dependencies to the project, you can install
them with regular install commands (e.g. install.packages()
or
devtools::install_github()
). To record this update to the package
dependencies, call
packrat::snapshot()
in order to have packrat
update the packrat.lock
file.
Rprofile
Any R developer has an .Rprofile
file, usually located in their home directory
(e.g., ~/.Rprofile
). That file maintains its own list of CRAN and CRAN-like
package repositories from which to source libraries. In addition to the main
CRAN and CRAN Extra repositories, a private Nexus repository has been added,
from which both internal and external packages can be pulled (pfsrsdk
is one
such internal package).
To configure your environment to use the Nexus repository, create environment
variables for ARTIFACT_REGISTRY_USER
and ARTIFACT_REGISTRY_PASSWORD
that
the below example of your ~/.Rprofile
file can use to authenticate. Request
credentials from the DSBU DevOps team.
local({ r <- getOption("repos") r["Nexus"] <- paste0("https://", Sys.getenv("ARTIFACT_REGISTRY_USER"), ":", Sys.getenv("ARTIFACT_REGISTRY_PASSWORD"), "@nexus.managed.coredev.cloud/repository/datascience-r-group") r["CRAN"] <- "https://cran.rstudio.com/" r["CRANextra"] <- "http://www.stats.ox.ac.uk/pub/RWin" options(repos = r) })
The pfsrsdk
package tests are written to use a configurable set of values for
evaluating the SDK calls against a user's development or automated test
environment. This configuration is made in tests/testthat/test_environment
,
on a corresponding set of Auth-X.Y.Z.json
and Data-X.Y.Z.json
files. Setting
values in the Data-X.Y.Z.json
files that match data present in a user's
development or test environment enable the tests to execute successfully,
regardless of environment or available data.
The testing suite uses setup.R
and teardown.R
for pre- and post-test
actions, so invoking such helpers is only available from the
testthat::test_dir()
or testthat::test_package()
functions. To test an
individual file, execute using a filter for that test file name:
testthat::test_dir("tests/testthat", filter = "updateEntityLocation")
The devtools
package provides crucial
package creation functionality, as it is used to build and install this package
from source.
devtools::build()
More useful for publishing, a built TAR of the package is generated with
devtools::build()
. By default, this is executed from the project root
directory, and creates the file in the parent directory (i.e., the directory
that contains the project). In practice, it is useful to generate the built
package in a specified directory, such as:
devtools::build(path = "someDir")
devtools::install()
When working with the package in a local environment, it is useful to make the package available as-is to other development projects. This is achieved by installing the package from source into your R environment.
devtools::install()
This package currently creates two forms of documentation:
man/
We use a call to devtools::document()
(which wraps the
roxygen2
package) to generate the
man/*.Rd
files. The *.Rd
files are generated from the formatted comments,
part of all *.R
source code. These files are under source-control, so it
should be a part of your pre-commit development workflow to run
devtools::document()
and commit any updates to the man/
directory, with
their corresponding R/
changes.
pkgdown
We also can generate a static HTML documentation site, using the
pkgdown
package. This package builds the
HTML, CSS, and JS files from the various package documentation sources: man/
,
vignettes/
, DESCRIPTION
, README.md
, and NEWS.md
. The site is created by
calling:
install.packages("pkgdown") pkgdown::build_site()
This function generates a docs/
directory, which can then be published and
hosted for end-users.
We maintain a consistent style of R code with the following two packages:
lintr
Use the lintr
package to receive syntax
and static code analysis feedback on R code.
Install the package and use on one file:
install.packages("lintr") lintr::lint("R/authBasic.R")
This will bring up a list of linting messages in the RStudio "Markers" pane.
You can also lint the whole package at once, and/or filter for higher priority
warning
messages:
lintr::lint_package("R/") warnings()
styler
Use the styler
package to auto-apply a
standard code style to R and Rmd code.
Install the package and use on one file:
install.packages("styler") styler::style_file("R/authBasic.R")
The output will show if your code style has been modified by the tool.
You can also apply style to directories or the whole package:
styler::style_dir("R/") styler::style_pkg()
Outside of local development, the package must be exercised as part of our SDLC process. As part of the integration with other software products, we extend upon those common tools used elsewhere to enable R package creation and validation as easily as possible.
The CI process runs on Jenkins agent Docker containers. These containers are
Debian-based, and have a specific version of R installed (see the
jenkins-agent
repo for more
details).
Included in that Docker image are a number of system dependencies specifically needed to build and publish this package.
R Package|Debian Dependency
---|---
XML
|libxml2-dev
curl
|libcurl4-gnutls-dev
git2r
|libgit2-dev
libssl-dev
pkgdown
|pandoc
gradle-plugin-r
Gradle is used to wrap a number of common R-package and software-development
tasks in Groovy-defined tasks and plugins. For this project, we use and extend
upon the gradle-plugin-r
project
to execute some of the above-described R commands in a Gradle context. That
context affords us other functionality, such as creating publishing artifacts.
Between the plugin and the gradle/r-package.gradle
file extensions on that
plugin, we are able to execute the following R command with corresponding
Gradle tasks:
R Command|Gradle Task
---|---
devtools::document()
|./gradlew document
packrat::clean()
|./gradlew packratClean
packrat::restore()
|./gradlew packratRestore
devtools::build(path = "build/package")
|./gradlew buildPackage
devtools::install(pkg = "build/package")
|.gradlew installPackage
devtools::test(reporter = JunitReporter)
|./gradlew testPackage
pkgdown::build_site(override = list(destination = "build/docs"))
|./gradlew pkgdownSite
Gradle has also been extended to parse the DESCRIPTION
file for the package
name ("Package") and the package version ("Version"). These values are then used
to generate a ZIP file of the pkgdown
-generated documentation static HTML
site. This ZIP is generated by calling:
./gradlew docsDistZip
The documentation ZIP and the package TAR files are then published to the Digital Science Business Unit's Nexus repository server, via Gradle:
./gradlew publish
Using the Gradle docker-plugin
we are also able to generate Docker images of the installed package with a basic
Shiny app (from inst/shiny) and of the pkgdown
documentation
site. These two images are built on top of the
rocker/tidyverse
and
nginx
public images, respectively. The
images can be generated on a system with Docker installed by calling:
./gradlew buildPfsRSdkShinyImage ./gradlew buildPfsRSdkDocsImage
Both of these images can be run as webapps:
docker run -d -p 8080:80 quay.coredev.cloud/core-informatics/pfsrsdk-docs:latest docker run -d -p 3838:3838 quay.coredev.cloud/core-informatics/pfsrsdk-shiny:latest
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.