R is a powerfull tool for data scientists but a huge pain for software developers and system administrators.
It’s hard to automate and integrate into other systems. That’s because it was developed mostly in academic environments for adhoc analytics instead of IT departments for business processes.
As every meal gets better if you gratinate it with cheese, every command line tool gets better if you wrap it in a PowerShell Commandlet.
PSRTools
You can do a lot with the R command line tools Rscript.exe
, but the developer of R seem to have a strange understanding of concepts like standard streams and return codes. So i created the PowerShell module PSRTools, that provides Commandlets for basic tasks needed for CI/CD pipelines.
If you have build dependecies, you have to install a R package from a repository. You can specify a snapshot to get reproducable builds. An example is:
Install-RPackage -Name 'devtools' -Repository 'https://mran.microsoft.com/' -Snapshot '2019-02-01'
In case you have the package on the disk you can install it with the Path parameter.
In both cases you can specify the library path, to install it on a specific location.
Install-RPackage -Path '.\devtools.tar.gz' -Library 'C:\temp\build\library'
If you have inline documentation in your R functions, you have to generate Rd files for the package. There is the Commandlet New-RDocumentation
for that.
The build can be executed using New-RPackage
. Both Commandlets have the parameters Path
for the project location and Library
for required R packages.
Build Script
The build script depends a little on your solution. It could be something like:
param (
$Project,
$StagingDirectory
)
$Repository = 'https://mran.microsoft.com/'
$Snapshot = '2019-02-01'
$Library = New-Item `
-ItemType Directory `
-Path ( Join-Path (
[System.IO.Path]::GetTempPath()
) (
[System.Guid]::NewGuid().ToString()
))
Import-Module PSRTools -Scope CurrentUser
Set-RScriptPath 'C:\Program Files\Microsoft\R Open\R-3.5.2\bin\x64\Rscript.exe'
Install-RPackage -Name 'devtools' -Repository $Repository -Snapshot $Snapshot -Library $Library
Install-RPackage -Name 'roxygen2' -Repository $Repository -Snapshot $Snapshot -Library $Library
New-RDocumentation -Path $Project -Library $Library
$Package = New-RPackage -Path $Project -Library $Library
Copy-Item -Path $Package -Destination $StagingDirectory
For build scripts i recommend InvokeBuild, but wanted a simple example.
Continuous Integration
To achive automated builds, you have to integrate it in a build script.
I tested it successfully in Appveyor and Azure Pipelines. Both work pretty much the same.
If you don’t have your own build agent, that can be prepared manually, you need to install R and RTools in your build script.
That can be done using Chocolatey.
In your appveyor.yml it is like:
install:
- choco install microsoft-r-open
- choco install rtools
build_script:
- ps: Build.ps1 -Project $env:APPVEYOR_BUILD_FOLDER -StagingDirectory "$env:APPVEYOR_BUILD_FOLDER\bin"
In you azure-pipelines.yml it is like:
steps:
- script: |
choco install microsoft-r-open
choco install rtools
displayName: Install build dependencies
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
Build.ps1 -Project '$(Build.SourcesDirectory)' -StagingDirectory '$(Build.ArtifactStagingDirectory)'
Not that terrible anymore, right?