July 11, 2019

Example: deploying containerized shiny apps

  • write shiny app

  • create an R package for the app

  • build package

  • check package

  • test package + shiny app

  • write a Dockerfile for the app

  • build docker image

  • deploy docker image

Example: deploying containerized shiny apps

  • write shiny app

  • create an R package for the app

  • → build package

  • → check package

  • → test package + shiny app

  • write a Dockerfile for the app

  • → build docker image

  • → deploy docker image

Goal

CI/CD pipeline which is

  • open-source
  • self-hosted
  • fully controllable from R

Jenkins + Rundeck

Jenkins

Traditional Jenkins

drawing

  • Continuous Integration server
  • Purpose: building artifacts
  • Web interface to configure several types of jobs
  • Jobs are stored internally as XML format
  • Job configuration not under version control (by default)

Jenkins 2

  • More general job type: Pipeline
  • Pipelines with file-based configuration: Jenkinsfile
  • Jenkinsfiles live next to the code under version control
pipeline {
    agent any
    stages {
        stage('Roxygen') {
            steps {
                sh 'R  -e \'roxygen2::roxygenize("myPackage")\''
            }
        }
        stage('Build') {
            steps {
                sh 'R CMD build myPackage'
            }
        }
    }
}

Rundeck

Rundeck

  • Operations server
  • Turn procedures into self-service operations
  • Designed to be aware of the details of your environments

rjenkins

rjenkins - basic commands

library(rjenkins)
jc <- jenkins("http://localhost", user = "dseyaeve", token = "my-token")
jc %>% listJobs()
## [1] "demoApp"              "my-jenkins-folder"    "my-jenkins-job"      
## [4] "my-other-jenkins-job"
job <- jc %>% getView("all") %>% getJob("my-jenkins-job")
job %>% scheduleBuild()
job %>% summary()
job %>% getBuildLog()
job %>% listArtifacts()

rjenkins - Jenkinsfile

ppl <- pipeline(
    agent("any"),
    stages(
        stage("Roxygen",
            steps(
                R(roxygen2::roxygenize('myPackage'))
            )
        ),
        stage("Build",
            steps(
                R(pkgbuild::build('myPackage'))
            )
        )
    )
)
job %>% createJob("new-job", pipelineConfig(pipeline = ppl))

rjenkins - multibranch jobs

jc %>% createJob("demoApp",
    multibranchPipelineConfig(
        gitHubBranchSource(owner = "dseynaev",
            repository = "rjenkins-demo-shiny",
            credentialsId = "github-dseynaev")))
job <- jc %>% getJob("demoApp", "master")

rrundeck

rrundeck - basic commands

library(rundeck)
rc <- rundeck("http://localhost", user = "dseynaeve", token = "my-token")
rc %>% rrundeck::listProjects()
##       name              description      label
## 1 UseR2019 Demo jobs for UseR! 2019 UseR! 2019
rc %>% rrundeck::getProject("UseR2019") %>% rrundeck::listJobs()
##          name                                  description
## 1 docker-pull # Update an image by pulling from docker hub
##                                     id
## 1 087af941-02dc-4c81-bcee-59b13c8f4fd6
job <- rc %>% getProject("UseR2019") %>% getJob(name = "docker-pull")

job %>% run(list(image = "openanalytics/rjenkins-demo-app"), follow = TRUE)

Demo

Thank You