¿Cómo puedo rastrear cuánto tiempo han estado abiertas las solicitudes de incorporación de cambios en GitHub?

5 minutos de lectura

Avatar de usuario del doctorado
Doctor

Usamos GitHub Enterprise para nuestra base de código interno. Un problema común al que nos enfrentamos en todos los equipos es que el “tiempo de respuesta de la revisión de la solicitud de extracción” a veces puede ser de unos pocos “días físicos” (muchas horas ideales).

Estamos ajustando algunas prácticas de ingeniería para evitar que las relaciones públicas sean innecesariamente grandes y permitir tiempos de respuesta más rápidos en las revisiones. Sin embargo, no pude encontrar nada que me ayudara a rastrear con precisión cuánto tiempo estuvieron abiertos los PR antes de que se fusionaran.

Nos gustaría usar métricas objetivas para validar algunos de nuestros enfoques para ver si hacemos diferencias significativas en los tiempos de revisión y la “duración de relaciones públicas abiertas hasta la fusión” es una métrica importante para realizar un seguimiento.

¿Tiene git/GitHub algo que pueda ayudar a obtener dichas métricas? Intenté buscar pero no aparece nada por ningún lado.

Avatar de usuario de Fbo
fbo

La API graphQL de GitHub podría ayudarlo a obtener metadatos de solicitudes de extracción, como cuándo se creó (createdAt) el PR y cuándo se fusionó (mergedAt) https://developer.github.com/v4/object/pullrequest/
Puede buscar todas las solicitudes de extracción con la consulta de búsqueda https://developer.github.com/v4/query/#connections luego calcule el tiempo para fusionarse.

También te puede interesar esta herramienta https://github.com/change-metrics/monocle ya que proporciona métricas de solicitud de extracción para los repositorios de GitHub. Entre otras diversas métricas, las herramientas calculan las métricas de “Tiempo medio para fusionar”. Gracias a los filtros que puede configurar, puede obtener el tiempo medio para fusionarse para toda la organización de GitHub, un repositorio específico, un desarrollador o un grupo de desarrolladores.

  • Monocle Suena bien, debería darle una oportunidad. Supongo que también podría funcionar para stash repos también, no?

    – Doctor

    14 mayo 2020 a las 20:23

  • @PhD Por lo que entiendo sobre el alijo, supongo que no, ya que el monóculo proporciona rastreadores para GitHub y Gerrit solo en este momento. Parece que stash y bitbucket son lo mismo, bueno, eso podría ser una buena adición en monóculo para agregar el rastreador de bitbucket.

    – Facebook

    15 de mayo de 2020 a las 6:58

avatar de usuario de kartikey rajvaidya
Kartikey Rajvaidya

  • También estaba buscando una solución para evitar que los PR fueran innecesariamente grandes y permitir tiempos de respuesta más rápidos en la revisión.

  • Simplemente quería trazar un gráfico de “horas requeridas para revisar un PR” frente a “Líneas de código” para averiguar cuál es el tamaño ideal de PR.

  • Probé Monocle, y aunque proporciona muchos análisis sobre las relaciones públicas desde el primer momento, faltaba este gráfico simple.

  • Finalmente, terminé escribiendo mi NO TAN ORDENADO guión para resolver este problema.

Primero, genere un token haciendo clic en este enlace https://github.com/settings/tokens

Una vez que tenga la ficha

puede usar la siguiente secuencia de comandos para almacenar los datos necesarios para trazar en un archivo csv.

import requests
from datetime import datetime
import csv



final_dataset = []
fmt = "%Y-%m-%dT%H:%M:%SZ"

page = 1

url = ("https://api.github.com/repos/<OWNER>/<REPO_NAME>/pulls?state=closed&per_page=100&page=%d" % page)
res=requests.get(url,headers={"Authorization": 'Bearer <GIT_HUB_TOKEN>'})


repos=res.json()
while res.json() != []:
  print(page)
  page= page + 1
  url = ("https://api.github.com/repos/<OWNER>/<REPO_NAME>/pulls?state=closed&per_page=100&page=%d" % page)
  res=requests.get(url,headers={"Authorization": 'Bearer <GIT_HUB_TOKEN>'})
  repos.extend(res.json())


print("Fetching PRs, Please Wait")
for data in repos:
  result = {}
  created_at = datetime.strptime(data['created_at'], fmt)
  closed_at = datetime.strptime(data['closed_at'], fmt)

  result['hours_to_review'] = round((closed_at - created_at).total_seconds() / 3600, 2)
  url_for_pr = ("https://api.github.com/repos/<OWNER>/<REPO_NAME>/pulls/%d" % data['number'])
  res=requests.get(url_for_pr,headers={"Authorization": 'Bearer <GIT_HUB_TOKEN>'})
  result['line_of_code'] = res.json()['additions']
  result['user_name'] = res.json()['user']['login']
  result['pr_number'] = data['number']
  final_dataset.append(result)


print("Writing to csv, Please Wait")
keys = final_dataset[0].keys()
with open('pr_review_data.csv', 'w', newline="") as output_file:
  dict_writer = csv.DictWriter(output_file, keys)
  dict_writer.writeheader()
  dict_writer.writerows(final_dataset)

print("*************DONE*****************")

Ahora puede simplemente importar estos datos a una hoja de Excel y trazar un gráfico. también puede usar herramientas en línea gratuitas como https://www.csvplot.com/ para trazar un gráfico.

Espero que esto haya sido útil

  • Este código fue realmente valioso para obtener mi propio análisis de la distribución del tiempo de cierre para los PR. Sin embargo, hay un error en el cálculo: / 360 debiera ser /3600 en la línea donde se realiza la conversión de segundos a horas.

    – Grigori Rechistov

    20 oct 2022 a las 11:39

avatar de usuario de karthick
Karthick

Puede usar Github Rest Api para obtener los detalles. He agregado un ejemplo con un repositorio de muestra. Creo que para las ediciones empresariales debe acceder a la información del repositorio mediante tokens (https://github.com/settings/tokens). En ese caso, la solicitud uri será

https://api.github.com/repos/srajagop/page-test/pulls?token=xxxxxxxxxxxxxxxxx

Por ejemplo

async function timeElapsed(){
   let response = await fetch('https://api.github.com/repos/srajagop/page-test/pulls');
   let jsonData = await response.json();
   let diff = new Date().getTime() - new Date(Date.parse('2019-04-26T05:56:33Z')).getTime();
   let hoursElapsed = Math.ceil(diff / (1000 * 60 * 60)); 
   return hoursElapsed;
}
timeElapsed().then(data => console.log("Hours elapsed", data)); 

¿Ha sido útil esta solución?