Communitygithub.com

déplier-stack-prs

Dérouler une chaîne de PRs empilées (chaque PR basée sur la branche de la PR précédente) et les atterrir une par une dans la branche de base (develop/main/master), sans nécessiter de liste d'autorisation CI pour les branches intermédiaires. Gère les stacks natives GitHub via l'API merge-async.

Qu'est-ce que déplier-stack-prs ?

Cette compétence automatise le déploiement d'une chaîne de Pull Requests empilées (stacked PRs) où chaque PR est basée sur la branche de la PR précédente. Au lieu de demander une autorisation CI pour chaque branche intermédiaire, elle retarget chaque couche vers la branche de base juste au moment nécessaire, en s'appuyant sur la protection de la branche de base pour la validation CI. Le processus suit un ordre de fusion strict basé sur les dépendances réelles, fusionne toujours dans la branche de base, et synchronise chaque couche avec la base avant la validation CI. Pour les stacks natives GitHub, elle utilise l'API `merge-async` qui fusionne également automatiquement les PRs en dessous. La compétence inclut la détection de conflits, la résolution des conflits de fichiers de workflow et de formatage, et des consignes de sécurité (pas de force-push, approbation humaine requise avant chaque fusion). Elle est liée à d'autres compétences pour l'ouverture de stacks, la vérification des approbations et la résolution de threads.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/sblattj/agent-chandlery/tree/main/skills/landing-stacked-prs

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Atterrir les PRs empilées dans la branche de base

À utiliser lorsque plusieurs PRs sont chaînées (PR N basée sur la branche de PR N-1) et doivent atteindre la vraie branche de base. Le principe clé : La CI de la branche intermédiaire n'est pas la barrière. La protection de la branche de base l'est. Donc, re-cibler chaque couche vers la base juste-à-temps et laisser la CI native la valider. Ne jamais se fier au codage en dur des noms de branches intermédiaires dans les déclencheurs CI.

Dépôt : passez -R propriétaire/dépôt à gh, ou exécutez depuis le clone (gh repo view --json nameWithOwner -q .nameWithOwner le résout). Ci-dessous, R est ce propriétaire/dépôt.

Principes

  • L'ordre de fusion est dicté par les vraies dépendances (dépendances de contenu + fichiers édités par plus d'une couche). Établissez d'abord cet ordre ; ne le réorganisez pas pour être pratique.
  • Ne fusionnez jamais une couche dans la branche de base, une à la fois. Ne fusionnez jamais un enfant dans son ancienne branche prérequise.
  • Avant que la CI d'une couche ne soit importante, fusionnez la base actuelle dans cette couche pour que son diff se réduise à son propre changement et qu'elle voie tout ce qui a déjà été atterri.
  • La branche de pointe contient chaque couche cumulativement ; une exécution CI sur la pointe (re-ciblée vers la base) valide l'ensemble du stack assemblé. Utilisez-la comme un pré-vol optionnel.

Étape 0 : établir l'ordre et détecter les conflits

Résolvez la vraie base du dépôt (branche par défaut du remote git, par exemple develop ou main ; le fichier d'instructions de l'agent utilisateur (AGENTS.md / CLAUDE.md) peut nommer les bases connues). Pour chaque PR, sondez les conflits contre la base, pas contre sa base empilée obsolète (qui lira CLEAN et vous induira en erreur) :

git fetch origin <base> <head> --quiet
git merge-tree --write-tree origin/<base> origin/<head> | grep -iE 'CONFLICT|changed in both' || echo "clean vs base"

Règle empirique pour l'ordre : contenu prérequis avant la porte qui en a besoin (par exemple, nettoyage du lint avant activation du lint) ; lorsque deux couches éditent le même fichier, la plus ancienne fusionne en premier.

Étape 1..N : par couche, dans l'ordre

PR=<numéro>
gh pr edit $PR -R $R --base <base>     # re-ciblage hors de la branche empilée
# un espace de travail séparé pour la branche head garde votre checkout principal propre :
WT=../<dépôt>-<head>                    # tout chemin en dehors de votre checkout principal
git worktree add "$WT" <head> 2>/dev/null || true
git -C "$WT" fetch origin --quiet
git -C "$WT" merge origin/<base>       # synchroniser la base ; résoudre les conflits (voir ci-dessous)
git -C "$WT" push
gh pr ready $PR -R $R                  # quand c'est la couche active
gh pr checks $PR -R $R --watch         # CI native, base=<base>
# après approbation de la revue uniquement :
gh pr merge $PR -R $R --squash --delete-branch
# puis passer à la couche suivante (son re-ciblage + synchronisation de base absorbera celle-ci)

Stacks natives GitHub (merge-async)

Une PR créée avec la fonctionnalité de stack native de GitHub refuse les étapes classiques ci-dessus :

  • gh pr edit --base : GraphQL: Cannot change the base branch because the pull request is part of a stack. (updatePullRequest)
  • gh pr merge --auto : GraphQL: Auto-merge is not supported for stacked pull requests.
  • gh pr merge : This pull request is part of a stack and must be merged using the asynchronous merge REST API.

Utilisez l'API asynchrone, d'abord la PR du bas (GitHub re-cible la suivante vers la base tout seul, accordez-lui ~30s) :

sha=$(gh pr view $PR -R $R --json headRefOid -q .headRefOid)
u=$(gh api -X PUT repos/$R/pulls/$PR/merge-async -f merge_method=squash -f sha=$sha \
      -f merge_action=direct_merge --jq '.details.uuid // .status')
gh api repos/$R/pulls/$PR/merge-async/$u --jq '.status+" "+(.details.message//"")'   # interroger jusqu'à ce que ne soit plus "pending"
  • Fusionner une PR empilée de cette manière fusionne également toutes les PR ouvertes en dessous d'elle, donc ne fusionnez que la couche que vous voulez atterrir.
  • Après chaque squash, la couche suivante est souvent DIRTY sur les deux fichiers touchés (un ADR, une liste de versions) : fusionnez la base dedans, résolvez, poussez, attendez la CI, puis merge-async la.
  • Les approbations survivent aux synchronisations de base dans les dépôts qui ne rejettent pas les revues obsolètes (vérifiez required_pull_request_reviews.dismiss_stale_reviews dans la protection de branche). La vraie barrière est souvent l'approbation CODEOWNERS pour chaque chemin touché, pas le nombre d'approbations (pr-approval-gate liste les lacunes).
  • Pour garder chaque PR ouverte à jour avec sa base entre les atterrissages, exécutez un passage de synchronisation de base : fusionnez la base dans chaque branche de PR ouverte et poussez (fusions simples, pas de force-push).

Résolution de conflits

  • Fichiers de workflow édités par plusieurs couches (workflows de build réutilisables, un workflow orchestrateur CI) : gardez LES DEUX modifications, ne choisissez pas un côté.
  • Collisions de balayage de format (une couche d'application de formatage Spotless/Prettier vs des modifications de contenu sur la base) : prenez le CONTENU de la base pour le fichier en conflit, puis réexécutez le formateur dessus (mvn -pl <module> -am spotless:apply ou pnpm fmt). Prendre le côté du balayage supprime les vraies modifications ; prendre la base sans reformater échoue la porte de formatage. Les exécutions du formateur nécessitent la résolution du build (certains dépôts tirent les dépendances d'un registre privé qui nécessite d'abord une connexion cloud ; actualisez-la si le build ne peut pas récupérer les dépendances).

Sécurité

  • Ne faites pas de force-push, ne réécrivez pas l'historique, ne poussez pas vers des branches protégées.
  • Suivez les conventions de paternité des commits du dépôt (certaines interdisent les tags de co-auteur IA).
  • Faites une pause pour approbation de la revue humaine avant chaque fusion dans la base.
  • S'il existe une PR de liste d'autorisation CI de branche intermédiaire (l'anti-patron que cette compétence remplace), recommandez de la fermer ; si elle a déjà été fusionnée, annulez les noms de branches et types d'événements ajoutés.

Lié

  • ouverture-une-séquence-de-prs-empilées : ouverture du stack (bases, ordre de fusion) et le correctif de restack par type de fusion (stack.sh restack).
  • pr-approbation-porte : quels code owners chaque couche nécessite encore.
  • résoudre-fils-pr-conflits-et-fusion : atterrir une couche une fois que ses fils et approbations sont terminés.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Skills associés