GitHub Integration with R

Problem

A Publisher wants to create an all-in-one status dashboard for their project hosted on Posit Connect, allowing users to see tasks assigned to them in GitHub right from the Connect dashboard. The Publisher wants to limit the display to issues assigned to the logged-in user.

Solution

Using Posit Connect’s GitHub Integration the Publisher is able to create a Shiny app that displays issues assigned to the logged-in user.

app.R
library(shiny)
library(bslib)
library(gh)
library(httr2)
library(connectapi)

ui <- page_sidebar(
  title = "My GitHub Issues",
  sidebar = sidebar(
    title = "GitHub Repo",
    textInput("gh_repo", "GitHub Repository", value = "octocat/Hello-World", placeholder = "octocat/Hello-World"),
  ),
  layout_columns(
    card(
      card_header("assigned"),
      verbatimTextOutput("assigned")
    ),
    card(
      card_header("issues"),
      verbatimTextOutput("issues")
    ),
    card(
      card_header("prs"),
      verbatimTextOutput("prs")
    ),
    card(
      card_header("whoami"),
      verbatimTextOutput("whoami")
    ),

  )
)


server <- function(input, output, session) {

  # check if running on Posit Connect
  if (Sys.getenv("RSTUDIO_PRODUCT") == "CONNECT") {
    # initialize Connect API client
    client <- connect()
    # read the user-session-token header
    user_session_token <- session$request$HTTP_POSIT_CONNECT_USER_SESSION_TOKEN
    # grab the OAuth Integration access token using the session token
    credentials <- get_oauth_credentials(client, user_session_token)
    token <- credentials$access_token
  } else {
    # grab the access token from the GITHUB_TOKEN env var if running locally
    token <- Sys.getenv("GITHUB_TOKEN")
  }

  output$assigned <- renderText ({
    assigned <- gh(
      "GET /issues",
      .token = token
    )
    paste(assigned)
  })

  output$issues <- renderText({
    req(input$gh_repo)

    my_issues <- gh(
      "GET /repos/{gh_repo}/issues",
      gh_repo = input$gh_repo,
      .token = token
    )
    paste(my_issues)
  })

  output$prs <- renderText({
    req(input$gh_repo)

    my_pulls <- gh(
      "GET /repos/{gh_repo}/pulls",
      gh_repo = input$gh_repo,
      .token = token
    )
    paste(my_pulls)
  })


  output$whoami <- renderText({
    gh_whoami(
      .token = token
    ) |>
      {\(x) c(x$name, x$login)}() |>
      {\(x) paste(x, collapse = "\n")}()
  })
}

shinyApp(ui, server)

Running the app locally

Terminal
export CONNECT_SERVER=<connect-host>
export CONNECT_API_KEY=<connect-api-key>
# GITHUB_TOKEN is only required when running the example locally
GITHUB_TOKEN="<github-token>" R -e "shiny::runApp()"