Skip to content

Instantly share code, notes, and snippets.

@gadenbuie
Last active April 22, 2025 14:17
Show Gist options
  • Save gadenbuie/44941e3ac9daaa331cda73f6f68cf414 to your computer and use it in GitHub Desktop.
Save gadenbuie/44941e3ac9daaa331cda73f6f68cf414 to your computer and use it in GitHub Desktop.
Investigate contributions to a repo
# Install and load required packages
# install.packages("gh")
library(gh)
library(dplyr)
library(purrr)
# Get all contributors to a GitHub repository
get_repo_contributors <- function(owner, repo) {
contributors <- gh::gh(
"GET /repos/{owner}/{repo}/contributors",
owner = owner,
repo = repo,
.limit = Inf # Get all contributors, not just the first page
)
tibble(
username = map_chr(contributors, "login"),
contributions = map_int(contributors, "contributions"),
profile_url = map_chr(contributors, "html_url")
) |>
arrange(desc(contributions))
}
gh_timestamp <- function(x) {
as.POSIXct(x, format = "%Y-%m-%dT%H:%M:%SZ", tz = "UTC")
}
get_contributor_prs <- function(owner, repo, username, state = "all") {
match.arg(state, c("all", "open", "closed"))
prs <- gh::gh(
"GET /repos/{owner}/{repo}/pulls",
owner = owner,
repo = repo,
state = state,
.limit = Inf # Get all PRs, not just the first page
)
user_prs <- keep(prs, ~ tolower(.x$user$login) == tolower(username))
if (length(user_prs) == 0) {
# If no PRs found, return empty tibble with appropriate structure
return(tibble(
pr_number = integer(),
title = character(),
state = character(),
created_at = character(),
updated_at = character(),
url = character()
))
}
tibble(
pr_number = map_int(user_prs, "number"),
title = map_chr(user_prs, "title"),
state = map_chr(user_prs, "state"),
created_at = map_chr(user_prs, "created_at"),
updated_at = map_chr(user_prs, "updated_at"),
url = map_chr(user_prs, "html_url")
) |>
mutate(across(c(created_at, updated_at), gh_timestamp)) |>
arrange(desc(pr_number))
}
get_contributor_commits <- function(owner, repo, username) {
commits <- tryCatch(
{
gh::gh(
"GET /repos/{owner}/{repo}/commits",
owner = owner,
repo = repo,
author = username,
.limit = Inf
)
},
error = function(e) {
message(sprintf("Error fetching commits: %s", e$message))
return(list())
}
)
if (length(commits) == 0) {
# If no commits found, return empty tibble with appropriate structure
return(tibble(
sha = character(),
message = character(),
created_at = character(),
commit_url = character()
))
}
tibble(
sha = map_chr(commits, "sha"),
message = map_chr(
commits,
function(.x) {
msg <- .x$commit$message
# Get first line of commit message (the subject)
ifelse(grepl("\n", msg), sub("\n.*", "", msg), msg)
}
),
created_at = map_chr(commits, ~ .x$commit$author$date),
commit_url = map_chr(
commits,
~ paste0("https://github.com/", owner, "/", repo, "/commit/", .x$sha)
)
) |>
mutate(across(created_at, gh_timestamp)) |>
arrange(desc(created_at))
}
contributors <- get_repo_contributors("rstudio", "shinydashboard")
## Follow up investigation examples:
# get_contributor_prs("rstudio", "shinydashboard", "dmpe")
# get_contributor_commits("rstudio", "shinydashboard", "dmpe")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment