Finding #RStats resources with Shiny and GitHub Actions

#ShinyConf2023

About Me


Data scientist at Jumping Rivers.


Academic background in statistics.


Blog about R and data science at nrennie.rbind.io/blog.

Photo of speaker wearing red jacket

Finding #RStats resources with Shiny and GitHub Actions

  • The R community builds a lot of incredible things

  • A lot of us share them on social media

  • Keeping a list of resources seems like a good idea!

Screenshot of blog post

Finding #RStats resources with Shiny and GitHub Actions


Build


Deploy


Update


Build

Collecting Twitter data with {rtweet}


library(rtweet)
username = "nrennie35"
words_to_keep = c("rstats", " r ", "quarto",
                  "rstudio", "tidyverse", 
                  "python", "shiny", "ggplot2", 
                  "tableau", "rladies",
                  "dataviz", "visualization", 
                  "visualisation")
likes = get_favorites(username)
...
saveRDS(likes, "likes.rds")

Twitter logo

Create the UI and server


UI

ui = navbarPage(
  
  title = "{shinytweet}",
  
  theme = bs_theme(version = 4,
                   bootswatch = "minty",   
                   primary = "#12a79d"),   
  
  tabPanel("Favourite Tweets",
      reactableOutput("table_output")
  )
  
)

Server

likes = readRDS('likes.rds')
server = function(input, output) {
  output$table_output = renderReactable({
    table_df = likes %>% 
      select(created_at, user, full_text,
             tweet_link, content_url) %>% 
      ...
    reactable(table_df,
              columns = list(...),
              striped = TRUE,
              defaultPageSize = 8)
  })
}

A simple Shiny app


Screenshot of shiny app

Deploy

One click deploy to shinyapps.io

Screenshot of Publish window in RStudio

Let’s make a deploy script…


# Authenticate
setAccountInfo(
  name = Sys.getenv("SHINY_ACC_NAME"),
  token = Sys.getenv("TOKEN"),
  secret = Sys.getenv("SECRET")
  )
# Deploy
deployApp(
  appFiles = c("ui.R",
               "server.R",
               "likes.rds")
  )

Update

The problem…

  • This is just a snapshot of things up until my code runs.

  • I don’t want to manually download data every day.

  • I don’t want to update the app when the data changes.

The solution

  • Use GitHub actions to run my code while I sleep!

Gif of Donald Duck going back to sleep

What is GitHub Actions?


  • A continuous integration and continuous delivery (CI/CD) platform


  • Allows you to automate your build, test, and deployment pipeline.

GitHub actions logo

Writing GitHub Actions


repository
├── .github
│   ├── workflows
│   │   ├── action1.yml
│   │   ├── action2.yml
├── other folders
│   ├── and other files

GitHub actions logo

Writing GitHub Actions: when?


name: Update data

on:
  schedule:
    - cron: "0 8 * * *"
  workflow_dispatch:


  • Every day at 8am

  • On demand

Writing GitHub Actions: where?


jobs:
  update:
    runs-on: ubuntu-latest
    env:
      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
    steps:
      - uses: actions/checkout@v2

      - uses: r-lib/actions/setup-r@v2
        with:
          use-public-rspm: true


Writing GitHub Actions: what?


- name: Install dependencies
  run: |
    install.packages(c("rtweet", "dplyr", "tibble",
                       "stringr", "lubridate", "readr"))
  shell: Rscript {0}
  
- name: Update data
  run: |
    source("update_data.R")
  shell: Rscript {0}
  env:
    BEARER: ${{ secrets.TWITTER_BEARER }}


  • Install required R packages

  • Run an update data script with {rtweet}

  • Authenticate via GitHub secrets

Writing GitHub Actions: who?


- name: Commit files
  run: |
    git config --local user.email "actions@github.com"
    git config --local user.name "GitHub Actions"
    git add --all
    git commit -m "add data"
    git push      


  • Push updated data to main

Interacting with GitHub Actions

Screenshot of GitHub shinytweet repository on the Actions tab

Interacting with GitHub Actions

Screenshot of GitHub shinytweet repository on the Actions tab

GitHub Actions for automated deployment


Flowchart for GitHub Actions

But first, Docker!

  • Package everything your software needs to run into a container.

  • Includes system dependencies, R packages, and code.

Docker logo

FROM rocker/shiny:4.2.1
RUN install2.r rsconnect tibble dplyr stringr rtweet htmltools lubridate bslib reactable
WORKDIR /home/shinytweet
COPY ui.R ui.R 
COPY server.R server.R 
COPY likes.rds likes.rds
COPY deploy.R deploy.R
CMD Rscript deploy.R

GitHub Actions for automated deployment


- name: Build image
  run: docker build -t main . 
  
- name: execute
  run: >
    docker run 
    -e SHINY_ACC_NAME=${{ secrets.SHINY_ACC_NAME }} 
    -e TOKEN=${{secrets.TOKEN}} 
    -e SECRET=${{secrets.SECRET}} 
    main     


  • Build docker image

  • Authenticate shinyapps.io via GitHub secrets

What went wrong?

  • Authentication for data collection took a few tries

  • GitHub Actions uses latest version of R (and packages)

What went well?

  • Learned how to write GitHub Actions scripts

  • Learned how to use Docker

  • I spend less time on Twitter (maybe)

Gif of elmo dancing

Resources

Questions?