From c8c4e1f06569b707712f0edf9f3739db528ac121 Mon Sep 17 00:00:00 2001 From: Maciej Banas Date: Thu, 31 Aug 2023 12:46:10 +0000 Subject: [PATCH 1/4] Handle GitLab subgroups and add `show_orgs` function. Handling for GitLab subgroups was needed as url for GitLab groups should not contain slash "/", instead a url code "%2f". The version is changed, as from now on, there is a need to control it, as different tools use/test GitStats with new features. --- DESCRIPTION | 2 +- NAMESPACE | 1 + NEWS.md | 5 +++-- R/EngineGraphQLGitLab.R | 1 + R/EngineRest.R | 3 +++ R/EngineRestGitLab.R | 6 +++--- R/GitStats.R | 12 ++++++++++- R/gitstats_functions.R | 12 +++++++++++ devel/example_workflow.R | 10 +++++++++ man/GitStats.Rd | 11 ++++++++++ man/show_orgs.Rd | 19 +++++++++++++++++ tests/testthat/_snaps/02-EngineRest.md | 11 ++++++++++ tests/testthat/_snaps/GitStats.md | 15 ++++++++++++++ tests/testthat/test-02-EngineRest.R | 23 +++++++++++++++++++-- tests/testthat/test-GitStats.R | 28 ++++++++++++++++++++++++++ tests/testthat/test-show.R | 7 +++++++ 16 files changed, 157 insertions(+), 9 deletions(-) create mode 100644 man/show_orgs.Rd create mode 100644 tests/testthat/test-show.R diff --git a/DESCRIPTION b/DESCRIPTION index 94055b8e..fd129995 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: GitStats Title: Get Statistics from Git Hosting Services -Version: 0.1.0.9000 +Version: 0.1.0.9001 Authors@R: c( person(given = "Maciej", family = "Banaś", email = "banasmaciek@gmail.com", role = c("aut", "cre")), person(given = "Kamil", family = "Koziej", email = "koziej.k@gmail.com", role = "aut"), diff --git a/NAMESPACE b/NAMESPACE index a982c123..015cc89d 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -13,6 +13,7 @@ export(reset) export(reset_language) export(set_connection) export(setup) +export(show_orgs) importFrom(R6,R6Class) importFrom(cli,cli_abort) importFrom(cli,cli_alert_danger) diff --git a/NEWS.md b/NEWS.md index 03156842..6c9332fc 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,10 +1,11 @@ -GitStats 0.1.0.9000 +GitStats 0.1.0.9001 - set new name for `set_connection` function: `add_host` as it is more informative (and shorter). `set_connection` will be eventually deprecated but for the time-being it will stay (I: #271), - added setting tokens by default - if a user does have all the PATs set up in environment variables (as e.g. `GITHUB_PAT` or `GITLAB_PAT`), there is no need to pass them as an arugment to `set_connection` (I: #120 PR: #268), - added `get_users()` function to pull information on users (I: #199 PR: #238), - added possibility of scanning whole internal git platforms if no `orgs` are passed (I: #258), - added switching to REST engine in case GraphQL fails with 502 error (I: #225 PRs: #227 (for repos) #261 (for commits)) +- added `show_orgs()` function to print all organizations (I: #283), - added GraphQL engine for getting GitLab repos by organization (I: #218 PR: #233) - removed `contributors` as basic stat when pulling `repos` by `org` and by `phrase` to improve speed of pulling repositories data. Added `add_repos_contributors()` user function and `add_contributors` parameter to `get_repos()` function to add conditionally information on contributors to repositories table (I: #235 PRs: #243 #264) - added resetting all settings to default with `reset()` function (I: #270) @@ -12,7 +13,7 @@ GitStats 0.1.0.9000 - OOP optimization: moved method on adding issues do repository table via REST to privates (I: #235 PR: #243) - handled errors when tokens do not grant access (I: #242 PR: #247) - in repositories output set `api_url` column as an address to the repo, not the host (I: #201 PR: #249) - +- fixed adding GitLab subgroups (I: #176) GitStats 0.1.0 diff --git a/R/EngineGraphQLGitLab.R b/R/EngineGraphQLGitLab.R index fa43417f..7a5dab06 100644 --- a/R/EngineGraphQLGitLab.R +++ b/R/EngineGraphQLGitLab.R @@ -45,6 +45,7 @@ EngineGraphQLGitLab <- R6::R6Class("EngineGraphQLGitLab", #' @return A table. get_repos = function(org, settings) { + org <- gsub("%2f", "/", org) if (settings$search_param == "org") { if (!private$scan_all) { cli::cli_alert_info("[GitLab][Engine:{cli::col_yellow('GraphQL')}][org:{org}] Pulling repositories...") diff --git a/R/EngineRest.R b/R/EngineRest.R index 70d4f37d..450ebde7 100644 --- a/R/EngineRest.R +++ b/R/EngineRest.R @@ -45,6 +45,9 @@ EngineRest <- R6::R6Class("EngineRest", check_organizations = function(orgs) { orgs <- purrr::map(orgs, function(org) { org_endpoint <- if(grepl("github", self$rest_api_url)) "/orgs/" else "/groups/" + if (grepl("/", org)) { + org <- gsub("/", "%2f", org) + } withCallingHandlers( { self$response(endpoint = paste0(self$rest_api_url, org_endpoint, org)) diff --git a/R/EngineRestGitLab.R b/R/EngineRestGitLab.R index fd60257a..61d17134 100644 --- a/R/EngineRestGitLab.R +++ b/R/EngineRestGitLab.R @@ -13,7 +13,7 @@ EngineRestGitLab <- R6::R6Class("EngineRestGitLab", settings) { if (settings$search_param == "phrase") { if (!private$scan_all) { - cli::cli_alert_info("[GitLab][Engine:{cli::col_green('REST')}][phrase:{settings$phrase}][org:{org}] Searching repositories...") + cli::cli_alert_info("[GitLab][Engine:{cli::col_green('REST')}][phrase:{settings$phrase}][org:{gsub('%2f', '/', org)}] Searching repositories...") } repos_table <- private$search_repos_by_phrase( org = org, @@ -25,7 +25,7 @@ EngineRestGitLab <- R6::R6Class("EngineRestGitLab", private$add_repos_issues() } else if (settings$search_param == "team") { if (!private$scan_all) { - cli::cli_alert_info("[GitLab][Engine:{cli::col_green('REST')}][org:{org}][team:{settings$team_name}] Pulling repositories...") + cli::cli_alert_info("[GitLab][Engine:{cli::col_green('REST')}][org:{gsub('%2f', '/', org)}][team:{settings$team_name}] Pulling repositories...") } org <- private$get_group_id(org) repos_table <- private$pull_repos_from_org(org) %>% @@ -53,7 +53,7 @@ EngineRestGitLab <- R6::R6Class("EngineRestGitLab", repos_table <- NULL if (settings$search_param == "org") { if (!private$scan_all) { - cli::cli_alert_info("[GitLab][Engine:{cli::col_green('REST')}][org:{org}] Pulling repositories...") + cli::cli_alert_info("[GitLab][Engine:{cli::col_green('REST')}][org:{gsub('%2f', '/', org)}] Pulling repositories...") } org <- private$get_group_id(org) repos_table <- private$pull_repos_from_org(org) %>% diff --git a/R/GitStats.R b/R/GitStats.R index 7459b945..cbfa2ec2 100644 --- a/R/GitStats.R +++ b/R/GitStats.R @@ -212,6 +212,14 @@ GitStats <- R6::R6Class("GitStats", return(users_table) }, + #' @description Print organizations. + show_orgs = function() { + purrr::map(private$hosts, function(host) { + orgs <- host$.__enclos_env__$private$orgs + purrr::map_vec(orgs, ~ gsub("%2f", "/", .)) + }) %>% unlist() + }, + #' @description Print repositories output. show_repos = function() { private$repos @@ -326,9 +334,11 @@ GitStats <- R6::R6Class("GitStats", item_to_print = item_to_check) { if (item_name == "Organisations") { item_to_print <- unlist(item_to_print) + item_to_print <- purrr::map_vec(item_to_print, function(org) { + gsub("%2f", "/", org) + }) if (length(item_to_print) < 10) { list_items <- paste0(item_to_print, collapse = ", ") - } else { item_to_print_cut <- item_to_print[1:10] list_items <- paste0(item_to_print_cut, collapse = ", ") %>% diff --git a/R/gitstats_functions.R b/R/gitstats_functions.R index dbd460ae..3e1a3fa6 100644 --- a/R/gitstats_functions.R +++ b/R/gitstats_functions.R @@ -269,3 +269,15 @@ reset_language <- function(gitstats_obj){ cli::cli_alert_info("Setting language parameter to 'All'.") return(gitstats_obj) } + +#' @title Show organizations +#' @name show_orgs +#' @description Prints organizations downloaded in `GitStats`. Especially +#' helpful when user is scanning whole git platform and want to have a glimpse +#' at organizations. +#' @param gitstats_obj A GitStats object. +#' @return A vector of organizations. +#' @export +show_orgs <- function(gitstats_obj){ + return(gitstats_obj$show_orgs()) +} diff --git a/devel/example_workflow.R b/devel/example_workflow.R index 3a4df370..c9552077 100644 --- a/devel/example_workflow.R +++ b/devel/example_workflow.R @@ -133,3 +133,13 @@ git_stats <- create_gitstats() %>% orgs = c("mbtests", "public health") ) git_stats + +## add gitlab subgroups + +git_stats <- create_gitstats() %>% + add_host( + api_url = "https://gitlab.com/api/v4", + token = Sys.getenv("GITLAB_PAT_PUBLIC"), + orgs = "mbtests/subgroup" + ) +git_stats diff --git a/man/GitStats.Rd b/man/GitStats.Rd index 41c26e68..ead3a735 100644 --- a/man/GitStats.Rd +++ b/man/GitStats.Rd @@ -16,6 +16,7 @@ An R6 class object with methods to derive information from multiple Git platform \item \href{#method-add_repos_contributors}{\code{GitStats$add_repos_contributors()}} \item \href{#method-get_commits}{\code{GitStats$get_commits()}} \item \href{#method-get_users}{\code{GitStats$get_users()}} +\item \href{#method-show_orgs}{\code{GitStats$show_orgs()}} \item \href{#method-show_repos}{\code{GitStats$show_repos()}} \item \href{#method-show_commits}{\code{GitStats$show_commits()}} \item \href{#method-show_users}{\code{GitStats$show_users()}} @@ -175,6 +176,16 @@ Get information on users. \subsection{Returns}{ A data.frame of users. } +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-show_orgs}{}}} +\subsection{Method \code{show_orgs()}}{ +Print organizations. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{GitStats$show_orgs()}\if{html}{\out{
}} +} + } \if{html}{\out{
}} \if{html}{\out{}} diff --git a/man/show_orgs.Rd b/man/show_orgs.Rd new file mode 100644 index 00000000..c77f3add --- /dev/null +++ b/man/show_orgs.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/gitstats_functions.R +\name{show_orgs} +\alias{show_orgs} +\title{Show organizations} +\usage{ +show_orgs(gitstats_obj) +} +\arguments{ +\item{gitstats_obj}{A GitStats object.} +} +\value{ +A vector of organizations. +} +\description{ +Prints organizations downloaded in \code{GitStats}. Especially +helpful when user is scanning whole git platform and want to have a glimpse +at organizations. +} diff --git a/tests/testthat/_snaps/02-EngineRest.md b/tests/testthat/_snaps/02-EngineRest.md index 5b63e228..32c3d649 100644 --- a/tests/testthat/_snaps/02-EngineRest.md +++ b/tests/testthat/_snaps/02-EngineRest.md @@ -5,3 +5,14 @@ Error i No token provided. +# check_organizations returns NULL if orgs are wrong + + Code + orgs <- test_rest$check_organizations("does_not_exist") + Message + x Organization you provided does not exist or its name was passed in a wrong way: does_not_exist + ! Please type your organization name as you see it in `url`. + i E.g. do not use spaces. Organization names as you see on the page may differ from their 'address' name. + Message + HTTP 404 No such address + diff --git a/tests/testthat/_snaps/GitStats.md b/tests/testthat/_snaps/GitStats.md index 5ed25219..4f77337e 100644 --- a/tests/testthat/_snaps/GitStats.md +++ b/tests/testthat/_snaps/GitStats.md @@ -59,3 +59,18 @@ i [GitHub][Engine:REST] Pulling contributors... i [GitLab][Engine:REST] Pulling contributors... +# subgroups are cleanly printed in GitStats + + Code + test_gitstats + Output + A object for 1 hosts: + Hosts: https://gitlab.com/api/v4 + Organisations: [1] mbtests/subgroup + Search preference: org + Team: + Phrase: + Language: All + Repositories output: + Commits output: + diff --git a/tests/testthat/test-02-EngineRest.R b/tests/testthat/test-02-EngineRest.R index 73df8a76..0917dad3 100644 --- a/tests/testthat/test-02-EngineRest.R +++ b/tests/testthat/test-02-EngineRest.R @@ -7,8 +7,6 @@ test_rest <- TestEngineRest$new( test_rest_priv <- environment(test_rest$response)$private - - test_that("When token is empty throw error", { expect_snapshot( error = TRUE, @@ -96,3 +94,24 @@ test_that("`response()` returns commits response from GitLab's REST API", { ) test_mocker$cache(gl_commits_rest_response_repo_2) }) + +test_that("check_organizations returns orgs if they are correct", { + expect_equal( + test_rest$check_organizations("mbtests"), + "mbtests" + ) +}) + +test_that("check_organizations returns orgs if GitLab subroups are passed", { + expect_equal( + test_rest$check_organizations("mbtests/subgroup"), + "mbtests%2fsubgroup" + ) +}) + +test_that("check_organizations returns NULL if orgs are wrong", { + expect_snapshot( + orgs <- test_rest$check_organizations("does_not_exist") + ) + expect_null(orgs) +}) diff --git a/tests/testthat/test-GitStats.R b/tests/testthat/test-GitStats.R index dbad59e1..cedfe30f 100644 --- a/tests/testthat/test-GitStats.R +++ b/tests/testthat/test-GitStats.R @@ -76,3 +76,31 @@ test_that("Add_repos_contributors adds repos contributors to repos table", { expect_repos_table_with_contributors(repos_with_contributors) expect_equal(nrow(repos_without_contributors), nrow(repos_with_contributors)) }) + +test_that("show_orgs print orgs properly", { + expect_equal( + test_gitstats$show_orgs(), + c("r-world-devs", "openpharma", "mbtests") + ) +}) + +suppressMessages( + test_gitstats <- create_gitstats() %>% + add_host( + api_url = "https://gitlab.com/api/v4", + orgs = "mbtests/subgroup" + ) +) + +test_that("show_orgs print subgroups properly", { + expect_equal( + test_gitstats$show_orgs(), + "mbtests/subgroup" + ) +}) + +test_that("subgroups are cleanly printed in GitStats", { + expect_snapshot( + test_gitstats + ) +}) diff --git a/tests/testthat/test-show.R b/tests/testthat/test-show.R new file mode 100644 index 00000000..e922f4c6 --- /dev/null +++ b/tests/testthat/test-show.R @@ -0,0 +1,7 @@ +test_that("show_orgs() shows orgs", { + test_gitstats <- create_test_gitstats(hosts = 2) + expect_equal( + show_orgs(test_gitstats), + c("r-world-devs", "openpharma", "mbtests") + ) +}) From c6c3a3e1a183ef81079bf2f1de0aeee4189d5ca7 Mon Sep 17 00:00:00 2001 From: Maciej Banas Date: Mon, 4 Sep 2023 09:38:42 +0000 Subject: [PATCH 2/4] Update feature version. --- DESCRIPTION | 2 +- NEWS.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index fd129995..b4e0f828 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: GitStats Title: Get Statistics from Git Hosting Services -Version: 0.1.0.9001 +Version: 0.1.0.9002 Authors@R: c( person(given = "Maciej", family = "Banaś", email = "banasmaciek@gmail.com", role = c("aut", "cre")), person(given = "Kamil", family = "Koziej", email = "koziej.k@gmail.com", role = "aut"), diff --git a/NEWS.md b/NEWS.md index 6c9332fc..9124a6ac 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,13 +1,13 @@ -GitStats 0.1.0.9001 +GitStats 0.1.0.9002 -- set new name for `set_connection` function: `add_host` as it is more informative (and shorter). `set_connection` will be eventually deprecated but for the time-being it will stay (I: #271), +- set new name for `set_connection` function: `set_host` as it is more informative (and shorter) (I: #271), - added setting tokens by default - if a user does have all the PATs set up in environment variables (as e.g. `GITHUB_PAT` or `GITLAB_PAT`), there is no need to pass them as an arugment to `set_connection` (I: #120 PR: #268), - added `get_users()` function to pull information on users (I: #199 PR: #238), - added possibility of scanning whole internal git platforms if no `orgs` are passed (I: #258), - added switching to REST engine in case GraphQL fails with 502 error (I: #225 PRs: #227 (for repos) #261 (for commits)) - added `show_orgs()` function to print all organizations (I: #283), - added GraphQL engine for getting GitLab repos by organization (I: #218 PR: #233) -- removed `contributors` as basic stat when pulling `repos` by `org` and by `phrase` to improve speed of pulling repositories data. Added `add_repos_contributors()` user function and `add_contributors` parameter to `get_repos()` function to add conditionally information on contributors to repositories table (I: #235 PRs: #243 #264) +- removed `contributors` as basic stat when pulling `repos` by `org` and by `phrase` to improve speed of pulling repositories data. Added `get_repos_contributors()` user function and `add_contributors` parameter to `get_repos()` function to add conditionally information on contributors to repositories table (I: #235 PRs: #243 #264) - added resetting all settings to default with `reset()` function (I: #270) - added resetting language in your search preferences with `reset_language()` or setting `language` parameter to `All` in `setup()` function (I: #231 PR: #265) - OOP optimization: moved method on adding issues do repository table via REST to privates (I: #235 PR: #243) From f7073b0358048efa19a35e6dd8c446f01f642dd3 Mon Sep 17 00:00:00 2001 From: Maciej Banas Date: Mon, 4 Sep 2023 10:34:40 +0000 Subject: [PATCH 3/4] Update test. --- tests/testthat/test-GitStats.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test-GitStats.R b/tests/testthat/test-GitStats.R index fa572372..67b2dd2c 100644 --- a/tests/testthat/test-GitStats.R +++ b/tests/testthat/test-GitStats.R @@ -86,7 +86,7 @@ test_that("show_orgs print orgs properly", { suppressMessages( test_gitstats <- create_gitstats() %>% - add_host( + set_host( api_url = "https://gitlab.com/api/v4", orgs = "mbtests/subgroup" ) From a408bf092adeb23211d28178adf8b752533fba6c Mon Sep 17 00:00:00 2001 From: Maciej Banas Date: Tue, 5 Sep 2023 08:08:38 +0000 Subject: [PATCH 4/4] Fix example. --- devel/example_workflow.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devel/example_workflow.R b/devel/example_workflow.R index c4627547..bf0fcca4 100644 --- a/devel/example_workflow.R +++ b/devel/example_workflow.R @@ -137,7 +137,7 @@ git_stats ## add gitlab subgroups git_stats <- create_gitstats() %>% - add_host( + set_host( api_url = "https://gitlab.com/api/v4", token = Sys.getenv("GITLAB_PAT_PUBLIC"), orgs = "mbtests/subgroup"