Runbook du cycle de publication
Flux de travail de publication complet, des contrôles locaux au GitHub Release signé jusqu'à la publication npm.
Ce runbook mène une publication vX.Y.Z de apothem d'un arbre de travail
propre jusqu'aux surfaces de distribution vérifiées. La procédure est écrite
pour le mainteneur qui manie gh, git et le shell de niveau publication ;
elle se termine par une page de Release vérifiée, un CHANGELOG archivé et un
test de fumée du chemin d'installation confirmant que chaque surface destinée à
l'utilisateur répond à la commande d'installation canonique.
Le modèle de publication est additif. Chaque publication ajoute un commit
sur main et une étiquette vX.Y.Z annotée et signée ; aucun force-push n'est
effectué et aucune étiquette, aucun GitHub Release ni aucune version npm
antérieurs ne sont retirés. Chaque publication conserve son étiquette, son GitHub Release et sa version npm, et toutes restent publiées : les versions npm sont immuables (un name@version publié ne peut
jamais être remplacé), et les installations épinglées dépendent des étiquettes.
Le push de l'étiquette démarre trois flux de travail.
.github/workflows/release.yml compile, signe, atteste et publie le GitHub
Release avec son ensemble complet d'artefacts : sdist, wheel, SBOM CycloneDX,
paquets cosign de Sigstore, provenance SLSA-3 et les archives du runtime de
chaque plateforme. publish-npm.yml publie @ahmed-g-gad/apothem sur
npmjs.com via la publication de confiance npm, et publish-vscode.yml
empaquette l'extension VS Code et la publie sur le Visual Studio Marketplace.
La section versionnée du
CHANGELOG atterrit dans le commit de publication ; l'opérateur exécute le test
de fumée du chemin d'installation une fois les deux flux de travail terminés.
1. Prérequis
Le mainteneur confirme les éléments suivants avant d'étiqueter :
-
Arbre de travail. Propre (
git statusn'affiche rien en attente). Tout le travail de fonctionnalités de la publication se trouve surmain. -
CI au vert. Pour le dernier
main,gh run list --branch=main --limit=1 --json conclusion --jq '.[0].conclusion'renvoiesuccess. -
Outillage.
gh(GitHub CLI) version 2.40 ou ultérieure authentifié auprès deahmed-g-gad;git2.40 ou ultérieure avec la sous-clé de signature GPG chargée ; le lien d'éditeur de confiance npm pour@ahmed-g-gad/apothemest actif (vérifié selon le runbook de configuration du compte d'éditeur). -
Ancrages de version alignés. La chaîne de version déclarée dans
pyproject.tomlcorrespond à l'étiquette prévue sans le préfixev(le §2.1 la définit, avec tous les autres ancrages). Vérifiez :grep '^version' pyproject.tomlSortie attendue (pour une publication
vX.Y.Z; les espaces réservés représentent l'étiquette de la publication en cours) :version = "X.Y.Z" -
Entrées du CHANGELOG préparées. Les points de la publication se trouvent sous
## [Unreleased]dans des en-têtes Keep-a-Changelog ; le §2.1 les transforme en section de version datée dans le commit qui fait atterrir l'étiquette.
2. Étiqueter et déclencher
2.1 Rédiger le commit de publication
La version figure dans plus d'une douzaine de fichiers ; ne les modifiez donc pas à la main. Une seule commande les met tous à jour :
git checkout main
git pull --ff-only origin main
python scripts/release/bump_version.py X.Y.Zbump_version.py met à jour tous les ancrages de version ensemble :
-
Chaque manifeste d'empaquetage, d'extension, de plugin et de marketplace, ainsi que le fichier de citation (version et date de publication). La liste complète :
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: les entrées[Unreleased]deviennent une section## [X.Y.Z]datée,[Unreleased]compare à partir devX.Y.Z, et un lien[X.Y.Z]est ajouté. -
SECURITY.md: une nouvelle version mineure obtient une ligneX.Y.xprise en charge. Le maintien ou non des versions mineures plus anciennes dans la liste relève de votre décision ; le script affiche un rappel.
Il régénère ensuite les arborescences dérivées : le paquet du plugin Claude
Code, les goldens de behavior-diff, ainsi que les pages de référence et de
changelog de la documentation. Passez --dry-run pour lister d'abord les
modifications, --date YYYY-MM-DD pour définir la date de publication (par défaut : aujourd'hui en
UTC), ou --no-regen pour ignorer la régénération. Le script refuse une version
malformée ou une rétrogradation, et le relancer avec la version actuelle ne fait
que réaligner les ancrages divergents.
Examinez le diff, puis créez le commit :
git add -A
git commit -S -m "chore(release): cut vX.Y.Z"
git push origin mainLe drapeau -S signe le commit avec la clé GPG. Le push déclenche la matrice
de CI standard (lint, test, build) ; attendez le vert avant d'étiqueter.
La vérification de l'état de préparation du §2.4 exige aussi que CodeQL et
Conformity soient au vert sur le commit de publication. Les deux ne
s'exécutent que lorsque leurs propres chemins changent, et un commit de
publication ne modifie généralement aucun de ces chemins ; lancez-les donc
une fois que le commit de publication est en tête de main, puis
vérifiez que chaque exécution nomme ce 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 1Attendez la réussite des deux avant d'étiqueter, et ne poussez rien d'autre
vers main tant que la publication n'est pas parue : un push ultérieur éloigne
main du commit de publication, et la CI annule toute exécution encore en
cours sur la même branche.
2.2 Signer et pousser l'étiquette
git tag -a -s vX.Y.Z -m "vX.Y.Z"
git push origin vX.Y.ZLa combinaison -a -s produit une étiquette annotée et signée avec GPG. Le push
déclenche .github/workflows/release.yml, qui compile, signe, atteste et
publie.
2.3 Confirmer que le flux de travail de publication est terminé
gh run watch $(gh run list --workflow=release.yml --limit=1 --json databaseId --jq '.[0].databaseId')Le flux de travail exécute la compilation (sdist + wheel, puis un SBOM
CycloneDX de ces distributions, écrit à côté d'elles), la signature cosign sans
clé, la génération et la vérification de la provenance SLSA-3, les compilations
d'archives de plateforme (darwin / linux / windows), la signature des archives
avec un manifeste SHA256SUMS agrégé, et la publication finale du GitHub
Release. Le mainteneur parcourt le journal du job publish GitHub Release à la
recherche des confirmations de téléversement des ressources.
Le job publish GitHub Release s'exécute dans l'environnement release, qui
exige l'approbation du mainteneur ; l'exécution attend donc à cette étape une
fois que les jobs précédents ont réussi. Approuvez-la sur la page de
l'exécution (Review deployments, examiner les déploiements), ou depuis le
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"Le push de l'étiquette démarre aussi les flux de travail npm et de l'extension VS Code. Leurs jobs de publication attendent la même approbation jusqu'au §2.4.
2.4 Confirmer la publication npm
Le push de l'étiquette exécute aussi publish-npm.yml à côté de release.yml. Le flux de travail npm n'attend pas le flux de travail de publication ; l'approbation de l'environnement release est le point de contrôle. Une fois le flux de travail de publication du §2.3 terminé, confirmez l'état de préparation. La vérification lit les publications (releases), les exécutions de flux de travail et le SBOM publié ; préparez donc d'abord deux éléments :
GH_TOKEN. Le script refuse de s'exécuter sans lui, même lorsqueghest déjà connecté. Utilisez un jeton d'accès personnel à granularité fine limité àahmed-g-gad/apothem, avec Actions: Read (exécutions de flux de travail) et Contents: Read (publications). La vérification n'écrit rien : aucune permission d'écriture n'est donc nécessaire. Un jeton issu degh auth tokenporte toutes les portées de la connexion ; privilégiez donc le jeton à granularité fine.- Le SBOM publié. La vérification lit
dist/release-assets/sbom.cdx.json, le fichier CycloneDX que la publication joint. Téléchargez la copie publiée par la publication plutôt qu'une compilation locale.
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.ZLa vérification échoue lorsque la publication est un brouillon ou une préversion, lorsqu'un flux de travail requis pour le commit de l'étiquette n'est pas au vert, lorsque le SBOM est absent, lorsqu'il décrit une autre version, ou lorsqu'il omet un paquet vendorisé. Le message d'échec indique la cause.
Lorsque la vérification réussit, approuvez l'exécution Publish npm en
attente, de la même manière qu'au §2.3 (son identifiant d'exécution provient de
gh run list --workflow=publish-npm.yml). Le flux de travail publie
@ahmed-g-gad/[email protected] sur npmjs.com via la publication de confiance npm
(OIDC) ; aucun jeton de registre n'est stocké dans le dépôt. Approuvez aussi
l'exécution Publish VS Code Extension en attente. Elle empaquette
apothem.vsix et le publie sur le Visual Studio Marketplace sous l'identifiant
ahmed-g-gad.apothem-vscode. L'étape de publication ne s'exécute que tant que la
variable de dépôt VSCODE_MARKETPLACE_READY est true et qu'un identifiant est
configuré : la variable VSCE_AUTH=oidc (Trusted Publishing du Marketplace, aucun
secret stocké), les variables VSCE_AUTH=entra, AZURE_CLIENT_ID et
AZURE_TENANT_ID (un jeton Microsoft Entra ID de courte durée, aucun secret
stocké), ou le secret VSCE_PAT. Sans aucun d'eux, l'exécution empaquette
l'extension et ignore la publication. L'identifiant est un commutateur, pas une
nouvelle tentative : une publication en échec sur une voie ne bascule pas d'elle-même
vers une autre. La configuration de chaque voie figure dans
Publication sur le Marketplace avec Trusted Publishing
(à privilégier) et
Publication sur le Marketplace avec Microsoft Entra ID
ci-dessous.
Pour publier de nouveau après une exécution en échec, déclenchez le flux de
travail pour la même étiquette
(gh workflow run publish-npm.yml --field tag=vX.Y.Z). Il ignore la
publication lorsque la version est déjà sur le registre, car les versions npm
sont immuables.
Publication sur le Marketplace avec Trusted Publishing
Trusted Publishing permet au Marketplace d'accepter directement le jeton OIDC
GitHub de ce dépôt : vsce publish --oidc échange le jeton du job de publication
contre un identifiant Marketplace de courte durée. Il n'y a ni secret stocké ni
ressource Azure ; c'est donc la voie à privilégier. La voie Entra ci-dessous et le
secret VSCE_PAT restent des alternatives que l'opérateur sélectionne.
-
Utilisez une version de vsce qui la prend en charge. Sur cette voie, le job de publication vérifie la version de vsce verrouillée dans
tools/vsceavant de publier, et s'arrête avec une erreur qui indique la version minimale lorsque le verrou est plus ancien. Dependabot propose des mises à jour de vsce pour ce fichier de verrouillage ; fusionnez celle qui atteint la version minimale avant de basculer. -
Créez la politique. Connectez-vous en tant qu'Owner de l'éditeur, ouvrez
https://marketplace.visualstudio.com/manage/publishers/ahmed-g-gad, et ajoutez une politique sous Trusted Publishing :- Nom de la politique : un nom quelconque, par exemple
apothem-release - Propriétaire du dépôt :
Ahmed-G-Gad - Dépôt :
apothem - Flux de travail :
publish-vscode.yml - Environnement :
release
Les noms de champs sont ceux qu'indique le guide de publication de VS Code, dans sa section sur la publication avec GitHub Actions et Trusted Publishing (
https://code.visualstudio.com/api/working-with-extensions/publishing-extension). Non confirmé : si chaque éditeur voit déjà l'onglet Trusted Publishing. Si ce n'est pas le cas du vôtre, utilisez la voie Entra. - Nom de la politique : un nom quelconque, par exemple
-
Basculez la voie. Laissez
VSCODE_MARKETPLACE_READYàtrueet définissez le sélecteur. Définissez-le lorsqu'aucune étiquette n'est en attente, car le prochain push d'étiquette publie par cette voie.gh variable set VSCE_AUTH --body oidc -
Publiez. Le prochain push d'étiquette, ou un déclenchement pour une étiquette existante, publie via Trusted Publishing. Cette voie n'a pas d'exécution à blanc : la première publication sert de vérification, et un déclenchement avec
dry_runavertit seulement que rien n'a été vérifié. -
Revenez en arrière en cas d'échec. Supprimez le sélecteur et déclenchez de nouveau pour la même étiquette ; avec le secret
VSCE_PATdéfini, la voie par jeton publie. Une publication en échec n'a rien publié, de sorte que la même étiquette peut être déclenchée de nouveau.gh variable delete VSCE_AUTH
Publication sur le Marketplace avec Microsoft Entra ID
La voie Entra remplace le jeton d'accès personnel stocké par un jeton de courte
durée. publish-vscode.yml demande un jeton OIDC à GitHub, l'action Azure/login
l'échange contre une connexion Entra via un identifiant fédéré, et
vsce publish --azure-credential publie avec le jeton obtenu. Aucun secret client
n'existe. Le secret VSCE_PAT reste une solution de repli que l'opérateur
sélectionne ; le flux de travail ne bascule jamais vers lui de lui-même.
La version de vsce épinglée dans tools/vsce prend en charge cette voie. Elle
nécessite un locataire Entra, une inscription d'application et l'appartenance à
l'éditeur, ce que Trusted Publishing ci-dessus n'exige pas ; utilisez-la lorsque
Trusted Publishing n'est pas disponible pour l'éditeur.
-
Vérifiez les prérequis. Trouvez le compte propriétaire de l'éditeur
ahmed-g-gad(l'onglet Members àhttps://marketplace.visualstudio.com/manage/publishers/ahmed-g-gad) et le locataire Entra dans lequel vous pouvez inscrire des applications. Non confirmé : si le locataire du propriétaire de l'éditeur doit correspondre à celui de l'application, et si l'organisation Azure DevOpsAhmed-G-Gaddoit être connectée à Entra (dev.azure.com/Ahmed-G-Gad, Organization settings, Microsoft Entra). Aucune source n'établit l'un ou l'autre. Si l'étape 5 ou 6 échoue, vérifiez d'abord ces points. -
Inscrivez l'application. Dans
https://entra.microsoft.com, ouvrez App registrations, puis New registration. Nommez-laapothem-vscode-publish, choisissez un seul locataire et laissez l'URI de redirection vide. Depuis Overview, copiez l'Application (client) ID et le Directory (tenant) ID. Ne créez aucun secret client et n'accordez aucune permission d'API. L'étape nécessite les droits de propriétaire de l'application ou un rôle Entra tel qu'Application Administrator. -
Ajoutez l'identifiant fédéré. Sur cette application, ouvrez Certificates & secrets, Federated credentials, Add credential, et choisissez le scénario « GitHub Actions deploying Azure resources ». Saisissez l'organisation
Ahmed-G-Gad, le dépôtapothem, le type d'entitéEnvironment, le nom d'environnementreleaseet le nom d'identifiantapothem-release. Les champs générés doivent indiquer :issuer: https://token.actions.githubusercontent.com subject: repo:Ahmed-G-Gad/apothem:environment:release audience: api://AzureADTokenExchangeLa correspondance est exacte et sensible à la casse. Si une connexion ultérieure échoue avec AADSTS700213 ou AADSTS7002138, comparez l'identifiant avec la ligne
subject claimqueAzure/loginécrit dans le journal du job. AADSTS70021 juste après la création signifie que l'identifiant ne s'est pas encore propagé ; attendez quelques minutes et réessayez. -
Définissez les variables de dépôt. Tant que
VSCODE_MARKETPLACE_READYesttrue, la voie Entra est active dès que les trois sont définies ; définissez-les donc lorsqu'aucune étiquette de version n'attend d'approbation. SansVSCODE_MARKETPLACE_READY=true, rien ne se connecte et l'exécution ignore la publication.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 entraLaissez
VSCODE_MARKETPLACE_READYetVSCE_PATtels quels. LorsqueVSCE_AUTHvautentramais queAZURE_CLIENT_IDouAZURE_TENANT_IDest vide, le flux de travail journalise un avertissement, queVSCE_PATsoit défini ou non, et n'utilise pas la voie Entra. Il utilise alors le secretVSCE_PATs'il est défini ; sans secret, il ne publie rien et l'exécution se termine tout de même au vert : cherchez donc l'avertissement. -
Lancez l'exécution à blanc. Déclenchez le flux de travail pour une étiquette de version existante avec
dry_runactivé. Sur la voie Entra, il se connecte, affiche le profil Azure DevOps et vérifie l'accès à l'éditeur sans publier. La voie par jeton n'a pas d'exécution à blanc : si le journal afficheMarketplace credential mode: pat, l'exécution se termine au vert avec un avertissement et n'a rien vérifié. Approuvez l'exécution de l'environnementreleaseen attente.gh workflow run publish-vscode.yml --ref main -f tag=vX.Y.Z -f dry_run=trueAttendu :
Marketplace credential mode: entra, une lignesubject claimégale au sujet de l'étape 3, ainsi que l'idet ledisplayNamedu profil affichés par la première étape de l'exécution à blanc. L'étape de vérification doit échouer avec un 403 jusqu'à l'étape 6. Non confirmé : qu'une connexion sans abonnement Azure fournisse un jeton pour le Marketplace via l'Azure CLI. Cette exécution en est le premier test. Si elle échoue ici, inscrivez plutôt une identité managée affectée par l'utilisateur dans un abonnement, qui est la voie que Microsoft documente. -
Ajoutez l'application à l'éditeur. Dans l'onglet Members de l'étape 1, connectez-vous en tant qu'Owner de l'éditeur et ajoutez un membre à l'aide de l'
iddu profil de l'étape 5, avec le rôle Contributor. Non confirmé : l'intitulé du champ de la boîte de dialogue, et si elle accepte l'id avant que l'application soit membre d'une organisation Azure DevOps. En règle générale, Azure DevOps ajoute les identités d'application par organisation. Si la boîte de dialogue rejette l'id, ajoutez le principal de service à l'organisationAhmed-G-Gad(Organization settings, Users, en utilisant l'Object ID de l'Enterprise application) et réessayez. Non confirmé également : si le profil existe avant le premier appel Azure DevOps de l'identité. -
Relancez l'exécution à blanc. L'étape de vérification réussit désormais avec « verification succeeded for the publisher » ; ses messages mentionnent toujours Personal Access Token, car le jeton Entra emprunte le même chemin. La vérification prouve l'appartenance à l'éditeur (Creator, Owner, Contributor ou Reader), pas les droits de publication. Non confirmé : que Contributor suffise pour publier une mise à jour. La description du rôle par Microsoft l'affirme, et aucune source ne montre de publication avec ce rôle ; la première vraie publication en est donc la preuve.
-
Publiez une version. Étiquetez comme au §2.2 et approuvez l'exécution. L'étape
Publish to Visual Studio Marketplace (Entra ID)s'exécute, son en-tête d'environnement ne liste queAZURE_TENANT_ID, l'étape de repli par jeton est ignorée, et vsce afficheDONE Published ahmed-g-gad.apothem-vscode. La galerie du Marketplace liste la nouvelle version au bout d'environ quatre minutes. -
Décidez du sort du jeton. Conservez
VSCE_PATjusqu'à la première publication Entra réussie, puis supprimez le secret si aucune solution de repli n'est souhaitée. Une fois qu'il a disparu, une variable Entra supprimée ou vide laisse l'exécution au vert sans publication : avec un avertissement lorsqueVSCE_AUTHvaut toujoursentra, et avec seulement l'avis d'omission lorsque ce n'est pas le cas. Lisez les annotations de l'exécution après chaque étiquette. Pour conserver une solution de repli au-delà du retrait des jetons d'accès personnels globaux, créez un jeton limité à l'organisationAhmed-G-Gadavec la portée personnalisée Marketplace Manage et la durée d'expiration la plus courte que vous acceptez, et stockez-le en tant queVSCE_PAT. Non confirmé : les intitulés du portail dans cette étape proviennent de la mémoire, pas d'une source primaire ; Microsoft qualifie les jetons limités à une organisation de solution de contournement temporaire et peut cesser de les honorer ; et les pages de Microsoft divergent sur la date de retrait des jetons globaux. -
Revenez au jeton. Supprimez le sélecteur et déclenchez de nouveau, puis approuvez l'exécution. Une publication Entra en échec n'a rien publié, de sorte que la même étiquette peut être déclenchée de nouveau ; vérifiez d'abord la page du Marketplace, car une version qui a atterri ne peut pas être publiée deux fois.
gh variable delete VSCE_AUTH gh workflow run publish-vscode.yml --ref main -f tag=vX.Y.Z
Lorsque la publication Entra échoue, lisez le journal de l'étape :
- Un message qui commence par « Can not acquire a Microsoft Entra ID access
token » signifie que la connexion ou la chaîne d'identifiants a échoué.
Vérifiez d'abord l'étape
Sign in to Microsoft Entra IDet l'identifiant fédéré. Si la connexion est au vert, retirezAZURE_TENANT_IDde l'envde l'étape vsce dans le flux de travail ; le propre flux de travail de publication d'extension de GitHub ne l'exporte pas. - « InvalidAccessException » ou « not allowed » signifie que l'identité du jeton
n'est pas membre de l'éditeur. Comparez l'
iddu profil issu de l'exécution à blanc avec l'onglet Members. - Un 403 de l'étape de vérification de l'exécution à blanc signifie que l'application n'a pas encore de rôle.
Trois limites s'appliquent à cette voie :
id-token: writeest accordé à l'ensemble du job de publication, de sorte que chacune de ses étapes peut demander un jeton OIDC, y compris en mode jeton. Le sujet du jeton est lié à l'environnementrelease, qui exige l'approbation d'un relecteur.- L'environnement
releasen'a aucune politique de branche ou d'étiquette de déploiement, de sorte que toute ref approuvée par un mainteneur peut obtenir le jeton au sujet d'environnement. Le restreindre aux étiquettesv*.*.*nécessite de vérifier d'abord ce querelease.ymletpublish-npm.ymldéclenchent. - Un renommage ou un transfert du dépôt modifie le format du sujet OIDC et casse
silencieusement l'identifiant fédéré. Recopiez le sujet depuis le journal
Azure/logindans l'identifiant après tout renommage.
2.5 Actualiser l'épinglage des condensés de modèles
Une fois l'étiquette créée, définissez _LATEST_RELEASE et _LATEST_RELEASE_DIGESTS
dans tests/unit/test_template_digests.py sur la nouvelle version et le condensé
SHA-256 de chaque modèle en texte brut tel que cette version l'a livré
(git show vX.Y.Z:<template path> | sha256sum). Faites-le dans la prochaine
modification de main, et ajoutez le condensé précédent aux earlier_digests de
l'entrée du manifeste lorsque le modèle a changé. Le job CI release-preflight
extrait chaque étiquette ; il échoue donc avec les noms des étiquettes tant que
l'épinglage n'est pas actualisé.
3. Surfaces de distribution
Chaque surface possède une commande de vérification qui répond à « la publication a-t-elle atterri ici ? » :
| # | Surface | Artefact | Vérification |
|---|---|---|---|
| 1 | GitHub Release (distributions Python) | apothem-X.Y.Z.tar.gz (sdist) + apothem-X.Y.Z-py3-none-any.whl | gh release view vX.Y.Z --json assets --jq '.assets[].name' inclut les deux noms de fichier |
| 2 | GitHub Release (SBOM) | sbom.cdx.json + sbom.cdx.json.cosign.bundle | la liste des ressources inclut les deux ; le metadata.component.purl du SBOM est pkg:pypi/[email protected] et ses composants incluent chaque paquet de src/apothem/_vendor/vendor.txt |
| 3 | GitHub Release (signatures) | un <asset>.cosign.bundle par sdist, wheel, SBOM, extension VS Code, archive de plateforme et SHA256SUMS (les publications antérieures nomment les paquets de l'archive et de SHA256SUMS <asset>.sig) | cosign verify-blob avec l'identité exacte du §5.5 se termine avec 0 |
| 4 | GitHub Release (provenance) | provenance.intoto.jsonl | bash scripts/release/verify-provenance.sh <download-dir> se termine avec 0 (§5.5) |
| 5 | GitHub Release (archives de plateforme) | apothem-vX.Y.Z-darwin.tar.gz, apothem-vX.Y.Z-linux.tar.gz, apothem-vX.Y.Z-windows.zip | la liste des ressources inclut chaque archive plus SHA256SUMS. Les archives darwin et linux sont les mêmes octets sous deux noms (le runtime est indépendant de la plateforme ; --platform choisit seulement tar.gz ou zip), de sorte que leurs lignes SHA256SUMS affichent deux fois le même condensé |
| 6 | GitHub Release (extension VS Code) | apothem.vsix + apothem.vsix.cosign.bundle | la liste des ressources inclut les deux ; code --install-extension apothem.vsix l'installe. Les publications antérieures à l'empaquetage de l'extension par le flux de travail de publication ne contiennent ni l'un ni l'autre |
| 7 | npmjs.com | @ahmed-g-gad/[email protected] | npm view @ahmed-g-gad/apothem version renvoie X.Y.Z ; npx @ahmed-g-gad/[email protected] --version affiche Apothem, version X.Y.Z |
| 8 | Pages (installateurs de script) | install.sh / install.ps1 sur le site de documentation | curl -fsSL https://apothem.ahmedgad.com/install.sh | head -n 1 renvoie l'en-tête du script |
| 9 | Visual Studio Marketplace | ahmed-g-gad.apothem-vscode version X.Y.Z | la page Marketplace de l'extension répertorie X.Y.Z ; code --install-extension ahmed-g-gad.apothem-vscode l'installe |
Le GitHub Release est la surface canonique des artefacts ; le paquet npm et les installateurs de script sont les chemins d'installation superposés par-dessus. La publication npm s'exécute à côté du flux de travail de publication, sur le même push d'étiquette.
4. Discipline du CHANGELOG
Le CHANGELOG.md porte une section par publication selon la convention
Keep-a-Changelog. La modification du CHANGELOG dans le commit de publication :
- Confirme que la section de version utilise l'en-tête
## [X.Y.Z] - YYYY-MM-DD(un trait d'union ;bump_version.pyl'écrit, etextract_release_notes.pyreconnaît le préfixe## [X.Y.Z]). - Confirme que les en-têtes standard — Added, Changed, Deprecated, Removed, Fixed, Security — sont utilisés là où c'est applicable. Les en-têtes vides sont supprimés du fichier rendu.
- Capture les capacités, pas l'implémentation. Langage du domaine uniquement ; aucune référence interne au plan ; aucun hash de commit ; aucun identifiant de plan ni de phase.
Une section du CHANGELOG qui a survécu à la revue du mainteneur se lit comme l'ancre des notes de publication pour le récit de l'annonce.
5. Test de fumée du chemin d'installation
Une fois les deux étapes terminées, le mainteneur exécute le test de fumée. Le test de fumée est la vérification canonique que les commandes d'installation destinées à l'utilisateur répondent.
5.1 Plugin Claude Code
/plugin marketplace add ahmed-g-gad/apothem
/plugin install apothem@apothemAttendu : le plugin s'installe et les commandes apothem sont disponibles dans
Claude Code.
5.2 Node.js (npx)
npx @ahmed-g-gad/[email protected] --versionSortie attendue : Apothem, version X.Y.Z.
5.3 Installateur de script en une seule étape (POSIX)
L'installateur écrit le lanceur apothem dans ~/.local/bin, ou dans le répertoire
nommé par APOTHEM_BIN_DIR lorsque cette variable est définie. La vérification
ci-dessous exige que ce répertoire figure dans PATH. Lorsqu'il n'y figure pas,
l'installateur affiche la ligne export PATH à ajouter. Tant que ce répertoire
ne figure pas dans PATH, le shell ne trouve pas apothem et la vérification
échoue. Si l'installateur ne peut pas placer le lanceur, il affiche un
avertissement et aucune ligne export PATH. Sur un hôte qui ne détient pas
encore la clé de signature du mainteneur, la première ligne l'importe ; sans
cette clé, l'installateur s'arrête.
curl -fsSL https://github.com/ahmed-g-gad.gpg | gpg --import
curl -fsSL https://apothem.ahmedgad.com/install.sh | sh
apothem --versionSortie attendue : Apothem, version X.Y.Z.
5.4 Installateur de script en une seule étape (Windows)
La première ligne importe la clé de signature du mainteneur par le bash de Git
lui-même, dont le trousseau gpg est celui que lit 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 --versionSortie attendue : Apothem, version X.Y.Z.
5.5 Vérification des artefacts (preuve de chaîne d'approvisionnement)
Téléchargez toutes les ressources dans un répertoire vide, puis vérifiez.
L'identité du certificat est le flux de travail de publication à cette étiquette
exacte. Les vérifications d'identité sont sensibles à la casse, et les
certificats portent le propriétaire tel que GitHub le rapporte, Ahmed-G-Gad ;
un propriétaire en minuscules échoue donc.
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 .Attendu : Verified OK, PASSED: SLSA verification passed et
verify-provenance: chain OK (3 of 3 layers verified). Le script vérifie
SHA256SUMS, chaque paquet de signature et la provenance en une seule
exécution ; il déduit l'étiquette du nom du wheel (--tag vX.Y.Z la remplace).
Le test de fumée produit une ligne PASS / FAIL par surface ; consignez les lignes dans le journal de publication du mainteneur.
6. Récupération après échec
Le flux de travail de publication a des modes de défaillance documentés pour le moteur de publication et l'éditeur npm :
| Échec | Diagnostic | Récupération |
|---|---|---|
| Push de l'étiquette rejeté (échec de signature) | git push origin vX.Y.Z renvoie error: failed to push some refs avec un message lié à GPG | Vérifiez que la sous-clé GPG est chargée (gpg --list-secret-keys --keyid-format=long) ; ré-étiquetez localement avec -s après avoir corrigé le trousseau ; poussez de nouveau |
La compilation de publication s'arrête à Check the plugin version changed with the plugin | Le journal du job de compilation nomme le plugin et l'étiquette précédente ; aucune ressource n'a été compilée ni publiée | Le paquet du plugin a changé depuis la publication précédente, mais pas sa version. Supprimez l'étiquette (git push --delete origin vX.Y.Z, git tag -d vX.Y.Z), exécutez python scripts/release/bump_version.py X.Y.Z, créez le commit, puis signez et poussez de nouveau l'étiquette (§2.2). La même vérification s'exécute sur chaque pull request sous forme d'annotation d'avertissement ; ce cas apparaît donc normalement avant l'étiquetage |
Un job de release.yml échoue à une seule étape | gh run view <run-id> --log nomme le job en échec (build, qui écrit aussi le SBOM / sign / provenance / archive / publish) | Relancez le job en échec seul via gh run rerun <run-id> --failed ; si l'échec se répète, corrigez l'entrée du job à sa source avant de ré-étiqueter |
| La vérification de la provenance SLSA échoue | Le job verify SLSA provenance artifact se termine avec un code non nul | Inspectez l'artefact de provenance à la recherche d'une incohérence de condensé du sujet ; recompilez à partir de la même étiquette — la provenance est liée aux condensés exacts des artefacts, donc toute régénération d'artefacts nécessite une réexécution complète du flux de travail |
| Publication sur npmjs.com rejetée | Le job npm se termine avec un code non nul pendant npm publish ; un 404 du registre pendant PUT est une incohérence d'autorisation / d'éditeur de confiance, pas une preuve que le code du paquet est absent | Vérifiez que npm Trusted Publishing pour @ahmed-g-gad/apothem nomme le propriétaire ahmed-g-gad, le dépôt apothem, le flux de travail publish-npm.yml et l'action autorisée npm publish ; confirmez que le job s'exécute avec la version de Node et le plancher OIDC de la CLI npm épinglés dans le flux de travail |
| Étiquette visible mais ressources absentes | gh release view vX.Y.Z renvoie une publication squelette | Relancez le job de publication du flux de travail de publication ; il modifie la publication existante et téléverse de nouveau chaque ressource. Ne supprimez et ne ré-étiquetez que lorsque rien de l'étiquette n'a atteint les utilisateurs (aucune ressource, aucune version npm) ; sinon, corrigez vers l'avant avec la publication de patch suivante (runbook de récupération de publication §2) |
Si un cycle de récupération ne parvient pas à faire atterrir une surface en une seule passe de diagnostic, la surface est consignée comme un échec connu dans les notes de publication avec un lien vers le ticket ouvert ; les utilisateurs en aval sont orientés vers les surfaces qui fonctionnent pendant que celle qui est cassée est corrigée dans une publication de patch.
7. Références croisées
- Configuration de l'éditeur. Le runbook de configuration du compte d'éditeur établit le lien d'éditeur de confiance npm et les prérequis côté GitHub que ce runbook suppose.
- Flux de récupération. Le runbook de récupération de publication suit le même modèle additif : il récupère, étape par étape, une étiquette ou une étape d'éditeur en échec, et effectue le retour arrière en publiant le correctif sous une nouvelle version de patch, jamais en supprimant ou en réaffectant une étiquette, une publication ou une version npm déjà publiée.
- Activation de Pages. Le flux de travail
publish-static-site.ymlvalide et déploie le site web du projet vers le domaine personnalisé ; le runbook d'activation de Pages (site/content/docs/runbooks/pages-enablement.mdx) est la procédure en amont qui a établi le domaine personnalisé en premier lieu. - Politique de versionnage.
site/content/docs/governance/release-engineering-policy.mdxporte la politique SemVer + signature + obsolescence que ce runbook respecte.
Runbooks
Runbooks d'Apothem — procédures opérationnelles pas à pas pour les publications, la configuration de l'éditeur, l'activation de Pages, la récupération et la rédaction d'adaptateurs.
Liste de contrôle de déploiement
Liste de contrôle de vérification préalable pour déployer ou partager l'écosystème Apothem