Skip to content

Instantly share code, notes, and snippets.

@jimhester
Last active April 27, 2018 15:31
Show Gist options
  • Save jimhester/9f3339f2a0ca81f7027e963356b80008 to your computer and use it in GitHub Desktop.
Save jimhester/9f3339f2a0ca81f7027e963356b80008 to your computer and use it in GitHub Desktop.
graphql query
library(tidyverse)
library(httr)
library(jsonlite)
library(glue)
library(lubridate)
# JSON friendly version of glue
jlue <- function(..., .envir = parent.frame()) {
glue(..., .envir = .envir, .open = "<", .close = ">")
}
org_data <- function(org) {
# TODO: paginate repos and maybe pullRequests?
query <- jlue('{
organization(login: "<org>") {
repositories(first: 50, orderBy: {field: PUSHED_AT, direction: DESC}) {
nodes {
name
pullRequests(first: 25, orderBy: {field: UPDATED_AT, direction: DESC}) {
nodes {
number
author {
login
}
createdAt
reviews(first: 10) {
nodes {
author {
login
}
submittedAt
}
}
}
}
}
}
}
}')
res <- gh::gh("/graphql", query = query)
d <- content(res)$data$organization$repositories$nodes
has_pr <- map_int(d, ~ length(.x$pullRequests$nodes)) > 0
d1 <- d[has_pr]
d2 <- map_dfr(d1, function(.x) {
res <- flatten_df(.x$pullRequests)
res$repo <- .x$name
res$author <- map_chr(res$author, pluck)
res
})
has_review <- lengths(d2$reviews) > 0
d3 <- bind_rows(
mutate(d2[has_review, ],
reviews = map(reviews,
~ tibble(
reviewer = map_chr(.x, c("author", "login")),
reviewedAt = map_chr(.x, "submittedAt")))) %>% unnest(),
select(d2[!has_review, ], -reviews))
d3
}
d <- bind_rows(
org_data("r-lib"),
org_data("tidyverse"),
org_data("r-dbi"))
prs <- d %>%
mutate(createdAt = lubridate::as_datetime(d$createdAt)) %>%
filter(createdAt > today() - ddays(30)) %>%
select(repo, number, author, reviewer) %>%
filter(author != reviewer) %>%
unique()
pr_authors <- prs %>% select(-reviewer) %>% unique() %>% group_by(author)
pr_reviewers <- prs %>% select(-author) %>% unique() %>% group_by(reviewer)
tally(pr_authors, sort = TRUE)
tally(pr_reviewers, sort = TRUE)
---
title: " Repository Dashboard"
output:
flexdashboard::flex_dashboard:
orientation: columns
vertical_layout: fill
---
```{r setup, include=FALSE, cache = TRUE}
library(flexdashboard)
library(tidyverse)
library(httr)
library(jsonlite)
library(glue)
library(lubridate)
library(dplyr)
library(codetools)
# JSON friendly version of glue
jlue <- function(..., .envir = parent.frame()) {
glue(..., .envir = .envir, .open = "<", .close = ">")
}
org_data <- function(org) {
# TODO: paginate repos and maybe pullRequests?
query <- jlue('{
organization(login: "<org>") {
repositories(first: 50, orderBy: {field: PUSHED_AT, direction: DESC}) {
nodes {
name
pullRequests(first: 25, orderBy: {field: UPDATED_AT, direction: DESC}) {
nodes {
number
author {
login
}
createdAt
reviews(first: 10) {
nodes {
author {
login
}
submittedAt
}
}
}
}
}
}
}
}')
res <- gh::gh("POST /graphql", query = query)
d <- res$data$organization$repositories$nodes
has_pr <- map_int(d, ~ length(.x$pullRequests$nodes)) > 0
d1 <- d[has_pr]
d2 <- map_dfr(d1, function(.x) {
res <- flatten_df(.x$pullRequests)
res$repo <- .x$name
res$author <- map_chr(res$author, pluck)
res
})
has_review <- lengths(d2$reviews) > 0
get_review_info <- function(x) {
tibble(
reviewer = map_chr(x, c("author", "login")),
reviewedAt = map_chr(x, ~ .$submittedAt %||% NA_character_))
}
d3 <- bind_rows(
mutate(d2[has_review, ], reviews = map(reviews, get_review_info)) %>% unnest(),
select(d2[!has_review, ], -reviews))
d3
}
d <- bind_rows(
org_data("r-lib"),
org_data("tidyverse"),
org_data("r-dbi"))
prs <- d %>%
mutate(createdAt = as_datetime(d$createdAt)) %>%
filter(createdAt > today() - ddays(30)) %>%
select(repo, number, author, reviewer) %>%
filter(author != reviewer) %>%
unique()
pr_authors <- prs %>% select(-reviewer) %>% unique() %>% group_by(author)
pr_reviewers <- prs %>% select(-author) %>% unique() %>% group_by(reviewer)
```
```{r repo_stats, include = FALSE, cache = TRUE}
parse_issue <- function(x) {
labels <- map_chr(x$labels$nodes, "name")
list(p1 = x$p1$totalCount %||% 0, bugs = "bug" %in% labels, features = "feature" %in% labels, unlabeled = !length(labels))
}
parse_repository <- function(x) {
if (x$open_issues$totalCount == 0) {
issues <- list(p1 = 0, bugs = FALSE, features = FALSE, unlabeled = FALSE)
} else {
issues <- map_dfr(x$open_issues$nodes, parse_issue)
}
if (x$open_issues$pageInfo$hasNextPage) {
message(x$repo, " has more than 100 open issues!")
}
#message(x$repo)
tibble::tibble(
owner = x$owner$login,
repo = x$repo,
prs = x$prs$totalCount,
watchers = x$watchers$totalCount,
open_issues = x$open_issues$totalCount,
p1 = sum(issues$p1),
bugs = sum(issues$bugs),
features = sum(issues$features),
unlabeled = sum(issues$unlabeled))
}
org_summary <- function(org) {
query <- readChar("summary.json", fs::file_info("summary.json")$size)
res <- gh::gh("POST /graphql", query = query, variables = list(org = org))
map_dfr(res$data$organization$repositories$nodes, parse_repository)
}
summary_data <- bind_rows(
org_summary("tidyverse"),
org_summary("r-lib"),
org_summary("r-dbi"))
```
Repository Statistics
=====================================
```{r}
DT::datatable(summary_data)
```
Pull Request Review counts
=====================================
Column
-------------------------------------
### PR authors
```{r}
DT::datatable(dplyr::tally(pr_authors, sort = TRUE))
```
Column
-------------------------------------
### PR Reviewers
```{r}
DT::datatable(dplyr::tally(pr_reviewers, sort = TRUE))
```
query repoSummary($org:String!) {
organization(login: $org) {
repositories(first:100) {
nodes {
owner {login},
repo:name,
open_issues : issues(first:100, states:OPEN) {
totalCount
nodes {
p1 : reactions(content:THUMBS_UP) {
totalCount
}
labels(first:10) {
nodes {
name
}
}
}
pageInfo {
endCursor
hasNextPage
}
}
prs : pullRequests(states:OPEN) {
totalCount
}
watchers : stargazers() {
totalCount
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment