Maintenance de Fork en Aval
Vue d'ensemble
Le but de la maintenance d'un fork en aval n'est pas de le laisser dériver progressivement de l'amont pour devenir un fork dur évoluant de manière indépendante. Il s'agit de maintenir en continu un ensemble de correctifs qui restent utilisables, compilables et testables.
Le fork en aval suit l'amont tout en fournissant rapidement aux utilisateurs du code et des artefacts contenant ces fonctionnalités et corrections lorsque les PR n'ont pas encore été fusionnées, que les mainteneurs amont sont occupés, ou qu'un correctif est spécialisé mais urgent. Ce n'est pas une archive de correctifs statique, mais un canal de distribution où les correctifs sont réellement exécutés et restent sous validation.
Un résultat intégré utilisable permet également à plus de personnes de tester librement les PR amont, les correctifs en aval et leurs propres modifications. À mesure que l'amont progresse, la compilation, le test et la révision continus des correctifs réduisent le risque que les PR pourrissent après avoir pris du retard sur l'amont, exposent les problèmes plus tôt et aident les modifications à remonter vers l'amont.
Objectifs principaux
- Empêcher le fork en aval de devenir un fork dur qui reste séparé de l'amont.
- Suivre continuellement l'amont plutôt que de ne conserver qu'une branche statique à un moment donné.
- Garder chaque correctif indépendamment compilable, testable, révisable et adapté à la soumission ou à la maintenance continue d'une PR.
- Fournir du code et des artefacts directement utilisables via la branche principale ou de release.
- Permettre aux utilisateurs de tester les PR, les correctifs et leurs propres modifications par rapport à un résultat intégré réel.
- Détecter les conflits entre les correctifs et l'amont tôt, maintenir les PR fusionnables et aider les correctifs à remonter vers l'amont.
Modèle de branches
Le dépôt détermine les noms de branches réels. Ne supposez pas de branche par défaut, de nom de dépôt distant ou de plateforme d'hébergement.
Branche principale amont
La branche principale amont est le point de départ de chaque reconstruction. Récupérez son dernier état avant la synchronisation et utilisez un commit amont spécifique comme référence pour la construction en cours.
La branche principale ou de release en aval ne doit pas devenir la nouvelle référence pour les correctifs. Un correctif doit toujours indiquer clairement ce qu'il modifie par rapport à l'amont.
Branches de correctifs
Maintenez chaque correctif indépendant sur sa propre branche et respectez les normes normales d'une PR :
- Gardez le périmètre ciblé, les commits et l'explication clairs.
- Incluez suffisamment de tests pour démontrer le comportement.
- Rendez-le indépendamment compilable et révisable sur l'amont actuel.
- Déclarez uniquement les dépendances nécessaires et évitez de le lier à d'autres correctifs en aval.
- Rendez-le adapté à une soumission directe en tant que PR amont ou à la maintenance continue d'une PR existante.
- En général, une branche de correctif ne doit pas modifier les fichiers de release centralement maintenus par les mainteneurs amont, tels que
CHANGELOG. Les modifications nécessaires de la documentation doivent se limiter aux commentaires de code, à la documentation de l'API et aux notes d'implémentation directement liées à ce correctif. Maintenez la liste des correctifs en aval et les notes de version de manière centralisée sur la branche de maintenance.
La branche de correctif est la source de vérité à long terme pour ce correctif. Un commit d'intégration sur la branche de release n'est pas la seule copie du correctif et ne doit pas contenir de correctifs temporaires qui n'existent que dans l'historique de release.
Branches de correctifs de compatibilité temporaires
Lorsque plusieurs correctifs s'appliquent indépendamment mais produisent un conflit de compilation, de test ou de comportement lorsqu'ils sont combinés, qui n'appartient à aucune branche de PR individuelle, maintenez un correctif de compatibilité sur une branche tmp/patch/<nom>.
Une telle branche ne résout que le problème de compatibilité en aval pour une combinaison spécifique de correctifs. N'intégrez pas de force la correction dans l'une des branches de PR indépendantes et ne la laissez pas devenir une nouvelle branche de fonctionnalité à long terme. Elle doit indiquer de quels correctifs elle dépend, où elle se situe dans l'ordre, quel comportement combiné elle valide et quand elle peut être retirée.
Dans l'orchestration de synchronisation sur la branche ci, ajoutez tmp/patch/<nom> dans l'ordre immédiatement après les correctifs dont elle dépend. Si une fusion Git antérieure a déjà produit des conflits textuels non résolus, une branche de compatibilité ultérieure ne peut pas franchir ce conflit. Dans ce cas, l'orchestration ci doit appliquer explicitement le traitement de compatibilité correspondant à l'étape où le conflit se produit avant de continuer la reconstruction ; le simple fait d'ajouter la branche à la fin de la liste ne suffit pas.
La branche de maintenance ci
Lorsque le fork doit intégrer de l'automatisation telle que GitHub Actions, maintenez une branche ci séparée. Si le dépôt a déjà une branche équivalente, conservez son nom. Cette branche est la superposition de release du fork en aval et est responsable de :
- CI/CD, packaging, releases et configuration du dépôt spécifiques à l'aval.
- Récupération automatique de l'amont, intégration des correctifs dans l'ordre, reconstruction de la branche de release et push sécurisé.
- Tests supplémentaires de correctif unique en aval et tests d'intégration multi-correctifs.
- Le README en aval, la liste des correctifs, les notes de version et toutes les instructions de maintenance spécifiques à l'aval.
- L'ordre d'intégration fixe des correctifs réguliers activés et des branches
tmp/patch/<nom>.
Si l'utilisateur ou le fork en aval a des exigences de maintenance au-delà de ce flux de travail général, conservez-les dans un fichier MAINTAIN.md appartenant à l'aval sur la branche ci. Il doit indiquer comment ce fork particulier doit être maintenu et enregistrer toutes les règles spéciales que les futurs mainteneurs et l'automatisation doivent suivre. Traitez-le comme un guide spécifique au dépôt : lisez-le avant de modifier les branches de correctifs, l'orchestration de synchronisation ou l'historique de release, et maintenez-le à jour lorsque ces exigences changent.
Lorsque les règles de maintenance spéciales pourraient autrement être manquées, ajoutez un avis concis dans le README.md de la branche ci pointant vers MAINTAIN.md. Conservez les règles détaillées dans MAINTAIN.md plutôt que de les dupliquer dans le README.
La branche ci peut porter de manière centralisée l'automatisation de release en aval, mais n'y mélangez pas les correctifs de comportement du produit. Les modifications d'exécution doivent rester sur des branches adaptées à la compilation, aux tests et à la soumission de PR amont indépendants.
Cette compétence inclut le fichier GitHub Actions utilisé par la pratique actuelle : ref/upstream-sync.yml. Lorsqu'une synchronisation automatique GitHub est nécessaire, copiez-le comme point de départ pour .github/workflows/upstream-sync.yml, puis adaptez l'adresse amont, la branche par défaut/ de release, les listes ci et de correctifs, l'ordre tmp/patch/<nom>, le planning de synchronisation, les fichiers appartenant à l'aval, les secrets et les vérifications pour le dépôt cible. Le fichier conserve la configuration spécifique au projet de son projet d'origine et ne doit pas être activé sans révision.
Lors de la configuration du schedule, demandez d'abord à l'utilisateur à quelles heures chaque jour la synchronisation doit s'exécuter. Le cron GitHub utilise UTC par défaut, sauf si le workflow définit explicitement un timezone pris en charge. Ne planifiez pas de tâches à la minute 0 de l'heure : la documentation officielle de GitHub indique que la charge est élevée au début de chaque heure, donc les tâches planifiées peuvent être retardées ou même abandonnées sous une charge suffisamment élevée. Pour éviter également les marques courantes de cinq minutes, n'utilisez pas un multiple de 5, comme 10, 15, 20, 30, 40 ou 45. Choisissez aléatoirement une minute de 1 à 59 qui n'est pas un multiple de 5 et écrivez-la comme valeur fixe dans le workflow, par exemple en exécutant python -c 'import secrets; print(secrets.choice([m for m in range(1, 60) if m % 5]))'. Ici, « aléatoire » s'applique uniquement lors de la génération de la configuration ; ne faites pas attendre le workflow pour un délai aléatoire dynamique à chaque exécution.
Branche principale ou de release
La branche principale ou de release part du dernier amont et intègre la branche de maintenance et les branches de correctifs requises dans un ordre fixe. Elle fournit le code complet, les compilations, les tests et les artefacts de release.
Cette branche représente uniquement le résultat intégré en aval actuel. Ce n'est pas la source de maintenance à long terme pour un correctif. Un problème peut d'abord être reproduit et analysé ici, mais la correction doit revenir à la branche de correctif ou de maintenance propriétaire, après quoi le résultat intégré doit être régénéré.
Dans l'historique de release, chaque correctif doit apparaître comme un commit d'intégration clair et dénombrable, rendant visibles à la fois le nombre de correctifs en aval et le nombre de commits dont le fork a pris du retard sur l'amont.
Flux de travail
1. Inspecter l'état actuel
Avant de commencer, lisez les instructions de maintenance et de contribution du dépôt lui-même, y compris le MAINTAIN.md en aval lorsqu'il est présent et tout avis README qui y pointe. Inspectez l'arbre de travail, les dépôts distants, la branche actuelle, les relations amont et le processus de synchronisation et de release existant. Préservez ou contournez tout travail utilisateur non validé ; ne le nettoyez pas et ne l'écrasez pas sans autorisation.
2. Vérifier les problèmes et les PR amont avant de coder
Avant d'implémenter toute nouvelle demande ou d'écrire du code, recherchez dans le suivi des problèmes amont et les PR amont les discussions ou implémentations connexes. Vérifiez les problèmes ouverts et fermés ainsi que les PR ouvertes, en brouillon, fermées et fusionnées ; recherchez non seulement le libellé exact de la demande, mais aussi les noms de composants pertinents, les messages d'erreur et les synonymes raisonnables. Suivez les problèmes liés, les révisions, les commits et les PR de remplacement suffisamment loin pour établir l'état actuel.
Utilisez le résultat pour choisir l'action suivante :
- Si l'amont implémente déjà l'exigence, vérifiez la version applicable et le comportement avant de décider si un changement en aval est toujours nécessaire.
- Si un problème ou une PR actif couvre le sujet, préférez contribuer à, tester, mettre à jour ou porter temporairement ce travail plutôt que de créer un doublon inconscient.
- Si une approche antérieure a été rejetée, annulée ou remplacée, comprenez la raison invoquée avant de proposer une nouvelle implémentation.
- Enregistrez les liens pertinents vers l'amont et la conclusion dans le plan de travail, les notes de correctif ou la description de la PR afin que la décision reste révisable.
Lorsque des problèmes ou PR amont connexes existent, ne passez pas directement à l'implémentation. Établissez d'abord leur statut réel, leur périmètre, leurs décisions, les préoccupations non résolues, les commentaires de révision, l'état de l'implémentation et la relation avec la demande de l'utilisateur. Synthétisez ensuite les informations pertinentes de l'amont pour l'utilisateur au lieu de transmettre une liste brute de liens. Expliquez clairement ce qui a été appris, comment cela affecte les hypothèses et le plan actuels, et quelles parties de la demande d'origine restent nécessaires.
Si cette investigation produit une nouvelle découverte qui pourrait changer le périmètre, l'approche, la priorité, la propriété, la stratégie de compatibilité ou le besoin du travail, demandez explicitement à l'utilisateur si le plan doit être modifié. Mettez l'implémentation en pause jusqu'à ce que l'utilisateur confirme s'il faut conserver ou réviser le plan. Ne réinterprétez pas silencieusement la demande en fonction de la discussion amont.
Ne commencez pas l'implémentation simplement parce qu'une recherche par terme exact n'a retourné aucun résultat. Effectuez d'abord une recherche raisonnable ; si aucune discussion ou implémentation pertinente n'est trouvée, indiquez ce résultat et continuez.
3. Reproduire sur le résultat intégré complet
Reproduisez d'abord le problème sur la branche principale ou de release actuelle pour confirmer comment il se produit dans la combinaison de correctifs que les utilisateurs exécutent réellement.
Pendant l'analyse, distinguez entre :
- Un problème dans l'amont lui-même.
- Un problème dans un correctif indépendant.
- Un problème d'intégration entre correctifs ; s'il n'appartient à aucune PR individuelle, placez-le dans
tmp/patch/<nom>. - Un problème dans la CI, le packaging, la synchronisation ou la documentation en aval.
4. Localiser et corriger la branche propriétaire
Trouvez la branche de correctif responsable du comportement et effectuez la correction et les tests sur cette branche. Si le problème concerne la compatibilité entre plusieurs correctifs, créez ou mettez à jour tmp/patch/<nom>. S'il concerne l'automatisation de release ou un autre travail de maintenance en aval, modifiez la branche ci.
Ne validez pas une correction de conflit ou une correction de produit uniquement sur la branche principale ou de release. Elle serait perdue lors de la prochaine reconstruction à partir de l'amont et empêcherait le correctif d'être révisé indépendamment.
5. Garder le correctif indépendamment utilisable
En suivant les conventions du dépôt, mettez à jour le correctif sur le dernier amont, résolvez les conflits sur la branche de correctif et exécutez les compilations et tests requis par ce correctif.
Confirmez qu'il ne repose pas sur des modifications cachées dans la branche de release et qu'il peut toujours être expliqué, révisé et soumis comme une PR seul. Si une PR amont existe déjà, mettez-la également à jour et continuez à la maintenir en réponse aux commentaires amont.
6. Reconstruire la branche principale ou de release
Récupérez à nouveau le dernier amont, créez une branche candidate propre à partir d'une tête amont spécifique, puis intégrez la superposition de release, les correctifs réguliers et les branches tmp/patch/<nom> requises dans l'ordre fixe déclaré par la branche ci.
Chaque correctif régulier et correctif de compatibilité temporaire doit produire son propre commit d'intégration clair dans l'historique de release. Un dépôt peut utiliser la fusion squash ou la méthode équivalente établie par le projet, mais le résultat doit être facile à réviser et à compter.
7. Valider le résultat utilisable
Exécutez les vérifications requises par le dépôt sur la version candidate complète, couvrant au moins :
- Des tests ciblés pour chaque correctif lui-même.
- Le comportement intégré après combinaison de plusieurs correctifs.
- Si la CI, le packaging et la documentation en aval proviennent des branches correctes.
- Si le code ou les artefacts que les utilisateurs obtiennent réellement correspondent au commit validé.
Mettez à jour la branche principale ou de release distante uniquement après que le code candidat et les artefacts ont passé toutes les validations requises.
Synchronisation automatique
Le but de la synchronisation automatique est de régénérer périodiquement un résultat de release en aval utilisable à partir d'une nouvelle tête amont, et non de continuer à accumuler des corrections sur une ancienne branche de release.
Le processus de synchronisation doit :
- Utiliser les contrôles de concurrence acceptés par le dépôt pour empêcher deux processus de synchronisation ou de release de mettre à jour la même branche en même temps.
- Récupérer le dernier amont, la branche
ci, tous les correctifs réguliers activés et toutes les branchestmp/patch/<nom>. - Créer une branche candidate propre à partir du commit amont explicitement sélectionné pour cette exécution.
- Intégrer la superposition de release en aval, les correctifs réguliers et les correctifs de compatibilité temporaires dans l'ordre fixe.
- Exécuter les validations sur cette branche candidate.
- Pousser la branche candidate vers la branche principale ou de release distante uniquement si toutes les validations réussissent.
[... le contenu continue avec le reste du fichier original qui doit être complété selon le même modèle ...]