Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
639 lines (530 sloc) 14.5 KB
#' Retrieve GitHub information
#'
#' @section Usage:
#' \preformatted{
#' myRepo <- GitHubRepo$new("repo_name", "user_name")
#' myRepo$get_stats()
#' myRepo$get_branches()
#' myRepo$get_issues()
#' myRepo$get_labels()
#' myRepo$get_milestones()
#' myRepo$get_coc()
#' myRepo$get_license()
#' myRepo$get_pull_requests()
#' myRepo$get_releases()
#' myRepo$get_travis_status()
#' myRepo$get_appveyor_status()
#' myRepo$get_coverage()
#' }
#'
#' @section Arguments:
#' \describe{
#' \item{user_name}{GitHub user or organization name.}
#' \item{repo_name}{Name of the GitHub repository.}
#' }
#'
#' @section Details:
#'
#' To create \code{GitHubRepo} objects, you need to use \code{GitHubRepo$new("repo_name", "user_name")}.
#'
#' \code{myRepo$get_stats()} will return the number of stars, forks and issues of the package.
#'
#' \code{myRepo$get_branches()} will return the name of the branches of the package.
#'
#' \code{myRepo$get_issues()} will return the list of open issues.
#'
#' \code{myRepo$get_labels()} will return the name and color labels used in issues filed in the package.
#'
#' \code{myRepo$get_milestones()} will return the details of milestones associated with the package.
#'
#' \code{myRepo$get_coc()} will return the code of conduct of the package.
#'
#' \code{myRepo$get_license()} will return license of the package.
#'
#' \code{myRepo$get_pull_requests()} will return all the open pull requests.
#'
#' \code{myRepo$get_releases()} will return all the releases of the package on GitHub.
#'
#' \code{myRepo$get_travis_status()} will return the build status of the package from Travis CI.
#'
#' \code{myRepo$get_appveyor_status()} will return the build status of the package from Appveyor.
#'
#' \code{myRepo$get_coverage()} will return code coverage of the package from Codecov.
#'
#' @examples
#' \dontrun{
#' # initialize object
#' myRepo <- GitHubRepo$new("dplyr", "tidyverse")
#'
#' # get stats
#' myRepo$get_stats()
#'
#' # get branches
#' myRepo$get_branches()
#'
#' # get travis ci build status
#' myRepo$get_travis_status()
#'
#' # get codecov code coverage
#' myRepo$get_coverage()
#' }
#'
#' @name GitHubRepo
#' @docType class
#' @format An R6 class.
#' @export
#'
NULL
GitHubRepo <- R6::R6Class("GitHubRepo",
public = list(
repo_name = NULL,
user_name = NULL,
initialize = function(repo_name = NA, user_name = NULL) {
self$user_name <- user_name
self$repo_name <- repo_name
},
get_stats = function() {
get_gh_stats(self$repo_name, self$user_name)
},
get_branches = function() {
get_gh_branches(self$repo_name, self$user_name)
},
get_issues = function() {
get_gh_issues(self$repo_name, self$user_name)
},
get_labels = function() {
get_gh_labels(self$repo_name, self$user_name)
},
get_milestones = function() {
get_gh_milestones(self$repo_name, self$user_name)
},
get_coc = function() {
get_gh_coc(self$repo_name, self$user_name)
},
get_license = function() {
get_gh_license(self$repo_name, self$user_name)
},
get_pull_requests = function() {
get_gh_pr(self$repo_name, self$user_name)
},
get_releases = function() {
get_gh_releases(self$repo_name, self$user_name)
},
get_travis_status = function() {
get_status_travis(self$repo_name, self$user_name)
},
get_appveyor_status = function() {
get_status_appveyor(self$repo_name, self$user_name)
},
get_coverage = function() {
get_code_coverage(self$repo_name, self$user_name)
}
)
)
#' Retrieve GitHub information.
#'
#' Returns the GitHub username, stars, forks, branches, issues, labels,
#' milestones, code of conduct, license, pull requests and releases.
#'
#' @param repo_name Name of the package.
#' @param user_name GitHub user or organization name.
#'
#' @examples
#' \dontrun{
#' # get github user/organization name
#' get_gh_username("olsrr")
#'
#' # get count of stars, forks & issues
#' get_gh_stats("dplyr", "tidyverse")
#'
#' # get details of github branches
#' get_gh_branches("dplyr", "tidyverse")
#'
#' # get details of open issues
#' get_gh_issues("dplyr", "tidyverse")
#'
#' # get labels
#' get_gh_labels("dplyr", "tidyverse")
#'
#' # get milestones
#' get_gh_milestones("dplyr", "tidyverse")
#'
#' # get code of conduct
#' get_gh_coc("dplyr", "tidyverse")
#'
#' # get license
#' get_gh_license("dplyr", "tidyverse")
#'
#' # get details of open pull requests
#' get_gh_pr("dplyr", "tidyverse")
#'
#' # get releases
#' get_gh_releases("dplyr", "tidyverse")
#'
#' }
#' @name github_info
#'
NULL
#' @rdname github_info
#' @export
#'
get_gh_username <- function(repo_name) {
check_cran(repo_name)
all_urls <-
repo_name %>%
get_pkg_details() %>%
get_pkg_urls()
check_git <-
all_urls %>%
dplyr::filter(stringr::str_detect(urls, "github")) %>%
nrow()
if (check_git > 0) {
urls <-
all_urls %>%
dplyr::filter(stringr::str_detect(urls, "github")) %>%
dplyr::pull(urls) %>%
dplyr::first()
locate_slash <- stringr::str_locate_all(urls, "/")
start <-
locate_slash %>%
get_location(position = 3) %>%
magrittr::add(1)
end <-
locate_slash %>%
get_location(position = 4) %>%
magrittr::subtract(1)
stringr::str_sub(urls, start, end)
} else {
message("There is no associated GitHub repository for this package.")
}
}
#' @rdname github_info
#' @export
#'
get_gh_stats <- function(repo_name, user_name = NULL) {
if (is.null(user_name)) {
user_name <- get_gh_username(repo_name)
}
if (is.null(user_name)) {
NULL
} else {
check_repo(user_name, repo_name)
pkg <- pkg_github(user_name, repo_name)
stars <- pkg$stargazers_count
issues <- pkg$open_issues_count
forks <- pkg$forks_count
tibble::tibble(
stars = stars,
issues = issues,
forks = forks
)
}
}
pkg_github <- function(user_name, repo_name) {
check_repo(user_name, repo_name)
pkg_name <- paste0("/repos/", user_name, "/", repo_name)
url <- httr::modify_url("https://api.github.com", path = pkg_name)
resp <- httr::GET(url)
jsonlite::fromJSON(httr::content(resp, "text", encoding = "UTF-8"),
simplifyVector = FALSE)
}
#' @rdname github_info
#' @export
#'
get_gh_branches <- function(repo_name, user_name = NULL) {
if (is.null(user_name)) {
user_name <- get_gh_username(repo_name)
}
if (is.null(user_name)) {
NULL
} else {
check_repo(user_name, repo_name)
out <- connect_api(user_name, repo_name, "branches")
tibble::tibble(branches = purrr::map_chr(out, "name"))
}
}
#' @rdname github_info
#' @export
#'
get_gh_issues <- function(repo_name, user_name = NULL) {
if (is.null(user_name)) {
user_name <- get_gh_username(repo_name)
}
if (is.null(user_name)) {
NULL
} else {
check_repo(user_name, repo_name)
out <- connect_api(user_name, repo_name, "issues")
issue_number <- purrr::map_int(out, "number")
issue_title <- purrr::map_chr(out, "title")
issue_body <- purrr::map_chr(out, "body")
issue_date <-
out %>%
purrr::map_chr("created_at") %>%
as.Date()
issue_user <-
out %>%
purrr::map("user") %>%
purrr::map_chr("login")
tibble::tibble(
date = issue_date,
number = issue_number,
author = issue_user,
title = issue_title
)
}
}
#' @rdname github_info
#' @export
#'
get_gh_labels <- function(repo_name, user_name = NULL) {
if (is.null(user_name)) {
user_name <- get_gh_username(repo_name)
}
if (is.null(user_name)) {
NULL
} else {
check_repo(user_name, repo_name)
out <- connect_api(user_name, repo_name, "labels")
label_name <- purrr::map_chr(out, "name")
label_color <- purrr::map_chr(out, "color")
tibble::tibble(
name = label_name,
color = label_color
)
}
}
#' @rdname github_info
#' @export
#'
get_gh_milestones <- function(repo_name, user_name = NULL) {
if (is.null(user_name)) {
user_name <- get_gh_username(repo_name)
}
if (is.null(user_name)) {
NULL
} else {
check_repo(user_name, repo_name)
out <- connect_api(user_name, repo_name, "milestones")
m_title <- purrr::map_chr(out, "title")
m_body <- purrr::map_chr(out, "description")
m_open <- purrr::map_int(out, "open_issues")
m_closed <- purrr::map_int(out, "closed_issues")
m_start <- as.Date(purrr::map_chr(out, "created_at"))
due <- magrittr::extract2(out, 1)$due_on
m_due <- ifelse(is.null(due), NA, as.Date(due))
tibble::tibble(
title = m_title,
tart_date = m_start,
due_date = m_due,
description = m_body,
open_issues = m_open,
closed_issues = m_closed
)
}
}
#' @rdname github_info
#' @export
#'
get_gh_coc <- function(repo_name, user_name = NULL) {
if (is.null(user_name)) {
user_name <- get_gh_username(repo_name)
}
if (is.null(user_name)) {
NULL
} else {
check_repo(user_name, repo_name)
pkg_name <- paste0("/repos/", user_name, "/", repo_name, "/community/code_of_conduct")
url <- httr::modify_url("https://api.github.com", path = pkg_name)
resp <- httr::GET(url, httr::add_headers(Accept = "application/vnd.github.scarlet-witch-preview+json"))
out <- jsonlite::fromJSON(httr::content(resp, "text", encoding = "UTF-8"),
simplifyVector = FALSE)
cat(out$body)
}
}
#' @rdname github_info
#' @export
#'
get_gh_license <- function(repo_name, user_name = NULL) {
if (is.null(user_name)) {
user_name <- get_gh_username(repo_name)
}
if (is.null(user_name)) {
NULL
} else {
check_repo(user_name, repo_name)
out <- connect_api(user_name, repo_name, "license")
if (length(out) == 2) {
cat("This repository does not have a license file.")
} else {
if (curl::has_internet()) {
utils::browseURL(out$html_url)
} else {
cat("Please ensure your internet connection is working.")
}
}
}
}
#' @rdname github_info
#' @export
#'
get_gh_pr <- function(repo_name, user_name = NULL) {
if (is.null(user_name)) {
user_name <- get_gh_username(repo_name)
}
if (is.null(user_name)) {
NULL
} else {
check_repo(user_name, repo_name)
out <- connect_api(user_name, repo_name, "pulls")
pull_number <- purrr::map_int(out, "number")
pull_start <- as.Date(purrr::map_chr(out, "created_at"))
pull_title <- purrr::map_chr(out, "title")
pull_status <- purrr::map_chr(out, "state")
tibble::tibble(
number = pull_number,
date = pull_start,
title = pull_title,
status = pull_status
)
}
}
#' @rdname github_info
#' @export
#'
get_gh_releases <- function(repo_name, user_name = NULL) {
if (is.null(user_name)) {
user_name <- get_gh_username(repo_name)
}
if (is.null(user_name)) {
NULL
} else {
check_repo(user_name, repo_name)
out <- connect_api(user_name, repo_name, "releases")
release_tag <- purrr::map_chr(out, "tag_name")
release_title <- purrr::map_chr(out, "name")
pre_release <- purrr::map_lgl(out, "prerelease")
release_published <- as.Date(purrr::map_chr(out, "published_at"))
tibble::tibble(
tag = release_tag,
date = release_published,
title = release_title,
prerelease = pre_release
)
}
}
#' Retrieve build information.
#'
#' Returns build status from Travis CI and Appveyor, and code coverage from
#' codecov.
#'
#' @param repo_name Name of the package.
#' @param user_name GitHub user or organization name.
#'
#' @examples
#' \dontrun{
#' # get travis ci build status
#' get_status_travis("dplyr", "tidyverse")
#'
#' # get appveyor build status
#' get_status_appveyor("dplyr", "tidyverse")
#'
#' # get codecov code coverage
#' get_code_coverage("dplyr", "tidyverse")
#' }
#'
#' @name build_info
#'
NULL
#' @rdname build_info
#' @export
#'
get_status_travis <- function(repo_name, user_name = NULL) {
if (is.null(user_name)) {
user_name <- get_gh_username(repo_name)
}
if (is.null(user_name)) {
NULL
} else {
check_repo(user_name, repo_name)
pkg_name <- paste0("repos/", user_name, "/", repo_name)
url <- httr::modify_url("https://api.travis-ci.org", path = pkg_name)
resp <- httr::GET(url)
httr::content(resp, "parsed", encoding = "UTF-8") %>%
xml2::as_list() %>%
magrittr::use_series('Projects') %>%
magrittr::use_series('Project') %>%
attributes() %>%
magrittr::use_series('lastBuildStatus') %>%
magrittr::extract(1)
}
}
#' @rdname build_info
#' @export
#'
get_status_appveyor <- function(repo_name, user_name = NULL) {
if (is.null(user_name)) {
user_name <- get_gh_username(repo_name)
}
check_repo(user_name, repo_name)
pkg_name <- paste0("/api/projects/", user_name, "/", repo_name)
url <- httr::modify_url("https://ci.appveyor.com", path = pkg_name)
resp <- httr::GET(url)
result <- jsonlite::fromJSON(httr::content(resp, "text", encoding = "UTF-8"),
simplifyVector = FALSE)
result$build$status
}
#' @rdname build_info
#' @export
#'
get_code_coverage <- function(repo_name, user_name = NULL) {
if (is.null(user_name)) {
user_name <- get_gh_username(repo_name)
}
if (is.null(user_name)) {
NULL
} else {
check_repo(user_name, repo_name)
pkg_name <- paste0("/api/gh/", user_name, "/", repo_name)
url <- httr::modify_url("https://codecov.io", path = pkg_name)
resp <- httr::GET(url)
result <- jsonlite::fromJSON(httr::content(resp, "text", encoding = "UTF-8"),
simplifyVector = FALSE)
result$commit$totals$c
}
}
connect_api <- function(user_name, repo_name, node) {
pkg_name <- paste0("/repos/", user_name, "/", repo_name, "/", node)
url <- httr::modify_url("https://api.github.com", path = pkg_name)
resp <- httr::GET(url)
jsonlite::fromJSON(httr::content(resp, "text", encoding = "UTF-8"),
simplifyVector = FALSE)
}
check_repo <- function(user_name, repo_name) {
if (curl::has_internet()) {
repo_url <- paste0("https://github.com/", user_name)
repo_status <-
repo_url %>%
httr::GET() %>%
httr::status_code()
if (repo_status != 200) {
stop("Please check the repository name.", call. = FALSE)
}
pkg_url <- paste0("https://github.com/", user_name, "/", repo_name)
pkg_status <-
pkg_url %>%
httr::GET() %>%
httr::status_code()
if (pkg_status != 200) {
stop("Please check the package name.", call. = FALSE)
}
} else {
stop("Please check your internet connection.", call. = FALSE)
}
}
get_location <- function(string, position) {
string %>%
magrittr::extract2(1) %>%
magrittr::extract(position, 1) %>%
unname()
}
You can’t perform that action at this time.