GitHub Integration with R

Note

All of the content listed below operates under the assumption that all of the necessary setup in the GitHub section of the OAuth Integrations Admin Guide has already been completed.

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
  # note: use RSTUDIO_PRODUCT (deprecated) for Connect versions < 2025.02.0
  if (Sys.getenv("POSIT_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()"