Skip to content
Apothem
Runbooks

Runbook del ciclo de lanzamiento

Flujo de lanzamiento completo, desde las puertas locales, pasando por el GitHub Release firmado, hasta la publicación en npm.

Este runbook lleva un lanzamiento vX.Y.Z de apothem desde un árbol de trabajo limpio hasta superficies de distribución verificadas. El procedimiento está escrito para el mantenedor que maneja gh, git y la shell de nivel de lanzamiento; termina con una página de Release verificada, un CHANGELOG archivado y una prueba de humo de las rutas de instalación que confirma que cada superficie orientada al usuario responde al comando de instalación canónico.

El modelo de lanzamiento es aditivo. Cada lanzamiento agrega un commit en main y una etiqueta vX.Y.Z anotada y firmada; no se hace force-push de nada y no se elimina ninguna etiqueta, GitHub Release ni versión de npm anterior. Cada lanzamiento conserva su etiqueta, su GitHub Release y su versión de npm, y todos siguen publicados: las versiones de npm son inmutables (un name@version publicado nunca puede reemplazarse), y las instalaciones fijadas dependen de las etiquetas.

El push de la etiqueta inicia tres flujos de trabajo. .github/workflows/release.yml compila, firma, atesta y publica el GitHub Release con su conjunto completo de artefactos: sdist, wheel, SBOM de CycloneDX, bundles cosign de Sigstore, procedencia SLSA-3 y los archivos comprimidos del runtime por plataforma. publish-npm.yml publica @ahmed-g-gad/apothem en npmjs.com mediante la publicación de confianza de npm, y publish-vscode.yml empaqueta la extensión de VS Code y la publica en Visual Studio Marketplace. La sección versionada del CHANGELOG llega en el commit de lanzamiento; el operador ejecuta la prueba de humo de las rutas de instalación cuando ambos flujos de trabajo terminan.

1. Requisitos previos

El mantenedor confirma lo siguiente antes de etiquetar:

  • Árbol de trabajo. Limpio (git status no muestra nada pendiente). Todo el trabajo de funcionalidades del lanzamiento está en main.

  • CI en verde. Para el último main, gh run list --branch=main --limit=1 --json conclusion --jq '.[0].conclusion' devuelve success.

  • Herramientas. gh (GitHub CLI) versión 2.40 o posterior, autenticado como ahmed-g-gad; git 2.40 o posterior con la subclave de firma GPG cargada; el vínculo de publicador de confianza de npm para @ahmed-g-gad/apothem está activo (verificado según el runbook de configuración de la cuenta de publicador).

  • Anclas de versión alineadas. La cadena de versión declarada en pyproject.toml coincide con la etiqueta planificada sin el prefijo v (§2.1 la establece, junto con todas las demás anclas). Verifica:

    grep '^version' pyproject.toml

    Salida esperada (para un lanzamiento vX.Y.Z; los marcadores de posición representan la etiqueta del lanzamiento en curso):

    version = "X.Y.Z"
  • Entradas del CHANGELOG preparadas. Los puntos del lanzamiento están bajo ## [Unreleased] en encabezados de Keep-a-Changelog; §2.1 los convierte en la sección de versión fechada en el commit que recibe la etiqueta.

2. Etiquetar y disparar

2.1 Redactar el commit de lanzamiento

La versión aparece en más de una docena de archivos, así que no los edites a mano. Un solo comando los actualiza todos:

git checkout main
git pull --ff-only origin main
python scripts/release/bump_version.py X.Y.Z

bump_version.py actualiza todas las anclas de versión a la vez:

  • Cada manifiesto de empaquetado, extensión, plugin y marketplace, además del archivo de cita (versión y fecha de lanzamiento). La lista completa:

    pyproject.toml
    package.json
    site/package.json
    site/package-lock.json            (the project entries only)
    vscode-extension/package.json
    gemini-extension.json
    qwen-extension.json
    .claude-plugin/marketplace.json   (top level and metadata)
    plugins/apothem/plugin.json
    plugins/apothem/.codex-plugin/plugin.json
    CITATION.cff
  • CHANGELOG.md: las entradas de [Unreleased] se convierten en una sección ## [X.Y.Z] fechada, [Unreleased] compara a partir de vX.Y.Z y se agrega un enlace [X.Y.Z].

  • SECURITY.md: una nueva versión menor recibe una fila X.Y.x admitida. Si las versiones menores anteriores siguen listadas es decisión tuya; el script imprime un recordatorio.

Después regenera los árboles derivados: el paquete del plugin de Claude Code, los goldens de behavior-diff y las páginas de referencia y de changelog de la documentación. Pasa --dry-run para listar primero los cambios, --date YYYY-MM-DD para fijar la fecha de lanzamiento (predeterminada: hoy en UTC) o --no-regen para omitir la regeneración. El script rechaza una versión mal formada o un retroceso de versión, y volver a ejecutarlo con la versión actual solo realinea las anclas desalineadas.

Revisa el diff y luego haz commit:

git add -A
git commit -S -m "chore(release): cut vX.Y.Z"
git push origin main

El indicador -S firma el commit con la clave GPG. El push dispara la matriz de CI estándar (lint, test, build); espera a que esté en verde antes de etiquetar.

La comprobación de §2.4 también necesita que CodeQL y Conformity estén en verde en el commit de lanzamiento. Ambos se ejecutan solo cuando cambian sus propias rutas de archivos, y un commit de lanzamiento normalmente no cambia ninguna de ellas, así que inícialos una vez que el commit de lanzamiento sea la punta de main y luego confirma que cada ejecución corresponde a ese commit:

gh workflow run codeql.yml --ref main
gh workflow run conformity.yml --ref main
gh run list --workflow codeql.yml --commit "$(git rev-parse HEAD)" --limit 1
gh run list --workflow conformity.yml --commit "$(git rev-parse HEAD)" --limit 1

Espera a que ambos estén en verde antes de etiquetar, y no hagas push de nada más a main hasta que el lanzamiento esté publicado: un push posterior aleja main del commit de lanzamiento, y la CI cancela una ejecución que todavía está en curso en la misma rama.

2.2 Firmar y hacer push de la etiqueta

git tag -a -s vX.Y.Z -m "vX.Y.Z"
git push origin vX.Y.Z

La combinación -a -s produce una etiqueta anotada y firmada con GPG. El push dispara .github/workflows/release.yml, que compila, firma, atesta y publica.

2.3 Confirmar que el flujo de trabajo de lanzamiento se completó

gh run watch $(gh run list --workflow=release.yml --limit=1 --json databaseId --jq '.[0].databaseId')

El flujo de trabajo ejecuta la compilación (sdist + wheel, y luego un SBOM de CycloneDX de esas distribuciones, escrito junto a ellas), la firma cosign sin clave, la generación y verificación de la procedencia SLSA-3, la compilación de los archivos comprimidos por plataforma (darwin / linux / windows), la firma de esos archivos con un manifiesto SHA256SUMS agregado y la publicación final del GitHub Release. El mantenedor revisa el registro del trabajo publish GitHub Release en busca de las confirmaciones de subida de recursos.

El trabajo publish GitHub Release se ejecuta en el entorno release, que requiere la aprobación del mantenedor, así que la ejecución espera ahí una vez que pasan los trabajos anteriores. Apruébala en la página de la ejecución (Review deployments), o desde la shell:

run_id=$(gh run list --workflow=release.yml --limit=1 --json databaseId --jq '.[0].databaseId')
env_id=$(gh api repos/ahmed-g-gad/apothem/environments/release --jq .id)
gh api -X POST "repos/ahmed-g-gad/apothem/actions/runs/${run_id}/pending_deployments" \
  -F "environment_ids[]=${env_id}" -f state=approved -f comment="vX.Y.Z"

El push de la etiqueta también inicia los flujos de trabajo de npm y de la extensión de VS Code. Sus trabajos de publicación esperan la misma aprobación hasta §2.4.

2.4 Confirmar la publicación en npm

El push de la etiqueta también ejecuta publish-npm.yml junto a release.yml. El flujo de trabajo de npm no espera al flujo de trabajo de lanzamiento; la aprobación del entorno release es la puerta. Cuando el flujo de trabajo de lanzamiento de §2.3 haya terminado, confirma que el lanzamiento está listo. La comprobación lee los lanzamientos, las ejecuciones de flujos de trabajo y el SBOM publicado, así que antes prepara dos entradas:

  • GH_TOKEN. El script se niega a ejecutarse sin él, aunque gh ya tenga una sesión iniciada. Usa un token de acceso personal de grano fino limitado a ahmed-g-gad/apothem, con Actions: Read (ejecuciones de flujos de trabajo) y Contents: Read (lanzamientos). La comprobación no escribe nada, así que no necesita ningún permiso de escritura. Un token obtenido con gh auth token tiene todos los alcances del inicio de sesión, así que usa preferentemente el token de grano fino.
  • El SBOM publicado. La comprobación lee dist/release-assets/sbom.cdx.json, el archivo CycloneDX que adjunta el lanzamiento. Descarga la copia que publicó el lanzamiento en lugar de una compilación local.
read -rs GH_TOKEN && export GH_TOKEN
mkdir -p dist/release-assets
gh release download vX.Y.Z --repo ahmed-g-gad/apothem \
  --pattern sbom.cdx.json --dir dist/release-assets --clobber
bash scripts/release/check-release-ready.sh vX.Y.Z

La comprobación falla cuando el lanzamiento es un borrador o una versión preliminar, cuando un flujo de trabajo requerido para el commit de la etiqueta no está en verde, cuando falta el SBOM, cuando describe otra versión o cuando omite un paquete vendorizado. El mensaje de fallo indica la causa.

Cuando la comprobación pase, aprueba la ejecución en espera Publish npm del mismo modo que en §2.3 (su ID de ejecución se obtiene de gh run list --workflow=publish-npm.yml). El flujo de trabajo publica @ahmed-g-gad/[email protected] en npmjs.com mediante la publicación de confianza de npm (OIDC); no se almacena ningún token de registro en el repositorio. Aprueba también la ejecución en espera Publish VS Code Extension. Este flujo de trabajo empaqueta apothem.vsix y lo publica en Visual Studio Marketplace como ahmed-g-gad.apothem-vscode. El paso de publicación se ejecuta solo mientras la variable del repositorio VSCODE_MARKETPLACE_READY sea true y haya una credencial configurada: la variable VSCE_AUTH=oidc (Trusted Publishing del Marketplace, sin secreto almacenado), las variables VSCE_AUTH=entra, AZURE_CLIENT_ID y AZURE_TENANT_ID (un token de Microsoft Entra ID de corta duración, sin secreto almacenado) o el secreto VSCE_PAT. Sin ninguna, la ejecución empaqueta la extensión y omite la publicación. La credencial es un interruptor, no un reintento: una publicación fallida en una ruta no recurre por sí sola a otra. La configuración de cada ruta está en Publicación en el Marketplace con Trusted Publishing (preferida) y en Publicación en el Marketplace con Microsoft Entra ID más abajo.

Para volver a publicar después de una ejecución fallida, despacha el flujo de trabajo para la misma etiqueta (gh workflow run publish-npm.yml --field tag=vX.Y.Z). Omite la publicación cuando la versión ya está en el registro, porque las versiones de npm son inmutables.

Publicación en el Marketplace con Trusted Publishing

Trusted Publishing permite que el Marketplace acepte directamente el token OIDC de GitHub de este repositorio: vsce publish --oidc intercambia el token del trabajo de publicación por una credencial del Marketplace de corta duración. No hay ningún secreto almacenado ni ningún recurso de Azure, así que esta es la ruta preferida. La ruta de Entra que se describe más abajo y el secreto VSCE_PAT siguen siendo alternativas que el operador selecciona.

  1. Usa una versión de vsce que lo admita. En esta ruta, el trabajo de publicación comprueba la versión de vsce bloqueada en tools/vsce antes de publicar, y se detiene con un error que indica la versión mínima cuando el bloqueo es más antiguo. Dependabot propone actualizaciones de vsce para ese archivo de bloqueo; fusiona la que alcance la versión mínima antes de cambiar de ruta.

  2. Crea la política. Inicia sesión como Owner del publicador, abre https://marketplace.visualstudio.com/manage/publishers/ahmed-g-gad y agrega una política en Trusted Publishing:

    • Nombre de la política: cualquier nombre, como apothem-release
    • Propietario del repositorio: Ahmed-G-Gad
    • Repositorio: apothem
    • Flujo de trabajo: publish-vscode.yml
    • Entorno: release

    Los nombres de los campos son los que enumera la guía de publicación de VS Code, en su sección sobre la publicación con GitHub Actions y Trusted Publishing (https://code.visualstudio.com/api/working-with-extensions/publishing-extension). Sin confirmar: si todos los publicadores ven ya la pestaña Trusted Publishing. Si el tuyo no la ve, usa la ruta de Entra.

  3. Cambia la ruta. Mantén VSCODE_MARKETPLACE_READY con el valor true y define el selector. Defínelo cuando no haya ninguna etiqueta en espera, porque el siguiente push de etiqueta publica por esta ruta.

    gh variable set VSCE_AUTH --body oidc
  4. Publica. El siguiente push de etiqueta, o un despacho para una etiqueta existente, publica mediante Trusted Publishing. Esta ruta no tiene ejecución de prueba: la primera publicación es la comprobación, y un despacho con dry_run solo advierte de que no se verificó nada.

  5. Recurre a la alternativa si falla. Elimina el selector y vuelve a despachar para la misma etiqueta; con el secreto VSCE_PAT definido, publica la ruta del token. Una publicación fallida no publicó nada, así que se puede volver a despachar la misma etiqueta.

    gh variable delete VSCE_AUTH

Publicación en el Marketplace con Microsoft Entra ID

La ruta de Entra sustituye el token de acceso personal almacenado por un token de corta duración. publish-vscode.yml solicita a GitHub un token OIDC, la acción Azure/login lo intercambia por un inicio de sesión de Entra mediante una credencial federada, y vsce publish --azure-credential publica con el token resultante. No existe ningún secreto de cliente. El secreto VSCE_PAT sigue siendo una alternativa que el operador selecciona; el flujo de trabajo nunca cambia a él por su cuenta.

La versión de vsce fijada en tools/vsce admite esta ruta. Necesita un tenant de Entra, un registro de aplicación y la pertenencia al publicador, que Trusted Publishing (descrito arriba) no necesita; úsala cuando Trusted Publishing no esté disponible para el publicador.

  1. Comprueba los requisitos previos. Busca la cuenta propietaria del publicador ahmed-g-gad (la pestaña Members en https://marketplace.visualstudio.com/manage/publishers/ahmed-g-gad) y el tenant de Entra donde puedes registrar aplicaciones. Sin confirmar: si el tenant del propietario del publicador debe coincidir con el tenant de la aplicación, y si la organización de Azure DevOps Ahmed-G-Gad debe estar conectada a Entra (dev.azure.com/Ahmed-G-Gad, Organization settings, Microsoft Entra). Ninguna fuente afirma ninguna de las dos cosas. Si el paso 5 o el 6 falla, comprueba esto primero.

  2. Registra la aplicación. En https://entra.microsoft.com, abre App registrations y luego New registration. Llámala apothem-vscode-publish, elige un solo tenant y deja vacío el URI de redirección. En Overview, copia el Application (client) ID y el Directory (tenant) ID. No crees ningún secreto de cliente ni concedas ningún permiso de API. El paso requiere derechos de propietario de la aplicación o un rol de Entra como Application Administrator.

  3. Agrega la credencial federada. En esa aplicación, abre Certificates & secrets, Federated credentials, Add credential, y elige el escenario "GitHub Actions deploying Azure resources". Introduce la organización Ahmed-G-Gad, el repositorio apothem, el tipo de entidad Environment, el nombre de entorno release y el nombre de credencial apothem-release. Los campos generados deben decir:

    issuer:   https://token.actions.githubusercontent.com
    subject:  repo:Ahmed-G-Gad/apothem:environment:release
    audience: api://AzureADTokenExchange

    La coincidencia es exacta y distingue mayúsculas de minúsculas. Si un inicio de sesión posterior falla con AADSTS700213 o AADSTS7002138, compara la credencial con la línea subject claim que Azure/login escribe en el registro del trabajo. AADSTS70021 justo después de la creación significa que la credencial todavía no se ha propagado; espera unos minutos y vuelve a intentarlo.

  4. Define las variables del repositorio. Mientras VSCODE_MARKETPLACE_READY sea true, la ruta de Entra se activa en cuanto las tres están definidas, así que defínelas cuando ninguna etiqueta de lanzamiento esté esperando aprobación. Sin VSCODE_MARKETPLACE_READY=true nada inicia sesión y la ejecución omite la publicación.

    gh variable set AZURE_CLIENT_ID --body "<application-client-id>"
    gh variable set AZURE_TENANT_ID --body "<directory-tenant-id>"
    gh variable set VSCE_AUTH --body entra

    Deja VSCODE_MARKETPLACE_READY y VSCE_PAT como están. Cuando VSCE_AUTH es entra pero AZURE_CLIENT_ID o AZURE_TENANT_ID está vacío, el flujo de trabajo registra una advertencia, esté o no definido VSCE_PAT, y no usa la ruta de Entra. Después usa el secreto VSCE_PAT si está definido; sin secreto no publica nada y la ejecución termina igualmente en verde, así que busca la advertencia.

  5. Ejecuta la ejecución de prueba. Despacha el flujo de trabajo para una etiqueta de lanzamiento existente con dry_run activado. En la ruta de Entra inicia sesión, imprime el perfil de Azure DevOps y verifica el acceso al publicador sin publicar. La ruta del token no tiene ejecución de prueba: si el registro muestra Marketplace credential mode: pat, la ejecución termina en verde con una advertencia y no ha verificado nada. Aprueba la ejecución en espera del entorno release.

    gh workflow run publish-vscode.yml --ref main -f tag=vX.Y.Z -f dry_run=true

    Resultado esperado: Marketplace credential mode: entra, una línea subject claim igual al subject del paso 3, y el id y el displayName del perfil impresos por el primer paso de la ejecución de prueba. Se espera que el paso de verificación falle con un 403 hasta el paso 6. Sin confirmar: que un inicio de sesión sin una suscripción de Azure produzca un token para el Marketplace a través de la CLI de Azure. Esta ejecución es la primera prueba de ello. Si falla aquí, registra en su lugar una identidad administrada asignada por el usuario en una suscripción, que es la ruta que documenta Microsoft.

  6. Agrega la aplicación al publicador. En la pestaña Members del paso 1, inicia sesión como Owner del publicador y agrega un miembro con el id del perfil del paso 5, con el rol Contributor. Sin confirmar: la etiqueta del campo del cuadro de diálogo, y si acepta el id antes de que la aplicación sea miembro de una organización de Azure DevOps. Por regla general, Azure DevOps agrega las identidades de aplicación por organización. Si el cuadro de diálogo rechaza el id, agrega la entidad de servicio a la organización Ahmed-G-Gad (Organization settings, Users, con el Object ID de la Enterprise application) y vuelve a intentarlo. También sin confirmar: si el perfil existe antes de la primera llamada de la identidad a Azure DevOps.

  7. Repite la ejecución de prueba. El paso de verificación ahora tiene éxito con "verification succeeded for the publisher"; sus mensajes siguen diciendo Personal Access Token, porque el token de Entra recorre el mismo camino. La comprobación demuestra la pertenencia al publicador (Creator, Owner, Contributor o Reader), no los derechos de publicación. Sin confirmar: que Contributor baste para publicar una actualización. La descripción del rol de Microsoft dice que sí, y ninguna fuente muestra una publicación con él, así que la primera publicación real es la prueba.

  8. Publica un lanzamiento. Etiqueta como en §2.2 y aprueba la ejecución. Se ejecuta el paso Publish to Visual Studio Marketplace (Entra ID), su encabezado de entorno lista solo AZURE_TENANT_ID, el paso de alternativa con token se omite y vsce imprime DONE Published ahmed-g-gad.apothem-vscode. La galería del Marketplace lista la nueva versión al cabo de unos cuatro minutos.

  9. Decide qué hacer con el token. Conserva VSCE_PAT hasta la primera publicación correcta con Entra y luego elimina el secreto si no quieres ninguna alternativa. Una vez eliminado, una variable de Entra eliminada o vacía deja la ejecución en verde sin publicar: con una advertencia cuando VSCE_AUTH sigue siendo entra, y solo con el aviso de omisión cuando no lo es. Lee las anotaciones de la ejecución después de cada etiqueta. Para conservar una alternativa más allá de la retirada de los tokens de acceso personal globales, crea un token con ámbito de organización para Ahmed-G-Gad con el ámbito personalizado Marketplace Manage y la caducidad más corta que aceptes, y guárdalo como VSCE_PAT. Sin confirmar: las etiquetas del portal de este paso proceden de memoria, no de una fuente primaria; Microsoft llama a los tokens con ámbito de organización una solución temporal y puede dejar de aceptarlos; y las páginas de Microsoft no coinciden en la fecha de retirada de los tokens globales.

  10. Recurre al token. Elimina el selector y vuelve a despachar; luego aprueba la ejecución. Una publicación fallida con Entra no publicó nada, así que se puede volver a despachar la misma etiqueta; comprueba antes la página del Marketplace, porque una versión que ya llegó no se puede publicar dos veces.

    gh variable delete VSCE_AUTH
    gh workflow run publish-vscode.yml --ref main -f tag=vX.Y.Z

Cuando la publicación con Entra falle, lee el registro del paso:

  • Un mensaje que empieza por "Can not acquire a Microsoft Entra ID access token" significa que falló el inicio de sesión o la cadena de credenciales. Comprueba primero el paso Sign in to Microsoft Entra ID y la credencial federada. Si el inicio de sesión está en verde, quita AZURE_TENANT_ID del env del paso de vsce en el flujo de trabajo; el propio flujo de trabajo de lanzamiento de extensiones de GitHub no lo exporta.
  • "InvalidAccessException" o "not allowed" significa que la identidad del token no es miembro del publicador. Compara el id del perfil de la ejecución de prueba con la pestaña Members.
  • Un 403 del paso de verificación de la ejecución de prueba significa que la aplicación todavía no tiene ningún rol.

A esta ruta se aplican tres límites:

  • id-token: write se concede a todo el trabajo de publicación, así que cualquier paso de ese trabajo puede solicitar un token OIDC, también en modo token. El subject del token está vinculado al entorno release, que requiere la aprobación de un revisor.
  • El entorno release no tiene ninguna política de ramas ni de etiquetas de despliegue, así que cualquier ref que apruebe un mantenedor puede obtener el token con el subject del entorno. Restringirlo a etiquetas v*.*.* requiere comprobar primero qué despachan release.yml y publish-npm.yml.
  • Un cambio de nombre o una transferencia del repositorio cambia el formato del subject de OIDC y rompe en silencio la credencial federada. Después de cualquier cambio de nombre, vuelve a copiar el subject del registro de Azure/login en la credencial.

2.5 Actualizar el pin del digest de plantillas

Una vez que exista la etiqueta, define _LATEST_RELEASE y _LATEST_RELEASE_DIGESTS en tests/unit/test_template_digests.py con el nuevo lanzamiento y el digest SHA-256 de cada plantilla de texto plano tal como la distribuyó ese lanzamiento (git show vX.Y.Z:<template path> | sha256sum). Hazlo en el siguiente cambio a main, y agrega el digest anterior a earlier_digests de la entrada del manifiesto cuando la plantilla haya cambiado. El trabajo de CI release-preflight hace checkout de cada etiqueta, así que falla con los nombres de las etiquetas hasta que se actualiza el pin.

3. Superficies de distribución

Cada superficie tiene un comando de verificación que responde a «¿llegó el lanzamiento aquí?»:

#SuperficieArtefactoVerificación
1GitHub Release (distribuciones de Python)apothem-X.Y.Z.tar.gz (sdist) + apothem-X.Y.Z-py3-none-any.whlgh release view vX.Y.Z --json assets --jq '.assets[].name' incluye ambos nombres de archivo
2GitHub Release (SBOM)sbom.cdx.json + sbom.cdx.json.cosign.bundlela lista de recursos incluye ambos; el metadata.component.purl del SBOM es pkg:pypi/[email protected] y sus componentes incluyen cada paquete de src/apothem/_vendor/vendor.txt
3GitHub Release (firmas)un <asset>.cosign.bundle por cada sdist, wheel, SBOM, extensión de VS Code, archivo comprimido por plataforma y SHA256SUMS (en los lanzamientos anteriores, los bundles de los archivos comprimidos y de SHA256SUMS se llaman <asset>.sig)cosign verify-blob con la identidad exacta de §5.5 termina con código 0
4GitHub Release (procedencia)provenance.intoto.jsonlbash scripts/release/verify-provenance.sh <download-dir> termina con código 0 (§5.5)
5GitHub Release (archivos comprimidos por plataforma)apothem-vX.Y.Z-darwin.tar.gz, apothem-vX.Y.Z-linux.tar.gz, apothem-vX.Y.Z-windows.zipla lista de recursos incluye cada archivo comprimido más SHA256SUMS. Los archivos comprimidos de darwin y linux son los mismos bytes con dos nombres (el runtime es independiente de la plataforma; --platform solo elige entre tar.gz y zip), por lo que sus líneas de SHA256SUMS muestran un mismo digest dos veces
6GitHub Release (extensión de VS Code)apothem.vsix + apothem.vsix.cosign.bundlela lista de recursos incluye ambos; code --install-extension apothem.vsix la instala. Los lanzamientos anteriores a que el flujo de trabajo de lanzamiento empaquetara la extensión no incluyen ninguno de los dos
7npmjs.com@ahmed-g-gad/[email protected]npm view @ahmed-g-gad/apothem version devuelve X.Y.Z; npx @ahmed-g-gad/[email protected] --version imprime Apothem, version X.Y.Z
8Pages (instaladores de script)install.sh / install.ps1 en el sitio de documentacióncurl -fsSL https://apothem.ahmedgad.com/install.sh | head -n 1 devuelve el encabezado del script
9Visual Studio Marketplaceahmed-g-gad.apothem-vscode versión X.Y.Zla página de la extensión en el Marketplace lista X.Y.Z; code --install-extension ahmed-g-gad.apothem-vscode la instala

El GitHub Release es la superficie canónica de artefactos; el paquete de npm y los instaladores de script son las rutas de instalación que se apoyan sobre él. La publicación en npm se ejecuta junto al flujo de trabajo de lanzamiento, con el mismo push de la etiqueta.

4. Disciplina del CHANGELOG

CHANGELOG.md lleva una sección por lanzamiento según la convención Keep-a-Changelog. La edición del CHANGELOG en el commit de lanzamiento:

  • Confirma que la sección de versión usa el encabezado ## [X.Y.Z] - YYYY-MM-DD (con guion; bump_version.py lo escribe, y extract_release_notes.py reconoce el prefijo ## [X.Y.Z]).
  • Confirma que los encabezados estándar —Added, Changed, Deprecated, Removed, Fixed, Security— se usan donde corresponda. Los encabezados vacíos se eliminan del archivo renderizado.
  • Recoge capacidades, no implementación. Solo lenguaje del dominio; sin referencias internas del plan; sin hashes de commit; sin identificadores de plan ni de fase.

Una sección del CHANGELOG que superó la revisión del mantenedor sirve como ancla de las notas de lanzamiento para el relato del anuncio.

5. Prueba de humo de las rutas de instalación

Cuando ambas etapas se completan, el mantenedor ejecuta la prueba de humo. La prueba de humo es la verificación canónica de que los comandos de instalación orientados al usuario responden.

5.1 Plugin de Claude Code

/plugin marketplace add ahmed-g-gad/apothem
/plugin install apothem@apothem

Esperado: el plugin se instala y los comandos apothem están disponibles dentro de Claude Code.

5.2 Node.js (npx)

npx @ahmed-g-gad/[email protected] --version

Salida esperada: Apothem, version X.Y.Z.

5.3 Instalador de script de un solo paso (POSIX)

El instalador escribe el lanzador apothem en ~/.local/bin, o en el directorio que indica APOTHEM_BIN_DIR cuando esa variable está definida. La comprobación siguiente necesita que ese directorio esté en PATH. Cuando no lo está, el instalador imprime la línea export PATH que hay que añadir. Mientras ese directorio no esté en PATH, el shell no encuentra apothem y la comprobación falla. Si el instalador no puede colocar el lanzador, imprime una advertencia y no imprime ninguna línea export PATH. En un equipo que todavía no tiene la clave de firma del mantenedor, la primera línea la importa; sin ella, el instalador se detiene.

curl -fsSL https://github.com/ahmed-g-gad.gpg | gpg --import
curl -fsSL https://apothem.ahmedgad.com/install.sh | sh
apothem --version

Salida esperada: Apothem, version X.Y.Z.

5.4 Instalador de script de un solo paso (Windows)

La primera línea importa la clave de firma del mantenedor a través del propio bash de Git, cuyo llavero de gpg es el que lee git verify-tag.

& "$env:ProgramFiles\Git\bin\bash.exe" -c 'curl -fsSL https://github.com/ahmed-g-gad.gpg | gpg --import'
irm https://apothem.ahmedgad.com/install.ps1 | iex
apothem --version

Salida esperada: Apothem, version X.Y.Z.

5.5 Verificación de artefactos (evidencia de la cadena de suministro)

Descarga todos los recursos en un directorio vacío y luego verifica. La identidad del certificado es el flujo de trabajo de lanzamiento en esta etiqueta exacta. Las comprobaciones de identidad distinguen entre mayúsculas y minúsculas, y los certificados llevan el propietario tal como lo reporta GitHub, Ahmed-G-Gad, por lo que un propietario en minúsculas falla.

mkdir release-vX.Y.Z && cd release-vX.Y.Z
gh release download vX.Y.Z --repo ahmed-g-gad/apothem
cosign verify-blob \
  --bundle apothem-X.Y.Z-py3-none-any.whl.cosign.bundle \
  --certificate-identity https://github.com/Ahmed-G-Gad/apothem/.github/workflows/release.yml@refs/tags/vX.Y.Z \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  apothem-X.Y.Z-py3-none-any.whl
slsa-verifier verify-artifact \
  --provenance-path provenance.intoto.jsonl \
  --source-uri github.com/Ahmed-G-Gad/apothem \
  --source-tag vX.Y.Z \
  apothem-X.Y.Z-py3-none-any.whl apothem-X.Y.Z.tar.gz
bash ../scripts/release/verify-provenance.sh .

Esperado: Verified OK, PASSED: SLSA verification passed y verify-provenance: chain OK (3 of 3 layers verified). El script comprueba SHA256SUMS, cada bundle de firma y la procedencia en una sola ejecución; deriva la etiqueta del nombre del wheel (--tag vX.Y.Z la reemplaza).

La prueba de humo produce una fila PASS / FAIL de una línea por superficie; registra las filas en el registro de lanzamientos del mantenedor.

6. Recuperación ante fallos

El flujo de trabajo de lanzamiento tiene modos de fallo documentados para el motor de lanzamiento y el publicador de npm:

FalloDiagnósticoRecuperación
Push de la etiqueta rechazado (fallo de firma)git push origin vX.Y.Z devuelve error: failed to push some refs con un mensaje relacionado con GPGVerifica que la subclave GPG esté cargada (gpg --list-secret-keys --keyid-format=long); vuelve a etiquetar localmente con -s después de corregir el llavero; vuelve a hacer push
La compilación del lanzamiento se detiene en Check the plugin version changed with the pluginEl registro del trabajo de compilación nombra el plugin y la etiqueta anterior; no se compiló ni se publicó ningún recursoEl paquete del plugin cambió desde el lanzamiento anterior, pero su versión no. Elimina la etiqueta (git push --delete origin vX.Y.Z, git tag -d vX.Y.Z), ejecuta python scripts/release/bump_version.py X.Y.Z, haz commit y luego vuelve a firmar y hacer push de la etiqueta (§2.2). La misma comprobación se ejecuta en cada pull request como anotación de advertencia, por lo que normalmente esto aparece antes de etiquetar
Un trabajo de release.yml falla en una sola etapagh run view <run-id> --log nombra el trabajo que falla (build, que también escribe el SBOM / sign / provenance / archive / publish)Vuelve a ejecutar solo el trabajo fallido mediante gh run rerun <run-id> --failed; si el fallo se repite, corrige la entrada del trabajo en su origen antes de volver a etiquetar
La verificación de la procedencia SLSA fallaEl trabajo verify SLSA provenance artifact termina con un código distinto de ceroInspecciona el artefacto de procedencia en busca de un desajuste del digest del sujeto; recompila desde la misma etiqueta: la procedencia se vincula a los digests exactos de los artefactos, por lo que cualquier regeneración de artefactos requiere volver a ejecutar el flujo de trabajo completo
Publicación en npmjs.com rechazadaEl trabajo de npm termina con un código distinto de cero durante npm publish; un 404 del registro durante PUT es un desajuste de autorización / publicador de confianza, no una prueba de que falte el código del paqueteVerifica que npm Trusted Publishing para @ahmed-g-gad/apothem nombre al propietario ahmed-g-gad, el repositorio apothem, el flujo de trabajo publish-npm.yml y la acción permitida npm publish; confirma que el trabajo se ejecuta con la versión de Node y la versión mínima de la CLI de npm para OIDC fijadas en el flujo de trabajo
Etiqueta visible, pero faltan recursosgh release view vX.Y.Z devuelve un lanzamiento incompletoVuelve a ejecutar el trabajo de publicación del flujo de trabajo de lanzamiento; este edita el lanzamiento existente y vuelve a subir cada recurso. Elimina la etiqueta y vuelve a etiquetar solo cuando nada de la etiqueta llegó a los usuarios (sin recursos, sin versión de npm); en caso contrario, corrige hacia adelante con el siguiente lanzamiento de parche (runbook de recuperación de lanzamientos §2)

Si un ciclo de recuperación no logra completar una superficie en una sola pasada de diagnóstico, la superficie se registra como fallo conocido en las notas de lanzamiento, con un enlace al issue abierto; a los usuarios de aguas abajo se les dirige a las superficies que funcionan mientras la defectuosa se corrige en un lanzamiento de parche.

7. Referencias cruzadas

  • Configuración del publicador. El runbook de configuración de la cuenta de publicador establece el vínculo de publicador de confianza de npm y los requisitos previos del lado de GitHub que este runbook da por supuestos.
  • Flujo de recuperación. El runbook de recuperación de lanzamientos sigue el mismo modelo aditivo: recupera una etiqueta o una etapa de publicador fallida, etapa por etapa, y revierte lanzando la corrección como una nueva versión de parche, nunca eliminando ni redirigiendo una etiqueta, un lanzamiento o una versión de npm publicados.
  • Habilitación de Pages. El flujo de trabajo publish-static-site.yml valida y despliega el sitio web del proyecto en el dominio personalizado; el runbook de habilitación de Pages (site/content/docs/runbooks/pages-enablement.mdx) es el procedimiento previo que estableció el dominio personalizado en primer lugar.
  • Política de versionado. site/content/docs/governance/release-engineering-policy.mdx contiene la política de SemVer + firma + obsolescencia que este runbook respeta.

On this page