BookinglyTech News
Software

Vigilar releases de GitHub sin quemar la cuota: ETags, 304 y un script en Python

Un script de biblioteca estándar consulta la API de GitHub con peticiones condicionales, guarda estado en JSON y no gasta cuota cuando nada ha cambiado.

3 min de lecturaDev.to0 vistas

Un script de poco más de cien líneas, escrito solo con la biblioteca estándar de Python, permite seguir las releases de repositorios que no administras sin comerse la cuota de la API de GitHub. La mecánica es conocida: en lugar de pedir la lista completa en cada pasada, se envía el ETag de la vez anterior en la cabecera If-None-Match y, si nada ha cambiado, GitHub contesta un 304 Not Modified sin cuerpo. El código va acompañado de una ejecución real, sin token, del 27 de septiembre de 2026.

Lo que dice la documentación

El endpoint es GET /repos/{owner}/{repo}/releases, con per_page a 30 por defecto y 100 como máximo, y funciona sin autenticación en repositorios públicos. Los borradores solo aparecen para quien tiene permiso de push. El límite sin token son 60 peticiones por hora contadas por dirección IP; con un token personal sube a 5.000.

Hay dos detalles que conviene fijar. El primero es X-GitHub-Api-Version: una petición que no la lleva usa la versión 2022-11-28, mientras que la actual es 2026-03-10, así que fijarla evita que un cambio de ruptura llegue al script sin avisar. El segundo es que un 304 no consume la cuota principal, pero solo si la petición se hizo con cabecera Authorization. Sin token ese perdón no existe y el 304 sigue contando.

Los detalles que se suelen pasar por alto

En Python, urllib lanza HTTPError tanto para un 304 como para un 404 o un 503. Capturarlo y devolver el código como un estado más simplifica el bucle: una sola variable sobre la que ramificar. La lógica de comparación también tiene su miga. El script guarda los IDs de release ya vistos, con un tope de 200, y compara IDs, no el hecho de haber recibido un 200, porque el ETag puede cambiar por motivos que no son una release nueva.

En la primera pasada por un repositorio guarda todo y no avisa de nada; de lo contrario anunciaría el historial entero del proyecto como si fuera recién salido. Cualquier respuesta que no sea 200 o 304 deja el estado intacto: un fallo de red no puede confundirse con "no hay releases". El fichero de estado se escribe primero en un temporal y se mueve con os.replace, para que una interrupción no deje un JSON a medias. Las peticiones salen de una en una, con un segundo de separación, y ante un 403 o un 429 el proceso se detiene.

Con per_page=20 se ven las 20 releases más recientes por consulta. Si un proyecto publica más que eso entre dos pasadas, hay que subir el parámetro hasta 100 o seguir la paginación.

El interés de esto no está en el script, sino en el margen que da. Con 60 peticiones por hora y sin token, vigilar diez repositorios cada cinco minutos no cabe ni de lejos; la petición condicional es lo que hace viable el seguimiento sin credenciales. El patrón, además, se traslada a cualquier API que devuelva ETag: si el servicio responde 304, no hay motivo para descargar el cuerpo otra vez.