├── .gitignore ├── LICENSE ├── .Rbuildignore ├── NAMESPACE ├── R └── foo.R ├── templates ├── r-setup-linux.yml ├── pkg-library.yml ├── r-setup-macOS.yml ├── pkg-cache_dependencies.yml ├── pkg-install_dependencies.yml ├── pkg-coverage.yml ├── pkg-workflow.yml ├── pkg-rcmd_check.yml └── r-setup-windows.yml ├── tests ├── testthat │ └── test-foo.R └── testthat.R ├── azure-pipelines.yml ├── man └── foo.Rd ├── azuretest.Rproj ├── DESCRIPTION ├── LICENSE.md ├── azure-tidyverse.yml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .Rhistory 2 | .RData 3 | .Rproj.user 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2019 2 | COPYRIGHT HOLDER: Jim Hester 3 | -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^LICENSE\.md$ 2 | ^.*\.Rproj$ 3 | ^\.Rproj\.user$ 4 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(foo) 4 | -------------------------------------------------------------------------------- /R/foo.R: -------------------------------------------------------------------------------- 1 | #' Foo Foo 2 | #' @param x x 3 | #' @export 4 | foo <- function(x) { 5 | 1 6 | } 7 | 8 | bar <- function(x) { 9 | stop("hi") 10 | } 11 | -------------------------------------------------------------------------------- /templates/r-setup-linux.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - script: sudo apt-get update && sudo apt-get install -y libxml2-dev libssl-dev 3 | displayName: "Install System Dependencies" 4 | -------------------------------------------------------------------------------- /templates/pkg-library.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - bash: | 3 | echo 'options(repos = "$(CRAN)", Ncpus = 2, crayon.enabled = TRUE)' > ~/.Rprofile 4 | mkdir -p $(R_LIBS_USER) 5 | displayName: "Setting up R library" 6 | -------------------------------------------------------------------------------- /templates/r-setup-macOS.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - script: | 3 | curl -fLo /tmp/R.pkg "$(CRAN)/bin/macosx/R-latest.pkg" 4 | sudo installer -pkg "/tmp/R.pkg" -target / 5 | rm /tmp/R.pkg 6 | displayName: 'Installing R' 7 | -------------------------------------------------------------------------------- /templates/pkg-cache_dependencies.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - task: CacheBeta@0 3 | inputs: 4 | key: ./DESCRIPTION | "$(Agent.JobName)" 5 | path: $(R_LIBS_USER) 6 | displayName: 'Caching Packages' 7 | continueOnError: true 8 | -------------------------------------------------------------------------------- /templates/pkg-install_dependencies.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - bash: | 3 | Rscript -e "install.packages(c('remotes', 'rcmdcheck'))" 4 | Rscript -e "remotes::install_deps(dependencies = TRUE)" 5 | displayName: 'Install package dependencies' 6 | -------------------------------------------------------------------------------- /tests/testthat/test-foo.R: -------------------------------------------------------------------------------- 1 | test_that("foo works", { 2 | expect_equal(foo(), 1) 3 | }) 4 | 5 | #test_that("foo does not work", { 6 | #expect_equal(foo(), 2) 7 | #}) 8 | 9 | #test_that("bar errors", { 10 | #expect_equal(bar(1), 2) 11 | #}) 12 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | resources: 2 | repositories: 3 | - repository: r-azure-pipelines 4 | type: github 5 | name: r-lib/r-azure-pipelines 6 | endpoint: r-lib 7 | 8 | jobs: 9 | - template: azure-tidyverse.yml@r-azure-pipelines 10 | -------------------------------------------------------------------------------- /man/foo.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/foo.R 3 | \name{foo} 4 | \alias{foo} 5 | \title{Foo Foo} 6 | \usage{ 7 | foo(x) 8 | } 9 | \arguments{ 10 | \item{x}{x} 11 | } 12 | \description{ 13 | Foo Foo 14 | } 15 | -------------------------------------------------------------------------------- /templates/pkg-coverage.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - bash: | 3 | Rscript -e "cov <- covr::azure()" 4 | displayName: 'Run code coverage' 5 | - task: PublishCodeCoverageResults@1 6 | inputs: 7 | codeCoverageTool: 'Cobertura' 8 | summaryFileLocation: 'coverage.xml' 9 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(azuretest) 3 | 4 | if (requireNamespace("xml2")) { 5 | test_check("azuretest", reporter = MultiReporter$new(reporters = list(JunitReporter$new(file = "test-results.xml"), CheckReporter$new()))) 6 | } else { 7 | test_check("azuretest") 8 | } 9 | -------------------------------------------------------------------------------- /azuretest.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | BuildType: Package 16 | PackageUseDevtools: Yes 17 | PackageInstallArgs: --no-multiarch --with-keep.source 18 | -------------------------------------------------------------------------------- /templates/pkg-workflow.yml: -------------------------------------------------------------------------------- 1 | # Run a full package workflow, including coverage and caching 2 | 3 | parameters: 4 | args: "'--no-manual'" 5 | cache: true 6 | coverage: false 7 | 8 | steps: 9 | - template: pkg-library.yml 10 | - ${{ if eq(parameters.cache, 'true') }}: 11 | - template: pkg-cache_dependencies.yml 12 | - template: pkg-install_dependencies.yml 13 | - template: pkg-rcmd_check.yml 14 | parameters: 15 | args: ${{parameters.args}} 16 | - ${{ if eq(parameters.coverage, 'true') }}: 17 | - template: pkg-coverage.yml 18 | -------------------------------------------------------------------------------- /templates/pkg-rcmd_check.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | args: "'--no-manual'" 3 | 4 | steps: 5 | - bash: | 6 | Rscript -e "rcmdcheck::rcmdcheck(args = ${{parameters.args}}, error_on = 'warning', check_dir = 'check')" 7 | displayName: 'Check package' 8 | - task: PublishTestResults@1 9 | inputs: 10 | testResultsFormat: 'JUnit' 11 | testResultsFiles: 'check/*.Rcheck/tests/test-*.xml' 12 | testRunTitle: $(Agent.JobName) 13 | condition: succeededOrFailed() 14 | - publish: check 15 | artifact: $(Build.BuildNumber)-$(Agent.JobName)-check_results 16 | condition: succeededOrFailed() 17 | -------------------------------------------------------------------------------- /templates/r-setup-windows.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - pwsh: | 3 | choco install r.project -y --no-progress 4 | Invoke-WebRequest "https://github.com/hannesmuehleisen/choco-rtools/raw/master/rtools.3.5.0.nupkg" -OutFile "..\rtools.3.5.0.nupkg" 5 | choco install rtools -s ..\rtools.3.5.0.nupkg -f -y --no-progress 6 | 7 | # Set the timezone 8 | tzutil /s "GMT Standard Time" 9 | displayName: 'Installing R' 10 | - pwsh: | 11 | Write-Host "##vso[task.setvariable variable=PATH]C:\Rtools\bin;C:\Rtools\mingw_64\bin;${env:PATH};C:\Progra~1\R\R-3.6.1\bin" 12 | displayName: 'Setting PATH' 13 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: azuretest 2 | Title: Test package for azure pipelines 3 | Version: 0.0.0.9000 4 | Authors@R: 5 | c(person(given = "Jim", 6 | family = "Hester", 7 | role = c("aut", "cre"), 8 | email = "james.f.hester@gmail.com", 9 | comment = c(ORCID = "0000-0002-2739-7082")), 10 | person(given = "RStudio", 11 | role = c("cph", "fnd"))) 12 | Description: What the package does (one paragraph). 13 | License: MIT + file LICENSE 14 | Encoding: UTF-8 15 | LazyData: true 16 | Suggests: 17 | testthat (>= 2.1.0), 18 | xml2, 19 | covr 20 | URL: https://github.com/jimhester/azuretest 21 | BugReports: https://github.com/jimhester/azuretest/issues 22 | RoxygenNote: 6.1.1 23 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2019 Jim Hester 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /azure-tidyverse.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | R_LIBS_USER: '$(Agent.BuildDirectory)/R/library' 3 | CRAN: 'https://cloud.r-project.org' 4 | coverage: true 5 | env: {} 6 | 7 | jobs: 8 | - job: 'Linux' 9 | variables: 10 | CRAN: 'https://demo.rstudiopm.com/all/__linux__/xenial/latest' 11 | R_LIBS_USER: ${{parameters.R_LIBS_USER}} 12 | TZ: UTC 13 | CI: true 14 | ${{ insert }}: ${{ parameters.env }} 15 | pool: 16 | vmImage: 'Ubuntu-16.04' 17 | strategy: 18 | matrix: 19 | R-3.2: 20 | containerImage: rstudio/r-base:3.2-xenial 21 | R-3.3: 22 | containerImage: rstudio/r-base:3.3-xenial 23 | R-3.4: 24 | containerImage: rstudio/r-base:3.4-xenial 25 | R-3.5: 26 | containerImage: rstudio/r-base:3.5-xenial 27 | R-3.6: 28 | containerImage: rstudio/r-base:3.6-xenial 29 | container: $[ variables['containerImage'] ] 30 | steps: 31 | - template: templates/r-setup-linux.yml 32 | - template: templates/pkg-workflow.yml 33 | parameters: 34 | coverage: false 35 | 36 | 37 | - job: 'macOS' 38 | variables: 39 | CRAN: ${{parameters.CRAN}} 40 | R_LIBS_USER: ${{parameters.R_LIBS_USER}} 41 | CI: true 42 | ${{ insert }}: ${{ parameters.env }} 43 | pool: 44 | vmImage: 'macOS-10.15' 45 | steps: 46 | - template: templates/r-setup-macOS.yml 47 | - template: templates/pkg-workflow.yml 48 | parameters: 49 | coverage: ${{parameters.coverage}} 50 | 51 | - job: 'Windows' 52 | variables: 53 | CRAN: ${{parameters.CRAN}} 54 | R_LIBS_USER: ${{parameters.R_LIBS_USER}} 55 | CI: true 56 | ${{ insert }}: ${{ parameters.env }} 57 | pool: 58 | vmImage: 'vs2017-win2016' 59 | steps: 60 | - template: templates/r-setup-windows.yml 61 | - template: templates/pkg-workflow.yml 62 | parameters: 63 | args: "c('--no-manual', '--no-multiarch')" 64 | coverage: false 65 | cache: false 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | [![Lifecycle: superseded](https://img.shields.io/badge/lifecycle-superseded-orange.svg)](https://www.tidyverse.org/lifecycle/#superseded) 3 | [![Build Status](https://dev.azure.com/r-lib/r-azure-pipelines/_apis/build/status/r-lib.r-azure-pipelines?branchName=master)](https://dev.azure.com/r-lib/r-azure-pipelines/\_build/latest?definitionId=3&branchName=master) 4 | 5 | 6 | ## R CI with Azure Pipelines 7 | 8 | This repository includes templates for using azure pipelines with R packages, 9 | as well as a simple R package for testing. 10 | 11 | ### Features 12 | 13 | - Uses [RStudio docker](https://github.com/rstudio/r-docker) containers to test 14 | on R 3.2, 3.3, 3.4, 3.5, 3.6 15 | - Installs package dependencies using [remotes](https://remotes.r-lib.org) 16 | - Build and checks packages using [rcmdcheck](https://github.com/r-lib/rcmdcheck) 17 | - Run code coverage using [covr](https://github.com/r-lib/covr) 18 | 19 | - Linux 20 | - Matrix builds of minor R versions from 3.2+ 21 | - Package caching 22 | - Windows 23 | - RTools installation 24 | - macOS 25 | 26 | ### Setup 27 | 28 | Add a yaml file named `azure-pipelines.yml` with the following content, this 29 | will setup your repo to use the tidyverse default configuration. 30 | 31 | You need to replace REPLACE-ME with the name of your [Service 32 | Connection](https://docs.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml) 33 | to GitHub. 34 | 35 | ```yaml 36 | resources: 37 | repositories: 38 | - repository: r-azure-pipelines 39 | type: github 40 | name: r-lib/r-azure-pipelines 41 | endpoint: REPLACE-ME 42 | 43 | jobs: 44 | - template: azure-tidyverse.yml@r-azure-pipelines 45 | ``` 46 | 47 | ## Status [![Lifecycle: superseded](https://img.shields.io/badge/lifecycle-superseded-orange.svg)](https://www.tidyverse.org/lifecycle/#superseded) 48 | 49 | r-azure-pipelines is superseded: this means it is no longer being actively supported. We recommend using [r-lib/actions](https://github.com/r-lib/actions) instead. 50 | --------------------------------------------------------------------------------