¿Qué hace gh-release?
Bump, changelog, tag, push, watch.
Los comandos a continuación escriben ~/.claude/skills/gh-release/scripts/ completo. Ejecútalos exactamente como están escritos: conserva el ~ inicial y no lo expandas. Una regla de permisos coincide con la cadena de comando literal, por lo que /home/<tu>/.claude/... (el tilde expandido), python3 ~/..., una ruta relativa, y un cd primero son cada uno una cadena diferente, y cada uno vuelve a pedir permiso. Una ruta con tilde no es "la ruta absoluta escrita informalmente" — para una regla de permisos es la ruta.
Dos cosas hacen que los lanzamientos salgan mal, y ambas ocurren antes de que exista la etiqueta:
- Reinventar un bump que el repositorio ya automatiza. Una edición hecha a mano toca archivos que la propia tarea del repositorio habría manejado, omite los que conoce y salta su compuerta.
- Una etiqueta que no dispara nada. Se ve exactamente como una cola de CI lenta, y te enteras veinte minutos después.
Los pasos 1 y 3 existen para detectar esos.
0. Decidir la versión
Lee las etiquetas (git tag --sort=-v:refname | head -5) para conocer el formato del repositorio (v1.2.3 vs 1.2.3) y la versión actual. Si el usuario nombró una versión, úsala. De lo contrario, propón una a partir de los commits desde la última etiqueta: cambio rupturista es major, feat: es minor, de lo contrario patch — y di cuál y por qué.
Rechaza continuar si el árbol está sucio, HEAD está desprendido, o la rama está detrás de su remoto. Liberar trabajo no confirmado produce una etiqueta que nadie puede reproducir.
1. Usar la propia maquinaria de lanzamiento del repositorio
Siempre mira antes de hacer algo manualmente:
~/.claude/skills/gh-release/scripts/versiontool.py discover
Reporta skills de proyecto, tareas de mise, scripts npm, objetivos Make, recetas just, entradas de scripts/-bin/, y configuraciones de herramientas (cargo-release, bumpversion, release-please, git-cliff). Precedencia:
kind=project-skill — deja de leer este skill y sigue ese. Es el propio procedimiento del repositorio y sabe cosas que este skill genérico no puede.
Una tarea o script (kind=mise-task|npm-script|make-target|just-recipe|script) — léelo antes de ejecutarlo, luego ejecútalo. Necesitas saber lo que cubre para no duplicar ni saltarte trabajo. Las tareas típicas hacen algunas pero no todas: bump, promoción de changelog, compuerta, commit, tag, push. Anota cuáles, luego haz solo el resto.
Muchas toman la versión desnuda y añaden el prefijo ellas mismas (mise run release 0.13.0 etiquetando v0.13.0), así que no pases una etiqueta donde se espera una versión. Si tiene --dry-run, úsalo primero y muestra al usuario el plan.
Una configuración de herramienta sin tarea — usa el comando propio de esa herramienta (cargo release <version>, bump-my-version bump ...), no una edición manual.
result=none — solo entonces recurre al paso 2.
2. Plan de respaldo: encontrar cada lugar donde vive la versión
Solo cuando el paso 1 no encontró nada.
~/.claude/skills/gh-release/scripts/versiontool.py locations <version-actual>
Busca la cadena de versión literal, no la palabra "version". Medido en un repositorio real: una búsqueda por clave version encontró 5 archivos, la cadena literal encontró 8. Las omisiones escribían la clave "version-name" (metadatos de GNOME) y "Version" (Plasma). Cualquier cosa que omitas envía un binario reportando la versión incorrecta.
La salida está clasificada: edit (cámbialo), regenerate (archivo de bloqueo — ejecuta el comando de la pista, nunca edites a mano, o --locked falla en CI), changelog (paso 4).
Luego verifica también la versión anterior — un acierto ahí es un archivo omitido en el último lanzamiento y obsoleto desde entonces. Arrégralo en este.
3. Pre-vuelo de la etiqueta
~/.claude/skills/gh-release/scripts/relwatch.py preflight <etiqueta>
Lee .github/workflows/*.yml, extrae cada patrón de on.push.tags, y te dice si tu etiqueta coincide con uno y si ese workflow parece que crea un lanzamiento. result=NO_MATCH significa que subir la etiqueta no hace nada.
Ejecuta esto antes de hacer commit, mientras cambiar la etiqueta es gratis.
También confirma visualmente que el paso de release del workflow usa la etiqueta que estás a punto de subir. Muchos workflows no verifican que la etiqueta coincida con la versión en el código, por lo que un desajuste produce un release cuyos binarios reportan la versión incorrecta, en silencio y con CI verde.
4. Changelog
Si la tarea del paso 1 promociona el changelog por sí misma, déjala hacerlo y salta al paso 5.
Mantener un Changelog (hay un encabezado ## [Unreleased]): promociónalo.
## [Unreleased]se convierte en## [X.Y.Z] - YYYY-MM-DD- añade un nuevo
## [Unreleased]vacío encima - actualiza las definiciones de enlaces al final, incluyendo la nueva base del enlace de comparación
[Unreleased]
Sin changelog, o sin sección Unreleased: escribe la entrada a partir de los commits desde la última etiqueta, agrupados como el archivo ya los agrupa. Coincide exactamente con la voz existente — si las entradas son de una línea, escribe de una línea; si son prosa con encabezados en negrita, escribe eso.
De cualquier manera: describe lo que cambió para un usuario del proyecto, no lo que hiciste al repositorio.
Aplica el skill unslop a cada entrada. Un changelog se lee durante años, por personas decidiendo si actualizar. "Varias mejoras y correcciones de errores" es peor que ninguna entrada; también lo es una entrada que reformula el asunto del commit en palabras más largas. Las señales específicas del documento se enumeran en docs-update/SKILL.md paso 5 y aplican aquí sin cambios: sin rodeos, sin intensificadores vacíos, sin ambigüedades donde la respuesta es definitiva.
5. Verificar antes de etiquetar
~/.claude/skills/gh-release/scripts/versiontool.py verify <versión-antigua> # debe imprimir result=clean
Ejecuta esto incluso cuando una tarea del repositorio hizo el bump. Un bumper escrito hace seis meses no sabe del archivo que alguien añadió la semana pasada, y así es exactamente como una versión se vuelve obsoleta en un rincón del árbol. El historial del changelog se ignora; solo cuentan los archivos editables.
Luego ejecuta la compuerta del proyecto (build, test, lint). Una etiqueta que apunta a un commit rojo tiene que ser eliminada y re-cortada, y eliminar una etiqueta subida es complicado para cualquiera que ya la haya obtenido.
6. Commit, tag, push
Salta lo que la tarea del paso 1 ya hizo. Si hizo commit, etiquetó y subió, ve directamente al paso 7.
De lo contrario: un commit para el lanzamiento, asunto prefijado con el nombre de la rama según ~/.claude/CLAUDE.md. El bump y el changelog pertenecen al mismo commit; son un solo cambio.
git commit -m "[<rama>] chore(release): <versión>"
git tag -a <etiqueta> -m "<etiqueta>"
git push && git push origin <etiqueta>
Sube el commit antes de la etiqueta. Una etiqueta que llega primero puede iniciar una compilación contra un commit que el remoto aún no tiene.
Anota la hora de subida; acota la vigilancia.
7. Vigilar hasta que exista el lanzamiento
~/.claude/skills/gh-release/scripts/relwatch.py watch <etiqueta> --timeout 1800
| Resultado | Significado |
|---|---|
released url=... | listo |
ci_failed run=... conclusion=... | paso 8 |
no_run | No se disparó nada. La etiqueta no coincidió con ningún patrón — ejecuta preflight |
still_running | No es un fallo. Vigila de nuevo |
CI verde no es un lanzamiento: el paso de publicación puede retrasarse respecto a la compilación, por lo que el vigilante sigue esperando hasta que el objeto Release realmente exista.
Misma regla de subagente que babysit-pr: una sola vigilancia dentro de una llamada Bash (--timeout 540) es más barata en línea; delega solo cuando la espera abarque varias llamadas. No te detengas antes de que el lanzamiento exista o tengas un bloqueador.
8. Cuando el CI falla después de la etiqueta
La etiqueta está mal, así que retírala en lugar de parchear alrededor:
git push --delete origin <etiqueta>
git tag -d <etiqueta>
Arregla, luego re-corta desde el paso 5 con el mismo número de versión. No incremente para saltar un fallo: una versión que nunca nadie lanzó no vale la pena quemar, y el espacio invita a alguien a buscar el lanzamiento perdido.
Si la etiqueta ha sido pública por un tiempo, o existe un lanzamiento parcial, dímelo y deja que el usuario elija entre eliminarla o enviar un parche encima.
9. Informe
Enlace de PR/comparación, la etiqueta, la URL del lanzamiento, lo que cambió y cada archivo incrementado. Si queda algo para el usuario, nómbralo.