GitHub es la Wikipedia del código. No todo lo que hay en GitHub puede darse por supuesto, pero contiene la esencia y la historia de cómo se crean algunas de las mejores herramientas de software.
Sería una pena no disponer de una API para acceder a un recurso tan valioso. Por suerte, tenemos una y se llama, sorprendentemente, API de GitHub.
Permíteme mencionar primero de qué no trata este artículo. No vamos a hablar de los comentarios de git o de cómo utilizar git en el desarrollo de software.
Este artículo trata más sobre el uso de la API de GitHub con fines analíticos. El primer y principal requisito para el análisis son los datos y GitHub tiene un montón de ellos.
La cantidad y variedad de información que podemos obtener de la API de GitHub es sencillamente asombrosa. Además, es una API bien mantenida y documentada por lo que no nos costará mucho conseguir la información que necesitamos.
Podemos obtener multitud de datos de la API de GitHub como:
- Commits por pull request
- Estructura de carpetas y archivos de un repositorio
- Número medio de archivos editados por confirmación
- Datos basados en los desarrolladores, como quién ha enviado más confirmaciones en el último mes.
- Datos basados en ficheros, como la longitud media de los ficheros de un repositorio.
Hay muchas cosas interesantes que podemos hacer una vez que tengamos los datos. Empecemos por cómo obtener acceso.
Primero necesitamos obtener un token de acceso. Ve a ajustes -> ajustes de desarrollador -> tokens de acceso personal y haz clic en generar nuevo token.
Una vez que hayas generado el token, asegúrate de copiarlo y guardarlo. Puedes usarlo como quieras, pero la forma correcta es guardarlo como una variable de entorno y acceder a él desde allí. No es recomendable tener claves de acceso escritas en tu código.
Tabla de contenidos
Diferencias entre diferentes pull requests
Los datos que podemos obtener utilizando la API de GitHub son sencillamente muchísimos. Por ello, en lugar de enumerar todos los tipos de datos que proporciona la API, intentaré construir un caso de uso y explicar cómo podemos obtener los datos necesarios para ello.
Cuando envías un commit, puedes ver los cambios introducidos en ese commit. Pero, puede haber casos en los que estés interesado en los cambios en un lapso de tiempo más largo. Dados los valores sha, la API de GitHub permite obtener los cambios en el código entre dos pull requests. El valor sha puede ser considerado como un ID para el commit.
Utilizaremos la biblioteca pandas para los ejemplos porque es una biblioteca de código abierto muy popular y todo el mundo tiene acceso a ella.
En GitHub ui, puedes copiar el sha de un commit en la pestaña commits de un pull request (recuadro rojo en la captura de pantalla de abajo):
Si haces click en el «<>» (al lado de la caja roja en la captura de pantalla de arriba), GitHub te llevará a la versión del repositorio en ese commit. Puedes ver el commit sha en la url de la página abierta:
Obteniendo el commit sha usando la API de GitHub
Hemos visto cómo obtener el commit sha desde la interfaz de usuario, pero tenemos que hacerlo mediante programación, lo que requiere que utilicemos la API de GitHub.
Podemos utilizar el endpoint commits para obtener los datos de commit de una pull request. Vamos a hacerlo para el pull request #59809 de la librería pandas.
# import libraries
import os
import requests
from dotenv import load_dotenv, find_dotenv
# load access token from env variables and create headers
_ = load_dotenv(find_dotenv())
access_token = os.getenv("GITHUB_PERSONAL_TOKEN")
HEADERS = {
'Authorization': f'token {access_token}',
'Accept': 'application/vnd.github.v3+json'
}
# repo and pull request data
owner = "pandas-dev"
repo = "pandas"
pull = 59809
# api url for commits endpoint
api_url = f"https://api.github.com/repos/{owner}/{repo}/pulls/{pull}/commits"
# request
response = requests.get(api_url, headers=HEADERS)
response_data = response.json()
El response_data es una lista de objetos json donde cada json contiene los datos de un commit. La clave sha contiene el sha de la confirmación, por lo que podemos usar la siguiente comprensión de lista para crear una lista de valores sha de confirmación.
commit_sha_list = [commit.get("sha") for commit in response_data]
commit_sha_list
# output
['b5a6648cb928fee5fbac0580b6fe509e1251328b',
'500bb6f88f4066797a617a5a64ee47c1299e33ab',
'9420549449e6dbdad03054818122255678f9a250',
'1bf53f29a6de29f87170f07317b6bf55b7800ddb',
'7a054fbb0df03f4426132540829355d744488933',
'4b47b394d26f66368fdf4118d3d6b95c815aa818',
'b9e7af2a67fedc26692a57cf6122092c93380a88',
'a3d353f2bb63a3a56290b141713cf4f2ff78093e',
'35261c0f18cd933d2b19c1eb8f8d2c76de55f915',
'566ca76e3e31828544cdd58feddef6c0e9fe91d1',
'7c82e5b70a68b19c00d68b40b6c9d8c1262a7c27',
'0ccc362da1910b1b655952d10d3270a75a55fead',
'3eddd981c29916d953ce9d895402c2b0f109b0e4',
'f9d6b8ca22ef8acc62b984badb2ed00a08a34a86']
Puedes validar esto desde GitHub ui y ver que pull request #59809 tiene 14 commits y sha valores coinciden con la lista anterior.
Obtener el diff
Digamos que queremos obtener el diff entre el tercer y el último commit de esta pull request.
third_commit = commit_sha_list[2]
last_commit = commit_sha_list[-1]
Por cierto, este enfoque se puede extender a diferentes pull requests (es decir, podemos obtener la diferencia entre commits en diferentes pull requests). Sólo necesitamos los valores de commit sha.
Usaremos diferentes endpoints y headers para esta tarea.
DIFF_HEADERS = {
'Authorization': f'token {access_token}',
'Accept': 'application/vnd.github.v3.diff'
}
# api url for getting the diff
basehead = f"{third_commit}...{last_commit}"
diff_api_url = f"https://api.github.com/repos/{owner}/{repo}/compare/{basehead}"
# request
diff_response = requests.get(diff_api_url, headers=DIFF_HEADERS)
diff_data = diff_response.text
La respuesta diff contiene los cambios en todos los ficheros en el siguiente formato:
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 77dd5d03d311c..ddbda0aa3bf65 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -254,7 +254,9 @@
"json_url": "https://pandas.pydata.org/versions.json",
"version_match": switcher_version,
},
- "show_version_warning_banner": True,
+ # This shows a warning for patch releases since the
+ # patch version doesn't compare as equal (e.g. 2.2.1 != 2.2.0 but it should be)
+ "show_version_warning_banner": False,
"icon_links": [
{
"name": "Mastodon",
Esto muestra los cambios en el archivo doc/source/conf.py.
Podemos hacer muchas cosas con estos datos. No está en el formato más utilizable pero podemos reformatearlo usando algunas operaciones de cadena. Digamos que sólo necesito el diff asociado al fichero doc/source/conf.py. Puedo extraerlo del texto de respuesta del diff de la siguiente manera:
file_name = "doc/source/conf.py"
# split raw diff response where each split represents a file
diffs = diff_data.split("diff --git ")[1:]
# get the diff for the required file
file_diff = [diff for diff in diffs if file_name in diff]
print(file_diff[0])
# output
"""
a/doc/source/conf.py b/doc/source/conf.py
index 77dd5d03d311c..ddbda0aa3bf65 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -254,7 +254,9 @@
"json_url": "https://pandas.pydata.org/versions.json",
"version_match": switcher_version,
},
- "show_version_warning_banner": True,
+ # This shows a warning for patch releases since the
+ # patch version doesn't compare as equal (e.g. 2.2.1 != 2.2.0 but it should be)
+ "show_version_warning_banner": False,
"icon_links": [
{
"name": "Mastodon",
"""
Palabras finales
Hay muchas cosas que podemos hacer con los datos de un repositorio. Se puede utilizar para fines analíticos, depuración, o la creación de nuevas prácticas de desarrollo de software.
En este artículo, hemos aprendido cómo obtener la diferencia entre dos commits (no sólo commits en el mismo pull request, sino también entre commits en diferentes pull requests).
Voy a escribir más sobre el uso de la API de GitHub y cómo hacer uso de los datos. Gracias por leer y estad atentos para más por venir.