diff --git a/dev/github_extraire.R b/dev/github_extraire.R new file mode 100644 index 0000000000000000000000000000000000000000..c39b98e7585dc9f693607df01ec073628df59529 --- /dev/null +++ b/dev/github_extraire.R @@ -0,0 +1,59 @@ +#dernier ----- +# Charger les packages nécessaires +library(httr) +library(jsonlite) +library(dplyr) +library(DT) +# Récupérer le token GitHub depuis l'environnement +api_key <- Sys.getenv("GITHUB_PAT") + +# Fonction pour récupérer les commits d'un projet GitHub avec clé API +get_github_commits <- function(repo) { + url <- paste0("https://api.github.com/repos/", repo, "/commits") + response <- GET(url, authenticate(api_key, "")) # Utilisation de la clé API + if (status_code(response) != 200) { + stop("Failed to fetch commits from GitHub API") + } + commits <- fromJSON(content(response, "text"), flatten = TRUE) + commits <- commits %>% + mutate(project_name = repo, # Ajouter le nom du projet + type = "commit", # Spécifier le type comme "commit" + message = commit.message, # Utiliser le message du commit + last_updated = commit.committer.date) %>% # Date de la dernière mise à jour + select(project_name, type, message, last_updated) # Conserver les colonnes pertinentes + return(commits) +} + +# Fonction pour récupérer les issues d'un projet GitHub avec clé API +get_github_issues <- function(repo) { + url <- paste0("https://api.github.com/repos/", repo, "/issues?state=all") + response <- GET(url, authenticate(api_key, "")) # Utilisation de la clé API + if (status_code(response) != 200) { + stop("Failed to fetch issues from GitHub API") + } + issues <- fromJSON(content(response, "text"), flatten = TRUE) + issues <- issues %>% + mutate(project_name = repo, # Ajouter le nom du projet + type = "issue", # Spécifier le type comme "issue" + message = title, # Utiliser le titre de l'issue + last_updated = updated_at) %>% # Date de la dernière mise à jour + select(project_name, type, message, last_updated) # Conserver les colonnes pertinentes + return(issues) +} + +# Récupérer les commits et les issues pour le projet spyrales/shinygouv +repo_shinygouv <- "spyrales/shinygouv" +commits_shinygouv <- get_github_commits(repo_shinygouv) +issues_shinygouv <- get_github_issues(repo_shinygouv) + +# Récupérer les commits et les issues pour le projet spyrales/gouvdown +repo_gouvdown <- "spyrales/gouvdown" +commits_gouvdown <- get_github_commits(repo_gouvdown) +issues_gouvdown <- get_github_issues(repo_gouvdown) + +# Combiner les dataframes de commits et issues pour les deux dépôts +combined_data <- bind_rows(commits_shinygouv, issues_shinygouv, commits_gouvdown, issues_gouvdown) +combined_data <- rename(combined_data, "updated_at" = 'last_updated') +# Afficher les premières lignes du tableau combiné +date_datamart <-format.Date(Sys.Date(), '%d/%m/%Y') +save.image("github.RData") diff --git a/dev/gitlab_classique.R b/dev/gitlab_classique.R new file mode 100644 index 0000000000000000000000000000000000000000..4aa920f4452f9b4065b591369480e340db003e62 --- /dev/null +++ b/dev/gitlab_classique.R @@ -0,0 +1,179 @@ +# Charger les packages nécessaires +library(httr) +library(jsonlite) +library(dplyr) +library(DT) +library(stringr) + +# Variables pour l'API GitLab ----- +base_url <- "https://gitlab.com" +private_token <- Sys.getenv("GITLAB_PAT") # Récupération du token depuis Renviron + +# Fonction pour gérer la pagination de l'API GitLab avec retry et timeout +get_all_pages <- function(url, private_token, max_retries = 3) { + # Fonction interne pour récupérer une page avec retry + get_page <- function(page) { + retries <- 0 + success <- FALSE + while (!success && retries < max_retries) { + tryCatch({ + # Faire la requête GET pour une page spécifique + response <- GET( + url, + query = list(page = page, per_page = 100), + add_headers("PRIVATE-TOKEN" = private_token), + timeout(120) # Timeout augmenté à 120 secondes + ) + + # Vérification du statut de la réponse + if (status_code(response) != 200) { + stop("La requête API a échoué avec le statut: ", status_code(response)) + } + + # Extraire les données de la réponse avec l'encodage UTF-8 pour éviter le message + data <- fromJSON(content(response, "text", encoding = "UTF-8"), flatten = TRUE) + success <- TRUE # Si la requête réussit, sortir de la boucle + return(data) + + }, error = function(e) { + retries <- retries + 1 + message("Erreur de connexion, tentative: ", retries, ". Détails: ", e$message) + Sys.sleep(2 * retries) # Attendre avant de réessayer + }) + } + + if (!success) { + stop("Echec de récupération des données après ", max_retries, " tentatives.") + } + } + + # Initialiser la récupération des données avec la première page + first_page_data <- get_page(1) + + # Vérifier s'il y a plusieurs pages en analysant l'en-tête "Link" + link_header <- headers(response)[["link"]] + if (!is.null(link_header) && str_detect(link_header, "rel=\"next\"")) { + # Trouver le nombre total de pages dans l'en-tête + num_pages <- max(str_extract_all(link_header, "page=\\d+")[[1]] %>% str_remove_all("page=") %>% as.integer()) + + # Utiliser lapply pour récupérer les pages suivantes + other_pages_data <- lapply(2:num_pages, get_page) + + # Combiner toutes les pages de données + all_data <- bind_rows(first_page_data, bind_rows(other_pages_data)) + } else { + # Si une seule page, renvoyer seulement les données de la première page + all_data <- first_page_data + } + + return(all_data) +} + +# Fonction pour extraire le nom du projet à partir de l'URL +extract_project_name <- function(web_url) { + # Utiliser une expression régulière pour capturer le dernier segment significatif avant "/-/" + str_extract(web_url, "(?<=/)[^/]+(?=/-/)") +} + +# Fonction pour récupérer les commits d'un projet GitLab +get_gitlab_commits <- function(base_url, project_id, private_token) { + api_url <- paste0(base_url, "/api/v4/projects/", project_id, "/repository/commits") + + # Récupérer toutes les pages avec pagination + data <- get_all_pages(api_url, private_token) + + # Harmoniser les types de colonnes et sélectionner les colonnes pertinentes + data <- data %>% + mutate( + id = as.character(id), + project_name = extract_project_name(web_url), + data_type = "commit", + discussion = message, + updated_at = committed_date + ) + return(data %>% select(project_name, data_type, discussion, updated_at)) +} + +# Fonction pour récupérer les issues d'un projet GitLab +get_gitlab_issues <- function(base_url, project_id, private_token) { + api_url <- paste0(base_url, "/api/v4/projects/", project_id, "/issues") + + # Récupérer toutes les pages avec pagination + data <- get_all_pages(api_url, private_token) + + # Harmoniser les types de colonnes et sélectionner les colonnes pertinentes + data <- data %>% + mutate( + id = as.character(id), + project_name = extract_project_name(web_url), + data_type = "issue", + discussion = title + ) + return(data %>% select(project_name, data_type, discussion, updated_at)) +} + +# Fonction pour récupérer et filtrer les events d'un projet GitLab +get_gitlab_events <- function(base_url, project_id, private_token) { + api_url <- paste0(base_url, "/api/v4/projects/", project_id, "/events") + + # Récupérer toutes les pages avec pagination + data <- get_all_pages(api_url, private_token) + + # Garder seulement les événements où action_name est "commented on" + data <- data %>% + filter(action_name == "commented on") %>% + mutate( + id = as.character(id), + project_name = extract_project_name(web_url), + data_type = "event", + discussion = note.body, + updated_at = note.updated_at + ) + return(data %>% select(project_name, data_type, discussion, updated_at)) +} + +# Fonction pour récupérer les données d'un projet +get_data_for_project <- function(base_url, project_id, private_token) { + commits_data <- tryCatch(get_gitlab_commits(base_url, project_id, private_token), error = function(e) NULL) + issues_data <- tryCatch(get_gitlab_issues(base_url, project_id, private_token), error = function(e) NULL) + events_data <- tryCatch(get_gitlab_events(base_url, project_id, private_token), error = function(e) NULL) + + # Combiner les résultats en un seul dataframe + return(bind_rows(commits_data, issues_data, events_data)) +} + +# Fonction pour traiter plusieurs projets avec lapply +get_data_from_multiple_projects <- function(base_url, project_ids, private_token) { + all_data <- lapply(project_ids, function(project_id) { + get_data_for_project(base_url, project_id, private_token) + }) + + # Combiner tous les dataframes en un seul + return(bind_rows(all_data)) +} + +# Define the query parameters pour récupérer les projets +params <- list( + include_subgroups = "true", + per_page = 100 +) + +# Fetch the projects avec pagination et retry +response <- GET( + "https://gitlab-forge.din.developpement-durable.gouv.fr/api/v4/groups/1013/projects", + add_headers(`PRIVATE-TOKEN` = Sys.getenv("GITLAB_COM_TOKEN")), + query = params, + timeout(120) # Timeout augmenté pour les projets +) + +# Parse the JSON content +projects <- content(response, as = "text", encoding = "UTF-8") %>% fromJSON() + +# Extract the project IDs +project_ids <- c(41600697, 19859695, 49118792, 21138017, 18439010, 44145525, 18441361, 17610613) + +# Récupérer les données pour tous les projets +all_data_gitlab <- get_data_from_multiple_projects(base_url, project_ids, private_token) +all_data_gitlab <- rename(all_data_gitlab, "type" = 'data_type',"message" = 'discussion') +# Afficher un aperçu des données combinées +save.image("gitlab.RData") diff --git a/dev/gitlab_forge.R b/dev/gitlab_forge.R new file mode 100644 index 0000000000000000000000000000000000000000..0129c9135454bdcc1b70658252c9167150a64807 --- /dev/null +++ b/dev/gitlab_forge.R @@ -0,0 +1,180 @@ +# Charger les packages nécessaires +library(httr) +library(jsonlite) +library(dplyr) +library(DT) +library(stringr) + +# Variables pour l'API GitLab ----- +base_url <- "https://gitlab-forge.din.developpement-durable.gouv.fr" +private_token <- Sys.getenv("GITLAB_COM_TOKEN") # Récupération du token depuis Renviron + +# Fonction pour gérer la pagination de l'API GitLab avec retry et timeout +get_all_pages <- function(url, private_token, max_retries = 3) { + # Fonction interne pour récupérer une page avec retry + get_page <- function(page) { + retries <- 0 + success <- FALSE + while (!success && retries < max_retries) { + tryCatch({ + # Faire la requête GET pour une page spécifique + response <- GET( + url, + query = list(page = page, per_page = 100), + add_headers("PRIVATE-TOKEN" = private_token), + timeout(120) # Timeout augmenté à 120 secondes + ) + + # Vérification du statut de la réponse + if (status_code(response) != 200) { + stop("La requête API a échoué avec le statut: ", status_code(response)) + } + + # Extraire les données de la réponse avec l'encodage UTF-8 pour éviter le message + data <- fromJSON(content(response, "text", encoding = "UTF-8"), flatten = TRUE) + success <- TRUE # Si la requête réussit, sortir de la boucle + return(data) + + }, error = function(e) { + retries <- retries + 1 + message("Erreur de connexion, tentative: ", retries, ". Détails: ", e$message) + Sys.sleep(2 * retries) # Attendre avant de réessayer + }) + } + + if (!success) { + stop("Echec de récupération des données après ", max_retries, " tentatives.") + } + } + + # Initialiser la récupération des données avec la première page + first_page_data <- get_page(1) + + # Vérifier s'il y a plusieurs pages en analysant l'en-tête "Link" + link_header <- headers(response)[["link"]] + if (!is.null(link_header) && str_detect(link_header, "rel=\"next\"")) { + # Trouver le nombre total de pages dans l'en-tête + num_pages <- max(str_extract_all(link_header, "page=\\d+")[[1]] %>% str_remove_all("page=") %>% as.integer()) + + # Utiliser lapply pour récupérer les pages suivantes + other_pages_data <- lapply(2:num_pages, get_page) + + # Combiner toutes les pages de données + all_data <- bind_rows(first_page_data, bind_rows(other_pages_data)) + } else { + # Si une seule page, renvoyer seulement les données de la première page + all_data <- first_page_data + } + + return(all_data) +} + +# Fonction pour extraire le nom du projet à partir de l'URL +extract_project_name <- function(web_url) { + # Utiliser une expression régulière pour capturer le dernier segment significatif avant "/-/" + str_extract(web_url, "(?<=/)[^/]+(?=/-/)") +} + +# Fonction pour récupérer les commits d'un projet GitLab +get_gitlab_commits <- function(base_url, project_id, private_token) { + api_url <- paste0(base_url, "/api/v4/projects/", project_id, "/repository/commits") + + # Récupérer toutes les pages avec pagination + data <- get_all_pages(api_url, private_token) + + # Harmoniser les types de colonnes et sélectionner les colonnes pertinentes + data <- data %>% + mutate( + id = as.character(id), + project_name = extract_project_name(web_url), + data_type = "commit", + discussion = message, + updated_at = committed_date + ) + return(data %>% select(project_name, data_type, discussion, updated_at)) +} + +# Fonction pour récupérer les issues d'un projet GitLab +get_gitlab_issues <- function(base_url, project_id, private_token) { + api_url <- paste0(base_url, "/api/v4/projects/", project_id, "/issues") + + # Récupérer toutes les pages avec pagination + data <- get_all_pages(api_url, private_token) + + # Harmoniser les types de colonnes et sélectionner les colonnes pertinentes + data <- data %>% + mutate( + id = as.character(id), + project_name = extract_project_name(web_url), + data_type = "issue", + discussion = title + ) + return(data %>% select(project_name, data_type, discussion, updated_at)) +} + +# Fonction pour récupérer et filtrer les events d'un projet GitLab +get_gitlab_events <- function(base_url, project_id, private_token) { + api_url <- paste0(base_url, "/api/v4/projects/", project_id, "/events") + + # Récupérer toutes les pages avec pagination + data <- get_all_pages(api_url, private_token) + + # Garder seulement les événements où action_name est "commented on" + data <- data %>% + filter(action_name == "commented on") %>% + mutate( + id = as.character(id), + project_name = extract_project_name(web_url), + data_type = "event", + discussion = note.body, + updated_at = note.updated_at + ) + return(data %>% select(project_name, data_type, discussion, updated_at)) +} + +# Fonction pour récupérer les données d'un projet +get_data_for_project <- function(base_url, project_id, private_token) { + commits_data <- tryCatch(get_gitlab_commits(base_url, project_id, private_token), error = function(e) NULL) + issues_data <- tryCatch(get_gitlab_issues(base_url, project_id, private_token), error = function(e) NULL) + events_data <- tryCatch(get_gitlab_events(base_url, project_id, private_token), error = function(e) NULL) + + # Combiner les résultats en un seul dataframe + return(bind_rows(commits_data, issues_data, events_data)) +} + +# Fonction pour traiter plusieurs projets avec lapply +get_data_from_multiple_projects <- function(base_url, project_ids, private_token) { + all_data <- lapply(project_ids, function(project_id) { + get_data_for_project(base_url, project_id, private_token) + }) + + # Combiner tous les dataframes en un seul + return(bind_rows(all_data)) +} + +# Define the query parameters pour récupérer les projets +params <- list( + include_subgroups = "true", + per_page = 100 +) + +# Fetch the projects avec pagination et retry +response <- GET( + "https://gitlab-forge.din.developpement-durable.gouv.fr/api/v4/groups/1013/projects", + add_headers(`PRIVATE-TOKEN` = Sys.getenv("GITLAB_COM_TOKEN")), + query = params, + timeout(120) # Timeout augmenté pour les projets +) + +# Parse the JSON content +projects <- content(response, as = "text", encoding = "UTF-8") %>% fromJSON() + +# Extract the project IDs +project_ids <- projects$id + +# Récupérer les données pour tous les projets +all_data_forge <- get_data_from_multiple_projects(base_url, project_ids, private_token) +all_data_forge <- rename(all_data_forge, "type" = 'data_type',"message" = 'discussion') +# Afficher un aperçu des données combinées +save.image("gitlab_forge.RData") + diff --git a/global.R b/global.R index 86753617f5c9338c82e8c74c9d80046fe0e9ea42..d5e82b91cf9ad98c2d7554967fe3d7fe92bc655b 100644 --- a/global.R +++ b/global.R @@ -17,9 +17,10 @@ library(jsonlite) library(utils) library(lubridate) library(bizdays) -# chargement des données (résultat du script "dev/script_chargement_rdata.R") -load("datamart_gitlabr.RData") - +# chargement des données (résultat du script "dev/script_chargement_rdata.R") +load("github.RData") +load("gitlab_forge.RData") +load("gitlab.RData") diff --git a/server.R b/server.R index 7a5dce798b7c07efe9754f6604ec40fa0a91ff23..10a5b52960733f36e0c46a1c320875b47f05babc 100644 --- a/server.R +++ b/server.R @@ -83,14 +83,15 @@ server <- function(input, output) { # utilisation du jeu de donnée data_chronol qui se trouve dans le global filteredData <- reactive({ - shiny::req(input$daterange) - gitlab_chronol %>% - dplyr::filter(temps >= as.Date(input$daterange[[1]]) & temps <= as.Date(input$daterange[[2]])) + req(input$daterange) + all_data %>% + filter(updated_at >= as.Date(input$daterange[[1]]) & updated_at <= as.Date(input$daterange[[2]])) }) + output$filteredPlot <- plotly::renderPlotly({ - p <- ggplot2::ggplot(filteredData(), ggplot2::aes(x = temps, y = as.factor(name))) + - ggplot2::geom_jitter(ggplot2::aes(color = type, text = paste(temps, info, sep = "\n")), + p <- ggplot2::ggplot(filteredData(), ggplot2::aes(x = updated_at, y = as.factor(project_name))) + + ggplot2::geom_jitter(ggplot2::aes(color = type, text = paste(updated_at, message, sep = "\n")), size = 3, alpha = 0.5, height = 0, width = 0.75 ) +