[{"data":1,"prerenderedAt":1058},["ShallowReactive",2],{"/fr-fr/blog/categories/engineering/":3,"navigation-fr-fr":22,"banner-fr-fr":443,"footer-fr-fr":456,"engineering-category-page-fr-fr":668},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":11,"config":12,"_id":15,"_type":16,"title":17,"_source":18,"_file":19,"_stem":20,"_extension":21},"/fr-fr/blog/categories/engineering","categories",false,"",{"title":9,"description":10},"Ingénierie","Browse articles related to Ingénierie on the GitLab Blog",{"name":9},{"template":13,"slug":14,"hide":6},"BlogCategory","engineering","content:fr-fr:blog:categories:engineering.yml","yaml","Engineering","content","fr-fr/blog/categories/engineering.yml","fr-fr/blog/categories/engineering","yml",{"_path":23,"_dir":24,"_draft":6,"_partial":6,"_locale":7,"data":25,"_id":439,"_type":16,"title":440,"_source":18,"_file":441,"_stem":442,"_extension":21},"/shared/fr-fr/main-navigation","fr-fr",{"logo":26,"freeTrial":31,"sales":36,"login":41,"items":46,"search":380,"minimal":416,"duo":430},{"config":27},{"href":28,"dataGaName":29,"dataGaLocation":30},"/fr-fr/","gitlab logo","header",{"text":32,"config":33},"Commencer un essai gratuit",{"href":34,"dataGaName":35,"dataGaLocation":30},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":37,"config":38},"Contacter l'équipe commerciale",{"href":39,"dataGaName":40,"dataGaLocation":30},"/fr-fr/sales/","sales",{"text":42,"config":43},"Connexion",{"href":44,"dataGaName":45,"dataGaLocation":30},"https://gitlab.com/users/sign_in/","sign in",[47,91,190,195,301,361],{"text":48,"config":49,"cards":51,"footer":74},"Plateforme",{"dataNavLevelOne":50},"platform",[52,58,66],{"title":48,"description":53,"link":54},"La plateforme DevSecOps alimentée par l'IA la plus complète",{"text":55,"config":56},"Découvrir notre plateforme",{"href":57,"dataGaName":50,"dataGaLocation":30},"/fr-fr/platform/",{"title":59,"description":60,"link":61},"GitLab Duo (IA)","Créez des logiciels plus rapidement en tirant parti de l'IA à chaque étape du développement",{"text":62,"config":63},"Découvrez GitLab Duo",{"href":64,"dataGaName":65,"dataGaLocation":30},"/fr-fr/gitlab-duo/","gitlab duo ai",{"title":67,"description":68,"link":69},"Choisir GitLab","10 raisons pour lesquelles les entreprises choisissent GitLab",{"text":70,"config":71},"En savoir plus",{"href":72,"dataGaName":73,"dataGaLocation":30},"/fr-fr/why-gitlab/","why gitlab",{"title":75,"items":76},"Démarrer avec",[77,82,87],{"text":78,"config":79},"Ingénierie de plateforme",{"href":80,"dataGaName":81,"dataGaLocation":30},"/fr-fr/solutions/platform-engineering/","platform engineering",{"text":83,"config":84},"Expérience développeur",{"href":85,"dataGaName":86,"dataGaLocation":30},"/fr-fr/developer-experience/","Developer experience",{"text":88,"config":89},"MLOps",{"href":90,"dataGaName":88,"dataGaLocation":30},"/fr-fr/topics/devops/the-role-of-ai-in-devops/",{"text":92,"left":93,"config":94,"link":96,"lists":100,"footer":172},"Produit",true,{"dataNavLevelOne":95},"solutions",{"text":97,"config":98},"Voir toutes les solutions",{"href":99,"dataGaName":95,"dataGaLocation":30},"/fr-fr/solutions/",[101,127,150],{"title":102,"description":103,"link":104,"items":109},"Automatisation","CI/CD et automatisation pour accélérer le déploiement",{"config":105},{"icon":106,"href":107,"dataGaName":108,"dataGaLocation":30},"AutomatedCodeAlt","/fr-fr/solutions/delivery-automation/","automated software delivery",[110,114,118,123],{"text":111,"config":112},"CI/CD",{"href":113,"dataGaLocation":30,"dataGaName":111},"/fr-fr/solutions/continuous-integration/",{"text":115,"config":116},"Développement assisté par l'IA",{"href":64,"dataGaLocation":30,"dataGaName":117},"AI assisted development",{"text":119,"config":120},"Gestion du code source",{"href":121,"dataGaLocation":30,"dataGaName":122},"/fr-fr/solutions/source-code-management/","Source Code Management",{"text":124,"config":125},"Livraison de logiciels automatisée",{"href":107,"dataGaLocation":30,"dataGaName":126},"Automated software delivery",{"title":128,"description":129,"link":130,"items":135},"Securité","Livrez du code plus rapidement sans compromettre la sécurité",{"config":131},{"href":132,"dataGaName":133,"dataGaLocation":30,"icon":134},"/fr-fr/solutions/security-compliance/","security and compliance","ShieldCheckLight",[136,141,146],{"text":137,"config":138},"Application Security Testing",{"href":139,"dataGaName":140,"dataGaLocation":30},"/solutions/application-security-testing/","Application security testing",{"text":142,"config":143},"Sécurité de la chaîne d'approvisionnement logicielle",{"href":144,"dataGaLocation":30,"dataGaName":145},"/fr-fr/solutions/supply-chain/","Software supply chain security",{"text":147,"config":148},"Software Compliance",{"href":149,"dataGaName":147,"dataGaLocation":30},"/solutions/software-compliance/",{"title":151,"link":152,"items":157},"Mesures",{"config":153},{"icon":154,"href":155,"dataGaName":156,"dataGaLocation":30},"DigitalTransformation","/fr-fr/solutions/visibility-measurement/","visibility and measurement",[158,162,167],{"text":159,"config":160},"Visibilité et mesures",{"href":155,"dataGaLocation":30,"dataGaName":161},"Visibility and Measurement",{"text":163,"config":164},"Gestion de la chaîne de valeur",{"href":165,"dataGaLocation":30,"dataGaName":166},"/fr-fr/solutions/value-stream-management/","Value Stream Management",{"text":168,"config":169},"Données d'analyse et informations clés",{"href":170,"dataGaLocation":30,"dataGaName":171},"/fr-fr/solutions/analytics-and-insights/","Analytics and insights",{"title":173,"items":174},"GitLab pour",[175,180,185],{"text":176,"config":177},"Entreprises",{"href":178,"dataGaLocation":30,"dataGaName":179},"/fr-fr/enterprise/","enterprise",{"text":181,"config":182},"PME",{"href":183,"dataGaLocation":30,"dataGaName":184},"/fr-fr/small-business/","small business",{"text":186,"config":187},"Secteur public",{"href":188,"dataGaLocation":30,"dataGaName":189},"/fr-fr/solutions/public-sector/","public sector",{"text":191,"config":192},"Tarifs",{"href":193,"dataGaName":194,"dataGaLocation":30,"dataNavLevelOne":194},"/fr-fr/pricing/","pricing",{"text":196,"config":197,"link":199,"lists":203,"feature":288},"Ressources",{"dataNavLevelOne":198},"resources",{"text":200,"config":201},"Afficher toutes les ressources",{"href":202,"dataGaName":198,"dataGaLocation":30},"/fr-fr/resources/",[204,237,260],{"title":205,"items":206},"Premiers pas",[207,212,217,222,227,232],{"text":208,"config":209},"Installation",{"href":210,"dataGaName":211,"dataGaLocation":30},"/fr-fr/install/","install",{"text":213,"config":214},"Guides de démarrage rapide",{"href":215,"dataGaName":216,"dataGaLocation":30},"/fr-fr/get-started/","quick setup checklists",{"text":218,"config":219},"Apprentissage",{"href":220,"dataGaLocation":30,"dataGaName":221},"https://university.gitlab.com/","learn",{"text":223,"config":224},"Documentation sur le produit",{"href":225,"dataGaName":226,"dataGaLocation":30},"https://docs.gitlab.com/","product documentation",{"text":228,"config":229},"Vidéos sur les bonnes pratiques",{"href":230,"dataGaName":231,"dataGaLocation":30},"/fr-fr/getting-started-videos/","best practice videos",{"text":233,"config":234},"Intégrations",{"href":235,"dataGaName":236,"dataGaLocation":30},"/fr-fr/integrations/","integrations",{"title":238,"items":239},"Découvrir",[240,245,250,255],{"text":241,"config":242},"Histoires de succès client",{"href":243,"dataGaName":244,"dataGaLocation":30},"/fr-fr/customers/","customer success stories",{"text":246,"config":247},"Blog",{"href":248,"dataGaName":249,"dataGaLocation":30},"/fr-fr/blog/","blog",{"text":251,"config":252},"Travail à distance",{"href":253,"dataGaName":254,"dataGaLocation":30},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":256,"config":257},"TeamOps",{"href":258,"dataGaName":259,"dataGaLocation":30},"/fr-fr/teamops/","teamops",{"title":261,"items":262},"Connecter",[263,268,273,278,283],{"text":264,"config":265},"Services GitLab",{"href":266,"dataGaName":267,"dataGaLocation":30},"/fr-fr/services/","services",{"text":269,"config":270},"Communauté",{"href":271,"dataGaName":272,"dataGaLocation":30},"/community/","community",{"text":274,"config":275},"Forum",{"href":276,"dataGaName":277,"dataGaLocation":30},"https://forum.gitlab.com/","forum",{"text":279,"config":280},"Événements",{"href":281,"dataGaName":282,"dataGaLocation":30},"/events/","events",{"text":284,"config":285},"Partenaires",{"href":286,"dataGaName":287,"dataGaLocation":30},"/fr-fr/partners/","partners",{"backgroundColor":289,"textColor":290,"text":291,"image":292,"link":296},"#2f2a6b","#fff","L'avenir du développement logiciel. Tendances et perspectives.",{"altText":293,"config":294},"carte promo The Source",{"src":295},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":297,"config":298},"Lire les articles les plus récents",{"href":299,"dataGaName":300,"dataGaLocation":30},"/fr-fr/the-source/","the source",{"text":302,"config":303,"lists":305},"Société",{"dataNavLevelOne":304},"company",[306],{"items":307},[308,313,319,321,326,331,336,341,346,351,356],{"text":309,"config":310},"À propos",{"href":311,"dataGaName":312,"dataGaLocation":30},"/fr-fr/company/","about",{"text":314,"config":315,"footerGa":318},"Emplois",{"href":316,"dataGaName":317,"dataGaLocation":30},"/jobs/","jobs",{"dataGaName":317},{"text":279,"config":320},{"href":281,"dataGaName":282,"dataGaLocation":30},{"text":322,"config":323},"Leadership",{"href":324,"dataGaName":325,"dataGaLocation":30},"/company/team/e-group/","leadership",{"text":327,"config":328},"Équipe",{"href":329,"dataGaName":330,"dataGaLocation":30},"/company/team/","team",{"text":332,"config":333},"Manuel",{"href":334,"dataGaName":335,"dataGaLocation":30},"https://handbook.gitlab.com/","handbook",{"text":337,"config":338},"Relations avec les investisseurs",{"href":339,"dataGaName":340,"dataGaLocation":30},"https://ir.gitlab.com/","investor relations",{"text":342,"config":343},"Centre de confiance",{"href":344,"dataGaName":345,"dataGaLocation":30},"/fr-fr/security/","trust center",{"text":347,"config":348},"Centre pour la transparence de l'IA",{"href":349,"dataGaName":350,"dataGaLocation":30},"/fr-fr/ai-transparency-center/","ai transparency center",{"text":352,"config":353},"Newsletter",{"href":354,"dataGaName":355,"dataGaLocation":30},"/company/contact/","newsletter",{"text":357,"config":358},"Presse",{"href":359,"dataGaName":360,"dataGaLocation":30},"/press/","press",{"text":362,"config":363,"lists":364},"Nous contacter",{"dataNavLevelOne":304},[365],{"items":366},[367,370,375],{"text":37,"config":368},{"href":39,"dataGaName":369,"dataGaLocation":30},"talk to sales",{"text":371,"config":372},"Aide",{"href":373,"dataGaName":374,"dataGaLocation":30},"/support/","get help",{"text":376,"config":377},"Portail clients GitLab",{"href":378,"dataGaName":379,"dataGaLocation":30},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":381,"login":382,"suggestions":389},"Fermer",{"text":383,"link":384},"Pour rechercher des dépôts et des projets, connectez-vous à",{"text":385,"config":386},"gitlab.com",{"href":44,"dataGaName":387,"dataGaLocation":388},"search login","search",{"text":390,"default":391},"Suggestions",[392,395,400,402,407,412],{"text":59,"config":393},{"href":64,"dataGaName":394,"dataGaLocation":388},"GitLab Duo (AI)",{"text":396,"config":397},"Suggestions de code (IA)",{"href":398,"dataGaName":399,"dataGaLocation":388},"/fr-fr/solutions/code-suggestions/","Code Suggestions (AI)",{"text":111,"config":401},{"href":113,"dataGaName":111,"dataGaLocation":388},{"text":403,"config":404},"GitLab sur AWS",{"href":405,"dataGaName":406,"dataGaLocation":388},"/fr-fr/partners/technology-partners/aws/","GitLab on AWS",{"text":408,"config":409},"GitLab sur Google Cloud ",{"href":410,"dataGaName":411,"dataGaLocation":388},"/fr-fr/partners/technology-partners/google-cloud-platform/","GitLab on Google Cloud",{"text":413,"config":414},"Pourquoi utiliser GitLab ?",{"href":72,"dataGaName":415,"dataGaLocation":388},"Why GitLab?",{"freeTrial":417,"mobileIcon":422,"desktopIcon":427},{"text":418,"config":419},"Commencer votre essai gratuit",{"href":420,"dataGaName":35,"dataGaLocation":421},"https://gitlab.com/-/trials/new/","nav",{"altText":423,"config":424},"Icône GitLab",{"src":425,"dataGaName":426,"dataGaLocation":421},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":423,"config":428},{"src":429,"dataGaName":426,"dataGaLocation":421},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"freeTrial":431,"mobileIcon":435,"desktopIcon":437},{"text":432,"config":433},"En savoir plus sur GitLab Duo",{"href":64,"dataGaName":434,"dataGaLocation":421},"gitlab duo",{"altText":423,"config":436},{"src":425,"dataGaName":426,"dataGaLocation":421},{"altText":423,"config":438},{"src":429,"dataGaName":426,"dataGaLocation":421},"content:shared:fr-fr:main-navigation.yml","Main Navigation","shared/fr-fr/main-navigation.yml","shared/fr-fr/main-navigation",{"_path":444,"_dir":24,"_draft":6,"_partial":6,"_locale":7,"title":445,"titleMobile":445,"button":446,"config":451,"_id":453,"_type":16,"_source":18,"_file":454,"_stem":455,"_extension":21},"/shared/fr-fr/banner","La plateforme GitLab Duo Agent est maintenant disponible en version bêta publique !",{"text":447,"config":448},"Essayer la version bêta",{"href":449,"dataGaName":450,"dataGaLocation":30},"/fr-fr/gitlab-duo/agent-platform/","duo banner",{"layout":452},"release","content:shared:fr-fr:banner.yml","shared/fr-fr/banner.yml","shared/fr-fr/banner",{"_path":457,"_dir":24,"_draft":6,"_partial":6,"_locale":7,"data":458,"_id":664,"_type":16,"title":665,"_source":18,"_file":666,"_stem":667,"_extension":21},"/shared/fr-fr/main-footer",{"text":459,"source":460,"edit":466,"contribute":471,"config":476,"items":481,"minimal":655},"Git est une marque déposée de Software Freedom Conservancy et notre utilisation de « GitLab » est sous licence",{"text":461,"config":462},"Afficher le code source de la page",{"href":463,"dataGaName":464,"dataGaLocation":465},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":467,"config":468},"Modifier cette page",{"href":469,"dataGaName":470,"dataGaLocation":465},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":472,"config":473},"Veuillez contribuer",{"href":474,"dataGaName":475,"dataGaLocation":465},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":477,"facebook":478,"youtube":479,"linkedin":480},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[482,505,559,592,626],{"title":48,"links":483,"subMenu":488},[484],{"text":485,"config":486},"Plateforme DevSecOps",{"href":57,"dataGaName":487,"dataGaLocation":465},"devsecops platform",[489],{"title":191,"links":490},[491,495,500],{"text":492,"config":493},"Voir les forfaits",{"href":193,"dataGaName":494,"dataGaLocation":465},"view plans",{"text":496,"config":497},"Pourquoi choisir GitLab Premium ?",{"href":498,"dataGaName":499,"dataGaLocation":465},"/fr-fr/pricing/premium/","why premium",{"text":501,"config":502},"Pourquoi choisir GitLab Ultimate ?",{"href":503,"dataGaName":504,"dataGaLocation":465},"/fr-fr/pricing/ultimate/","why ultimate",{"title":506,"links":507},"Solutions",[508,513,516,518,523,528,532,535,538,543,545,547,549,554],{"text":509,"config":510},"Transformation digitale",{"href":511,"dataGaName":512,"dataGaLocation":465},"/fr-fr/topics/digital-transformation/","digital transformation",{"text":514,"config":515},"Sécurité et conformité",{"href":139,"dataGaName":140,"dataGaLocation":465},{"text":124,"config":517},{"href":107,"dataGaName":108,"dataGaLocation":465},{"text":519,"config":520},"Développement agile",{"href":521,"dataGaName":522,"dataGaLocation":465},"/fr-fr/solutions/agile-delivery/","agile delivery",{"text":524,"config":525},"Transformation cloud",{"href":526,"dataGaName":527,"dataGaLocation":465},"/fr-fr/topics/cloud-native/","cloud transformation",{"text":529,"config":530},"SCM",{"href":121,"dataGaName":531,"dataGaLocation":465},"source code management",{"text":111,"config":533},{"href":113,"dataGaName":534,"dataGaLocation":465},"continuous integration & delivery",{"text":163,"config":536},{"href":165,"dataGaName":537,"dataGaLocation":465},"value stream management",{"text":539,"config":540},"GitOps",{"href":541,"dataGaName":542,"dataGaLocation":465},"/fr-fr/solutions/gitops/","gitops",{"text":176,"config":544},{"href":178,"dataGaName":179,"dataGaLocation":465},{"text":181,"config":546},{"href":183,"dataGaName":184,"dataGaLocation":465},{"text":186,"config":548},{"href":188,"dataGaName":189,"dataGaLocation":465},{"text":550,"config":551},"Formation",{"href":552,"dataGaName":553,"dataGaLocation":465},"/fr-fr/solutions/education/","education",{"text":555,"config":556},"Services financiers",{"href":557,"dataGaName":558,"dataGaLocation":465},"/fr-fr/solutions/finance/","financial services",{"title":196,"links":560},[561,563,565,567,570,572,576,578,580,582,584,586,588,590],{"text":208,"config":562},{"href":210,"dataGaName":211,"dataGaLocation":465},{"text":213,"config":564},{"href":215,"dataGaName":216,"dataGaLocation":465},{"text":218,"config":566},{"href":220,"dataGaName":221,"dataGaLocation":465},{"text":223,"config":568},{"href":225,"dataGaName":569,"dataGaLocation":465},"docs",{"text":246,"config":571},{"href":248,"dataGaName":249},{"text":573,"config":574},"Histoires de réussite client",{"href":575,"dataGaLocation":465},"/customers/",{"text":241,"config":577},{"href":243,"dataGaName":244,"dataGaLocation":465},{"text":251,"config":579},{"href":253,"dataGaName":254,"dataGaLocation":465},{"text":264,"config":581},{"href":266,"dataGaName":267,"dataGaLocation":465},{"text":256,"config":583},{"href":258,"dataGaName":259,"dataGaLocation":465},{"text":269,"config":585},{"href":271,"dataGaName":272,"dataGaLocation":465},{"text":274,"config":587},{"href":276,"dataGaName":277,"dataGaLocation":465},{"text":279,"config":589},{"href":281,"dataGaName":282,"dataGaLocation":465},{"text":284,"config":591},{"href":286,"dataGaName":287,"dataGaLocation":465},{"title":302,"links":593},[594,596,598,600,602,604,606,610,615,617,619,621],{"text":309,"config":595},{"href":311,"dataGaName":304,"dataGaLocation":465},{"text":314,"config":597},{"href":316,"dataGaName":317,"dataGaLocation":465},{"text":322,"config":599},{"href":324,"dataGaName":325,"dataGaLocation":465},{"text":327,"config":601},{"href":329,"dataGaName":330,"dataGaLocation":465},{"text":332,"config":603},{"href":334,"dataGaName":335,"dataGaLocation":465},{"text":337,"config":605},{"href":339,"dataGaName":340,"dataGaLocation":465},{"text":607,"config":608},"Sustainability",{"href":609,"dataGaName":607,"dataGaLocation":465},"/sustainability/",{"text":611,"config":612},"Diversité, inclusion et appartenance (DIB)",{"href":613,"dataGaName":614,"dataGaLocation":465},"/fr-fr/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":342,"config":616},{"href":344,"dataGaName":345,"dataGaLocation":465},{"text":352,"config":618},{"href":354,"dataGaName":355,"dataGaLocation":465},{"text":357,"config":620},{"href":359,"dataGaName":360,"dataGaLocation":465},{"text":622,"config":623},"Déclaration de transparence sur l'esclavage moderne",{"href":624,"dataGaName":625,"dataGaLocation":465},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":362,"links":627},[628,631,633,635,640,645,650],{"text":629,"config":630},"Échanger avec un expert",{"href":39,"dataGaName":40,"dataGaLocation":465},{"text":371,"config":632},{"href":373,"dataGaName":374,"dataGaLocation":465},{"text":376,"config":634},{"href":378,"dataGaName":379,"dataGaLocation":465},{"text":636,"config":637},"Statut",{"href":638,"dataGaName":639,"dataGaLocation":465},"https://status.gitlab.com/","status",{"text":641,"config":642},"Conditions d'utilisation",{"href":643,"dataGaName":644},"/terms/","terms of use",{"text":646,"config":647},"Déclaration de confidentialité",{"href":648,"dataGaName":649,"dataGaLocation":465},"/fr-fr/privacy/","privacy statement",{"text":651,"config":652},"Préférences en matière de cookies",{"dataGaName":653,"dataGaLocation":465,"id":654,"isOneTrustButton":93},"cookie preferences","ot-sdk-btn",{"items":656},[657,659,662],{"text":641,"config":658},{"href":643,"dataGaName":644,"dataGaLocation":465},{"text":660,"config":661},"Politique de confidentialité",{"href":648,"dataGaName":649,"dataGaLocation":465},{"text":651,"config":663},{"dataGaName":653,"dataGaLocation":465,"id":654,"isOneTrustButton":93},"content:shared:fr-fr:main-footer.yml","Main Footer","shared/fr-fr/main-footer.yml","shared/fr-fr/main-footer",{"featuredPost":669,"allPosts":692,"totalPages":1056,"initialPosts":1057},{"_path":670,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":671,"content":676,"config":685,"_id":688,"_type":16,"title":689,"_source":18,"_file":690,"_stem":691,"_extension":21},"/fr-fr/blog/docs-site-design-overhaul",{"config":672,"title":673,"ogTitle":673,"description":674,"ogDescription":674,"ogImage":675},{"noIndex":6},"La documentation de GitLab fait peau neuve","La documentation produit de GitLab est désormais plus claire et plus facile à parcourir avec un nouveau mode sombre.","https://res.cloudinary.com/about-gitlab-com/image/upload/f_auto,q_auto,c_lfill/blog/hero%20images/workflow_1800x945",{"heroImage":675,"date":677,"title":673,"description":678,"authors":679,"category":14,"tags":683,"body":684},"2025-09-01","Découvrez les fonctionnalités de notre nouvelle documentation produit, qui facilite désormais les retours et prend en charge le mode sombre tant demandé.",[680,681,682],"Suzanne Selhorn","Julia Miocene","Sarah German",[272],"La documentation de GitLab arbore désormais une toute nouvelle apparence. Ce qui a commencé comme une demande de corrections de design ciblées s'est transformé en une refonte complète avec cinq améliorations majeures :\n\n**Un mode sombre** : la fonctionnalité la plus demandée est enfin disponible. Alternez entre thème clair et thème sombre en cliquant dans le coin supérieur droit pour améliorer la lisibilité et réduire la fatigue oculaire.\n\n**Un alignement de la marque** : notre documentation reflète désormais les couleurs et le design de notre site web et de notre interface utilisateur afin de garantir une expérience cohérente à travers toutes les propriétés de GitLab.\n\n**Des retours simplifiés** : les utilisateurs peuvent désormais donner leur avis (positif ou négatif) et laisser des commentaires sur n'importe quelle page de la documentation.\n\n**Une navigation repensée** : nous avons déplacé la navigation principale vers le haut et restructuré notre barre latérale gauche pour rendre nos plus de 2 300 pages moins intimidantes et plus faciles à parcourir.\n\n**Une dette technique résolue** : des dizaines de corrections mineures ont été apportées à la typographie, à l'espacement, aux blocs de code et aux incohérences visuelles qui s'étaient accumulées au fil des ans.\n\n## Pourquoi maintenant ? \n\nAu début de l'année, sous la direction de Sarah German, notre équipe d'ingénierie chargée de la documentation a mené à bien un projet crucial de refonte de la plateforme, migrant de Nanoc vers Hugo. Bien que largement invisible pour les utilisateurs, ce changement a permis d’améliorer considérablement les performances (avec des compilations locales 130 fois plus rapides et des compilations complètes 30 fois plus rapides ) et a fourni la base technique solide nécessaire à ces améliorations.\n\nCette refonte était une étape essentielle qui nous a permis de nous concentrer sur l’amélioration de l'expérience utilisateur. Examinons de plus près ces changements.\n\n### Mode sombre\n\nProbablement la plus grande nouveauté parmi ces améliorations : le mode sombre est maintenant disponible sur l'ensemble de la documentation. Il vous suffit de modifier le paramètre dans le coin supérieur droit, et le site se souviendra de votre préférence. Pour de nombreux utilisateurs, le mode sombre rend le contenu plus lisible et réduit la fatigue oculaire.\n\n![image du mode sombre](https://res.cloudinary.com/about-gitlab-com/image/upload/v1755617168/gz45eaygeb0nizf1kwyu.png)\n\n### Alignement de la marque avec le site web\n\nLe nouveau design crée une harmonie visuelle entre notre documentation et l'expérience GitLab au sens large. Nous avons intégré la palette de couleurs et les éléments de design modernes de GitLab tout en conservant l'aspect épuré et fonctionnel que les utilisateurs attendent d’une documentation technique.\n\n![image de la nouvelle page d'accueil](https://res.cloudinary.com/about-gitlab-com/image/upload/v1755617230/ialfadj3i3theizk08p5.png)\n\nLa page d'accueil mise à jour se concentre sur nos principaux domaines de documentation, y compris les tutoriels et les guides de démarrage qui aident les nouveaux utilisateurs à se familiariser avec GitLab.\n\n### Mécanisme de retours simplifié\n\nNous avons simplifié le processus des retours. Au lieu d'obliger les utilisateurs à quitter la documentation et à créer des tickets GitLab, ils peuvent désormais laisser des commentaires et rédiger des avis sans quitter le site. Faites défiler n'importe quelle page de la documentation vers le bas pour voir cette nouvelle fonctionnalité en action.\n\n![image de la zone de commentaires](https://res.cloudinary.com/about-gitlab-com/image/upload/v1755617289/rjocpkmqumacaw7thjqi.png)\n\n### Refonte de la navigation\n\nL'un de nos plus grands défis consistait à organiser plus de 2 300 pages de manière à ne pas submerger les utilisateurs. Notre ancienne navigation à gauche, bien que complète, était plutôt intimidante :\n\n![image de l'ancienne navigation](https://res.cloudinary.com/about-gitlab-com/image/upload/v1755617332/k75fwr3rhjxfjyxmc49d.png)\n\nDans cette refonte, la navigation principale a été déplacée vers le haut. Les sections de table des matières sont plus courtes, plus faciles à gérer et plus simples à parcourir :\n\n![image de la nouvelle navigation](https://res.cloudinary.com/about-gitlab-com/image/upload/v1755617366/wziabrijury9jl5j7ica.png)\n\nCette structure reflète mieux les relations entre les fonctionnalités et rend les sections individuelles plus digestes.\n\n### Mises à jour stylistiques et dette technique\n\nAu fil des ans, de petites incohérences de style s'étaient accumulées : remplissage irrégulier dans les listes, espacement supplémentaire autour des alertes et divers problèmes de typographie. Bien qu'elles puissent sembler mineures, ces incohérences créaient une expérience légèrement dérangeante pour les utilisateurs quotidiens.\n\nNous nous sommes tout particulièrement penchés sur nos onglets et blocs de code au cours du processus de refonte afin de mieux les définir.\n\nAuparavant, les onglets contenant du code ressemblaient à ceci :\n\n![image des anciens onglets avec bloc de code](https://res.cloudinary.com/about-gitlab-com/image/upload/v1755617460/jsa2gz3b2slqu0udrg28.png)\n\nMaintenant, avec quelques petits ajustements, ils ressemblent à ceci :\n\n![image des nouveaux onglets avec bloc de code](https://res.cloudinary.com/about-gitlab-com/image/upload/v1755617493/jpxiybvnadsex39lyawu.png)\n\nCes corrections « mineures » peuvent sembler insignifiantes individuellement, mais collectivement, elles créent une expérience beaucoup plus soignée et professionnelle.\n\n## Et maintenant ?\n\nCette refonte représente la façon dont nous itérons chez GitLab : nous apportons des améliorations significatives et construisons un avenir encore meilleur. Nous prévoyons de continuer à affiner la structure et à ajouter des fonctionnalités qui aideront les utilisateurs à trouver plus facilement ce dont ils ont besoin.\n\nLes retours des utilisateurs guideront nos prochaines itérations, et avec notre nouveau mécanisme de retour simplifié, nous sommes mieux placés que jamais pour répondre directement aux attentes des utilisateurs de notre documentation.\n\n## L'équipe\n\nCette transformation a été le fruit d’un véritable travail d’équipe. Félicitations à UX Papercuts et Julia Miocene pour avoir transformé ce qui n'était au départ qu'une simple demande en une vision complète. Merci aux ingénieurs de l’équipe Technical Writing : Sarah German, Pearl Latteier, et Hiru Fernando, qui ont donné vie à ces améliorations.\n\nLe nouveau design trouve le juste équilibre entre densité des informations et clarté visuelle, modernise notre site tout en conservant les normes d'utilisabilité et d'accessibilité et représente une étape importante en matière d'expérience utilisateur et de design visuel.\n",{"featured":6,"template":686,"slug":687},"BlogPost","docs-site-design-overhaul","content:fr-fr:blog:docs-site-design-overhaul.yml","Docs Site Design Overhaul","fr-fr/blog/docs-site-design-overhaul.yml","fr-fr/blog/docs-site-design-overhaul",[693,716,744,769,793,814,836,857,880,902,925,947,969,990,1010,1035],{"_path":694,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":695,"content":700,"config":710,"_id":712,"_type":16,"title":713,"_source":18,"_file":714,"_stem":715,"_extension":21},"/fr-fr/blog/inside-gitlabs-healthy-backlog-initiative",{"config":696,"title":697,"description":698,"ogImage":699},{"noIndex":6},"Amélioration de la gestion des tickets de la communauté","Nous avons amélioré la gestion des tickets pour prioriser le travail stratégique, optimiser la livraison et créer des boucles de rétroaction plus efficaces avec nos utilisateurs. ","https://res.cloudinary.com/about-gitlab-com/image/upload/f_auto,q_auto,c_lfill/v1749664458/Blog/Hero%20Images/Gartner_AI_Code_Assistants_Blog_Post_Cover_Image_1800x945.png",{"title":701,"description":702,"date":703,"body":704,"heroImage":699,"authors":705,"category":14,"tags":707},"Amélioration de la gestion des tickets créés par la communauté GitLab","Découvrez comment nous améliorons la gestion des tickets pour prioriser le travail stratégique, optimiser la livraison de logiciels et créer des boucles de rétroaction plus efficaces avec nos utilisateurs.","2025-07-30","Chez GitLab, nous sommes fiers de la relation solide et collaborative que nous entretenons avec notre communauté. Nous encourageons chacun à contribuer à GitLab. Au fil des années, ces contributions communautaires ont permis de renforcer notre plateforme. Mais au fur et à mesure de notre croissance, la participation de la communauté via les tickets GitLab a également augmenté, créant un backlog de tickets difficile à gérer.\n\nLes équipes chargées du produit et de l'ingénierie de GitLab ont récemment lancé [une initiative pour traiter ce backlog et affiner notre approche de la gestion des tickets](https://gitlab.com/groups/gitlab-org/-/epics/18639). \n\nLes tickets avec un engagement communautaire continu, une activité récente ou un alignement stratégique clair resteront ouverts. Nous fermerons les tickets qui ne sont plus pertinents, qui manquent d'intérêt ou qui ne correspondent plus à notre direction produit.\n\nCette approche ciblée conduira à une innovation accrue, à une meilleure définition des attentes et à des cycles de développement et de livraison plus rapides pour les fonctionnalités proposées par la communauté.\n\n## Présentation de l'initiative\n\nAu fil du temps, la communauté GitLab a soumis des dizaines de milliers de tickets, incluant des bogues, des demandes de fonctionnalités et des retours. Actuellement, [notre système principal de suivi des tickets](https://gitlab.com/gitlab-org/gitlab/-/issues) contient plus de 65 000 tickets. Certains ne sont plus applicables à la plateforme, tandis que d'autres restent toujours pertinents. \n\nAvec cette initiative, nos équipes chargées du produit et de l'ingénierie pourront réduire le backlog et établir un workflow afin de mettre en œuvre une approche plus ciblée de la gestion du backlog. Elles effectueront des évaluations hebdomadaires du backlog pour s'assurer que nous priorisons les tickets qui s'alignent avec notre stratégie produit et notre roadmap.\n\nRemarque : Si vous pensez qu’un ticket fermé s'aligne avec la stratégie produit et la roadmap de GitLab, ou si vous contribuez activement à cette demande, nous vous encourageons à commenter le ticket. Nous nous engageons à examiner ces tickets mis à jour dans le cadre de nos efforts d'évaluation réguliers.\n\n## Quels sont les avantages ?\n\nCette approche rationalisée apporte des améliorations directes et concrètes pour chaque utilisateur de GitLab :\n\n* **Un focus plus précis et une livraison plus rapide :** en recentrant notre backlog sur des fonctionnalités stratégiquement alignées, nous pouvons allouer nos ressources de développement plus efficacement. Cela signifie que vous pouvez vous attendre à des cycles de développement plus courts et à des améliorations plus significatives de votre expérience GitLab.\n* **Des attentes plus claires :** nous nous engageons à communiquer de manière transparente sur ce qui figure ou non dans notre roadmap, afin que vous puissiez prendre des décisions éclairées concernant vos workflows et vos contributions.\n* **Des boucles de rétroaction accélérées :** avec un backlog épuré, les nouveaux retours et demandes de fonctionnalités seront examinés et priorisés plus efficacement, réduisant le temps global de triage et garantissant que les tickets urgents reçoivent l'attention nécessaire. Cela crée une boucle de rétroaction plus réactive pour tous.\n\nCette initiative ne diminue pas l'importance des retours et des contributions de la communauté. Nous prenons cette mesure pour clarifier ce que les membres de l'équipe GitLab peuvent réellement s'engager à livrer, et pour garantir que tous les retours reçoivent la considération appropriée.\n\n## Perspectives d'avenir\n\nCette initiative reflète notre engagement à être des gestionnaires transparents et efficaces de la plateforme GitLab. En communiquant clairement nos priorités et en concentrant nos efforts sur ce que nous pouvons réellement livrer au cours de l'année à venir, nous sommes mieux positionnés pour répondre et dépasser vos attentes.\n\nVotre participation et vos retours continus contribuent à renforcer GitLab. Chaque commentaire, merge request, rapport de bogue et suggestion de fonctionnalité contribue à notre vision commune. Et nous continuons à vous récompenser pour cela, avec des initiatives comme notre programme mensuel Notable Contributor, des récompenses, et plus encore, via notre [portail dédié aux contributeurs](https://contributors.gitlab.com/).\n\nPour en savoir plus sur comment contribuer à GitLab, consultez notre [page Communauté](https://about.gitlab.com/community/). Pour partager vos retours sur cette initiative, veuillez ajouter vos commentaires sur [ce ticket](https://gitlab.com/gitlab-org/gitlab/-/issues/556865).",[706],"Stan Hu",[272,708,709],"product","news",{"featured":6,"template":686,"slug":711},"inside-gitlabs-healthy-backlog-initiative","content:fr-fr:blog:inside-gitlabs-healthy-backlog-initiative.yml","Inside Gitlabs Healthy Backlog Initiative","fr-fr/blog/inside-gitlabs-healthy-backlog-initiative.yml","fr-fr/blog/inside-gitlabs-healthy-backlog-initiative",{"_path":717,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":718,"content":726,"config":738,"_id":740,"_type":16,"title":741,"_source":18,"_file":742,"_stem":743,"_extension":21},"/fr-fr/blog/how-we-decreased-gitlab-repo-backup-times-from-48-hours-to-41-minutes",{"ogTitle":719,"schema":720,"ogImage":721,"ogDescription":722,"ogSiteName":723,"noIndex":6,"ogType":724,"ogUrl":725,"title":719,"canonicalUrls":725,"description":722},"Dépôts GitLab : forte diminution des temps de sauvegarde","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Dépôts GitLab : forte diminution des temps de sauvegarde\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Karthik Nayak\"},{\"@type\":\"Person\",\"name\":\"Manuel Kraft\"}],\n        \"datePublished\": \"2025-06-05\",\n      }","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097166/Blog/Hero%20Images/Blog/Hero%20Images/REFERENCE%20-%20display%20preview%20for%20blog%20images%20%282%29_2pKf8RsKzAaThmQfqHIaa7_1750097166565.png","L'optimisation d'une fonction Git vieille de 15 ans a permis d'augmenter la productivité, de renforcer les stratégies de sauvegarde et de réduire les risques.","https://about.gitlab.com","article","https://about.gitlab.com/blog/how-we-decreased-gitlab-repo-backup-times-from-48-hours-to-41-minutes",{"heroImage":721,"body":727,"authors":728,"updatedDate":731,"date":732,"title":733,"tags":734,"description":722,"category":14},"Les sauvegardes de dépôt sont un élément essentiel de toute stratégie de\nreprise après un sinistre important. Cependant, à mesure que les dépôts\ngrossissent, garantir des sauvegardes fiables devient de plus en plus\ndifficile. Notre propre [dépôt Rails](https://gitlab.com/gitlab-org/gitlab)\nmettait 48 heures à être sauvegardé, ce qui nous obligeait à faire un choix\nimpossible entre la fréquence des sauvegardes et les performances du\nsystème. Nous avons donc décidé de trouver une solution à ce problème pour\nnos clients et pour nos propres équipes internes.\n\n\nAprès investigation, nous avons pu déterminer la cause du problème, qui remontait à une fonction Git vieille de 15 ans dont la complexité algorithmique O(N²) freinait lourdement les opérations. Nous l'avons corrigée en repensant l'algorithme et **avons ainsi réduit les temps de sauvegarde de manière exponentielle**. \n\n\nRésultat : des coûts réduits, des risques diminués, et surtout, des stratégies de sauvegarde désormais adaptées à la croissance de votre code source.\n\n\nCe problème d'évolutivité de [Git](https://about.gitlab.com/fr-fr/blog/what-is-git/ \"Qu'est-ce que Git ?\") affectait tout utilisateur disposant de grands dépôts. Découvrez dans cet article comment nous l'avons identifié et résolu.\n\n\n## Sauvegarde à grande échelle : enjeux et solutions\n\n\nÀ mesure que les entreprises développent leurs dépôts et que les sauvegardes se complexifient, elles sont confrontées aux défis suivants :\n\n\n* **Sauvegardes trop longues** : pour les très grands dépôts, la sauvegarde peut prendre plusieurs heures, ce qui rend impossible la planification de sauvegardes régulières.\n\n* **Utilisation intensive des ressources** : ces processus de sauvegarde prolongés mobilisent d'importantes ressources serveur, au risque d'impacter d'autres opérations critiques.\n\n* **Fenêtres de sauvegarde** : il peut être difficile de trouver des créneaux de maintenance adaptés à des processus aussi longs, en particulier pour les équipes qui fonctionnent 24 h/24 et 7 j/7.\n\n* **Risque accru d'échec** : les longues sauvegardes sont plus exposées aux interruptions causées par des problèmes réseau, des redémarrages de serveur ou des erreurs système, et obligent souvent les équipes à recommencer tout le processus depuis le début.\n\n* **Conditions de concurrence** : la durée allongée d'une sauvegarde augmente le risque que le dépôt ait beaucoup changé pendant le processus et peut conduire à une sauvegarde invalide ou à des interruptions liées à des objets devenus indisponibles.\n\n\nCes défis peuvent conduire à faire des compromis sur la fréquence ou l'exhaustivité des sauvegardes, ce qui est inacceptable en matière de protection des données. L'allongement des fenêtres de sauvegarde peut contraindre certains clients à adopter des solutions de contournement, comme l'utilisation d'outils externes ou la réduction de la fréquence des sauvegardes, ce qui fragilise les stratégies de protection des données au sein des entreprises.\n\n\nDécouvrez maintenant comment nous avons identifié ce goulot d'étranglement de performance, trouvé une solution et déployé une mesure corrective capable de réduire drastiquement les temps de sauvegarde.\n\n\n## Le défi technique\n\n\nLa fonctionnalité de sauvegarde des dépôts de GitLab repose sur la commande [`git bundle create`](https://git-scm.com/docs/git-bundle/fr), qui génère un aperçu complet du dépôt avec tous les objets et références comme les branches et les tags. Ce paquet sert de point de restauration pour recréer le dépôt dans son état exact.\n\n\nCependant, l'implémentation de cette commande souffrait d'un problème d'évolutivité lié au nombre de références et entraînait un véritable goulot d'étranglement en termes de performance. À mesure que les dépôts accumulaient un nombre croissant de références, le temps de traitement des données augmentait de façon exponentielle. Dans nos plus grands dépôts, contenant des millions de références, les opérations de sauvegarde pouvaient dépasser les 48 heures.\n\n\n### Analyse des causes profondes\n\n\nPour identifier la cause profonde de ce ralentissement, nous avons analysé un flame graph de la commande pendant son exécution.\n\n\n![Flame graph montrant la commande pendant son exécution](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097176/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097176388.jpg)\n\n\nCe graphique illustre le parcours d'exécution d'une commande à travers sa trace de piles d'appels, où chaque barre correspond à une fonction dans le code, et sa largeur indique le temps que la commande a passé à s'exécuter dans cette fonction spécifique.\n\n\nLe flame graph de `git bundle create` exécuté sur un dépôt contenant 10 000 références révèle qu'environ 80 % du temps d'exécution est consommé par la fonction `object_array_remove_duplicates()`, introduite dans Git par le biais du [commit b2a6d1c686](https://gitlab.com/gitlab-org/git/-/commit/b2a6d1c686) (paquet : permettre à la même référence d'être spécifiée plusieurs fois, 17/01/2009).\n\n\nPour comprendre ce changement, il est important de savoir que la commande `git bundle create` permet de préciser les références à inclure dans le paquet et que, pour les paquets de dépôt complets, le flag `--all` compacte toutes les références.\n\n\nCe commit corrigeait un problème lié aux références dupliquées fournies via la ligne de commande, telles que `git bundle create main.bundle main main`, et créait un paquet sans gérer correctement la duplication de la référence « main ». Lors de la décompression, Git tentait d'écrire la même référence deux fois, ce qui provoquait une erreur. \n\n\nLe code ajouté pour éviter ces duplications utilise des boucles `for` imbriquées qui parcourent toutes les références afin de détecter les doublons. Cet algorithme de complexité O(N²) est un goulot d'étranglement majeur en termes de performance dans les dépôts car il contient un grand nombre de références et prolonge considérablement le temps de traitement des données.\n\n\n### La solution : d'O(N²) à un mappage efficace\n\n\nPour résoudre ce problème, nous avons proposé une correction en amont dans Git pour remplacer les boucles imbriquées par une structure de type map. Chaque référence y est ajoutée une seule fois, ce qui élimine automatiquement les doublons et optimise le traitement.\n\n\nCe changement améliore considérablement les performances de la commande `git bundle create` et garantit une bien meilleure évolutivité dans les dépôts avec un grand nombre de références. Des tests de benchmark effectués sur un dépôt contenant 10 000 références montrent une amélioration des performances par un facteur de 6.\n\n\n```shell\n\nBenchmark 1: bundle (refcount = 100000, revision = master)\n  Time (mean ± σ): \t14.653 s ±  0.203 s\t[User: 13.940 s, System: 0.762 s]\n  Range (min … max):   14.237 s … 14.920 s\t10 runs\n\nBenchmark 2: bundle (refcount = 100000, revision = HEAD)\n  Time (mean ± σ):  \t2.394 s ±  0.023 s\t[User: 1.684 s, System: 0.798 s]\n  Range (min … max):\t2.364 s …  2.425 s\t10 runs\n\nSummary\n  bundle (refcount = 100000, revision = HEAD) ran\n  6.12 ± 0.10 times faster than bundle (refcount = 100000, revision = master)\n```\n\n\nLe correctif a été accepté et [fusionné](https://gitlab.com/gitlab-org/git/-/commit/bb74c0abbc31da35be52999569ea481ebd149d1d) dans Git en amont. Chez GitLab, nous l'avons rétroporté afin que nos clients puissent en bénéficier immédiatement sans attendre la prochaine version officielle de Git.\n\n\n## Résultat : des temps de sauvegarde radicalement réduits\n\n\nLes gains de performance qui découlent de cette amélioration sont considérables :\n\n\n* **De 48 heures à 41 minutes** : la sauvegarde de notre plus grand dépôt (gitlab-org/gitlab) ne prend désormais plus que 1,4 % du temps initial.\n\n* **Performances constantes** : l'amélioration est stable et s'adapte efficacement, quelle que soit la taille du dépôt.\n\n* **Efficacité des ressources** : la charge du serveur lors des opérations de sauvegarde a été fortement réduite.\n\n* **Applicabilité étendue** : si le processus de sauvegarde est celui qui bénéficie le plus de cette amélioration, toutes les opérations basées sur des paquets avec un grand nombre de références en profitent également.\n\n\n## Avantages pour nos clients GitLab\n\n\nPour les clients GitLab, cette amélioration apporte des bénéfices immédiats et concrets en matière de sauvegarde de leurs dépôts et de leur planification de reprise après sinistre :\n\n\n* **Transformation des stratégies de sauvegarde**   \n\n  * Les équipes peuvent désormais planifier des sauvegardes complètes chaque nuit, sans impacter les workflows de développement ni nécessiter de longues fenêtres de maintenance.   \n  * Les sauvegardes s'exécutent désormais en arrière-plan, de manière fluide, pendant les créneaux nocturnes, sans processus longs ni dédiés.  \n* **Continuité des activités améliorée**  \n\n  * Avec des temps de sauvegarde réduits de plusieurs jours à quelques minutes, les objectifs de point de récupération (RPO) sont considérablement réduits, tout comme le risque métier : en cas de sinistre, ce sont potentiellement seulement quelques heures de travail qui sont perdues, au lieu de plusieurs jours.\n* **Réduction de la charge opérationnelle**   \n\n  * La consommation de ressources serveur diminue, tout comme la durée des fenêtres de maintenance.  \n  * Des sauvegardes plus rapides réduisent également les coûts de calcul, en particulier dans les environnements cloud où chaque minute de traitement des données se traduit directement en factures plus élevées.\n* **Pérennisation de l'infrastructure**   \n\n  * La croissance des dépôts ne contraint plus les entreprises à faire des choix difficiles entre la fréquence des sauvegardes et les performances du système.   \n  * À mesure que votre code source se développe, votre stratégie de sauvegarde peut désormais évoluer.\n\nLes entreprises peuvent à présent mettre en œuvre des stratégies de sauvegarde plus robustes sans compromettre les performances ou l'exhaustivité. Ce qui relevait autrefois d'un compromis difficile est devenu une pratique opérationnelle simple.\n\n\nÀ partir de la version [GitLab 18.0](https://about.gitlab.com/releases/2025/05/15/gitlab-18-0-released/), tous les clients GitLab, quelle que soit leur version de licence, profitent désormais pleinement de ces améliorations pour leur stratégie de sauvegarde et l'exécution de leurs [sauvegardes](https://docs.gitlab.com/administration/backup_restore/backup_gitlab/), sans aucune autre modification de la configuration.\n\n\n## Et après ?\n\n\nCette avancée s'inscrit dans notre engagement continu à proposer une infrastructure Git évolutive, adaptée aux exigences des entreprises. Bien que réduire le temps de sauvegarde de 48 heures à 41 minutes représente une étape majeure, nous poursuivons nos efforts pour identifier et éliminer d'autres goulots d'étranglement dans l'ensemble de notre pile.\n\n\nNous sommes particulièrement fiers que cette amélioration ait été intégrée en amont dans le projet Git afin de profiter non seulement aux utilisateurs de GitLab, mais aussi à l'ensemble de la communauté Git. Cette approche collaborative du développement garantit que les améliorations sont rigoureusement revues, largement testées et accessibles à tous.\n\n\n> Des travaux d'infrastructure en profondeur comme celui-ci illustrent notre approche de la performance chez GitLab. Consultez le [replay de notre événement virtuel de lancement de GitLab 18](https://about.gitlab.com/fr-fr/eighteen/) et découvrez les autres améliorations fondamentales que nous proposons.\n",[729,730],"Karthik Nayak","Manuel Kraft","2025-07-09","2025-06-05","Dépôts GitLab : diminution du temps de sauvegarde de 48 h à 41 min ",[735,736,737],"git","open source","performance",{"slug":739,"featured":93,"template":686},"how-we-decreased-gitlab-repo-backup-times-from-48-hours-to-41-minutes","content:fr-fr:blog:how-we-decreased-gitlab-repo-backup-times-from-48-hours-to-41-minutes.yml","How We Decreased Gitlab Repo Backup Times From 48 Hours To 41 Minutes","fr-fr/blog/how-we-decreased-gitlab-repo-backup-times-from-48-hours-to-41-minutes.yml","fr-fr/blog/how-we-decreased-gitlab-repo-backup-times-from-48-hours-to-41-minutes",{"_path":745,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":746,"content":752,"config":763,"_id":765,"_type":16,"title":766,"_source":18,"_file":767,"_stem":768,"_extension":21},"/fr-fr/blog/automating-container-image-migration-from-amazon-ecr-to-gitlab",{"title":747,"description":748,"ogTitle":747,"ogDescription":748,"noIndex":6,"ogImage":749,"ogUrl":750,"ogSiteName":723,"ogType":724,"canonicalUrls":750,"schema":751},"Comment automatiser la migration des images de conteneurs d'Amazon ECR vers GitLab","Suivez ce guide étape par étape pour automatiser le processus de migration de vos images de conteneurs d’Amazon ECR vers GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663129/Blog/Hero%20Images/blog-image-template-1800x945__28_.png","https://about.gitlab.com/blog/automating-container-image-migration-from-amazon-ecr-to-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Comment automatiser la migration des images de conteneurs d'Amazon ECR vers GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tim Rizzi\"}],\n        \"datePublished\": \"2025-02-13\",\n      }\n                  ",{"title":747,"description":748,"authors":753,"heroImage":749,"date":755,"body":756,"category":14,"tags":757,"updatedDate":762},[754],"Tim Rizzi","2025-02-13","« Nous devons migrer des centaines d'images de conteneurs d'Amazon Elastic Container Registry (ECR) vers GitLab. Pouvez-vous nous aider ? » Cette question revenait sans cesse lors de nos échanges avec des ingénieurs de plateforme. En pleine modernisation de leur chaîne d'outils DevSecOps avec GitLab, ils se retrouvaient bloqués au moment de déplacer leurs images de conteneurs. D’un point de vue technique, chaque transfert est simple. Mais, l'opération était longue et fastidieuse en raison du volume considérable d'images.\n\nUn ingénieur de plateforme a parfaitement résumé la situation : « Je connais parfaitement le processus : effectuer un pull, retagger, effectuer un push. Le problème, c'est que je gère 200 microservices, chacun contenant plusieurs tags. Je ne peux pas passer plusieurs semaines sur cette migration alors que j'ai des tâches critiques à effectuer au niveau de l'infrastructure. »\n\n## Le défi\n\nCette conversation nous a fait réfléchir et a donné naissance à une idée. Et si nous pouvions automatiser l'ensemble du processus ? Lorsqu'une équipe de plateforme DevOps transfère ses [pipelines CI/CD](https://about.gitlab.com/fr-fr/topics/ci-cd/cicd-pipeline/ \"Qu'est-ce qu'un pipeline CI/CD ?\") vers GitLab, la migration des images de conteneurs ne devrait pas poser de difficulté particulière. Le processus manuel est rudimentaire, mais répétitif : il s'agit d'effectuer un pull de chaque image, de la retagger et d'effectuer un push pour la migrer vers le registre de conteneurs de GitLab. Réaliser cette même opération pour des dizaines de dépôts et plusieurs tags par image requiert des jours ou des semaines de travail chronophage.\n\n## La solution\n\nNous avons donc entrepris de créer un pipeline GitLab qui effectuerait automatiquement cette lourde tâche. L'objectif était clair : fournir aux ingénieurs de plateforme un outil qu'ils pourraient configurer en quelques minutes et qui, en une seule nuit, parviendrait à migrer toutes leurs images.\n\n### Configuration des accès\n\nCommençons par l'essentiel : les aspects liés à la sécurité. Nous voulions nous assurer que les équipes puissent exécuter cette migration avec un minimum d'autorisations sur AWS. Voici la politique de gestion des identités et des accès (IAM) en lecture seule dont vous avez besoin :\n\n```json\n{\n    \"Version\": \"2012-10-17\",\n    \"Statement\": [\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"ecr:GetAuthorizationToken\",\n                \"ecr:BatchCheckLayerAvailability\",\n                \"ecr:GetDownloadUrlForLayer\",\n                \"ecr:DescribeRepositories\",\n                \"ecr:ListImages\",\n                \"ecr:DescribeImages\",\n                \"ecr:BatchGetImage\"\n            ],\n            \"Resource\": \"*\"\n        }\n    ]\n}\n```\n\n### Configuration de GitLab\n\nUne fois la sécurité en place, l'étape suivante consiste à configurer GitLab. Nous avons volontairement réduit cela au strict minimum : il vous suffit de configurer les variables suivantes dans les paramètres CI/CD de votre projet :\n\n```\nAWS_ACCOUNT_ID: Your AWS account number\nAWS_DEFAULT_REGION: Your ECR region\nAWS_ACCESS_KEY_ID: [Masked]\nAWS_SECRET_ACCESS_KEY: [Masked]\nBULK_MIGRATE: true\n```\n\n### Le pipeline de migration \n\nPassons maintenant à la partie la plus intéressante. Nous avons créé le pipeline en utilisant Docker-in-Docker pour gérer toutes les opérations liées aux images de manière fiable :\n\n```yaml\nimage: docker:20.10\nservices:\n  - docker:20.10-dind\n\nbefore_script:\n  - apk add --no-cache aws-cli jq\n  - aws sts get-caller-identity\n  - aws ecr get-login-password | docker login --username AWS --password-stdin\n  - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY}\n```\n\nLe pipeline fonctionne en trois phases, chacune s'appuyant sur la précédente :\n\n1. Identification\n\nDans un premier temps, il détecte l'ensemble de vos dépôts :\n\n```bash\nREPOS=$(aws ecr describe-repositories --query 'repositories[*].repositoryName' --output text)\n```\n\n2. Énumération des tags\n\nEnsuite, pour chaque dépôt, il récupère l'ensemble des tags :\n\n```bash\nTAGS=$(aws ecr describe-images --repository-name $repo --query 'imageDetails[*].imageTags[]' --output text)\n```\n\n3. Transfert\n\nEnfin, il gère la migration proprement dite :\n\n```bash\ndocker pull ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${repo}:${tag}\ndocker tag ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${repo}:${tag} ${CI_REGISTRY_IMAGE}/${repo}:${tag}\ndocker push ${CI_REGISTRY_IMAGE}/${repo}:${tag}\n```\n\n## Résultats\n\nVoici ce que cette solution offre comme avantages aux ingénieurs de plateforme qui ne veulent pas passer plusieurs semaines sur la migration :\n\n- Identification et migration automatisées de l'ensemble des dépôts et tags\n- Dénomination cohérente des images entre ECR et GitLab\n- Gestion des échecs de transferts\n- Journalisation claire pour suivre la progression\n\nAu lieu d'écrire des scripts et de surveiller la migration, l'ingénieur de plateforme peut se concentrer sur des tâches à plus grande valeur ajoutée.\n\n## Utilisation\n\nLa première étape est très simple :\n\n1. Copiez le fichier `.gitlab-ci.yml` dans votre dépôt.\n2. Configurez les variables AWS et GitLab.\n3. Définissez `BULK_MIGRATE` sur « true » pour déclencher la migration.\n\n## Bonnes pratiques\n\nEn accompagnant plusieurs équipes dans leur migration, nous avons tiré quelques enseignements pratiques :\n\n- Exécutez la migration en dehors des heures de pointe pour réduire au maximum l'impact sur votre équipe.\n- Consultez les logs de pipeline qui vous indiqueront si un élément nécessite votre attention.\n- Ne désactivez pas votre registre ECR avant d'avoir vérifié que toutes les images ont bien été transférées.\n- Pour les migrations à grande échelle, envisagez d'ajouter une limite de débit pour éviter de saturer votre réseau.\n\nNous mettons ce pipeline à disposition en open source dans notre dépôt GitLab public, car nous sommes convaincus que les ingénieurs de plateforme devraient passer leur temps à créer de la valeur, plutôt qu'à copier des images de conteneurs. N'hésitez pas à l'adapter à vos besoins ou à poser vos questions sur sa mise en œuvre. Consultez notre documentation pour en savoir plus sur les [catalogues CI/CD](https://gitlab.com/explore/catalog/components/package \"Catalogues CI/CD\"). ",[111,758,759,760,708,761],"AWS","tutorial","DevSecOps platform","solutions architecture","2025-04-07",{"slug":764,"featured":93,"template":686},"automating-container-image-migration-from-amazon-ecr-to-gitlab","content:fr-fr:blog:automating-container-image-migration-from-amazon-ecr-to-gitlab.yml","Automating Container Image Migration From Amazon Ecr To Gitlab","fr-fr/blog/automating-container-image-migration-from-amazon-ecr-to-gitlab.yml","fr-fr/blog/automating-container-image-migration-from-amazon-ecr-to-gitlab",{"_path":770,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":771,"content":777,"config":787,"_id":789,"_type":16,"title":790,"_source":18,"_file":791,"_stem":792,"_extension":21},"/fr-fr/blog/using-child-pipelines-to-continuously-deploy-to-five-environments",{"ogTitle":772,"schema":773,"ogImage":774,"ogDescription":775,"ogSiteName":723,"noIndex":6,"ogType":724,"ogUrl":776,"title":772,"canonicalUrls":776,"description":775},"Déployer en continu dans de multiples environnements","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Déployer en continu dans de multiples environnements avec les pipelines enfants\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Olivier Dupré\"}],\n        \"datePublished\": \"2024-09-26\",\n      }","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097012/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_397632156_3Ldy1urjMStQCl4qnOBvE0_1750097011626.jpg","Découvrez comment créer un workflow rationalisé dans GitLab pour gérer le déploiement continu dans de multiples environnements.","https://about.gitlab.com/blog/using-child-pipelines-to-continuously-deploy-to-five-environments",{"heroImage":774,"body":778,"authors":779,"updatedDate":781,"date":782,"title":783,"tags":784,"description":775,"category":14},"Les équipes DevSecOps doivent parfois coordonner le déploiement continu dans\ndes environnements différents, tout en préservant leurs workflows. La\n[plateforme DevSecOps de GitLab](https://about.gitlab.com/fr-fr) répond à ce\nbesoin, de manière simple et efficace, y compris avec des environnements\nsandbox temporaires créés à la demande. Découvrez dans cet article un\nexemple de mise en œuvre de ce processus en déployant une architecture avec\nTerraform sur plusieurs environnements cibles.\n\n\nCette stratégie s'adapte facilement qu'il s'agisse d'un projet d'Infrastructure as Code (IaC) utilisant une autre technologie comme [Pulumi](https://www.pulumi.com/) ou [Ansible](https://www.ansible.com/), d'un projet de code source ou d'un projet de dépôt monolithique combinant plusieurs langages.\n\n\nÀ la fin de ce tutoriel, le pipeline que vous aurez créé permettra de déployer :\n\n\n* Un environnement temporaire de **développement** pour chaque branche de fonctionnalité.\n\n* Un environnement d'**intégration**, qu'il est facile de supprimer et redéployer à partir de la branche principale.\n\n* Un environnement d'**assurance qualité (QA)**, également déployé à partir de la branche principale, pour exécuter les étapes de QA.\n\n* Un environnement de **préproduction** pour chaque tag, dernière étape avant la phase de production.\n\n* Un environnement de **production** qui dans cet exemple sera déployé manuellement, mais qui peut également être déployé en continu.\n\n\n> Légende des schémas figurant dans cet article :\n\n>\n\n> * Les encarts aux angles arrondis représentent les branches de GitLab.\n\n> * Les encarts rectangulaires représentent les environnements.\n\n> * Le texte sur les flèches représente les actions requises pour passer d'un encart à l'autre.\n\n> * Les encarts carrés représentent une prise de décision.\n\n\n\u003Cpre class=\"mermaid\">\n\nflowchart LR\n    A(main) -->|new feature| B(feature_X)\n\n    B -->|auto deploy| C[review/feature_X]\n    B -->|merge| D(main)\n    C -->|destroy| D\n\n    D -->|auto deploy| E[integration]\n    E -->|manual| F[qa]\n\n    D -->|tag| G(X.Y.Z)\n    F -->|validate| G\n\n    G -->|auto deploy| H[staging]\n    H -->|manual| I{plan}\n    I -->|manual| J[production]\n\u003C/pre>\n\n\nNous allons vous expliquer les [raisons](#why) des [actions](#what) présentées dans le flowchart ci-dessus, ainsi que [les étapes à suivre](#how) pour chacune d'elles. Ce tutoriel sera ainsi plus facile à suivre et vous pourrez le reproduire sans difficulté.\n\n\n## Raisons\n\n\n* [L'intégration continue (CI)](https://about.gitlab.com/fr-fr/topics/ci-cd/) constitue quasiment une norme établie. La plupart des entreprises implémentent des pipelines CI ou cherchent à standardiser leurs pratiques.\n\n* La [livraison continue (CD)](https://about.gitlab.com/fr-fr/topics/ci-cd/), qui consiste à effectuer la publication des artefacts vers un dépôt ou un registre à la fin du pipeline CI, est également courante.\n\n* L'étape suivante, le [déploiement continu](https://about.gitlab.com/fr-fr/topics/ci-cd/#what-is-continuous-deployment \"Qu'est-ce que le déploiement continu ? \"), qui automatise le déploiement de ces artefacts, est en revanche moins répandu. Il est essentiellement implémenté dans le domaine des applications. Le déploiement continu d'une infrastructure est plus compliqué et implique la gestion de plusieurs environnements. Tester, sécuriser et vérifier le code de l'infrastructure constitue un défi supplémentaire et c'est un domaine où le processus [DevOps](https://about.gitlab.com/fr-fr/topics/devops/ \"Que signifie DevOps ?\") n'a pas encore atteint sa pleine maturité. L'intégration de la sécurité en amont, qui nécessite l'implication des équipes de sécurité, représente également une difficulté. Et il est très important de prendre en compte les problèmes de sécurité dès les premières étapes du développement, afin de passer d'une approche DevOps à un processus **[DevSecOps](https://about.gitlab.com/fr-fr/topics/devsecops/ \"Qu'est-ce que DevSecOps ?\")**.\n\n\nCe tutoriel vous invite à tester une méthode simple et efficace pour adopter une approche DevSecOps pour votre infrastructure. Nous prendrons l'exemple du déploiement de ressources dans cinq environnements, du développement à la production.\n\n\n**Remarque :** même si je préconise l'adoption d'une [approche FinOps](https://about.gitlab.com/fr-fr/the-source/platform/finops-balancing-financial-responsibility-and-innovation/ \"Qu'est-ce que l'approche FinOps ? \") et la réduction du nombre d'environnements, il existe parfois d'excellentes raisons de ne pas se limiter aux simples étapes de développement, préproduction et production. N'hésitez pas à adapter les exemples en fonction de vos besoins.\n\n\n## Actions\n\n\nL’avènement du cloud a boosté l'utilisation de l'IaC. Ansible et Terraform ont ouvert la voie, suivis par OpenTofu, Pulumi, AWS CDK, Google Deploy Manager et bien d'autres.\n\n\nUne Infrastructure as Code est la solution parfaite pour déployer une infrastructure de manière sécurisée. Vous pouvez la tester, la déployer et la réappliquer autant de fois que nécessaire pour atteindre votre objectif.\n\n\nMalheureusement, les entreprises maintiennent souvent plusieurs branches, voire de multiples dépôts, pour chacun de leurs environnements cibles, ce qui crée des problèmes. Elles ne respectent plus un processus rigoureux. Elles ne s'assurent plus que chaque modification du code en production a été soigneusement testée dans les environnements précédents. Par conséquent, des décalages apparaissent peu à peu d'un environnement à l'autre.\n\n\nJ'ai réalisé que ce tutoriel était nécessaire lors d'une conférence à laquelle j'ai assisté : tous les participants ont déclaré que leur workflow n'imposait des tests rigoureux de l'infrastructure qu'avant le déploiement en production. Et ils ont tous convenu qu'ils appliquaient parfois des correctifs directement en production. Bien sûr, cette démarche permet d'aller vite, mais est-elle sûre ? Comment reporter les correctifs sur les environnements précédents ? Comment vérifier qu'il n'y a pas d'effets de bord ? Comment limiter les risques auxquels votre entreprise est exposée lorsque vous déployez votre code trop rapidement en production ?\n\n\nLa question essentielle est de savoir *pourquoi* les [équipes DevOps](https://about.gitlab.com/fr-fr/topics/devops/build-a-devops-team/ \"Créer une structure d'équipe DevOps idéale\") déploient directement en production. Le pipeline devrait-il être plus efficace ou plus rapide ? N'est-il pas possible d'automatiser le processus ? Ou, pire encore, n'y a-t-il *aucun moyen de tester le code en dehors de l'environnement de production* ?\n\n\nDans la section suivante, vous apprendrez à automatiser votre infrastructure et à garantir que votre équipe DevOps mène des tests efficaces avant d'effectuer un push vers un environnement qui affectera le reste du processus. Vous verrez comment sécuriser votre code et contrôler son déploiement de bout en bout.\n\n\n## Les étapes à suivre\n\n\nComme mentionné précédemment, de nombreux langages permettent actuellement de gérer l'IaC et nous ne pouvons pas *tous* les aborder ici. Je vais m'appuyer sur un code Terraform version 1.4. Ne prêtez pas attention au langage utilisé pour gérer l'IaC, mais plutôt au processus transposable à votre écosystème.\n\n\n### Le code Terraform\n\n\nCommençons par un code Terraform de base.\n\n\nNous allons déployer sur AWS, un cloud privé virtuel (VPC), qui est un réseau virtuel. Dans ce VPC, nous déploierons un sous-réseau public et un sous-réseau privé. Comme leur nom l'indique, il s'agit de sous-réseaux du VPC principal. Enfin, nous ajouterons une instance Elastic Cloud Compute (EC2) (une machine virtuelle) dans le sous-réseau public.\n\n\nNous allons ainsi déployer quatre ressources de manière relativement simple. L'idée est de se concentrer sur le pipeline, et non sur le code.\n\n\nVoici la cible que nous voulons atteindre pour votre dépôt.\n\n\n![cible du dépôt](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097033/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750097033415.png)\n\n\nDécomposons le processus.\n\n\nTout d'abord, nous déclarons toutes les ressources dans un fichier `terraform/main.tf` :\n\n\n```terraform\n\nprovider \"aws\" {\n  region = var.aws_default_region\n}\n\n\nresource \"aws_vpc\" \"main\" {\n  cidr_block = var.aws_vpc_cidr\n\n  tags = {\n    Name     = var.aws_resources_name\n  }\n}\n\n\nresource \"aws_subnet\" \"public_subnet\" {\n  vpc_id     = aws_vpc.main.id\n  cidr_block = var.aws_public_subnet_cidr\n\n  tags = {\n    Name = \"Public Subnet\"\n  }\n}\n\nresource \"aws_subnet\" \"private_subnet\" {\n  vpc_id     = aws_vpc.main.id\n  cidr_block = var.aws_private_subnet_cidr\n\n  tags = {\n    Name = \"Private Subnet\"\n  }\n}\n\n\nresource \"aws_instance\" \"sandbox\" {\n  ami           = var.aws_ami_id\n  instance_type = var.aws_instance_type\n\n  subnet_id = aws_subnet.public_subnet.id\n\n  tags = {\n    Name     = var.aws_resources_name\n  }\n}\n\n```\n\n\nComme vous pouvez le constater, ce code nécessite plusieurs variables. Nous les déclarons dans un fichier `terraform/variables.tf` :\n\n\n```terraform\n\nvariable \"aws_ami_id\" {\n  description = \"The AMI ID of the image being deployed.\"\n  type        = string\n}\n\n\nvariable \"aws_instance_type\" {\n  description = \"The instance type of the VM being deployed.\"\n  type        = string\n  default     = \"t2.micro\"\n}\n\n\nvariable \"aws_vpc_cidr\" {\n  description = \"The CIDR of the VPC.\"\n  type        = string\n  default     = \"10.0.0.0/16\"\n}\n\n\nvariable \"aws_public_subnet_cidr\" {\n  description = \"The CIDR of the public subnet.\"\n  type        = string\n  default     = \"10.0.1.0/24\"\n}\n\n\nvariable \"aws_private_subnet_cidr\" {\n  description = \"The CIDR of the private subnet.\"\n  type        = string\n  default     = \"10.0.2.0/24\"\n}\n\n\nvariable \"aws_default_region\" {\n  description = \"Default region where resources are deployed.\"\n  type        = string\n  default     = \"eu-west-3\"\n}\n\n\nvariable \"aws_resources_name\" {\n  description = \"Default name for the resources.\"\n  type        = string\n  default     = \"demo\"\n}\n\n```\n\n\nÀ ce stade, nous avons presque terminé la partie IaC. Il nous manque simplement une méthode pour partager les états Terraform. Si vous l'ignorez, Terraform fonctionne schématiquement comme suit :\n\n\n* La commande `plan` vérifie les différences entre l'infrastructure actuelle et celle définie dans le code. Elle génère ensuite un rapport des différences.\n\n* La commande `apply` exécute les modifications en fonction du rapport `plan` et met à jour l'état.\n\n\nLors du premier passage, l'état est vide. Il comporte ensuite les détails (ID, etc.) des ressources appliquées par Terraform.\n\n\nLe problème est le suivant : où cet état est-il stocké ? Comment le partager pour permettre à plusieurs développeurs et développeuses de collaborer sur le code ?\n\n\nLa solution est assez simple : stockez et partagez l'état dans GitLab via un [backend HTTP Terraform](https://docs.gitlab.com/ee/user/infrastructure/iac/terraform_state.html).\n\n\nLorsque vous utilisez ce backend, la première étape consiste à créer le fichier `terraform/backend.tf` le plus simple qui soit. La deuxième étape est prise en charge dans le pipeline.\n\n\n```terraform\n\nterraform {\n  backend \"http\" {\n  }\n}\n\n```\n\n\nEt voilà ! Nous disposons maintenant d'un code Terraform minimaliste pour déployer ces quatre ressources. Nous renseignerons les valeurs des variables lors de l'exécution à une étape ultérieure.\n\n\n### Le workflow\n\n\nMettons en œuvre le workflow suivant :\n\n\n\u003Cpre class=\"mermaid\">\n\nflowchart LR\n    A(main) -->|new feature| B(feature_X)\n\n    B -->|auto deploy| C[review/feature_X]\n    B -->|merge| D(main)\n    C -->|destroy| D\n\n    D -->|auto deploy| E[integration]\n    E -->|manual| F[qa]\n\n    D -->|tag| G(X.Y.Z)\n    F -->|validate| G\n\n    G -->|auto deploy| H[staging]\n    H -->|manual| I{plan}\n    I -->|manual| J[production]\n\u003C/pre>\n\n\n1. Créez une branche de **fonctionnalité**. Elle exécute tous les scanners en continu sur le code pour s'assurer qu'il est toujours conforme et sécurisé. Ce code est déployé en continu dans un environnement temporaire `review/feature_branch` portant le nom de la branche actuelle. Il s'agit d'un environnement sûr où les équipes de développement et d'opérations peuvent tester leur code sans impact sur le reste du Système d’Information (SI). Le processus, comme les revues de code et l'exécution de scanners, est imposé à cette étape pour assurer que la qualité et la sécurité du code sont suffisantes et ne mettent pas votre SI en danger. L'infrastructure déployée par cette branche est automatiquement détruite lorsque la branche est fermée. Vous pouvez ainsi contrôler votre budget.\n\n2. Une fois approuvée, la branche de fonctionnalité est **fusionnée** dans la branche principale. Il s'agit d'une [branche protégée](https://docs.gitlab.com/ee/user/project/protected_branches.html) où aucun push ne peut être effectué directement. Elle est nécessaire pour veiller à ce que chaque demande de modification de l'environnement de production soit minutieusement testée. Cette branche est également déployée en continu. La cible ici est l'environnement `integration`. La suppression de cet environnement n'est pas automatisée pour des questions de stabilité, mais elle peut être déclenchée manuellement.\n\n\n\u003Cpre class=\"mermaid\">\n\nflowchart LR\n    D(main) -->|auto deploy| E[integration]\n\u003C/pre>\n\n\n3. Une approbation manuelle est ensuite nécessaire pour déclencher le déploiement suivant. La branche principale sera déployée dans l'environnement `qa`. J'ai défini une règle ici pour empêcher la suppression depuis le pipeline. Cet environnement devrait être assez stable (après tout, c'est déjà le troisième) et je souhaite éviter une suppression accidentelle. N'hésitez pas à adapter les règles à vos processus.\n\n\n\u003Cpre class=\"mermaid\">\n\nflowchart LR\n    D(main)-->|auto deploy| E[integration]\n    E -->|manual| F[qa]\n\u003C/pre>\n\n\n4. Pour continuer, nous devons **ajouter un tag** au code. Nous utilisons les [tags protégés](https://docs.gitlab.com/ee/user/project/protected_tags.html) pour que seul un ensemble spécifique d'utilisateurs ait l'autorisation de déployer dans ces deux derniers environnements. Ce tag va immédiatement déclencher un déploiement dans l'environnement `staging`.\n\n\n\u003Cpre class=\"mermaid\">\n\nflowchart LR\n    D(main) -->|tag| G(X.Y.Z)\n    F[qa] -->|validate| G\n\n    G -->|auto deploy| H[staging]\n\u003C/pre>\n\n\n5. Nous arrivons enfin à l'environnement `production`. Il est souvent difficile de déployer l'infrastructure progressivement (10 %, 25 %, etc.). Nous la déployons donc dans son intégralité. Nous contrôlons toutefois ce déploiement à l'aide d'un déclencheur manuel intégré dans cette dernière étape. Afin de garder un contrôle maximal sur cet environnement hautement critique, nous le contrôlons en tant qu'[environnement protégé](https://docs.gitlab.com/ee/ci/environments/protected_environments.html).\n\n\n\u003Cpre class=\"mermaid\">\n\nflowchart LR\n    H[staging] -->|manual| I{plan}\n    I -->|manual| J[production]\n\u003C/pre>\n\n\n### Le pipeline\n\n\nPour mettre en œuvre le [workflow](#the-workflow) ci-dessus, nous allons maintenant implémenter un pipeline comportant deux [pipelines enfants](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html).\n\n\n#### Le pipeline principal\n\n\nCommençons par le pipeline principal. Il est déclenché automatiquement par un **push effectué vers une branche de fonctionnalité**, une **fusion vers la branche par défaut** ou un **tag**. *Il* effectue un vrai **déploiement continu** dans les environnements suivants : `dev`, `integration` et `staging`. Il est déclaré dans le fichier `.gitlab-ci.yml` à la racine de votre projet.\n\n\n![la cible du dépôt](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097033/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097033417.png)\n\n\n```yml\n\nstages:\n  - test\n  - environments\n\n.environment:\n  stage: environments\n  variables:\n    TF_ROOT: terraform\n    TF_CLI_ARGS_plan: \"-var-file=../vars/$variables_file.tfvars\"\n  trigger:\n    include: .gitlab-ci/.first-layer.gitlab-ci.yml\n    strategy: depend            # Wait for the triggered pipeline to successfully complete\n    forward:\n      yaml_variables: true      # Forward variables defined in the trigger job\n      pipeline_variables: true  # Forward manual pipeline variables and scheduled pipeline variables\n\nreview:\n  extends: .environment\n  variables:\n    environment: review/$CI_COMMIT_REF_SLUG\n    TF_STATE_NAME: $CI_COMMIT_REF_SLUG\n    variables_file: review\n    TF_VAR_aws_resources_name: $CI_COMMIT_REF_SLUG  # Used in the tag Name of the resources deployed, to easily differenciate them\n  rules:\n    - if: $CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH\n\nintegration:\n  extends: .environment\n  variables:\n    environment: integration\n    TF_STATE_NAME: $environment\n    variables_file: $environment\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n\nstaging:\n  extends: .environment\n  variables:\n    environment: staging\n    TF_STATE_NAME: $environment\n    variables_file: $environment\n  rules:\n    - if: $CI_COMMIT_TAG\n\n#### TWEAK\n\n# This tweak is needed to display vulnerability results in the merge widgets.\n\n# As soon as this issue https://gitlab.com/gitlab-org/gitlab/-/issues/439700 is resolved, the `include` instruction below can be removed.\n\n# Until then, the SAST IaC scanners will run in the downstream pipelines, but their results will not be available directly in the merge request widget, making it harder to track them.\n\n# Note: This workaround is perfectly safe and will not slow down your pipeline.\n\ninclude:\n  - template: Security/SAST-IaC.gitlab-ci.yml\n#### END TWEAK\n\n```\n\n\nCe pipeline n'exécute que deux étapes : `test` et  `environments`. La première est nécessaire pour que le *TWEAK* exécute les scanners. La seconde déclenche un pipeline enfant contenant un ensemble de variables différent pour chaque cas défini ci-dessus (push vers la branche, fusion dans la branche par défaut ou tag).\n\n\nNous ajoutons ici une dépendance avec le mot-clé [strategy:depend](https://docs.gitlab.com/ee/ci/yaml/index.html#triggerstrategy) sur notre pipeline enfant afin que la vue du pipeline dans GitLab ne soit mise à jour qu'une fois le déploiement terminé.\n\n\nComme vous le voyez, nous définissons un job de base [masqué](https://docs.gitlab.com/ee/ci/jobs/#hide-jobs), puis nous ajoutons des variables et des règles spécifiques afin de déclencher un seul déploiement pour chaque environnement cible.\n\n\nOutre les [variables prédéfinies](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html), nous utilisons deux nouveaux éléments que nous devons définir :\n\n\n1. [Les variables spécifiques](#the-variable-definitions) à chaque environnement : `../vars/$variables_file.tfvars`\n\n2. [Le pipeline enfant](#the-child-pipeline), défini dans `.gitlab-ci/.first-layer.gitlab-ci.yml`\n\n\nCommençons par le plus rapide, les définitions des variables.\n\n\n### Les définitions des variables\n\n\nNous allons ici mélanger deux solutions pour fournir des variables à Terraform :\n\n\n* La première utilise des [fichiers .tfvars](https://developer.hashicorp.com/terraform/language/values/variables#variable-definitions-tfvars-files) pour tous les intrants ne contenant pas de données sensibles, qui doivent être stockées dans GitLab.\n\n\n![solution 1 pour fournir des variables à Terraform](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097034/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097033419.png)\n\n\n* La seconde utilise des [variables d'environnement](https://developer.hashicorp.com/terraform/language/values/variables#environment-variables) avec le préfixe `TF_VAR`. Combinée à la capacité de GitLab à [masquer les variables](https://docs.gitlab.com/ee/ci/variables/#mask-a-cicd-variable), à [les protéger](https://docs.gitlab.com/ee/ci/variables/#protect-a-cicd-variable) et à les rendre [accessibles uniquement pour certains environnements](https://docs.gitlab.com/ee/ci/environments/index.html#limit-the-environment-scope-of-a-cicd-variable), cette deuxième façon d'injecter des variables est une solution puissante pour **empêcher les fuites d'informations contenant des données sensibles**. Par exemple, si vous considérez que le routage CIDR privé de votre environnement de production est une donnée sensible, vous pouvez le protéger de cette manière. Veillez à ce qu'il ne soit disponible que pour l'environnement `production`, pour les pipelines fonctionnant avec des branches et des tags protégés, et que sa valeur soit masquée dans les journaux du job.\n\n\n![solution 2 pour fournir des variables à Terraform](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097034/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750097033422.png)\n\n\nDe plus, chaque fichier de variables doit être contrôlé via un [fichier `CODEOWNERS`](https://docs.gitlab.com/ee/user/project/codeowners/) où sont définies les personnes ayant l'autorisation d'apporter des modifications.\n\n\n```\n\n[Production owners] \n\nvars/production.tfvars @operations-group\n\n\n[Staging owners]\n\nvars/staging.tfvars @odupre @operations-group\n\n\n[CodeOwners owners]\n\nCODEOWNERS @odupre\n\n```\n\n\nCet article n'a pas pour but d'expliquer Terraform, nous allons donc simplement montrer le fichier `vars/review.tfvars`. Les fichiers d'environnement suivants sont, bien sûr, très similaires. Il suffit de définir les variables ne contenant pas de données sensibles et leurs valeurs ici.\n\n\n```shell\n\naws_vpc_cidr = \"10.1.0.0/16\"\n\naws_public_subnet_cidr = \"10.1.1.0/24\"\n\naws_private_subnet_cidr = \"10.1.2.0/24\"\n\n```\n\n\n#### Le pipeline enfant\n\n\nC'est dans ce pipeline que le travail concret est effectué. Il est donc un peu plus complexe que le premier. Mais rien qu'on ne puisse surmonter ensemble !\n\n\nComme nous l'avons vu dans la définition du pipeline principal, ce pipeline enfant est déclaré dans le fichier `.gitlab-ci/.first-layer.gitlab-ci.yml`.\n\n\n![Pipeline downstream déclaré dans le fichier](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097033/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097033424.png)\n\n\nDécomposons-le en petites étapes avant de revenir à une vue d'ensemble.\n\n\n##### Exécution des commandes Terraform et sécurisation du code\n\n\nNous allons d'abord mettre en place un pipeline pour Terraform. GitLab est une plateforme open source tout comme notre template de pipeline pour Terraform. Il vous suffit de l'inclure, en utilisant l'extrait de code suivant :\n\n\n```yml\n\ninclude:\n  - template: Terraform.gitlab-ci.yml\n```\n\n\nCe template exécute les vérifications Terraform sur le formatage et valide votre code, avant de le planifier et de l'appliquer. Il vous permet également de détruire ce que vous avez déployé.\n\n\nEn tant que plateforme DevSecOps unifiée, GitLab intègre deux scanners de sécurité directement dans ce template afin de détecter les menaces potentielles dans votre code et de vous avertir avant tout déploiement dans les environnements suivants.\n\n\nMaintenant que nous avons vérifié, sécurisé, compilé et déployé notre code, explorons quelques astuces supplémentaires.\n\n\n##### Partage du cache entre les jobs\n\n\nPour réutiliser les résultats des jobs dans les étapes suivantes du pipeline, nous allons activer la mise en cache. Il suffit d'ajouter le code suivant :\n\n\n```yml\n\ndefault:\n  cache:  # Use a shared cache or tagged runners to ensure terraform can run on apply and destroy\n    - key: cache-$CI_COMMIT_REF_SLUG\n      fallback_keys:\n        - cache-$CI_DEFAULT_BRANCH\n      paths:\n        - .\n```\n\n\nNous définissons ici un cache différent pour chaque commit, en revenant au nom de la branche principale si nécessaire.\n\n\nEn regardant de près les templates utilisés, on observe qu’ils contiennent des règles contrôlant l’exécution des jobs. Nous voulons exécuter tous les contrôles (assurance qualité et sécurité) sur toutes les branches. Nous allons donc personnaliser ces paramètres.\n\n\n##### Exécution des contrôles sur toutes les branches\n\n\nLes templates GitLab offrent une fonctionnalité puissante permettant de modifier uniquement certaines parties d’un template. Nous souhaitons seulement remplacer les règles de certains jobs afin de toujours exécuter des contrôles d'assurance qualité et de sécurité. Les autres paramètres de ces jobs resteront conformes au template.\n\n\n```yml\n\nfmt:\n  rules:\n    - when: always\n\nvalidate:\n  rules:\n    - when: always\n\nkics-iac-sast:\n  rules:\n    - when: always\n\niac-sast:\n  rules:\n    - when: always\n```\n\n\nMaintenant que nous avons appliqué les contrôles d'assurance qualité et de sécurité, nous voulons différencier le comportement des environnements principaux (intégration et préproduction) dans le [workflow](#the-workflow) par rapport aux environnements de revue. Commençons par définir le comportement des environnements principaux. Nous modifierons ensuite cette configuration pour les environnements de revue.\n\n\n##### Pipeline CD pour l'intégration et la préproduction\n\n\nComme indiqué, nous voulons déployer la branche principale et les tags dans ces deux environnements. Nous ajoutons des règles pour contrôler ce déploiement sur les jobs `build` et `deploy`. Ensuite, nous activons la fonction `destroy` uniquement pour `integration`, car l'environnement `staging` est trop critique pour être supprimé en un seul clic. Les erreurs sont possibles et nous souhaitons les éviter.\n\n\nEnfin, nous relions le job `deploy` au job `destroy`, afin de pouvoir déclencher un `stop` sur l'environnement directement à partir de l'interface utilisateur graphique de GitLab.\n\n\n`GIT_STRATEGY` positionné à `none` empêche la récupération du code de la branche source dans le runner lors de la destruction. L'opération échouerait si la branche avait été supprimée manuellement. Nous comptons donc sur le cache pour obtenir tout ce dont nous avons besoin pour exécuter les instructions Terraform.\n\n\n```yml\n\nbuild:  # terraform plan\n  environment:\n    name: $TF_STATE_NAME\n    action: prepare\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n    - if: $CI_COMMIT_TAG\n\ndeploy: # terraform apply --> automatically deploy on corresponding env (integration or staging) when merging to default branch or tagging. Second layer environments (qa and production) will be controlled manually\n  environment: \n    name: $TF_STATE_NAME\n    action: start\n    on_stop: destroy\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n    - if: $CI_COMMIT_TAG\n\ndestroy:\n  extends: .terraform:destroy\n  variables:\n    GIT_STRATEGY: none\n  dependencies:\n    - build\n  environment:\n    name: $TF_STATE_NAME\n    action: stop\n  rules:\n    - if: $CI_COMMIT_TAG  # Do not destroy production\n      when: never\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $TF_DESTROY == \"true\" # Manually destroy integration env.\n      when: manual\n```\n\n\nComme indiqué, cela nous permet de déployer sur les environnements `integration` et `staging`. Mais il manque toujours un environnement temporaire où les développeurs et développeuses peuvent expérimenter et valider leur code sans affecter le travail des autres. C'est tout l'intérêt du déploiement dans l'environnement `review`.\n\n\n##### Pipeline CD pour les environnements de revue\n\n\nLe déploiement dans l'environnement de revue n'est pas très différent du déploiement dans les environnements `integration` et `staging`. Nous allons une fois de plus tirer parti de la capacité de GitLab à remplacer uniquement des éléments de définition de job.\n\n\nTout d'abord, nous définissons des règles pour exécuter ces jobs uniquement sur les branches de fonctionnalités.\n\n\nEnsuite, nous relions le job `deploy_review` à `destroy_review`. Nous pouvons ainsi arrêter l'environnement **manuellement** à partir de l'interface utilisateur de GitLab. Plus important encore, ce job **déclenche automatiquement la destruction de l'environnement** lorsque la branche de fonctionnalité est fermée. Cette bonne pratique FinOps vous aide à contrôler vos dépenses opérationnelles.\n\n\nPuisque Terraform a besoin d'un fichier de plan pour la destruction d'une infrastructure, comme pour la compilation, nous ajoutons une dépendance de `destroy_review` à `build_review` afin de récupérer ses artefacts.\n\n\nEnfin, nous voyons ici que le nom de l'environnement est `$environment`. Il a été défini sur `review/$CI_COMMIT_REF_SLUG` dans le [pipeline principal](#the-main-pipeline) et transmis à ce pipeline enfant avec l'instruction `trigger:forward:yaml_variables:true`.\n\n\n```yml\n\nbuild_review:\n  extends: build\n  rules:\n    - if: $CI_COMMIT_TAG\n      when: never\n    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH\n      when: on_success\n\ndeploy_review:\n  extends: deploy\n  dependencies:\n    - build_review\n  environment:\n    name: $environment\n    action: start\n    on_stop: destroy_review\n    # url: https://$CI_ENVIRONMENT_SLUG.example.com\n  rules:\n    - if: $CI_COMMIT_TAG\n      when: never\n    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH\n      when: on_success\n\ndestroy_review:\n  extends: destroy\n  dependencies:\n    - build_review\n  environment:\n    name: $environment\n    action: stop\n  rules:\n    - if: $CI_COMMIT_TAG  # Do not destroy production\n      when: never\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH   # Do not destroy staging\n      when: never\n    - when: manual\n```\n\n\nPour récapituler, nous avons maintenant un pipeline qui peut :\n\n\n* Déployer des environnements de revue temporaires, qui sont automatiquement détruits lorsque la branche de fonctionnalité est fermée\n\n* Déployer en continu la **branche par défaut** sur `integration`\n\n* Déployer en continu les **tags** sur l'environnement `staging`\n\n\nAjoutons maintenant un niveau supplémentaire, où nous allons déployer sur les environnements `qa` et `production` avec un déclencheur manuel.\n\n\n##### Pipeline CD pour l'assurance qualité et la production\n\n\nComme tout le monde n'est pas prêt à effectuer des déploiements continus en production, nous ajoutons une validation manuelle pour les deux prochains déploiements. À strictement parler, nous ne devrions pas ajouter ce déclencheur dans un processus **CD**, mais profitons de cette occasion pour vous apprendre à exécuter des jobs à partir d'autres déclencheurs.\n\n\nJusqu'à présent, nous avons lancé un [pipeline enfant](#the-child-pipeline) à partir du [pipeline principal](#the-main-pipeline) pour exécuter tous les déploiements.\n\n\nComme nous voulons exécuter d'autres déploiements à partir de la branche par défaut et des tags, nous ajoutons un nouveau niveau pour ces étapes supplémentaires. Rien de bien nouveau. Nous allons répéter le processus utilisé pour le [pipeline principal](#the-main-pipeline). En procédant de cette façon, vous pouvez manipuler autant de niveaux que vous le souhaitez. J'ai déjà vu jusqu'à neuf environnements.\n\n\nSans revenir sur les avantages d'un nombre limité d'environnements, le processus que nous utilisons ici permet d'implémenter très facilement le même pipeline, de la phase initiale jusqu’à la livraison finale, tout en gardant la définition de votre pipeline simple et divisée en petits segments que vous pouvez maintenir facilement.\n\n\nPour éviter les conflits de variables, nous utilisons simplement de nouveaux noms pour identifier l'état Terraform et le fichier d'intrant.\n\n\n```yml\n\n.2nd_layer:\n  stage: 2nd_layer\n  variables:\n    TF_ROOT: terraform\n  trigger:\n    include: .gitlab-ci/.second-layer.gitlab-ci.yml\n    # strategy: depend            # Do NOT wait for the downstream pipeline to finish to mark upstream pipeline as successful. Otherwise, all pipelines will fail when reaching the pipeline timeout before deployment to 2nd layer.\n    forward:\n      yaml_variables: true      # Forward variables defined in the trigger job\n      pipeline_variables: true  # Forward manual pipeline variables and scheduled pipeline variables\n\nqa:\n  extends: .2nd_layer\n  variables:\n    TF_STATE_NAME_2: qa\n    environment: $TF_STATE_NAME_2\n    TF_CLI_ARGS_plan_2: \"-var-file=../vars/$TF_STATE_NAME_2.tfvars\"\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n\nproduction:\n  extends: .2nd_layer\n  variables:\n    TF_STATE_NAME_2: production\n    environment: $TF_STATE_NAME_2\n    TF_CLI_ARGS_plan_2: \"-var-file=../vars/$TF_STATE_NAME_2.tfvars\"\n  rules:\n    - if: $CI_COMMIT_TAG\n```\n\n\n**Un point important ici est la stratégie utilisée pour le nouveau pipeline enfant.** Nous maintenons la valeur par défaut du déclencheur `trigger:strategy`. Dans le cas contraire, le [pipeline principal](#the-main-pipeline) attend la fin de votre [pipeline de niveau « petit-enfant »](#the-grand-child-pipeline). Si vous utilisez un déclencheur manuel, cette opération peut prendre beaucoup de temps et rendre votre tableau de bord de pipeline plus difficile à lire et à comprendre.\n\n\nVous vous demandez probablement ce que contient le fichier `.gitlab-ci/.second-layer.gitlab-ci.yml` qui est inclus ici. Nous aborderons cette question dans la section suivante.\n\n\n##### Le premier niveau complet de définition de pipeline\n\n\nSi vous recherchez une vue complète de ce premier niveau (stocké dans `.gitlab-ci/.first-layer.gitlab-ci.yml`), consultez la section suivante.\n\n\n```yml\n\nvariables:\n  TF_VAR_aws_ami_id: $AWS_AMI_ID\n  TF_VAR_aws_instance_type: $AWS_INSTANCE_TYPE\n  TF_VAR_aws_default_region: $AWS_DEFAULT_REGION\n\ninclude:\n  - template: Terraform.gitlab-ci.yml\n\ndefault:\n  cache:  # Use a shared cache or tagged runners to ensure terraform can run on apply and destroy\n    - key: cache-$CI_COMMIT_REF_SLUG\n      fallback_keys:\n        - cache-$CI_DEFAULT_BRANCH\n      paths:\n        - .\n\nstages:\n  - validate\n  - test\n  - build\n  - deploy\n  - cleanup\n  - 2nd_layer       # Use to deploy a 2nd environment on both the main branch and on the tags\n\nfmt:\n  rules:\n    - when: always\n\nvalidate:\n  rules:\n    - when: always\n\nkics-iac-sast:\n  rules:\n    - if: $SAST_DISABLED == 'true' || $SAST_DISABLED == '1'\n      when: never\n    - if: $SAST_EXCLUDED_ANALYZERS =~ /kics/\n      when: never\n    - when: on_success\n\niac-sast:\n  rules:\n    - if: $SAST_DISABLED == 'true' || $SAST_DISABLED == '1'\n      when: never\n    - if: $SAST_EXCLUDED_ANALYZERS =~ /kics/\n      when: never\n    - when: on_success\n\n###########################################################################################################\n\n## Integration env. and Staging. env\n\n##  * Auto-deploy to Integration on merge to main.\n\n##  * Auto-deploy to Staging on tag.\n\n##  * Integration can be manually destroyed if TF_DESTROY is set to true.\n\n##  * Destroy of next env. is not automated to prevent errors.\n\n###########################################################################################################\n\nbuild:  # terraform plan\n  environment:\n    name: $TF_STATE_NAME\n    action: prepare\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n    - if: $CI_COMMIT_TAG\n\ndeploy: # terraform apply --> automatically deploy on corresponding env (integration or staging) when merging to default branch or tagging. Second layer environments (qa and production) will be controlled manually\n  environment: \n    name: $TF_STATE_NAME\n    action: start\n    on_stop: destroy\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n    - if: $CI_COMMIT_TAG\n\ndestroy:\n  extends: .terraform:destroy\n  variables:\n    GIT_STRATEGY: none\n  dependencies:\n    - build\n  environment:\n    name: $TF_STATE_NAME\n    action: stop\n  rules:\n    - if: $CI_COMMIT_TAG  # Do not destroy production\n      when: never\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $TF_DESTROY == \"true\" # Manually destroy integration env.\n      when: manual\n###########################################################################################################\n\n\n###########################################################################################################\n\n## Dev env.\n\n##  * Temporary environment. Lives and dies with the Merge Request.\n\n##  * Auto-deploy on push to feature branch.\n\n##  * Auto-destroy on when Merge Request is closed.\n\n###########################################################################################################\n\nbuild_review:\n  extends: build\n  rules:\n    - if: $CI_COMMIT_TAG\n      when: never\n    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH\n      when: on_success\n\ndeploy_review:\n  extends: deploy\n  dependencies:\n    - build_review\n  environment:\n    name: $environment\n    action: start\n    on_stop: destroy_review\n    # url: https://$CI_ENVIRONMENT_SLUG.example.com\n  rules:\n    - if: $CI_COMMIT_TAG\n      when: never\n    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH\n      when: on_success\n\ndestroy_review:\n  extends: destroy\n  dependencies:\n    - build_review\n  environment:\n    name: $environment\n    action: stop\n  rules:\n    - if: $CI_COMMIT_TAG  # Do not destroy production\n      when: never\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH   # Do not destroy staging\n      when: never\n    - when: manual\n###########################################################################################################\n\n\n###########################################################################################################\n\n## Second layer\n\n##  * Deploys from main branch to qa env.\n\n##  * Deploys from tag to production.\n\n###########################################################################################################\n\n.2nd_layer:\n  stage: 2nd_layer\n  variables:\n    TF_ROOT: terraform\n  trigger:\n    include: .gitlab-ci/.second-layer.gitlab-ci.yml\n    # strategy: depend            # Do NOT wait for the downstream pipeline to finish to mark upstream pipeline as successful. Otherwise, all pipelines will fail when reaching the pipeline timeout before deployment to 2nd layer.\n    forward:\n      yaml_variables: true      # Forward variables defined in the trigger job\n      pipeline_variables: true  # Forward manual pipeline variables and scheduled pipeline variables\n\nqa:\n  extends: .2nd_layer\n  variables:\n    TF_STATE_NAME_2: qa\n    environment: $TF_STATE_NAME_2\n    TF_CLI_ARGS_plan_2: \"-var-file=../vars/$TF_STATE_NAME_2.tfvars\"\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n\nproduction:\n  extends: .2nd_layer\n  variables:\n    TF_STATE_NAME_2: production\n    environment: $TF_STATE_NAME_2\n    TF_CLI_ARGS_plan_2: \"-var-file=../vars/$TF_STATE_NAME_2.tfvars\"\n  rules:\n    - if: $CI_COMMIT_TAG\n###########################################################################################################\n\n```\n\n\nÀ cette étape, nous avons déjà effectué des déploiements vers trois environnements en toute sécurité. Je trouve personnellement que cette démarche est idéale. Cependant, si vous avez besoin d'autres environnements, ajoutez-les à votre pipeline CD.\n\n\nVous avez sûrement remarqué que nous incluons un pipeline enfant avec le mot-clé `trigger:include`. Il inclut le fichier `.gitlab-ci/.second-layer.gitlab-ci.yml`. Nous souhaitons exécuter un pipeline très similaire, son contenu ressemble donc évidemment beaucoup à celui présenté ci-dessus. Le principal avantage de ce [pipeline de niveau « petit-enfant »](#the-grand-child-pipeline) est qu'il existe par lui-même, ce qui facilite la définition des variables et des règles.\n\n\n### Le pipeline de niveau « petit-enfant »\n\n\nCe pipeline de deuxième couche est tout nouveau. Par conséquent, il doit imiter la définition de la première couche, à savoir :\n\n\n* [Il doit inclure le template Terraform](#run-terraform-commands-and-secure-the-code).\n\n* [Il doit exécuter des contrôles de sécurité](#run-controls-on-all-branches). La validation Terraform dupliquerait le premier niveau, mais les scanners de sécurité peuvent identifier des menaces qui n'existaient pas encore lors des précédents scans (par exemple, si vous déployez en production quelques jours après votre déploiement en préproduction).\n\n* [Il doit remplacer les jobs de compilation et de déploiement pour définir des règles spécifiques](#cd-to-review-environments). Notez que l'étape `destroy` n'est plus automatisée pour éviter des suppressions accidentelles.\n\n\nComme expliqué ci-dessus, les variables `TF_STATE_NAME` et `TF_CLI_ARGS_plan` sont copiées du pipeline principal au pipeline enfant. Nous avions besoin d'un nom de variable différent pour transférer ces valeurs du pipeline enfant au pipeline « petit-enfant ». C'est pourquoi, dans le pipeline enfant, les noms de ces variables incluent le suffixe `_2`. La valeur est ensuite copiée dans la variable correspondante appropriée lors de l'exécution de la section `before_script`.\n\n\nComme nous avons déjà décomposé chaque étape, nous pouvons passer directement à la vue d'ensemble du deuxième niveau (codé dans `.gitlab-ci/.second-layer.gitlab-ci.yml`).\n\n\n```yml\n\n# Use to deploy a second environment on both the default branch and the tags.\n\n\ninclude:\n  template: Terraform.gitlab-ci.yml\n\nstages:\n  - validate\n  - test\n  - build\n  - deploy\n\nfmt:\n  rules:\n    - when: never\n\nvalidate:\n  rules:\n    - when: never\n\nkics-iac-sast:\n  rules:\n    - if: $SAST_DISABLED == 'true' || $SAST_DISABLED == '1'\n      when: never\n    - if: $SAST_EXCLUDED_ANALYZERS =~ /kics/\n      when: never\n    - when: always\n\n###########################################################################################################\n\n## QA env. and Prod. env\n\n##  * Manually trigger build and auto-deploy in QA\n\n##  * Manually trigger both build and deploy in Production\n\n##  * Destroy of these env. is not automated to prevent errors.\n\n###########################################################################################################\n\nbuild:  # terraform plan\n  cache:  # Use a shared cache or tagged runners to ensure terraform can run on apply and destroy\n    - key: $TF_STATE_NAME_2\n      fallback_keys:\n        - cache-$CI_DEFAULT_BRANCH\n      paths:\n        - .\n  environment:\n    name: $TF_STATE_NAME_2\n    action: prepare\n  before_script:  # Hack to set new variable values on the second layer, while still using the same variable names. Otherwise, due to variable precedence order, setting new value in the trigger job, does not cascade these new values to the downstream pipeline\n    - TF_STATE_NAME=$TF_STATE_NAME_2\n    - TF_CLI_ARGS_plan=$TF_CLI_ARGS_plan_2\n  rules:\n    - when: manual\n\ndeploy: # terraform apply\n  cache:  # Use a shared cache or tagged runners to ensure terraform can run on apply and destroy\n    - key: $TF_STATE_NAME_2\n      fallback_keys:\n        - cache-$CI_DEFAULT_BRANCH\n      paths:\n        - .\n  environment: \n    name: $TF_STATE_NAME_2\n    action: start\n  before_script:  # Hack to set new variable values on the second layer, while still using the same variable names. Otherwise, due to variable precedence order, setting new value in the trigger job, does not cascade these new values to the downstream pipeline\n    - TF_STATE_NAME=$TF_STATE_NAME_2\n    - TF_CLI_ARGS_plan=$TF_CLI_ARGS_plan_2\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n    - if: $CI_COMMIT_TAG && $TF_AUTO_DEPLOY == \"true\"\n    - if: $CI_COMMIT_TAG\n      when: manual\n###########################################################################################################\n\n```\n\n\nVoilà qui est fait. **Tout est prêt.** N'hésitez pas à changer la façon dont vous contrôlez l'exécution de vos jobs, en tirant parti, par exemple, de la capacité de GitLab à [retarder un job](https://docs.gitlab.com/ee/ci/jobs/job_control.html#run-a-job-after-a-delay) avant de le déployer en production.\n\n\n## Essayez par vous-même\n\n\nCe tutoriel est maintenant terminé. Nous savons désormais comment contrôler les **déploiements vers cinq environnements différents** en utilisant uniquement les **branches de fonctionnalités**, la **branche principale** et les **tags**.\n\n\n* Nous réutilisons intensivement les templates open source GitLab pour assurer la productivité et la sécurité de nos pipelines.\n\n* Nous tirons parti des capacités du template GitLab pour remplacer uniquement les blocs nécessitant un contrôle personnalisé.\n\n* Nous avons divisé le pipeline en petits segments et contrôlons les pipelines enfants afin qu'ils correspondent exactement à nos besoins.\n\n\nÀ vous de jouer maintenant. Vous pouvez, par exemple, facilement mettre à jour le pipeline principal afin de déclencher des pipelines enfants, pour votre code source logiciel, avec le mot-clé [trigger:rules:changes](https://docs.gitlab.com/ee/ci/yaml/#ruleschanges). Vous pouvez utiliser un autre [template](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/) en fonction des changements qui se sont produits. Mais c'est une autre histoire.\n",[780],"Olivier Dupré","2025-01-09","2024-09-26","Déployer en continu dans de multiples environnements avec les pipelines enfants",[111,785,786,760,759],"CI","CD",{"slug":788,"featured":6,"template":686},"using-child-pipelines-to-continuously-deploy-to-five-environments","content:fr-fr:blog:using-child-pipelines-to-continuously-deploy-to-five-environments.yml","Using Child Pipelines To Continuously Deploy To Five Environments","fr-fr/blog/using-child-pipelines-to-continuously-deploy-to-five-environments.yml","fr-fr/blog/using-child-pipelines-to-continuously-deploy-to-five-environments",{"_path":794,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":795,"content":801,"config":808,"_id":810,"_type":16,"title":811,"_source":18,"_file":812,"_stem":813,"_extension":21},"/fr-fr/blog/building-a-gitlab-ci-cd-pipeline-for-a-monorepo-the-easy-way",{"title":796,"description":797,"ogTitle":796,"ogDescription":797,"noIndex":6,"ogImage":798,"ogUrl":799,"ogSiteName":723,"ogType":724,"canonicalUrls":799,"schema":800},"GitLab CI/CD : comment créer facilement un pipeline pour un monorepo","Découvrez comment configurer un pipeline CI/CD dans GitLab pour un dépôt monorepo et simplifier l'hébergement de plusieurs applications dans un seul dépôt.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749660151/Blog/Hero%20Images/blog-image-template-1800x945__26_.png","https://about.gitlab.com/blog/building-a-gitlab-ci-cd-pipeline-for-a-monorepo-the-easy-way","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLab CI/CD : comment créer facilement un pipeline pour un monorepo\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sam Morris\"}],\n        \"datePublished\": \"2024-07-30\",\n      }\n                  ",{"title":796,"description":797,"authors":802,"heroImage":798,"date":804,"body":805,"category":14,"tags":806,"updatedDate":807},[803],"Sam Morris","2024-07-30","Les monorepos permettent d’héberger le code de plusieurs applications au sein d'un seul dépôt. Dans GitLab, cela consiste à organiser le code source de chaque application dans des répertoires distincts au sein d'un même projet. Bien que cette approche facilite le [contrôle de version](https://about.gitlab.com/fr-fr/topics/version-control/ \"Qu'est-ce que le contrôle de version ? \") pour l'ensemble du code, tirer parti des capacités avancées des [pipelines CI/CD](https://about.gitlab.com/fr-fr/topics/ci-cd/cicd-pipeline/ \"Qu'est-ce qu'un pipeline CI/CD ? \") de GitLab pouvait s'avérer complexe... jusqu'à l'arrivée d'une nouvelle fonctionnalité dans GitLab 16.4 !\n\n## Le cas idéal : des pipelines CI/CD indépendants pour un monorepo\n\nLorsque plusieurs applications coexistent dans un même dépôt, il est logique de vouloir disposer de pipelines CI/CD distincts pour chacune d'elles. Par exemple, si l'un de vos projets regroupe une application .NET et une application Spring, chacune d'elle nécessitera des jobs de compilation et de test différents. L'idéal serait donc de pouvoir découpler ces pipelines pour qu'ils s'exécutent uniquement lorsque des modifications sont apportées au code source de l'application concernée.\n\nTechniquement, cela revient à configurer un fichier de pipeline `.gitlab-ci.yml` au niveau du projet, qui inclut des fichiers YAML spécifiques basés sur les modifications détectées dans certains répertoires. Le fichier de pipeline `.gitlab-ci.yml` agit comme un plan de contrôle qui déclenche le pipeline approprié en fonction des modifications apportées au code.\n\n## Ancienne approche : le contournement\n\nAvant l'introduction de nouvelles fonctionnalités dans GitLab 16.4, il n'était pas possible d'inclure directement un fichier YAML en fonction des modifications apportées à un répertoire ou un fichier spécifique. Une solution de contournement était toutefois disponible. \n\nPrenons un exemple concret : un monorepo avec deux répertoires, `java` et `python`, contenant respectivement le code source d'une application Java et d'une application Python. Chaque répertoire disposait d'un fichier YAML propre à l'application pour gérer sa compilation. Le fichier de pipeline principal du projet incluait simplement les deux fichiers YAML des applications, mais une logique de gestion des modifications devait être directement intégrée dans ces fichiers.\n\n`.gitlab-ci.yml` :\n\n```\nstages:\n  - build\n  - test\n  - deploy\n\ntop-level-job:\n  stage: build\n  script:\n    - echo \"Hello world...\"\n\ninclude:\n  - local: '/java/j.gitlab-ci.yml'\n  - local: '/python/py.gitlab-ci.yml'\n\n```\n\nPour chaque application, il était nécessaire de créer un job masqué (par exemple, .java-common ou .python-common), qui ne s'exécutait qu'en présence de modifications apportées au répertoire correspondant. Les [jobs masqués](https://docs.gitlab.com/ee/ci/jobs/#hide-jobs) ne s'exécutaient pas par défaut. Ils servaient à centraliser la logique de déclenchement et à la réutiliser dans d'autres jobs. Cependant, cela impliquait d'étendre le job masqué dans chaque pipeline afin de respecter les règles de détection des modifications, qui déclenchaient alors le job d'exécution du pipeline. \n\n'j.gitlab-ci.yml':\n\n'''\nstages:\n  - build\n  - test\n  - deploy\n\n.java-common:\n  rules:\n    - changes:\n      - ../java/*'\n\njava-build-job:\n  extends: .java-common\n  stage: build\n  script:\n    - echo \"Building Java\"\n\njava-test-job:\n  extends: .java-common\n  stage: test\n  script:\n    - echo \"Testing Java\"\n\n'''\n\n'py.gitlab-ci.yml':\n\n'''\nstages:\n  - build\n  - test\n  - deploy\n\n.python-common:\n  rules:\n    - changes:\n      - \"../python/*\"\n\npython-build-job:\n  extends: .python-common\n  stage: build\n  script:\n    - echo \"Building Python\"\n\npython-test-job:\n  extends: .python-common\n  stage: test\n  script:\n    - echo \"Testing Python\"\n\n'''\n\nCette méthode fonctionnait, mais présentait des inconvénients majeurs. En effet, chaque pipeline devait étendre le job masqué pour chaque autre job dans le fichier YAML afin de respecter les règles de déclenchement. Elle avait pour conséquence la création de code redondant et l'augmentation du risque d'erreur humaine. De plus, les jobs étendus n'acceptaient pas de clés en double. Vous ne pouviez donc pas définir votre propre logique de règles (`rules`), car cela entraînait des conflits de clés et leurs [valeurs n'étaient pas fusionnées](https://docs.gitlab.com/ee/ci/yaml/index.html#extends). \n\nMalgré tout, avec cette méthode, le pipeline est opérationnel, incluant les jobs j.gitlab-ci.yml dès que le répertoire `java/` est mis à jour, et les jobs py.gitlab-ci.yml dès que le répertoire `python/` est mis à jour. \n\n## Nouvelle approche : l'inclusion conditionnelle des fichiers de pipeline\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/6phvk8jioAo?si=y6ztZODvUtM-cHmZ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line ->\n\nAvec le lancement de GitLab 16.4, nous avons introduit une nouvelle fonctionnalité : la possibilité d'utiliser le terme [`include` avec `rules:changes` dans les pipelines CI/CD](https://docs.gitlab.com/ee/ci/yaml/includes.html#include-with-ruleschanges). Auparavant, vous pouviez utiliser l'option `include` avec `rules:if`, mais pas avec `rules:changes`. Cette nouvelle version est donc une amélioration majeure. Désormais, vous pouvez simplement utiliser le terme `include` et définir les règles du monorepo dans la configuration du pipeline de votre projet. \n\nNouveau fichier `.gitlab-ci.yml` :\n\n```\nstages:\n  - build\n  - test\n\ntop-level-job:\n  stage: build\n  script:\n    - echo \"Hello world...\"\n\ninclude:\n  - local: '/java/j.gitlab-ci.yml'\n    rules:\n      - changes:\n        - 'java/*'\n  - local: '/python/py.gitlab-ci.yml'\n    rules:\n      - changes:\n        - 'python/*'\n\n```\n\nAinsi, le fichier YAML de chaque application se concentre exclusivement sur les jobs nécessaires à cette application, comme la compilation et le test du code, sans avoir à étendre à plusieurs reprises un job masqué. Cette approche permet une plus grande flexibilité dans les définitions de job et les ingénieurs n'ont plus besoin de réécrire le code des configurations.\n\nNouveau fichier `j.gitlab-ci.yml` (Java) :\n\n```\nstages:\n  - build\n  - test\n  - deploy\n\njava-build-job:\n  stage: build\n  script:\n    - echo \"Building Java\"\n\njava-test-job:\n  stage: test\n  script:\n    - echo \"Testing Java\"\n\n```\n\nNouveau fichier `py.gitlab-ci.yml` (Python) :\n```\nstages:\n  - build\n  - test\n  - deploy\n\npython-build-job:\n  stage: build\n  script:\n    - echo \"Building Python\"\n\npython-test-job:\n  stage: test\n  script:\n    - echo \"Testing Python\"\n\n```\n\nCette méthode permet d'inclure les jobs Java et Python uniquement lorsque leurs répertoires respectifs sont modifiés. Cependant, il convient de noter que [les jobs peuvent s'exécuter de manière inattendue lors de l'utilisation de `changes`](https://docs.gitlab.com/ee/ci/jobs/job_troubleshooting.html#jobs-or-pipelines-run-unexpectedly-when-using-changes). La règle de déclenchement des modifications est toujours évaluée comme vraie lors du push d'une nouvelle branche ou d'un nouveau tag dans GitLab. Ainsi, tous les jobs inclus dans le pipeline s'exécuteront lors du premier push d'une branche, même si des règles `rules:changes` spécifiques sont définies. Vous pouvez résoudre ce problème en créant d'abord votre branche de fonctionnalité, puis en ouvrant une merge request pour commencer votre développement, car le premier push vers la branche lors de sa création forcera l'exécution de tous les jobs.\n\nEn fin de compte, les monorepos constituent une stratégie adaptée à GitLab et à l'approche CI/CD. La fonctionnalité `include` avec `rules:changes` est une bonne pratique que nous recommandons lors de l'utilisation de GitLab CI avec des monorepos. Pour utiliser les monorepos, commencez par essayer Gitlab Ultimate gratuitement dès aujourd'hui.\n",[111,759],"2025-05-27",{"slug":809,"featured":6,"template":686},"building-a-gitlab-ci-cd-pipeline-for-a-monorepo-the-easy-way","content:fr-fr:blog:building-a-gitlab-ci-cd-pipeline-for-a-monorepo-the-easy-way.yml","Building A Gitlab Ci Cd Pipeline For A Monorepo The Easy Way","fr-fr/blog/building-a-gitlab-ci-cd-pipeline-for-a-monorepo-the-easy-way.yml","fr-fr/blog/building-a-gitlab-ci-cd-pipeline-for-a-monorepo-the-easy-way",{"_path":815,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":816,"content":822,"config":830,"_id":832,"_type":16,"title":833,"_source":18,"_file":834,"_stem":835,"_extension":21},"/fr-fr/blog/how-to-deploy-react-to-amazon-s3",{"title":817,"description":818,"ogTitle":817,"ogDescription":818,"noIndex":6,"ogImage":819,"ogUrl":820,"ogSiteName":723,"ogType":724,"canonicalUrls":820,"schema":821},"Comment déployer une application React sur Amazon S3 avec GitLab CI/CD","Vous souhaitez déployer une application React sur Amazon S3 avec GitLab CI/CD ? Suivez notre guide étape par étape.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663291/Blog/Hero%20Images/cover1.jpg","https://about.gitlab.com/blog/how-to-deploy-react-to-amazon-s3","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Comment déployer une application React sur Amazon S3 avec GitLab CI/CD\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jeremy Wagner\"}],\n        \"datePublished\": \"2023-03-01\",\n      }",{"title":817,"description":818,"authors":823,"heroImage":819,"date":825,"body":826,"category":14,"tags":827,"updatedDate":829},[824],"Jeremy Wagner","2023-03-01","Amazon S3 dispose d'une fonctionnalité d'hébergement qui vous permet\nd'héberger un site Web statique directement à partir d'un bucket S3,\négalement appelé compartiment. Lorsque vous hébergez votre site Web sur\nAmazon S3, son contenu est stocké dans un bucket S3 et servi directement à\nvos utilisateurs, sans besoin de ressources supplémentaires. \n\n\nCombinez cela avec Amazon CloudFront et vous obtiendrez une solution\nrentable et évolutive pour l'hébergement de vos sites Web statiques. Une\nfonctionnalité particulièrement utile pour les applications à page unique.\n\n\nDans cet article, nous vous guidons dans la configuration de votre bucket\nAmazon S3, la configuration d'OpenID Connect\n([OIDC](https://openid.net/developers/how-connect-works/ \"OpenID Connect\"))\ndans AWS et le déploiement de votre application sur Amazon S3 à l'aide d'un\npipeline GitLab [CI/CD](https://about.gitlab.com/fr-fr/topics/ci-cd/\n\"Qu'est-ce que le CI/CD ?\").\n\n\nÀ la fin de cet article, vous disposerez d'un [pipeline\nCI/CD](https://about.gitlab.com/fr-fr/topics/ci-cd/cicd-pipeline/ \"Qu'est-ce\nqu'un pipeline CI/CD ?\") construit dans GitLab qui se déploie\nautomatiquement dans votre bucket Amazon S3. \n\n\n## Prérequis\n\n\nPour ce guide, vous aurez besoin des éléments suivants :\n\n\n- [Node.js](https://nodejs.org/fr) >= 14.0.0 et npm >= 5.6 installés sur\nvotre système\n\n- [Git](https://git-scm.com/) installé sur votre système\n\n- Un [compte GitLab](https://gitlab.com/-/trials/new)\n\n- Un [compte AWS](https://aws.amazon.com/fr/free/)\n\n\nDans un [précédent\ntutoriel](https://about.gitlab.com/blog/how-to-automate-testing-for-a-react-application-with-gitlab/)\nnous vous avons expliqué comment : \n\n- créer une nouvelle application React,\n\n- exécuter des tests unitaires dans le cadre du processus CI dans GitLab,\n\n- générer les résultats des tests ainsi que la couverture de code dans le\npipeline.\n\n\nCet article constitue la [suite de ce\nprojet](https://gitlab.com/guided-explorations/engineering-tutorials/react-unit-testing).\nLibre à vous de le parcourir et de le dupliquer (fork). \n\n\n## Configuration de votre bucket S3 \n\n\nPour commencer, vous devez configurer votre bucket Amazon S3. \n\n\n### Créez votre compartiment\n\n\nAprès vous être connecté à votre compte AWS, recherchez « S3 » à l'aide de\nla barre de recherche et sélectionnez le service S3. Cela ouvrira la page\nd'accueil du service.\n\n\nVous devriez immédiatement voir l'option permettant de créer un bucket\n(compartiment). Ce compartiment est l'endroit où vous allez stocker votre\napplication React une fois créée. Cliquez sur le bouton « Créer un\ncompartiment » pour continuer.\n\n\n![Création d'un bucket\nS3](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/create_bucket.png){:\n.shadow}\n\n\nDonnez un nom à votre compartiment, sélectionnez votre région, laissez le\nreste des paramètres par défaut (nous y reviendrons plus tard) et continuez\nen cliquant sur le bouton « Créer un compartiment ». \n\n\nLorsque vous nommez votre compartiment, il est important de se rappeler que\nle nom doit être unique et suivre les règles de nommage des compartiments.\nNous avons nommé le nôtre `jw-gl-react`.\n\n\nUne fois votre compartiment créé, vous devriez être redirigé vers une liste\nde vos compartiments, comme montré ci-dessous. \n\n\n![Liste bucket S3\nAWS](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/bucket_list.png){:\n.shadow}\n\n\n### Configurez l'hébergement de site web statique \n\n\nL'étape suivante consiste à configurer l'hébergement de site web statique.\nOuvrez votre compartiment en cliquant sur son nom. Sélectionnez l'onglet «\nPropriétés »  et faites défiler vers le bas pour trouver l'option\nd'hébergement de site web statique.\n\n\n![Configuration de l'hébergement de site web\nstatique](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/static_hosting_1.png){:\n.shadow}\n\n\nCliquez sur « Modifier », puis activez l'hébergement de site web statique.\nPour les documents d’index et d’erreur, saisissez `index.html`, puis cliquez\nsur « Enregistrer les modifications ».\n\n\n![Activation de l'hébergement de site web statique sur Amazon\nS3](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/static_hosting_2.png){:\n.shadow}\n\n\n### Configurez les autorisations de votre application React\n\n\nMaintenant que vous avez activé l'hébergement de site web statique, vous\ndevez mettre à jour vos autorisations afin que votre audience puisse accéder\nà votre site web. Revenez à votre compartiment et sélectionnez l'onglet «\nAutorisations ».\n\n\nSous « Bloquer l'accès public » (paramètres du compartiment), cliquez sur «\nModifier », décochez « Bloquer tous les accès publics » et continuez en\ncliquant sur « Enregistrer les modifications ».\n\n\n![Bloquer l'accès\npublic](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/block_access_1.png){:\n.shadow}\n\n\nVotre page devrait maintenant ressembler à ceci : \n\n\n![Configurer permission bucket S3\nAWS](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/block_access_2.png){:\n.shadow}\n\n\nMaintenant, vous devez modifier la stratégie de compartiment. Pour cela,\ncliquez sur le bouton « Modifier » dans la section « Stratégie de\ncompartiment » et collez le code suivant :\n\n\n```javascript\n\n{\n    \"Version\": \"2012-10-17\",\n    \"Statement\": [\n        {\n            \"Sid\": \"PublicReadGetObject\",\n            \"Effect\": \"Allow\",\n            \"Principal\": \"*\",\n            \"Action\": \"s3:GetObject\",\n            \"Resource\": \"arn:aws:s3:::jw-gl-react/*\"\n        }\n    ]\n}\n\n```\n\n\nÀ la ligne « Ressource », remplacez `jw-gl-react`  par le nom de votre\ncompartiment et enregistrez les modifications.\n\n\nVotre compartiment devrait ressembler à ceci : \n\n\n![Bucket S3 accès\npublic](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/block_access_3.png){:\n.shadow}\n\n\n## Chargement de votre application React\n\n\nMaintenant, créons votre application React et publions-la manuellement dans\nvotre bucket S3.\n\n\nPour créer l'application, assurez-vous que votre projet soit cloné sur votre\nmachine locale et exécutez la commande suivante dans votre terminal à\nl'intérieur du répertoire de votre dépôt :\n\n\n```\n\nnpm run build\n\n```\n\nCela créera un dossier `build` à l'intérieur du répertoire de votre dépôt. \n\n\nDans votre compartiment, cliquez sur le bouton « Charger »\n\n\n![Chargement de l'application\nReact](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/upload_1.png){:\n.shadow}\n\n\nFaites glisser le contenu de votre dossier nouvellement créé (et non le\ndossier lui-même) dans la zone de chargement. Cela chargera le contenu de\nvotre application React dans votre compartiment. Assurez-vous de cliquer sur\n« Charger » en bas de la page pour démarrer le chargement.\n\n\nRevenez maintenant à l'onglet « Propriétés » de votre compartiment et faites\ndéfiler vers le bas pour trouver l'URL de votre site web statique.\n\n\n![URL du site web\nstatique](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/upload_2.png){:\n.shadow}\n\n\nCliquez sur le lien et vous devriez voir votre application React\nnouvellement créée s'ouvrir dans votre navigateur.\n\n\n![Application React\ndéployée](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/manual_deploy.png){:\n.shadow}\n\n\n## Configuration d’OpenID Connect dans AWS\n\n\nPour déployer sur votre bucket S3 depuis GitLab, nous allons utiliser un job\nGitLab CI/CD pour  recevoir des informations d'identification temporaires\nd'AWS sans avoir besoin de stocker des secrets. Pour ce faire, nous allons\nconfigurer OpenID Connect pour la fédération d'identité entre GitLab et AWS.\nNous suivrons la [documentation de GitLab\nassociée](https://docs.gitlab.com/ee/ci/cloud_services/aws/).\n\n\n### Ajoutez un fournisseur d'identité \n\n\nLa première étape consiste à ajouter GitLab en tant que fournisseur\nd’identité OpenID Connect (OIDC) dans IAM. AWS fournit des\n[instructions](https://docs.aws.amazon.com/fr_fr/IAM/latest/UserGuide/id_roles_providers_create_oidc.html),\nmais nous allons les parcourir étape par étape dans ce guide.\n\n\nOuvrez tout d'abord la console IAM dans AWS.\n\n\n![Console IAM dans\nAWS](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/iam_1.png){:\n.shadow} \n\n\nDans le volet de navigation de gauche, sous « Gestion des accès »,\nchoisissez « Fournisseurs d'identité », puis « Ajouter un fournisseur ».\nPour le type de fournisseur, sélectionnez « OpenID Connect ».\n\n\nPour l'URL du fournisseur, saisissez l'adresse de votre instance GitLab,\ntelle que `https://gitlab.com` ou `https://gitlab.example.com`.\n\n\nPour « Audience », saisissez quelque chose de générique mais spécifique à\nvotre application React. Dans notre cas, nous allons utiliser `react_s3_gl`.\nVeillez à choisir quelque chose qui ne soit pas facile à deviner et prenez\nnote de cette valeur, car vous l'utiliserez pour définir l'`ID_TOKEN` dans\nvotre fichier `.gitLab-ci.yml`.\n\n\nAprès avoir saisi l'URL du fournisseur, cliquez sur « Obtenir une empreinte\nnumérique »  pour vérifier le certificat du serveur de votre fournisseur\nd'identité. Ensuite, continuez et cliquez sur « Ajouter un fournisseur »\npour terminer.\n\n\n### Créez une politique d’autorisations\n\n\nAprès avoir créé le fournisseur d'identité, vous devez créer une politique\nd’autorisations. \n\n\nDepuis le tableau de bord IAM, sous « Gestion des accès », sélectionnez «\nPolitiques » puis « Créer une politique ». Sélectionnez l'onglet JSON et\ncollez le code suivant en remplaçant `jw-gl-react` par le nom de votre\ncompartiment à la ligne « Ressource ».\n\n\n```javascript\n\n{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\"s3:ListBucket\"],\n      \"Resource\": [\"arn:aws:s3:::jw-gl-react\"]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"s3:PutObject\",\n        \"s3:GetObject\",\n        \"s3:DeleteObject\"\n      ],\n      \"Resource\": [\"arn:aws:s3:::jw-gl-react/*\"]\n    }\n  ]\n}\n\n```\n\n\nSélectionnez le bouton « Suivant : Balises » , ajoutez les balises\nsouhaitées, puis sélectionnez le bouton « Suivant : Confirmer ». Entrez un\nnom pour votre politique avant de terminer sa création.\n\n\n### Configurez le rôle\n\n\nIl est maintenant temps d'ajouter le rôle. Depuis le tableau de bord IAM,\nsous « Gestion des accès  », sélectionnez « Rôles », puis cliquez sur «\nCréer un rôle » et choisissez « Identité Web ».\n\n\nDans la section « Identité Web », sélectionnez le fournisseur d'identité que\nvous avez créé précédemment. Pour l'audience, sélectionnez également\nl'audience que vous avez créée précédemment. Cliquez sur le bouton « Suivant\n» pour continuer.\n\n\nSi vous souhaitez limiter l'autorisation à un groupe, un projet, une branche\nou une balise spécifique, vous pouvez créer une « Politique d’approbation\npersonnalisée » (Custom Trust Policy) au lieu d'une « Identité Web ».\n\n\nPour une liste complète des types de filtres qu'il est possible d'appliquer,\n[consultez notre\ndocumentation](https://docs.gitlab.com/ee/ci/cloud_services/index.html#configure-a-conditional-role-with-oidc-claims). \n\n\n![Configuration du rôle dans\nl'IAM](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/iam_2.png){:\n.shadow}\n\n\nAu cours de l'étape « Ajout des autorisations », sélectionnez la politique\nque vous avez créée, puis cliquez sur « Suivant » pour continuer. Donnez un\nnom à votre rôle et cliquez sur « Créer un rôle ».\n\n\nOuvrez le rôle que vous venez de créer. Dans la section « Récapitulatif »,\nrecherchez le nom de ressource Amazon (ARN) et enregistrez-le dans un\nendroit sécurisé. Vous l'utiliserez dans votre pipeline.\n\n\n![Déployer le rôle dans\nl'IAM](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/iam_3.png){:\n.shadow}\n\n\n## Déploiement sur votre compartiment Amazon S3 à l'aide d'un pipeline\nGitLab CI/CD\n\n\nDans votre projet, créez deux [variables\nCI/CD](https://docs.gitlab.com/ci/variables/#define-a-cicd-variable-in-the-ui)\n:\n\n\n- La première variable doit être nommée `ROLE_ARN`. Pour la valeur, collez\nl'ARN du rôle que vous venez de créer.\n\n- La deuxième variable doit être nommée `S3_BUCKET`. Pour la valeur, collez\nle nom du compartiment que vous avez créé plus tôt.\n\n\nPour des raisons de sécurité, dans cet article nous avons choisi de masquer\nnos variables.\n\n\n### Récupérez vos identifiants temporaires\n\n\nDans votre fichier `.gitlab-ci.yml`, collez le code suivant :\n\n\n```\n\n.assume_role: &assume_role\n    - >\n      STS=($(aws sts assume-role-with-web-identity\n      --role-arn ${ROLE_ARN}\n      --role-session-name \"GitLabRunner-${CI_PROJECT_ID}-${CI_PIPELINE_ID}\"\n      --web-identity-token $ID_TOKEN\n      --duration-seconds 3600\n      --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]'\n      --output text))\n    - export AWS_ACCESS_KEY_ID=\"${STS[0]}\"\n    - export AWS_SECRET_ACCESS_KEY=\"${STS[1]}\"\n    - export AWS_SESSION_TOKEN=\"${STS[2]}\"\n```\n\n\nCela va utiliser le service de jeton de sécurité AWS (AWS Security Token\nService) pour générer des identifiants temporaires (3 600 secondes) en\nutilisant le rôle OpenID Connect que vous avez créé précédemment.\n\n\n### Créez le job de déploiement pour votre application React\n\n\nMaintenant, ajoutons un job de compilation et de déploiement pour créer\nvotre application et la déployer sur votre bucket S3.\n\n\nTout d'abord, mettez à jour les étapes dans votre fichier `.gitlab-ci.yml`\npour inclure une étape `build` et `deploy`, comme indiqué ci-dessous :\n\n\n```\n\nstages:\n  - build\n  - test\n  - deploy\n```\n\n\nEnsuite, ajoutons un job pour créer votre application. Collez le code\nsuivant dans votre fichier `.gitLab-ci.yml` :\n\n\n```\n\nbuild artifact:\n  stage: build\n  image: node:latest\n  before_script:\n    - npm install\n  script:\n    - npm run build\n  artifacts:\n    paths:\n      - build/\n    when: always\n  rules:\n    - if: '$CI_COMMIT_REF_NAME == \"main\"'\n      when: always\n```\n\n\nCela va exécuter `npm run build` si le changement se produit sur la branche\n`main` et télécharger le répertoire de compilation (build directory) en tant\nqu'artefact à utiliser lors de l'étape suivante.\n\n\nEnsuite, ajoutons un job qui sera réellement déployé sur votre bucket S3.\nCollez le code suivant dans votre fichier `.gitLab-ci.yml` :\n\n\n```\n\ndeploy s3:\n  stage: deploy\n  image:\n    name: amazon/aws-cli:latest\n    entrypoint: \n      - '/usr/bin/env'\n  id_tokens:\n      ID_TOKEN:\n        aud: react_s3_gl\n  script:\n    - *assume_role\n    - aws s3 sync build/ s3://$S3_BUCKET\n  rules:\n    - if: '$CI_COMMIT_REF_NAME == \"main\"'\n      when: always\n```\n\n\nCela utilise les [ancres\nYAML](https://docs.gitlab.com/ee/ci/yaml/yaml_optimization.html#yaml-anchors-for-scripts)\npour exécuter le script `assume_role`, puis utilise `aws cli` pour\ntélécharger votre artefact de compilation dans le compartiment que vous avez\ndéfini en tant que variable. Ce job ne s'exécute que si le changement se\nproduit sur la branche `main`.\n\n\nAssurez-vous que la valeur `aud` correspond à celle que vous avez saisie\npour votre audience au moment de la configuration du fournisseur d'identité.\nDans notre cas, nous avons saisi `react-s3_gl`.\n\n\nVotre fichier `.gitLab-ci.yml` complet devrait ressembler à ceci :\n\n\n```\n\nstages:\n  - build\n  - test\n  - deploy\n\n.assume_role: &assume_role\n    - >\n      STS=($(aws sts assume-role-with-web-identity\n      --role-arn ${ROLE_ARN}\n      --role-session-name \"GitLabRunner-${CI_PROJECT_ID}-${CI_PIPELINE_ID}\"\n      --web-identity-token $ID_TOKEN\n      --duration-seconds 3600\n      --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]'\n      --output text))\n    - export AWS_ACCESS_KEY_ID=\"${STS[0]}\"\n    - export AWS_SECRET_ACCESS_KEY=\"${STS[1]}\"\n    - export AWS_SESSION_TOKEN=\"${STS[2]}\"\n\nunit test:\n  image: node:latest\n  stage: test\n  before_script:\n    - npm install\n  script:\n    - npm run test:ci\n  coverage: /All files[^|]*\\|[^|]*\\s+([\\d\\.]+)/\n  artifacts:\n    paths:\n      - coverage/\n    when: always\n    reports:\n      junit:\n        - junit.xml\n\nbuild artifact:\n  stage: build\n  image: node:latest\n  before_script:\n    - npm install\n  script:\n    - npm run build\n  artifacts:\n    paths:\n      - build/\n    when: always\n  rules:\n    - if: '$CI_COMMIT_REF_NAME == \"main\"'\n      when: always\n\ndeploy s3:\n  stage: deploy\n  image:\n    name: amazon/aws-cli:latest\n    entrypoint: \n      - '/usr/bin/env'\n  id_tokens:\n      ID_TOKEN:\n        aud: react_s3_gl\n  script:\n    - *assume_role\n    - aws s3 sync build/ s3://$S3_BUCKET\n  rules:\n    - if: '$CI_COMMIT_REF_NAME == \"main\"'\n      when: always\n```\n\n\n### Testez votre pipeline\n\n\nPour tester votre pipeline, dans `App.js`, modifiez cette ligne `Edit\n\u003Ccode>src/App.js\u003C/code> and save to reload.` par ceci :  `This was deployed\nfrom GitLab`. Maintenant, validez vos modifications dans la branche `main`.\nLe pipeline devrait se lancer et une fois terminé avec succès, vous devriez\nvoir votre application mise à jour avec l'URL de votre site web statique.\n\n\n![Application React mise à\njour](https://about.gitlab.com/images/blogimages/2023-02-10-how-to-deploy-react-to-amazon-s3/auto_deploy.png){:\n.shadow}\n\n\nVous disposez désormais d'un pipeline CI/CD construit dans GitLab qui reçoit\ndes informations d'identification temporaires d'AWS à l'aide d'OpenID\nConnect et qui se déploie automatiquement dans votre compartiment Amazon S3.\nPour aller plus loin, vous pouvez [sécuriser votre\napplication](https://docs.gitlab.com/ee/user/application_security/secure_your_application.html)\navec les outils de sécurité intégrés de GitLab.\n\n\nDécouvrez [tout le\ncode](https://gitlab.com/guided-explorations/engineering-tutorials/react-s3)\nde ce projet.\n",[828,111],"DevOps","2025-03-27",{"slug":831,"featured":6,"template":686},"how-to-deploy-react-to-amazon-s3","content:fr-fr:blog:how-to-deploy-react-to-amazon-s3.yml","How To Deploy React To Amazon S3","fr-fr/blog/how-to-deploy-react-to-amazon-s3.yml","fr-fr/blog/how-to-deploy-react-to-amazon-s3",{"_path":837,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":838,"content":844,"config":851,"_id":853,"_type":16,"title":854,"_source":18,"_file":855,"_stem":856,"_extension":21},"/fr-fr/blog/efficient-devsecops-workflows-hands-on-python-gitlab-api-automation",{"title":839,"description":840,"ogTitle":839,"ogDescription":840,"noIndex":6,"ogImage":841,"ogUrl":842,"ogSiteName":723,"ogType":724,"canonicalUrls":842,"schema":843},"Utiliser l'API python-gitlab pour améliorer vos workflows DevSecOps","Vous souhaitez améliorer vos workflows DevSecOps ? Découvrez dans ce tutoriel des exemples et bonnes pratiques d’utilisation de l’API python-gitlab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659883/Blog/Hero%20Images/post-cover-image.jpg","https://about.gitlab.com/blog/efficient-devsecops-workflows-hands-on-python-gitlab-api-automation","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Utiliser l'API python-gitlab pour améliorer vos workflows DevSecOps\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Michael Friedrich\"}],\n        \"datePublished\": \"2023-02-01\",\n      }",{"title":839,"description":840,"authors":845,"heroImage":841,"date":847,"body":848,"category":14,"tags":849},[846],"Michael Friedrich","2023-02-01","Un jour, un ami m’a dit : « Le travail manuel est un bug ». Depuis, face à\ndes tâches répétitives, j’ai pris l’habitude de les automatiser autant que\npossible. \n\n\nPar exemple, en interrogeant une [API\nREST](https://about.gitlab.com/fr-fr/blog/what-is-rest-api/ \"API\nREST\") pour faire un inventaire des paramètres, ou en effectuant des appels\nd’API pour créer de nouveaux commentaires dans les tickets ou les merge\nrequests de GitLab. L'interaction avec l'API REST de GitLab peut se faire de\ndifférentes manières, en utilisant des requêtes HTTP avec curl (ou\n[hurl](https://about.gitlab.com/blog/how-to-continously-test-web-apps-apis-with-hurl-and-gitlab-ci-cd/\n\"hurl\")) en ligne de commande, ou en écrivant un script dans un langage de\nprogrammation. \n\n\nDans ce dernier cas, il faut effectuer des tâches fastidieuses avec le code\nbrut des requêtes HTTP et l'analyse des réponses JSON. Grâce à la communauté\nGitLab, de nombreux langages sont pris en charge par les bibliothèques\nd'abstraction d'API. Elles prennent en charge tous les attributs de l’API,\najoutent des fonctions d'aide pour obtenir, créer et supprimer des objets,\net facilitent ainsi la tâche des équipes de développement. La [bibliothèque\npython-gitlab](https://python-gitlab.readthedocs.io/en/stable/ \"Bibliothèque\npython-gitlab\") est une bibliothèque écrite en Python, riche en\nfonctionnalités et facile à utiliser.\n\n\nDans cet article, vous apprendrez les bases de l’utilisation de la\nbibliothèque python-gitlab en vous familiarisant avec les objets de l’API,\nles attributs, la pagination et les ensembles de résultats. Vous découvrirez\négalement des cas d'utilisation concrets tels que la collecte de données, la\ngénération de synthèses et l’écriture de données dans l'API pour créer des\ncommentaires et des validations. \n\n\nIl y a encore beaucoup à apprendre, avec de nombreux cas d'utilisation\ninspirés des questions posées par la communauté sur le forum, Hacker News,\ndes tickets, et bien plus encore.\n\n\n## Premiers pas\n\n\nLa [documentation\npython-gitlab](https://python-gitlab.readthedocs.io/en/stable/api-usage.html\n\"Documentation python-gitlab\") est une excellente ressource pour débuter.\nElle offre un aperçu des types d'objets et de leurs méthodes, ainsi que des\nexemples de workflows combinés. Cette ressource est idéale pour faire vos\npremiers pas, en plus de la [documentation sur les ressources de l'API\nGitLab](https://docs.gitlab.com/ee/api/api_resources.html \"Documentation sur\nles ressources de l'API GitLab\") qui fournit les attributs d'objet associés.\n\n\nLes exemples de code présentés dans cet article nécessitent Python 3.8+ et\nla bibliothèque `python-gitlab`. Des exigences supplémentaires sont\nspécifiées dans le fichier `requirements.txt`. Un exemple nécessite `pyyaml`\npour l'analyse de la configuration YAML. Pour suivre et mettre en pratique\nle code des cas d'utilisation, il est recommandé de cloner le projet,\nd'installer les prérequis et d'exécuter les scripts. \n\n\nExemple avec Homebrew sur macOS :\n\n\n```shell\n\ngit clone\nhttps://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python.git\n\n\ncd gitlab-api-python\n\n\nbrew install python\n\n\npip3 install -r requirements.txt\n\n\npython3 \u003Cscriptname>.py\n\n```\n\n\nLes scripts n'utilisent pas de bibliothèque partagée commune fournissant des\nfonctions génériques pour la lecture des paramètres ou d’autres\nfonctionnalités d'aide supplémentaires. L’objectif est de montrer des\nexemples faciles à suivre, qui peuvent être utilisés de manière autonome\npour des tests, et qui nécessitent uniquement l'installation de la\nbibliothèque python-gitlab.\n\n\nNous recommandons d'améliorer le code pour une utilisation en production.\nCela vous aidera à créer un projet d’API tooling maintenu, incluant par\nexemple des images de conteneurs et des modèles CI/CD que les équipes de\ndéveloppement peuvent utiliser au sein d'une plateforme\n[DevSecOps](https://about.gitlab.com/fr-fr/topics/devsecops/ \"Qu'est-ce que\nDevSecOps ?\").\n\n\n## Configuration\n\n\nSans configuration, python-gitlab exécutera des requêtes non authentifiées\nsur le serveur par défaut : `https://gitlab.com`. Les paramètres de\nconfiguration les plus courants concernent l'instance GitLab à laquelle se\nconnecter, et la méthode d'authentification en spécifiant les jetons\nd'accès. Python-gitlab prend en charge différents types de configuration :\nun fichier de configuration ou des variables d'environnement.\n\n\nLe [fichier de\nconfiguration](https://python-gitlab.readthedocs.io/en/stable/cli-usage.html#cli-configuration\n\"Fichier de configuration CLI\") est disponible pour les liaisons de\nbibliothèque d’API et pour l'interface de ligne de commande (que nous\nn’aborderons pas dans cet article). Le fichier de configuration prend en\ncharge les [credential\nhelpers](https://python-gitlab.readthedocs.io/en/stable/cli-usage.html#credential-helpers\n\"Credential helpers\") pour accéder directement aux jetons.\n\n\nLes variables d'environnement, en tant que méthode de configuration\nalternative, vous offrent un moyen simple d'exécuter le script dans un\nterminal, de l'intégrer dans des images de conteneurs et de le préparer à\nêtre exécuté dans des [pipelines\nCI/CD](https://about.gitlab.com/fr-fr/topics/ci-cd/cicd-pipeline/ \"Pipeline\nCI/CD\").\n\n\nVous devez lancer la configuration dans le contexte du script Python.\nImportez la bibliothèque `os` pour récupérer les variables d'environnement à\nl'aide de la méthode `os.environ.get()`. Le premier paramètre spécifie la\nclé, le second paramètre définit la valeur par défaut lorsque la variable\nn'est pas disponible dans l'environnement.\n\n\n```python\n\nimport os\n\n\ngl_server = os.environ.get('GL_SERVER', 'https://gitlab.com')\n\n\nprint(gl_server)\n\n```\n\n\nLe paramétrage dans le terminal peut se faire directement pour la commande\nuniquement, ou être exporté dans l'environnement shell.\n\n\n```shell\n\n$ GL_SERVER=’https://gitlab.company.com’ python3 script.py\n\n\n$ export GL_SERVER=’https://gitlab.company.com’\n\n$ python3 script.py\n\n```\n\n\nNous recommandons d'ajouter des contrôles de sécurité pour s’assurer que\ntoutes les variables sont définies avant de continuer l'exécution du\nprogramme. L'extrait de code suivant importe les bibliothèques requises, lit\nla variable d'environnement `GL_SERVER`, et attend de l'utilisateur qu'il\ndéfinisse la variable `GL_TOKEN`. Si ce n'est pas le cas, le script affiche\net génère des erreurs, puis appelle `sys.exit(1)`, pour indiquer un statut\nd’erreur. \n\n\n```python\n\nimport gitlab\n\nimport os\n\nimport sys\n\n\nGITLAB_SERVER = os.environ.get('GL_SERVER', 'https://gitlab.com')\n\nGITLAB_TOKEN = os.environ.get('GL_TOKEN')\n\n\nif not GITLAB_TOKEN:\n    print(\"Please set the GL_TOKEN env variable.\")\n    sys.exit(1)\n```\n\n\nExaminons maintenant un exemple plus détaillé, qui crée une connexion à\nl'API et effectue une requête de données.\n\n\n## Gestion des objets : l'objet GitLab\n\n\nToute interaction avec l'API nécessite une instanciation de l'objet GitLab.\nC'est le point d'entrée pour configurer le serveur GitLab auquel se\nconnecter et s'authentifier à l'aide de jetons d'accès, et définir d’autres\nparamètres globaux pour la pagination, le chargement d’objets, et plus\nencore. \n\n\nL'exemple suivant exécute une requête non authentifiée sur GitLab.com. Il\nest possible d'accéder aux points de terminaison d’API publique, et\nd'obtenir par exemple un [modèle .gitignore pour\nPython](https://python-gitlab.readthedocs.io/en/stable/gl_objects/templates.html#gitignore-templates\n\"Modèle .gitignore pour Python\").\n\n\n[python_gitlab_object_unauthenticated.py](https://gitlab.com/gitlab-da/use-cases/gitlab-api/gitlab-api-python/-/blob/main/python_gitlab_object_unauthenticated.py)\n\n\n```python\n\nimport gitlab\n\n\ngl = gitlab.Gitlab()\n\n\n# Get .gitignore templates without authentication\n\ngitignore_templates = gl.gitignores.get('Python')\n\n\nprint(gitignore_templates.content)\n\n```\n\n\nDans les sections suivantes, nous vous partageons des informations\ndétaillées sur : \n\n\n- La gestion et le chargement des objets,\n\n- La pagination des résultats,\n\n- Le travail avec les relations entre objets,\n\n- Le travail avec différents scopes de collection d'objets.\n\n\n### La gestion et le chargement des objets\n\n\nLa bibliothèque python-gitlab donne accès aux ressources GitLab en utilisant\nce que l’on appelle des «\n[Gestionnaires](https://python-gitlab.readthedocs.io/en/stable/api-usage.html#managers)\n». Chaque type de gestionnaire implémente des méthodes pour travailler avec\nles ensembles de données (list, get, etc.).\n\n\nLe script ci-dessous montre comment accéder aux sous-groupes, aux projets\ndirects et à tous les projets, y compris les sous-groupes, aux tickets, aux\nepics et aux tâches. Une authentification est nécessaire pour accéder à tous\nles attributs. L'extrait de code utilise donc des variables pour obtenir le\njeton d'authentification, et utilise également la variable `GROUP_ID` pour\nspécifier un groupe principal à partir duquel il faut commencer la\nrecherche.\n\n\n```python\n\n#!/usr/bin/env python\n\n\nimport gitlab\n\nimport os\n\nimport sys\n\n\nGITLAB_SERVER = os.environ.get('GL_SERVER', 'https://gitlab.com')\n\n# https://gitlab.com/gitlab-de/use-cases/\n\nGROUP_ID = os.environ.get('GL_GROUP_ID', 16058698)\n\nGITLAB_TOKEN = os.environ.get('GL_TOKEN')\n\n\nif not GITLAB_TOKEN:\n    print(\"Please set the GL_TOKEN env variable.\")\n    sys.exit(1)\n\ngl = gitlab.Gitlab(GITLAB_SERVER, private_token=GITLAB_TOKEN)\n\n\n# Main\n\nmain_group = gl.groups.get(GROUP_ID)\n\n\nprint(\"Sub groups\")\n\nfor sg in main_group.subgroups.list():\n    print(\"Subgroup name: {sg}\".format(sg=sg.name))\n\nprint(\"Projects (direct)\")\n\nfor p in main_group.projects.list():\n    print(\"Project name: {p}\".format(p=p.name))\n\nprint(\"Projects (including subgroups)\")\n\nfor p in main_group.projects.list(include_subgroups=True, all=True):\n     print(\"Project name: {p}\".format(p=p.name))\n\nprint(\"Issues\")\n\nfor i in main_group.issues.list(state='opened'):\n    print(\"Issue title: {t}\".format(t=i.title))\n\nprint(\"Epics\")\n\nfor e in main_group.issues.list():\n    print(\"Epic title: {t}\".format(t=e.title))\n\nprint(\"Todos\")\n\nfor t in gl.todos.list(state='pending'):\n    print(\"Todo: {t} url: {u}\".format(t=t.body, u=t.target_url\n```\n\n\nVous pouvez exécuter le script `python_gitlab_object_manager_methods.py` en\nremplaçant la variable `GROUP_ID` sur GitLab.com SaaS pour analyser votre\npropre groupe. Vous devez spécifier la variable `GL_SERVER` pour les\ninstances auto-gérées. `GL_TOKEN` doit fournir le jeton d'accès personnel.\n\n\n```shell\n\nexport GL_TOKEN=xxx\n\n\nexport GL_SERVER=”https://gitlab.company.com”\n\n\nexport GL_SERVER=”https://gitlab.com”\n\n\nexport GL_GROUP_ID=1234\n\n\npython3 python_gitlab_object_manager_methods.py\n\n```\n\n\nÀ partir de maintenant, les exemples n'affichent plus les en-têtes Python et\nl'analyse des variables d'environnement, afin de se concentrer sur\nl'algorithme et les fonctionnalités. Tous les scripts sont open source sous\nlicence MIT, et sont disponibles dans [ce\nprojet](https://gitlab.com/gitlab-da/use-cases/gitlab-api/gitlab-api-python).\n\n\n### La pagination des résultats\n\n\nPar défaut, l’API GitLab ne renvoie pas tous les ensembles de résultats et\nexige que les clients utilisent la\n[pagination](https://docs.gitlab.com/ee/api/rest/index.html#pagination\n\"Pagination GitLab\") pour parcourir toutes les pages de résultats. La\nbibliothèque python-gitlab permet aux utilisateurs de [définir les\nparamètres](https://python-gitlab.readthedocs.io/en/stable/api-usage.html#pagination)\nglobalement dans l'objet GitLab, ou sur chaque appel `list()`. Cela permet\nd'éviter que tous les ensembles de résultats déclenchent des requêtes API,\nce qui peut ralentir l'exécution du script. Utilisez `iterator=True`, et les\nappels d'API sont déclenchés à la demande lors de l'accès à l'objet.\n\n\nL'exemple suivant recherche le nom de groupe `everyonecancontribute` et\nutilise la pagination du jeu de clés pour afficher 100 résultats sur chaque\npage. L'itérateur est défini sur true dans `gl.groups.list(iterator=True)`\npour récupérer de nouveaux ensembles de résultats à la demande. Si le nom du\ngroupe recherché est trouvé, la boucle s'interrompt et affiche un résumé,\nincluant la mesure de la durée totale de la requête de recherche.\n\n\n```python\n\nSEARCH_GROUP_NAME=\"everyonecancontribute\"\n\n\n# Use keyset pagination\n\n# https://python-gitlab.readthedocs.io/en/stable/api-usage.html#pagination\n\ngl = gitlab.Gitlab(GITLAB_SERVER, private_token=GITLAB_TOKEN,\n    pagination=\"keyset\", order_by=\"id\", per_page=100)\n\n# Iterate over the list, and fire new API calls in case the result set does\nnot match yet\n\ngroups = gl.groups.list(iterator=True)\n\n\nfound_page = 0\n\nstart = timer()\n\n\nfor group in groups:\n    if SEARCH_GROUP_NAME == group.name:\n        # print(group) # debug\n        found_page = groups.current_page\n        break\n\nend = timer()\n\n\nduration = f'{end-start:.2f}'\n\n\nif found_page > 0:\n    print(\"Pagination API example for Python with GitLab{desc} - found group {g} on page {p}, duration {d}s\".format(\n        desc=\", the DevSecOps platform\", g=SEARCH_GROUP_NAME, p=found_page, d=duration))\nelse:\n    print(\"Could not find group name '{g}', duration {d}\".format(g=SEARCH_GROUP_NAME, d=duration))\n```\n\nL'exécution de `python_gitlab_pagination.py` a permis de trouver le groupe\n[everyonecancontribute](https://gitlab.com/everyonecancontribute) à la page\n5.\n\n\n```shell\n\n$ python3 python_gitlab_pagination.py\n\nPagination API example for Python with GitLab, the DevSecOps platform -\nfound group everyonecancontribute on page 5, duration 8.51s\n\n```\n\n\n### Le travail avec les relations entre objets\n\n\nLorsque vous travaillez avec des relations entre objets, par exemple pour\ncollecter tous les projets dans un groupe donné, vous devez envisager des\nétapes supplémentaires. Par défaut, les objets de projet renvoyés présentent\ndes attributs limités. Les objets gérables nécessitent un appel\nsupplémentaire `get()` pour obtenir l'objet de projet complet de l'API en\narrière-plan. Ce workflow permet de réduire les temps d’attente et le trafic\nen limitant les attributs immédiatement renvoyés.\n\n\nL'exemple suivant illustre le problème en parcourant tous les projets d'un\ngroupe et en essayant d'appeler la fonction `project.branches.list()`. Cela\ngénère une exception dans le flux try/except. Le deuxième exemple obtient un\nobjet de projet gérable et tente à nouveau d'appeler la fonction.\n\n\n```python\n\n# Main\n\ngroup = gl.groups.get(GROUP_ID)\n\n\n# Collect all projects in group and subgroups\n\nprojects = group.projects.list(include_subgroups=True, all=True)\n\n\nfor project in projects:\n    # Try running a method on a weak object\n    try:\n       print(\"🤔 Project: {pn} 💡 Branches: {b}\\n\".format(\n        pn=project.name,\n        b=\", \".join([x.name for x in project.branches.list()])))\n    except Exception as e:\n        print(\"Got exception: {e} \\n ===================================== \\n\".format(e=e))\n\n    # Retrieve a full manageable project object\n    # https://python-gitlab.readthedocs.io/en/stable/gl_objects/groups.html#examples\n    manageable_project = gl.projects.get(project.id)\n\n    # Print a method available on a manageable object\n    print(\"🤔 Project: {pn} 💡 Branches: {b}\\n\".format(\n        pn=manageable_project.name,\n        b=\", \".join([x.name for x in manageable_project.branches.list()])))\n```\n\n\nLe gestionnaire d'exceptions dans la bibliothèque python-gitlab affiche le\nmessage d'erreur et renvoie à la documentation. Pour le débogage, notez que\nles objets peuvent ne pas être disponibles pour la gestion lorsque vous ne\npouvez pas accéder aux attributs de l'objet ou aux appels de fonction.\n\n\n```shell\n\n$ python3 python_gitlab_manageable_objects.py\n\n\n🤔 Project: GitLab API Playground 💡 Branches: cicd-demo-automated-comments,\ndocs-mr-approval-settings, main\n\n\nGot exception: 'GroupProject' object has no attribute 'branches'\n\n\n\u003Cclass 'gitlab.v4.objects.projects.GroupProject'> was created via a\n\nlist() call and only a subset of the data may be present. To ensure\n\nall data is present get the object using a get(object.id) call. For\n\nmore details, see:\n\n\nhttps://python-gitlab.readthedocs.io/en/v3.8.1/faq.html#attribute-error-list\n =====================================\n```\n\n\n[Consultez le script\ncomplet](https://gitlab.com/gitlab-da/use-cases/gitlab-api/gitlab-api-python/-/blob/main/python_gitlab_manageable_objects.py).\n\n\n### Le travail avec différents scopes de collection d'objets\n\n\nParfois, le script doit collecter tous les projets d'une instance\nauto-gérée, d'un groupe avec des sous-groupes, ou d'un projet unique. Ce\ndernier cas est utile pour accélérer les tests sur les attributs requis, et\nla récupération du groupe facilite les tests à grande échelle par la suite.\nL'extrait de code suivant collecte tous les objets de projet dans la liste\n`projects` et y ajoute les objets provenant des différentes configurations\nentrantes. Vous retrouverez également à nouveau le modèle d'objet gérable\npour le projet dans les groupes.\n\n\n```python\n    # Collect all projects, or prefer projects from a group id, or a project id\n    projects = []\n\n    # Direct project ID\n    if PROJECT_ID:\n        projects.append(gl.projects.get(PROJECT_ID))\n\n    # Groups and projects inside\n    elif GROUP_ID:\n        group = gl.groups.get(GROUP_ID)\n\n        for project in group.projects.list(include_subgroups=True, all=True):\n            # https://python-gitlab.readthedocs.io/en/stable/gl_objects/groups.html#examples\n            manageable_project = gl.projects.get(project.id)\n            projects.append(manageable_project)\n\n    # All projects on the instance (may take a while to process)\n    else:\n        projects = gl.projects.list(get_all=True)\n```\n\n\nL'exemple complet se trouve dans [ce\nscript](https://gitlab.com/gitlab-da/use-cases/gitlab-api/gitlab-api-python/-/blob/main/get_mr_approval_rules.py)\npour lister les paramètres des règles d'approbation des merge requests pour\nles cibles de projet spécifiées.\n\n\n## Utilisation de l’approche DevSecOps pour les actions de lecture API\n\n\nLe jeton d'accès authentifié nécessite un scope `read_api`.\n\n\nLes cas d’utilisation suivants seront abordés :\n\n- Lister les branches par état de fusion,\n\n- Afficher les paramètres du projet pour révision : règles d'approbation des\nmerge requests,\n\n- Inventaire : obtenir toutes les variables CI/CD protégées ou masquées,\n\n- Télécharger un fichier depuis le dépôt,\n\n- Aide à la migration : lister tous les clusters Kubernetes basés sur des\ncertificats,\n\n- Productivité des équipes : vérifier si les merge requests existantes\nnécessitent un rebase après avoir fusionné une merge request de\nrefactorisation majeure.  \n\n\n### Lister les branches par état de fusion \n\n\nPour nettoyer un projet\n[Git](https://about.gitlab.com/fr-fr/blog/what-is-git/ \"Qu'est-ce\nque Git ?\"), il est courant d'évaluer le nombre de branches fusionnées et\nnon fusionnées. En réponse à une [question sur le forum de la communauté\nGitLab](https://forum.gitlab.com/t/python-gitlab-project-branch-list-filter/80257)\nconcernant le filtrage des listes de branches, j'ai écrit un\n[script](https://gitlab.com/gitlab-da/use-cases/gitlab-api/gitlab-api-python/-/tree/main)\naidant à cela. La méthode `branches.list()` renvoie tous les objets de\nbranche stockés dans une liste temporaire, pour un traitement ultérieur en\ndeux boucles : la collecte des noms de branches fusionnées, et celle des\nnoms de branches non fusionnées. L'attribut `merged` sur l'objet `branch`\nest une valeur booléenne qui indique si la branche a été fusionnée ou non.\n\n\n```python\n\nproject = gl.projects.get(PROJECT_ID, lazy=False, pagination=\"keyset\",\norder_by=\"updated_at\", per_page=100)\n\n\n# Get all branches\n\nreal_branches = []\n\nfor branch in project.branches.list():\n    real_branches.append(branch)\n\nprint(\"All branches\")\n\nfor rb in real_branches:\n    print(\"Branch: {b}\".format(b=rb.name))\n\n# Get all merged branches\n\nmerged_branches_names = []\n\nfor branch in real_branches:\n    if branch.default:\n        continue # ignore the default branch for merge status\n\n    if branch.merged:\n        merged_branches_names.append(branch.name)\n\nprint(\"Branches merged: {b}\".format(b=\", \".join(merged_branches_names)))\n\n\n# Get un-merged branches\n\nnot_merged_branches_names = []\n\nfor branch in real_branches:\n    if branch.default:\n        continue # ignore the default branch for merge status\n\n    if not branch.merged:\n        not_merged_branches_names.append(branch.name)\n\nprint(\"Branches not merged: {b}\".format(b=\",\n\".join(not_merged_branches_names)))\n\n```\n\n\nLe workflow est destiné à être lu étape par étape. Vous pouvez vous\nentraîner à optimiser le code Python pour la collecte conditionnelle des\nnoms de branches.\n\n\n### Afficher les paramètres du projet pour examen : règles d'approbation des\nmerge requests\n\n\nLe\n[script](https://gitlab.com/gitlab-da/use-cases/gitlab-api/gitlab-api-python/-/blob/main/get_mr_approval_rules.py)\nsuivant parcourt tous les objets de projet collectés et vérifie si des\nrègles d'approbation sont spécifiées. Si la longueur de la liste est\nsupérieure à zéro, il parcourt la liste en boucle et affiche les paramètres\navec la méthode JSON pretty print.\n\n\n```python\n    # Loop over projects and print the settings\n    # https://python-gitlab.readthedocs.io/en/stable/gl_objects/merge_request_approvals.html\n    for project in projects:\n        if len(project.approvalrules.list()) > 0:\n            #print(project) #debug\n            print(\"# Project: {name}, ID: {id}\\n\\n\".format(name=project.name_with_namespace, id=project.id))\n            print(\"[MR Approval settings]({url}/-/settings/merge_requests)\\n\\n\".format(url=project.web_url))\n\n            for ar in project.approvalrules.list():\n                print(\"## Approval rule: {name}, ID: {id}\".format(name=ar.name, id=ar.id))\n                print(\"\\n```json\\n\")\n                print(json.dumps(ar.attributes, indent=2)) # TODO: can be more beautiful, but serves its purpose with pretty print JSON\n                print(\"\\n```\\n\")\n\n```\n\n\n### Inventaire : obtenir toutes les variables CI/CD protégées ou masquées\n\n\nLes [variables CI/CD](https://docs.gitlab.com/ee/ci/variables/ \"Variables\nCI/CD\") sont utiles au paramétrage des pipelines et peuvent être configurées\nglobalement sur l'instance, dans les groupes et dans les projets. Nous\npouvons aussi y stocker des informations confidentielles, des mots de passe\nou encore des secrets. Il peut parfois être nécessaire d’avoir une vue\nd'ensemble de toutes les variables CI/CD protégées ou masquées pour estimer\nle nombre de variables à actualiser, lors de la rotation des jetons par\nexemple.\n\n\nLe\n[script](https://gitlab.com/gitlab-da/use-cases/gitlab-api/gitlab-api-python/-/blob/main/get_all_cicd_variables_masked_or_protected.py)\nsuivant récupère tous les groupes et projets, puis tente de collecter les\nvariables CI/CD de l'instance globale (cela nécessite des autorisations\nd'administrateur), des groupes et des projets (cela nécessite des\nautorisations de chargé de maintenance/propriétaire). Il affiche toutes les\nvariables CI/CD qui sont soit protégées, soit masquées, en précisant qu'une\nvaleur potentiellement secrète y est stockée.\n\n\n```python\n\n#!/usr/bin/env python\n\n\nimport gitlab\n\nimport os\n\nimport sys\n\n\n# Helper function to evaluate secrets and print the variables\n\ndef eval_print_var(var):\n    if var.protected or var.masked:\n        print(\"🛡️🛡️🛡️ Potential secret: Variable '{name}', protected {p}, masked: {m}\".format(name=var.key,p=var.protected,m=var.masked))\n\nGITLAB_SERVER = os.environ.get('GL_SERVER', 'https://gitlab.com')\n\nGITLAB_TOKEN = os.environ.get('GL_TOKEN') # token requires maintainer+\npermissions. Instance variables require admin access.\n\nPROJECT_ID = os.environ.get('GL_PROJECT_ID') #optional\n\nGROUP_ID = os.environ.get('GL_GROUP_ID', 8034603) #\nhttps://gitlab.com/everyonecancontribute\n\n\nif not GITLAB_TOKEN:\n    print(\"🤔 Please set the GL_TOKEN env variable.\")\n    sys.exit(1)\n\ngl = gitlab.Gitlab(GITLAB_SERVER, private_token=GITLAB_TOKEN)\n\n\n# Collect all projects, or prefer projects from a group id, or a project id\n\nprojects = []\n\n# Collect all groups, or prefer group from a group id\n\ngroups = []\n\n\n# Direct project ID\n\nif PROJECT_ID:\n    projects.append(gl.projects.get(PROJECT_ID))\n\n# Groups and projects inside\n\nelif GROUP_ID:\n    group = gl.groups.get(GROUP_ID)\n\n    for project in group.projects.list(include_subgroups=True, all=True):\n        # https://python-gitlab.readthedocs.io/en/stable/gl_objects/groups.html#examples\n        manageable_project = gl.projects.get(project.id)\n        projects.append(manageable_project)\n\n    groups.append(group)\n\n# All projects/groups on the instance (may take a while to process, use\niterators to fetch on-demand).\n\nelse:\n    projects = gl.projects.list(iterator=True)\n    groups = gl.groups.list(iterator=True)\n\nprint(\"# List of all CI/CD variables marked as secret (instance, groups,\nprojects)\")\n\n\n# https://python-gitlab.readthedocs.io/en/stable/gl_objects/variables.html\n\n\n# Instance variables (if the token has permissions)\n\nprint(\"Instance variables, if accessible\")\n\ntry:\n    for i_var in gl.variables.list(iterator=True):\n        eval_print_var(i_var)\nexcept:\n    print(\"No permission to fetch global instance variables, continueing without.\")\n    print(\"\\n\")\n\n# group variables (maintainer permissions for groups required)\n\nfor group in groups:\n    print(\"Group {n}, URL: {u}\".format(n=group.full_path, u=group.web_url))\n    for g_var in group.variables.list(iterator=True):\n        eval_print_var(g_var)\n\n    print(\"\\n\")\n\n# Loop over projects and print the settings\n\nfor project in projects:\n    # skip archived projects, they throw 403 errors\n    if project.archived:\n        continue\n\n    print(\"Project {n}, URL: {u}\".format(n=project.path_with_namespace, u=project.web_url))\n    for p_var in project.variables.list(iterator=True):\n        eval_print_var(p_var)\n\n    print(\"\\n\")\n```\n\n\nLe script n’affiche pas les valeurs des variables, cela étant réservé comme\nexercice pour les environnements sécurisés. Pour stocker des secrets, faites\nplutôt appel à des [fournisseurs\nexternes](https://docs.gitlab.com/ee/ci/secrets/).\n\n\n### Télécharger un fichier depuis le dépôt\n\n\nL'objectif de ce\n[script](https://gitlab.com/gitlab-da/use-cases/gitlab-api/gitlab-api-python/-/blob/main/get_raw_file_content.py)\nest de télécharger un fichier à partir d’un chemin spécifié dans une branche\ndonnée, et de stocker son contenu dans un nouveau fichier.\n\n\n```python\n\n# Goal: Try to download README.md from\nhttps://gitlab.com/gitlab-de/use-cases/gitlab-api/gitlab-api-python/-/blob/main/README.md\n\nFILE_NAME = 'README.md'\n\nBRANCH_NAME = 'main'\n\n\n# Search the file in the repository tree and get the raw blob\n\nfor f in project.repository_tree():\n    print(\"File path '{name}' with id '{id}'\".format(name=f['name'], id=f['id']))\n\n    if f['name'] == FILE_NAME:\n        f_content = project.repository_raw_blob(f['id'])\n        print(f_content)\n\n# Alternative approach: Get the raw file from the main branch\n\nraw_content = project.files.raw(file_path=FILE_NAME, ref=BRANCH_NAME)\n\nprint(raw_content)\n\n\n# Store the file on disk\n\nwith open('raw_README.md', 'wb') as f:\n    project.files.raw(file_path=FILE_NAME, ref=BRANCH_NAME, streamed=True, action=f.write)\n```\n\n\n### Aide à la migration : lister tous les clusters Kubernetes basés sur des\ncertificats\n\n\nL'intégration des clusters\n[Kubernetes](https://about.gitlab.com/fr-fr/blog/kubernetes-the-container-orchestration-solution/\n\"Qu'est-ce que Kubernetes ?\") basée sur des certificats dans GitLab [a été\ndépréciée](https://docs.gitlab.com/ee/update/deprecations.html#self-managed-certificate-based-integration-with-kubernetes).\nPour faciliter les plans de migration, l'inventaire des groupes et projets\nexistants peut être automatisé à l'aide de l'API GitLab.\n\n\n```python\n\ngroups = [ ]\n\n\n# get GROUP_ID group\n\ngroups.append(gl.groups.get(GROUP_ID))\n\n\nfor group in groups:\n    for sg in group.subgroups.list(include_subgroups=True, all=True):\n        real_group = gl.groups.get(sg.id)\n        groups.append(real_group)\n\ngroup_clusters = {}\n\nproject_clusters = {}\n\n\nfor group in groups:\n    #Collect group clusters\n    g_clusters = group.clusters.list()\n\n    if len(g_clusters) > 0:\n        group_clusters[group.id] = g_clusters\n\n    # Collect all projects in group and subgroups and their clusters\n    projects = group.projects.list(include_subgroups=True, all=True)\n\n    for project in projects:\n        # https://python-gitlab.readthedocs.io/en/stable/gl_objects/groups.html#examples\n        manageable_project = gl.projects.get(project.id)\n\n        # skip archived projects\n        if project.archived:\n            continue\n\n        p_clusters = manageable_project.clusters.list()\n\n        if len(p_clusters) > 0:\n            project_clusters[project.id] = p_clusters\n\n# Print summary\n\nprint(\"## Group clusters\\n\\n\")\n\nfor g_id, g_clusters in group_clusters.items():\n    url = gl.groups.get(g_id).web_url\n    print(\"Group ID {g_id}: {u}\\n\\n\".format(g_id=g_id, u=url))\n    print_clusters(g_clusters)\n\nprint(\"## Project clusters\\n\\n\")\n\nfor p_id, p_clusters in project_clusters.items():\n    url = gl.projects.get(p_id).web_url\n    print(\"Project ID {p_id}: {u}\\n\\n\".format(p_id=p_id, u=url))\n    print_clusters(p_clusters)\n```\n\n\n[Consultez le script\ncomplet](https://gitlab.com/gitlab-da/use-cases/gitlab-api/gitlab-api-python/-/blob/main/list_cert_based_kubernetes_clusters.py).\n\n\n### Productivité des équipes : vérifier si les merge requests existantes\nnécessitent un rebase après avoir fusionné une merge request de\nrefactorisation majeure\n\n\nLe dépôt du [manuel GitLab](https://about.gitlab.com/handbook/ \"Manuel de\nGitLab\") est un large monorepo qui contient de nombreuses merge requests\ncréées, examinées, approuvées et fusionnées. Certaines revues prennent plus\nde temps que d'autres, et certaines merge requests impactent plusieurs\npages, lorsqu'il s'agit par exemple de renommer une chaîne de caractères ou\n[toutes les pages du\nmanuel](https://about.gitlab.com/handbook/about/#count-handbook-pages). Le\nmanuel Marketing avait besoin d’une restructuration (pensez à une\nrefactorisation du code), et de nombreux répertoires et chemins d'accès ont\nété déplacés ou renommés. \n\n\nLes [tâches liées aux\ntickets](https://gitlab.com/gitlab-com/www-gitlab-com/-/issues/13991#tasks)\nont augmenté au fil du temps, et nous craignons que des conflits sur\nd'autres merge requests apparaissent après avoir fusionné des changements\nimportants. Avec python-gitlab vous pouvez récupérer toutes les merge\nrequests dans un projet donné, y compris les détails sur la branche Git, sur\nles chemins sources modifiés, et bien plus encore.\n\n\nLe script résultant configure une liste des sources touchées par toutes les\nmerge requests, vérifie si la merge request diffère avec `mr.diffs.list()`,\net si un modèle correspond à la valeur dans `old_path`. Si une\ncorrespondance est trouvée, le script l'enregistre et sauvegarde la merge\nrequest dans le dictionnaire `seen_mr`, pour un résumé ultérieur. Des\nattributs supplémentaires sont collectés pour afficher une liste de tâches\nen Markdown contenant des URL, afin de faciliter le copier-coller dans les\n[descriptions des\ntickets](https://gitlab.com/gitlab-com/www-gitlab-com/-/issues/13991#additional-tasks).\n[Consultez le script\ncomplet](https://gitlab.com/gitlab-da/use-cases/gitlab-api/gitlab-api-python/-/blob/main/search_mr_contains_updated_path.py).\n\n\n```python\n\nPATH_PATTERNS = [\n    'path/to/handbook/source/page.md',\n]\n\n\n# Only list opened MRs\n\n#\nhttps://python-gitlab.readthedocs.io/en/stable/gl_objects/merge_requests.html#project-merge-requests\n\nmrs = project.mergerequests.list(state='opened', iterator=True)\n\n\nseen_mr = {}\n\n\nfor mr in mrs:\n    # https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-request-diffs\n    real_mr = project.mergerequests.get(mr.get_id())\n    real_mr_id = real_mr.attributes['iid']\n    real_mr_url = real_mr.attributes['web_url']\n\n    for diff in real_mr.diffs.list(iterator=True):\n        real_diff = real_mr.diffs.get(diff.id)\n\n        for d in real_diff.attributes['diffs']:\n            for p in PATH_PATTERNS:\n                if p in d['old_path']:\n                    print(\"MATCH: {p} in MR {mr_id}, status '{s}', title '{t}' - URL: {mr_url}\".format(\n                        p=p,\n                        mr_id=real_mr_id,\n                        s=mr_status,\n                        t=real_mr.attributes['title'],\n                        mr_url=real_mr_url))\n\n                    if not real_mr_id in seen_mr:\n                        seen_mr[real_mr_id] = real_mr\n\nprint(\"\\n# MRs to update\\n\")\n\n\nfor id, real_mr in seen_mr.items():\n    print(\"- [ ] !{mr_id} - {mr_url}+ Status: {s}, Title: {t}\".format(\n        mr_id=id,\n        mr_url=real_mr.attributes['web_url'],\n        s=real_mr.attributes['detailed_merge_status'],\n        t=real_mr.attributes['title']))\n```\n\n\n## Cas d’utilisation DevSecOps pour les actions d'écriture de l’API\n\n\nLe jeton d'accès authentifié nécessite une [portée d’autorisation complète\nde\nl’API](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#personal-access-token-scopes). \n\n\nLes cas d’utilisation suivants sont abordés :\n\n- Déplacer des epics d’un groupe à l’autre,\n\n- Conformité : vérifier que les paramètres du projet ne sont pas remplacés,\n\n- Prendre des notes, générer un aperçu de la date d'échéance,\n\n\n### Déplacer des epics d’un groupe à l’autre\n\n\nVous devez parfois déplacer des epics dans un autre groupe. Une question\nposée dans le Slack de GitLab nous a incité à examiner une [proposition de\nfonctionnalité pour l'interface\nutilisateur](https://gitlab.com/gitlab-org/gitlab/-/issues/12689), pour plus\ntard écrire un script API permettant d'automatiser ces étapes. L'idée\nconsiste à déplacer une epic d'un groupe source vers un groupe cible, et de\ncopier son titre, sa description et ses labels. Puisque les epics permettent\nde regrouper les tickets, elles doivent également être réaffectées à l'epic\ncible. Il faut aussi prendre en compte les relations parent-enfant des\nepics, toutes les epics enfants des epics sources devant être réaffectées à\nl'epic cible.\n\n\nLe script suivant recherche d'abord tous les attributs de l'epic source,\npuis crée une nouvelle epic cible avec des attributs minimaux : titre et\ndescription. La liste des labels est copiée et les modifications sont\nconservées grâce à l'appel `save()`. Les tickets attribués à l'epic doivent\nêtre recréés dans l'epic cible. L'appel `create()` crée l'élément de\nrelation, et non un nouvel objet de ticket en tant que tel. Le déplacement\ndes epics enfants nécessite une approche différente, car la relation est\ninversée : le `parent_id` de l'epic enfant doit être comparé à l'identifiant\nde l'epic source et, s'il correspond, mis à jour vers l'identifiant de\nl'epic cible. Après avoir tout copié avec succès, l'epic source doit être\npassée à l'état `closed`.\n\n\n```python\n\n#!/usr/bin/env python\n\n\n# Description: Show how epics can be moved between groups, including title,\ndescription, labels, child epics and issues.\n\n# Requirements: python-gitlab Python libraries. GitLab API write access, and\nmaintainer access to all configured groups/projects.\n\n# Author: Michael Friedrich \u003Cmfriedrich@gitlab.com>\n\n# License: MIT, (c) 2023-present GitLab B.V.\n\n\nimport gitlab\n\nimport os\n\nimport sys\n\n\nGITLAB_SERVER = os.environ.get('GL_SERVER', 'https://gitlab.com')\n\n# https://gitlab.com/gitlab-da/use-cases/gitlab-api\n\nSOURCE_GROUP_ID = os.environ.get('GL_SOURCE_GROUP_ID', 62378643)\n\n# https://gitlab.com/gitlab-da/use-cases/gitlab-api/epic-move-target\n\nTARGET_GROUP_ID = os.environ.get('GL_TARGET_GROUP_ID', 62742177)\n\n# https://gitlab.com/groups/gitlab-da/use-cases/gitlab-api/-/epics/1\n\nEPIC_ID = os.environ.get('GL_EPIC_ID', 1)\n\nGITLAB_TOKEN = os.environ.get('GL_TOKEN')\n\n\nif not GITLAB_TOKEN:\n    print(\"Please set the GL_TOKEN env variable.\")\n    sys.exit(1)\n\ngl = gitlab.Gitlab(GITLAB_SERVER, private_token=GITLAB_TOKEN)\n\n\n# Main\n\n# Goal: Move epic to target group, including title, body, labels, and child\nepics and issues.\n\nsource_group = gl.groups.get(SOURCE_GROUP_ID)\n\ntarget_group = gl.groups.get(TARGET_GROUP_ID)\n\n\n# Create a new target epic and copy all its items, then close the source\nepic.\n\nsource_epic = source_group.epics.get(EPIC_ID)\n\n# print(source_epic) #debug\n\n\nepic_title = source_epic.title\n\nepic_description = source_epic.description\n\nepic_labels = source_epic.labels\n\nepic_issues = source_epic.issues.list()\n\n\n# Create the epic with minimal attributes\n\ntarget_epic = target_group.epics.create({\n    'title': epic_title,\n    'description': epic_description,\n})\n\n\n# Assign the list\n\ntarget_epic.labels = epic_labels\n\n\n# Persist the changes in the new epic\n\ntarget_epic.save()\n\n\n# Epic issues need to be re-assigned in a loop\n\nfor epic_issue in epic_issues:\n    ei = target_epic.issues.create({'issue_id': epic_issue.id})\n\n# Child epics need to update their parent_id to the new epic\n\n# Need to search in all epics, use lazy object loading\n\nfor sge in source_group.epics.list(lazy=True):\n    # this epic has the source epic as parent epic?\n    if sge.parent_id == source_epic.id:\n        # Update the parent id\n        sge.parent_id = target_epic.id\n        sge.save()\n\nprint(\"Copied source epic {source_id} ({source_url}) to target epic\n{target_id} ({target_url})\".format(\n    source_id=source_epic.id, source_url=source_epic.web_url,\n    target_id=target_epic.id, target_url=target_epic.web_url))\n\n# Close the old epic\n\nsource_epic.state_event = 'close'\n\nsource_epic.save()\n\nprint(\"Closed source epic {source_id} ({source_url})\".format(\n    source_id=source_epic.id, source_url=source_epic.web_url))\n```\n\n\n```shell\n\n$  python3 move_epic_between_groups.py\n\nCopied source epic 725341\n(https://gitlab.com/groups/gitlab-da/use-cases/gitlab-api/-/epics/1) to\ntarget epic 725358\n(https://gitlab.com/groups/gitlab-da/use-cases/gitlab-api/epic-move-target/-/epics/6)\n\nClosed source epic 725341\n(https://gitlab.com/groups/gitlab-da/use-cases/gitlab-api/-/epics/1)\n\n```\n\n\nL'[epic\ncible](https://gitlab.com/groups/gitlab-da/use-cases/gitlab-api/epic-move-target/-/epics/5\n\"Epic cible\") a été créée et affiche le résultat attendu : même titre,\ndescription, labels, epic enfant et tickets. \n\n\n![Tutoriel sur l'API GitLab : déplacer des\nepics](https://about.gitlab.com/images/blogimages/efficient-devsecops-workflows-python-gitlab-handson/python_gitlab_moved_epic_with_all_attributes.png){:\n.shadow}\n\n\n__Exercice :__ le script ne copie pas encore les\n[commentaires](https://python-gitlab.readthedocs.io/en/stable/gl_objects/notes.html)\net les [fils de\ndiscussion](https://python-gitlab.readthedocs.io/en/stable/gl_objects/discussions.html).\nFaites des recherches et aidez-nous à mettre à jour le script. Les merge\nrequests sont les bienvenues !\n\n\n### Conformité : vérifier que les paramètres du projet ne sont pas remplacés\n\n\nLes paramètres des projets et des groupes peuvent être modifiés\naccidentellement par des membres de l'équipe. Les exigences de conformité\ndoivent être respectées. Autre cas d’utilisation : gérer la configuration\navec des outils d’[Infrastructure as\nCode](https://about.gitlab.com/fr-fr/topics/gitops/infrastructure-as-code/\n\"Infrastructure as Code\") et s'assurer que la configuration de GitLab reste\nla même au niveau du groupe, du projet et autres. Des outils comme Ansible\nou Terraform peuvent invoquer un script API ou utiliser la bibliothèque\npython-gitlab pour effectuer des tâches de gestion des paramètres.\n\n\nDans l'exemple suivant, seule la branche `main` est protégée.\n\n\n![API python-gitlab : protection des\nbranches](https://about.gitlab.com/images/blogimages/efficient-devsecops-workflows-python-gitlab-handson/python_gitlab_protected_branches_settings_main.png){:\n.shadow}\n\n\nSupposons qu'une nouvelle branche `production` a été ajoutée et qu’elle doit\négalement être protégée. Le script suivant définit le dictionnaire des\nbranches protégées et leurs niveaux d'accès pour les autorisations de push\net de fusion au niveau du chargé de maintenance. Il établit la logique de\ncomparaison de la [documentation python-gitlab sur les branches\nprotégées](https://python-gitlab.readthedocs.io/en/stable/gl_objects/protected_branches.html).\n\n\n```python\n\n#!/usr/bin/env python\n\n\nimport gitlab\n\nimport os\n\nimport sys\n\n\nGITLAB_SERVER = os.environ.get('GL_SERVER', 'https://gitlab.com')\n\n# https://gitlab.com/gitlab-da/use-cases/\n\nGROUP_ID = os.environ.get('GL_GROUP_ID', 16058698)\n\nGITLAB_TOKEN = os.environ.get('GL_TOKEN')\n\n\nPROTECTED_BRANCHES = {\n    'main': {\n        'merge_access_level': gitlab.const.AccessLevel.MAINTAINER,\n        'push_access_level': gitlab.const.AccessLevel.MAINTAINER\n    },\n    'production': {\n        'merge_access_level': gitlab.const.AccessLevel.MAINTAINER,\n        'push_access_level': gitlab.const.AccessLevel.MAINTAINER\n    },\n}\n\n\nif not GITLAB_TOKEN:\n    print(\"Please set the GL_TOKEN env variable.\")\n    sys.exit(1)\n\ngl = gitlab.Gitlab(GITLAB_SERVER, private_token=GITLAB_TOKEN)\n\n\n# Main\n\ngroup = gl.groups.get(GROUP_ID)\n\n\n# Collect all projects in group and subgroups\n\nprojects = group.projects.list(include_subgroups=True, all=True)\n\n\nfor project in projects:\n    # Retrieve a full manageable project object\n    # https://python-gitlab.readthedocs.io/en/stable/gl_objects/groups.html#examples\n    manageable_project = gl.projects.get(project.id)\n\n    # https://python-gitlab.readthedocs.io/en/stable/gl_objects/protected_branches.html\n    protected_branch_names = []\n\n    for pb in manageable_project.protectedbranches.list():\n        manageable_protected_branch = manageable_project.protectedbranches.get(pb.name)\n        print(\"Protected branch name: {n}, merge_access_level: {mal}, push_access_level: {pal}\".format(\n            n=manageable_protected_branch.name,\n            mal=manageable_protected_branch.merge_access_levels,\n            pal=manageable_protected_branch.push_access_levels\n        ))\n\n        protected_branch_names.append(manageable_protected_branch.name)\n\n    for branch_to_protect, levels in PROTECTED_BRANCHES.items():\n        # Fix missing protected branches\n        if branch_to_protect not in protected_branch_names:\n            print(\"Adding branch {n} to protected branches settings\".format(n=branch_to_protect))\n            p_branch = manageable_project.protectedbranches.create({\n                'name': branch_to_protect,\n                'merge_access_level': gitlab.const.AccessLevel.MAINTAINER,\n                'push_access_level': gitlab.const.AccessLevel.MAINTAINER\n            })\n```\n\n\nL'exécution du script affiche la branche `main` existante, ainsi qu’une note\nindiquant que la branche `production` sera mise à jour. La capture d'écran\ndes paramètres du dépôt démontre cette action.\n\n\n```\n\n$ python3\nenforce_protected_branches.py                                               \n─╯\n\nProtected branch name: main, merge_access_level: [{'id': 67294702,\n'access_level': 40, 'access_level_description': 'Maintainers', 'user_id':\nNone, 'group_id': None}], push_access_level: [{'id': 68546039,\n'access_level': 40, 'access_level_description': 'Maintainers', 'user_id':\nNone, 'group_id': None}]\n\nAdding branch production to protected branches settings\n\n```\n\n\n![Capture d'écran de code en Python avec\nGitLab](https://about.gitlab.com/images/blogimages/efficient-devsecops-workflows-python-gitlab-handson/python_gitlab_protected_branches_settings_main_production.png){:\n.shadow}\n\n\n### Prise de notes : générer un aperçu de la date d'échéance\n\n\nUne [discussion de Hacker News sur les outils de prise de\nnotes](https://news.ycombinator.com/item?id=32155848) nous a inspiré la\ncréation d'un tableau Markdown, extrait de fichiers de prise de notes, et\ntrié par date d'échéance. Le script est plus complexe à comprendre.\n",[236,759,850,760],"DevSecOps",{"slug":852,"featured":6,"template":686},"efficient-devsecops-workflows-hands-on-python-gitlab-api-automation","content:fr-fr:blog:efficient-devsecops-workflows-hands-on-python-gitlab-api-automation.yml","Efficient Devsecops Workflows Hands On Python Gitlab Api Automation","fr-fr/blog/efficient-devsecops-workflows-hands-on-python-gitlab-api-automation.yml","fr-fr/blog/efficient-devsecops-workflows-hands-on-python-gitlab-api-automation",{"_path":858,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":859,"content":865,"config":874,"_id":876,"_type":16,"title":877,"_source":18,"_file":878,"_stem":879,"_extension":21},"/fr-fr/blog/take-advantage-of-git-rebase",{"title":860,"description":861,"ogTitle":860,"ogDescription":861,"noIndex":6,"ogImage":862,"ogUrl":863,"ogSiteName":723,"ogType":724,"canonicalUrls":863,"schema":864},"Améliorez votre workflow avec Git rebase","Exploitez les fonctionnalités de Git rebase pour améliorer votre workflow.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665560/Blog/Hero%20Images/speedmonorepo.jpg","https://about.gitlab.com/blog/take-advantage-of-git-rebase","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Améliorez votre workflow avec Git rebase\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christian Couder\"}],\n        \"datePublished\": \"2022-10-06\",\n      }",{"title":860,"description":861,"authors":866,"heroImage":862,"date":868,"body":869,"category":14,"tags":870,"updatedDate":873},[867],"Christian Couder","2022-10-06","Les merge requests permettent à l'équipe de développement logiciel de passer en revue les modifications du code avant de les intégrer au projet principal. De nos jours, cette tâche prend beaucoup de temps. Découvrez comment [Git rebase](https://git-scm.com/docs/git-rebase/fr) peut vous aider à accélérer ces cycles de revues de code. Commençons par certaines\nconsidérations relatives au workflow.\n\n## Comment rectifier le code d'une merge request ? \n\nUn développeur qui a travaillé sur des modifications de code et a créé une merge request pour les intégrer au projet devra souvent procéder à des ajustements ou des corrections. Pourquoi ? Parce que certains tests peuvent échouer, des bogues peuvent être découverts, ou les relecteurs peuvent suggérer des améliorations et repérer des anomalies.\n\n### Méthode simple, mais désordonnée : multiplier les validations\n\nPour rectifier le code de la merge request, vous pouvez simplement apporter d'autres modifications par l'intermédiaire de nouvelles validations sur la branche utilisée pour créer la merge request, puis effectuer à nouveau un push de la branche afin de mettre à jour la merge request.\n\nCependant, lorsque plusieurs validations ont été ajoutées de cette manière, la merge request peut devenir un vrai défi :\n\n- Il est difficile d'effectuer une revue de code de toutes les modifications en les examinant toutes ensemble.\n- Il est difficile d'examiner les validations séparément, car elles peuvent contenir des modifications différentes sans rapport entre elles, voire de plusieurs versions d'un même code.\n\nLes relecteurs préfèrent souvent examiner les modifications de code réparties sur plusieurs petites validations autonomes pouvant faire l'objet de revues de code individuelles.\n\n### Méthode de professionnels : rebaser !\n\nLe meilleur moyen de préparer ou de rectifier le code d'une merge request consiste à toujours s'assurer que chaque validation contient de petites modifications, indépendantes et faciles à réviser.\n\nChaque validation de la branche peut nécessiter des ajustements, plutôt que d'ajouter de nouvelles validations. De prime abord plus complexe et fastidieuse, cette approche dispose d'une botte secrète : `git rebase` !\n\n## Rectifier vos validations avec `git rebase`\n\nSi votre objectif consiste à créer une merge request à partir d'une série de petites validations indépendantes, il est possible que votre branche nécessite un travail précis de rectification avant que ses validations ne soient suffisamment fiables. Une fois les validations prêtes, vous pouvez effectuer un push de la branche et mettre à jour ou créer une merge request avec cette branche.\n\n### Démarrer un rebasage interactif\n\nSi votre branche est basée sur la branche principale `main`, la commande pour rectifier votre branche est la suivante :\n\n```plaintext\ngit rebase -i main\n```\n\nCréer [un alias Git](https://git-scm.com/book/fr/v2/Les-bases-de-Git-Les-alias-Git), un alias shell ou encore une fonction shell pour cette commande pourra s'avérer très pratique dans la mesure où vous l'utiliserez très souvent.\n\nL'option `-i` passée à `git rebase` est un alias pour `--interactive`. Elle lance [un rebasage « interactif »](https://git-scm.com/docs/git-rebase/fr#git-rebase---interactive) qui ouvrira votre éditeur de code. Vous y trouverez une liste des validations de votre branche, suivie de lignes de commentaires commençant par `#`. \n\nVoici à quoi ressemble la liste des validations :\n\n```plaintext\npick 1aac632db2 first commit subject\npick a385014ad4 second commit subject\npick 6af12a88cf other commit subject\npick 5cd121e2a1 last commit subject\n```\n\nCes lignes sont des instructions sur la façon dont `git rebase` doit traiter ces validations. Les validations sont listées dans l'ordre chronologique, la validation la plus ancienne apparaissant en tête. (Cet ordre est l'inverse de l'ordre par défaut de `git log`.) Que contiennent ces lignes ?\n\n- Une instruction (dans cet exemple, `pick`) qui indique à Git l'action à entreprendre\n- Un identifiant abrégé de la validation\n- Un sujet qui vous aide à identifier le contenu de la validation\n\n### Modifier la liste des instructions\n\nVous pouvez modifier ces instructions ! Lorsque vous quittez votre éditeur de texte, `git rebase` lit les instructions que vous venez de modifier et les exécute dans l'ordre pour recréer votre branche comme vous le souhaitez.\n\nAprès les instructions pour toutes les validations, une série de lignes de commentaires explique comment modifier les lignes d'instruction, et comment chaque instruction affectera votre branche :\n\n- Si vous **supprimez la totalité de la ligne d'instruction d'une validation** de la liste,\ncette validation ne sera pas recréée.\n- Si vous **réorganisez les lignes d'instruction**, les validations seront\nrecréées dans l'ordre que vous spécifiez.\n- Si vous **changez l'action** de l'instruction `pick` en la remplaçant par exemple par\n`squash` ou `reword`, Git effectuera l'action que vous spécifiez sur cette\nvalidation.\n- Vous pouvez même **ajouter de nouvelles lignes d'instruction** avant, après ou entre\nles lignes actuelles.\n\nSi les lignes de commentaires ne sont pas suffisantes, vous pouvez trouver de plus amples informations sur ce que vous pouvez faire et le fonctionnement du rebasage Git dans les ressources suivantes :\n\n- Le chapitre [Utilitaires Git - Réécrire l'historique](https://git-scm.com/book/fr/v2/Utilitaires-Git-R%c3%a9%c3%a9crire-l%e2%80%99historique)\ndu livre « Pro Git ».\n- Le chapitre [Mode interactif](https://git-scm.com/docs/git-rebase/fr#_mode_interactif)\n  de la documentation `git rebase`.\n\n### Continuer ou abandonner le rebasage\n\nUn rebasage interactif peut être interrompu en cas de conflit (comme le ferait un rebasage\nstandard) ou si vous avez utilisé une instruction telle que `edit` dans la\nligne d'instruction. Cela vous permet d'apporter certaines modifications : vous pouvez, par exemple, diviser la validation actuelle en deux validations distinctes ou résoudre le conflit de rebasage le cas échéant. Ensuite, deux options s'offrent à vous :\n\n- Continuer le rebasage interactif à l'aide de la commande `git rebase --continue`.\n- Abandonner le rebasage à l'aide de la commande `git rebase --abort`.\n\n(Ces options `git rebase` fonctionnent également lorsqu'un rebasage standard, non interactif,\ns'arrête).\n\n## Autres conseils et avantages\n\n### Essayer les différentes instructions\n\nNous vous recommandons d'essayer les différentes instructions que vous pouvez utiliser dans\nchaque ligne d'instruction, en particulier `reword`, `edit`, `squash` et `fixup`. Vous\npouvez utiliser les versions abrégées de ces instructions : `r`, \n`e`, `s` et `f`.\n\n### Exécuter des commandes shell dans votre rebasage\n\nVous avez peut-être remarqué l'instruction `exec \u003Ccommand>` qui vous permet d'exécuter une commande shell quelle qu'elle soit à tout moment pendant le rebasage interactif. Cette commande sera plus utile pour les rebasages non interactifs, par exemple :\n\n```plaintext\ngit rebase --exec 'make test' main\n```\n\n(Il ne s'agit pas d'un rebasage interactif, car il ne contient pas l'option `-i`).\n\nL'option `--exec \u003Ccommand>` vous permet d'exécuter une commande shell après\nchaque validation rebasée, avec un arrêt du rebase dans le cas où la commande shell échoue (ce qui est signalé par un code de sortie différent de zéro).\n\n### Tester l'ensemble de vos validations\n\nEn passant la commande adéquate qui compile votre logiciel et exécute ses tests (par exemple, `make test`) à l'option `--exec`, vous pouvez vérifier que chaque validation dans votre branche se compile correctement et passe les tests.\n\nSi la commande `make test` échoue, le processus de rebasage s'arrêtera. Vous pouvez alors corriger la validation en cours immédiatement, puis poursuivre le rebasage afin de tester les validations suivantes.\n\nVérifier que la compilation de chaque validation s'effectue correctement et passe tous les tests permet de s'assurer que votre code reste opérationnel. Ceci est particulièrement utile si vous souhaitez utiliser [Git bisect](https://git-scm.com/docs/git-bisect/fr) quand vous rencontrez des régressions.\n\n## Conclusion\n\nDans Git, le rebasage est un outil très polyvalent et très utile pour rectifier le code\ndes validations. Il permet de mettre en place un workflow avec des modifications qualitatives\nproposées dans des validations et des merge requests bien structurées. Développeurs et relecteurs\nn'en seront que plus efficaces. Les revues de code et le débogage gagnent également en facilité et en efficacité.\n",[735,871,872,759],"workflow","releases","2024-11-14",{"slug":875,"featured":6,"template":686},"take-advantage-of-git-rebase","content:fr-fr:blog:take-advantage-of-git-rebase.yml","Take Advantage Of Git Rebase","fr-fr/blog/take-advantage-of-git-rebase.yml","fr-fr/blog/take-advantage-of-git-rebase",{"_path":881,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":882,"content":888,"config":896,"_id":898,"_type":16,"title":899,"_source":18,"_file":900,"_stem":901,"_extension":21},"/fr-fr/blog/observability-vs-monitoring-in-devops",{"title":883,"description":884,"ogTitle":883,"ogDescription":884,"noIndex":6,"ogImage":885,"ogUrl":886,"ogSiteName":723,"ogType":724,"canonicalUrls":886,"schema":887},"DevOps : de la surveillance à l'observabilité","Vous souhaitez bénéficier d'une visibilité totale sur l'ensemble du cycle de développement de vos logiciels ? La réponse tient en un mot : l'observabilité.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665484/Blog/Hero%20Images/monitoring-update-feature-image.jpg","https://about.gitlab.com/blog/observability-vs-monitoring-in-devops","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"DevOps : de la surveillance à l'observabilité\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mike Vanbuskirk\"}],\n        \"datePublished\": \"2022-06-14\",\n      }",{"title":883,"description":884,"authors":889,"heroImage":885,"date":891,"body":892,"category":14,"tags":893,"updatedDate":895},[890],"Mike Vanbuskirk","2022-06-14","Presque toutes les infrastructures logicielles modernes comportent des fonctions de surveillance ou de journalisation. Lancé dans les années 1980, le protocole Syslog pour les systèmes Unix a constitué un premier exemple d'audit et d'analyse des opérations à l'intérieur d'un système. Il illustre l'importance d'un mécanisme de surveillance dédié et distinct sur le plan architectural.\n\nEn dépit de son importance, la surveillance (ou monitoring) est cependant trop souvent envisagée et utilisée après coup. Les informations des systèmes de journalisation ne sont pas agrégées ou analysées pour établir des diagnostics, tandis que les systèmes de surveillance installés des années auparavant ne sont pas mis aux normes.\n\nLe paysage opérationnel a cependant évolué, donnant naissance au concept d'observabilité. Plutôt que de former des hypothèses à partir de mesures statiques, l'observabilité apporte une vue d'ensemble du comportement d'une application, et permet de comprendre comment ses performances sont perçues par les utilisateurs et utilisatrices. \n\n## Qu’est-ce que l'observabilité ?\n\nL’observabilité est la collecte et l'analyse exhaustive des données de l'ensemble des composants d'un système informatique. Elle fournit des informations détaillées sur les applications de l'environnement, qui sont essentielles à la compréhension du fonctionnement des architectures dynamiques modernes, et notamment des plateformes dans le cloud. \n\nPour comprendre l’importance de l'observabilité, commençons par définir la notion de surveillance, ainsi que les informations que cette approche permet ou non de couvrir.\n\nLa surveillance consiste à mesurer certaines données et valeurs au sein d'un système ou d'un logiciel, et à en présenter les résultats. Les mesures les plus courantes sont l'utilisation d’un processeur, d’une mémoire vive, et des temps de réponse ou de latence. De même, les systèmes de journalisation classiques fournissent une information statique sur des événements survenus pendant le fonctionnement du système.\n\nLa surveillance fournit des mesures dans un contexte limité, pouvant indiquer un problème plus important dans le système. Les outils de surveillance traditionnels permettent d'agréger et de corréler les informations. Cependant, une configuration manuelle est souvent nécessaire afin d'obtenir une vue d'ensemble. \n\n### Observabilité ou monitoring\n\nAvec le temps, le concept de surveillance a dépassé les mesures statiques d'éléments tels que l'utilisation du processeur. Dans son célèbre ouvrage *Site Reliability Engineering*, Google souligne l'impératif de se concentrer sur quatre [Golden Signals (ou signaux d'or)](https://sre.google/sre-book/monitoring-distributed-systems/ \"Golden Signals de Google\") : \n- La latence : le temps nécessaire pour traiter une requête\n- Le trafic : la mesure du haut niveau de charge global\n- Les erreurs : le taux d'échec des requêtes\n- La saturation : la mesure de l'utilisation des ressources comme fraction de l'ensemble, consacrée généralement aux ressources limitées.\n\nBien que ces mesures aident à comprendre les performances globales du système, elles nécessitent encore un investissement technique tangible afin de concevoir, mettre en place et configurer un système de surveillance complet. L'énumération des modes de défaillance possible demande un effort considérable, tout comme la définition et l’association manuelle des corrélations, même pour des cas simples. \n\nEn revanche, l'observabilité offre une image beaucoup plus intuitive et complète, interopérable avec l'ensemble des modules du système. Ainsi, vous n'avez pas besoin de concevoir un tableau de bord agrégeant des outils de surveillance disparates. Une plateforme d'observabilité est suffisamment flexible pour présenter automatiquement les informations critiques dans le contexte adéquat. Les outils d'observabilité peuvent ainsi fournir aux équipes de développement un retour sur les performances des exécutions CI/CD et une information sur la qualité de leur code.\n\nEn fin de compte, l'observabilité informatique fournit une forme de débogage et de compréhension des erreurs plus globale. Les données d'observabilité d'un système peuvent mettre en évidence des incidents totalement nouveaux (*unknown unknowns*). Ce qui peut revêtir une importance capitale, comme le montre l'exemple fourni dans la section suivante.\n\n## Pourquoi privilégier l'observabilité ?\n\nL'observabilité aide à réduire le temps moyen de résolution (MTTR). Cela se traduit par des interruptions plus courtes, des applications plus performantes et une amélioration de l'expérience des utilisateurs. Si à première vue la surveillance peut sembler offrir les mêmes avantages, considérez l’anecdote suivante. \n\nUne équipe d'ingénieurs reçoit un message du service comptable. La facture des fournisseurs de service cloud est devenue si onéreuse que le directeur financier s'en est rendu compte. Les ingénieurs DevOps consultent le système de surveillance, mais en vain : chaque partie du système est au vert pour des éléments tels que la mémoire, le processeur et les entrées et sorties de disque. En réalité, la cause profonde provient d'un autre événement totalement inconnu. \n\nUne latence DNS dans les [pipelines CI/CD](https://docs.gitlab.com/ee/ci/pipelines/ \"Pipelines CI/CD de GitLab\") provoque un taux d'échec des compilations élevé, et les nouvelles tentatives consomment fortement les ressources cloud. Cependant, le phénomène ne perdure pas assez longtemps pour être repéré par le système de surveillance. En ajoutant des outils d'observabilité et en collectant tous les types d'événements dans l'environnement, l'équipe a pu enfin identifier la source du problème et y remédier. Avec un système de surveillance traditionnel, l'organisation aurait dû a priori connaître le problème de latence DNS pour pouvoir l'identifier.\n\nL'observabilité d'un système a également de l'importance pour les équipes non techniques et commerciales. La technologie étant de plus en plus prégnante au sein de chaque pilier d'activité d'un groupe, les indicateurs clés de performance de l'infrastructure logicielle se confondent avec ceux de l'entreprise. L'observabilité peut ainsi fournir une meilleure vision des indicateurs clés de performance, et des options utilisables en libre-service pour les différentes équipes.\n\nLa qualité de l'expérience utilisateur (UX) se doit d'être au cœur des logiciels et applications modernes. Comme l'illustre l'histoire précédente, la surveillance des mesures statiques ne suffit pas pour connaître l'ensemble des performances de l'expérience utilisateur ou du système. Des tableaux de bord apparemment sains peuvent cacher de graves problèmes. \n\n## Quelles sont les mesures clés de l'observabilité ?\n\nPour les entreprises qui souhaitent utiliser des outils d'observabilité, leur mise en œuvre passe par l'identification d’objectifs principaux de l'observabilité et de la manière dont elle peut être implémentée au sein de leur structure informatique.\n\nLes trois piliers de l'observabilité constituent un excellent point de départ :\n- Les journaux (ou logs) : le suivi des informations et des événements,\n- Les métriques : la mesure de métriques spécifiques et de données de performance,\n- Le traçage : l'enregistrement des performances des requêtes d'un bout à l'autre de leur exécution.\n\nS'ils ont pu paraître insurmontables au départ, des projets comme [OpenTelemetry](https://opentelemetry.io/ \"OpenTelemetry\") aident à standardiser les normes de journalisation, de métriques et de traçage, créant ainsi un écosystème plus cohérent et un retour sur investissement plus rapide pour les entreprises mettant en œuvre l'observabilité.\n\nDes données et des piliers supplémentaires pour l'observabilité incluent :\n\n- Le suivi des erreurs : des journaux à l'information plus fine et agrégée,\n- Le *Continuous Profiling* : l'évaluation de la performance du code en temps réel dans l'environnement de production\n- Le *Real User Monitoring (RUM)* : la surveillance de l'utilisateur réel pour comprendre les performances de l'application de son point de vue.\n\nUn thème commun émerge de l'examen de ces piliers. Un examen limité dans le temps et dans l'espace ne suffit plus. Les systèmes distribués modernes requièrent une vision globale. Pour comprendre les performances d'une application, il faut d’abord effectuer un échantillonnage au niveau du client réel, et effectuer ensuite une analyse complète de ses interactions avec l'ensemble des composants du logiciel.\n\nAu-delà de la surveillance traditionnelle des applications, l'observabilité contribue à améliorer l'excellence opérationnelle des équipes d'ingénierie. C'est souvent à partir de pannes réelles et des leçons que nous en tirons que nous concevons des programmes de surveillance efficaces. La mise en œuvre de l'ingénierie du chaos permet de tester les outils d'observabilité lors de défaillances réelles, mais dans un environnement contrôlé, avec des résultats connus à l'avance. Cette approche peut apporter des gains significatifs en termes d'équilibre opérationnel, dans des systèmes où des « inconnus inconnus » peuvent se cacher dans n'importe quel workflow de l'infrastructure IT. \n\n## L'observabilité, un élément essentiel de l’approche DevOps\n\nL'observabilité est essentielle pour les [équipes DevOps](https://about.gitlab.com/fr-fr/topics/devops/ \"DevOps\"), mais aussi pour l'ensemble de l'entreprise. En remplaçant les données statiques des solutions de surveillance traditionnelles, l'[observabilité](https://about.gitlab.com/blog/observability-is-key-to-cloud-native-transitions-and-modern-application-development/ \"Observabilité\") offre une vue complète de l'infrastructure applicative.\n\nLes équipes DevOps doivent collaborer avec toutes les parties prenantes pour améliorer la mise en œuvre de l'observabilité au sein de l'entreprise et s'assurer qu'elle profite à l'ensemble des équipes. Il est aussi important de former et de sensibiliser les équipes de développement aux avantages de l'observabilité.\n\nLes équipes DevOps peuvent également aider à identifier plus rapidement la cause première des incidents de production. Une bonne instrumentation du code des applications facilitera aussi la distinction entre problèmes de code et d'infrastructure. Enfin, en déplaçant l'observabilité plus en amont dans le cycle de conception logicielle, de possibles dévers dans les objectifs de niveau de service (SLO) peuvent être détectés plus tôt.\n\nLes équipes DevOps qui souhaitent améliorer significativement les performances des applications et les résultats de l'entreprise peuvent considérer l'observabilité comme un moyen d'atteindre ces deux objectifs.\n",[828,894,737],"security","2024-08-20",{"slug":897,"featured":6,"template":686},"observability-vs-monitoring-in-devops","content:fr-fr:blog:observability-vs-monitoring-in-devops.yml","Observability Vs Monitoring In Devops","fr-fr/blog/observability-vs-monitoring-in-devops.yml","fr-fr/blog/observability-vs-monitoring-in-devops",{"_path":903,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":904,"content":910,"config":919,"_id":921,"_type":16,"title":922,"_source":18,"_file":923,"_stem":924,"_extension":21},"/fr-fr/blog/demystifying-ci-cd-variables",{"title":905,"description":906,"ogTitle":905,"ogDescription":906,"noIndex":6,"ogImage":907,"ogUrl":908,"ogSiteName":723,"ogType":724,"canonicalUrls":908,"schema":909},"Variables d’environnement : tout savoir sur les variables CI/CD de GitLab","Les variables CI/CD permettent de contrôler les jobs et les pipelines. Découvrez tout ce que vous devez savoir sur les variables d'environnement de GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664679/Blog/Hero%20Images/blog-image-template-1800x945__24_.png","https://about.gitlab.com/blog/demystifying-ci-cd-variables","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Variables d’environnement : tout savoir sur les variables CI/CD de GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Veethika Mishra\"}],\n        \"datePublished\": \"2021-04-09\",\n      }",{"title":905,"description":906,"authors":911,"heroImage":907,"date":913,"body":914,"category":14,"tags":915,"updatedDate":918},[912],"Veethika Mishra","2021-04-09","Définir et utiliser des variables dans le cadre d'une approche [CI/CD](https://about.gitlab.com/fr-fr/topics/ci-cd/) s'avère une méthode très flexible. Ces variables sont d'une grande utilité pour contrôler les jobs et les pipelines, tout en vous permettant d'éviter de coder en dur des valeurs directement dans votre fichier de configuration `.gitlab-ci.yml`. \n\nDans [GitLab CI/CD](https://docs.gitlab.com/ee/ci/), les variables peuvent être utilisées pour personnaliser les jobs en définissant et en stockant des valeurs spécifiques. Pour définir vos variables CI/CD dans GitLab, accédez à **Paramètres >> CI/CD >> Variables** ou définissez-les simplement dans le fichier `.gitlab-ci.yml`. Sachez que les variables servent également d'alternative aux valeurs codées en dur.\n\nUtiliser des variables s’avère particulièrement utile pour configurer des services tiers dans différents environnements de déploiement, tels que l'environnement de test (`testing`), l'environnement de préproduction (`staging`), l'environnement de production (`production`), et plus encore. Pour modifier les services liés à ces environnements, il suffit de changer simplement la variable qui pointe vers le point de terminaison d'API associé aux services. Vous pouvez également utiliser des variables pour configurer les jobs et les rendre disponibles en tant que variables d'environnement dans les jobs lorsqu'ils s'exécutent.\n\nDécouvrez dans cet article tout ce que vous devez savoir sur les variables d’environnement afin de mieux comprendre leur fonctionnement et leur portée. \n\n![GitLab lit le fichier .gitlab-ci.yml pour analyser la variable référencée, puis envoie les informations à GitLab Runner. Les variables sont exposées et générées par le runner.](https://about.gitlab.com/images/blogimages/demystifying-ci-cd-variables/variables_processing.jpeg)\n\n## La relation entre les variables et les environnements\n\nLe processus de développement logiciel comprend plusieurs étapes destinées à tester un produit avant de le déployer et de le mettre à disposition des utilisateurs. Les [environnements](https://docs.gitlab.com/ee/ci/environments/) sont utilisés pour définir ces étapes, qui peuvent différer d'une équipe à l'autre, voire d'une entreprise à l'autre.\n\nLes variables, quant à elles, sont des valeurs de données susceptibles de changer à la suite d'une interaction entre un utilisateur et un produit. Par exemple, son âge, ses préférences ou toute autre information qui pourrait déterminer l'étape suivante qui lui sera présentée dans le flux de tâches du produit.\n\nLe terme [variable d'environnement](https://docs.gitlab.com/ee/administration/environment_variables.html) fait souvent référence à des variables définies dans un environnement donné, mais en dehors de l'application. Les variables dans GitLab CI/CD offrent aux équipes de développement la possibilité de configurer des valeurs dans le code. L'intérêt principal étant de garantir sa flexibilité. Ces variables permettent aux utilisateurs de modifier une application déployée dans un certain environnement sans toucher au code. Il est possible d'exécuter des tests en toute simplicité ou même d'intégrer des services tiers en modifiant une variable d'environnement de configuration en dehors de l'application.\n\n## La portée des variables dans l'approche CI/CD\n\n![Ordre de priorité des variables CI/CD : 1) Exécution manuelle du pipeline, variables de déclenchement et de planification du pipeline, 2) Variables protégées au niveau du projet, au niveau du groupe et au niveau de l'instance, 3) Variables CI/CD héritées, 4) Variables globales définies dans yml au niveau du job, 5) Variables de déploiement, 6) Variables CI/CD prédéfinies](https://about.gitlab.com/images/blogimages/demystifying-ci-cd-variables/variables_precedence.jpeg)\n\n### Variables définies dans `.gitlab-ci.yml`\n\nLes variables qui doivent être disponibles dans l'environnement du job peuvent être ajoutées à GitLab. Ces variables CI/CD stockent la configuration du projet ne contenant pas de données sensibles, comme l'URL de la base de données dans le fichier `.gitlab-ci.yml`. Réutilisez cette variable dans plusieurs jobs ou scripts, là où la valeur est nécessaire. Si la valeur change, vous n'avez besoin de mettre à jour la variable qu'une seule fois. Le changement se reflète ensuite partout où la variable est utilisée.\n\n### Variables CI/CD au niveau du projet\n\nUn cran au-dessus des exigences spécifiques au dépôt, vous pouvez définir des variables CI/CD dans les [paramètres du projet](https://docs.gitlab.com/ee/ci/variables/#for-a-project), afin qu'elles soient disponibles dans les [pipelines CI/CD](https://about.gitlab.com/fr-fr/topics/ci-cd/cicd-pipeline/ \"Qu'est-ce qu'un pipeline CI/CD ?\"). Celles-ci sont stockées en dehors du dépôt (c'est-à-dire qu'elles ne figurent pas dans le fichier `.gitlab-ci.yml`), mais peuvent néanmoins être utilisées dans les scripts et la configuration CI/CD. Le stockage des variables en dehors du fichier `.gitlab-ci.yml` limite ces valeurs à la portée du projet uniquement, sans les enregistrer en texte brut dans le projet.\n\n### Variables CI/CD au niveau du groupe et de l'instance\n\nCertaines variables sont pertinentes à l'échelle du groupe ou de l'instance et peuvent être utiles à tous les projets associés à un groupe ou à une instance spécifique. Définissez les variables dans les [paramètres du groupe ou de l'instance](https://docs.gitlab.com/ee/ci/variables/#for-a-group) afin que tous les projets de ces portées puissent utiliser les variables sans avoir besoin d'en connaître la valeur ou de les recréer pour chaque projet de portée inférieure. Par exemple, une valeur commune à plusieurs projets se gère facilement si elle ne doit être mise à jour qu'à un seul endroit. Alternativement, plusieurs projets peuvent utiliser un mot de passe spécifique sans avoir besoin de connaître la valeur du mot de passe lui-même.\n\n## Jobs et pipelines en tant qu'environnements\n\nEn plus d'être utilisées comme des variables d'environnement, les variables dans GitLab CI/CD fonctionnent également dans la portée du fichier de configuration `.gitlab-ci.yml` pour définir le comportement du pipeline, indépendamment de son environnement. Les variables peuvent être stockées dans les paramètres du projet/groupe/instance et mises à la disposition des jobs dans les pipelines.\n\nPar exemple :\n\n```  \njob:  \n  rules:  \n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH  \n  script:  \n  - echo \"This job ran on the $CI_COMMIT_BRANCH branch.\"  \n```\n\nLa variable `($CI_COMMIT_BRANCH)` dans la section du script s'exécute dans la portée du job dans lequel elle a été définie. Cette portée est l'« environnement du job », ce qui signifie que lorsque le job se lance, le GitLab Runner démarre un conteneur Docker et exécute le job dans cet environnement. Le runner met cette variable (et toutes les autres variables prédéfinies ou personnalisées) à la disposition du job et peut également afficher leur valeur dans les données de sortie du log si nécessaire.\n\nToutefois, la variable est aussi utilisée dans la section `if:` pour déterminer quand le job doit s'exécuter. Il ne s'agit pas en soi d'un environnement, c'est pourquoi nous les appelons variables CI/CD. Elles peuvent être utilisées pour configurer dynamiquement vos jobs CI/CD, ainsi que comme variables d'environnement lorsque le job est en cours d'exécution.\n\n## Variables prédéfinies\n\nUn certain nombre de variables sont [prédéfinies](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html) lorsqu'un pipeline GitLab CI/CD démarre. Un utilisateur peut immédiatement accéder aux valeurs pour des éléments tels que les validations, le projet ou les détails du pipeline sans avoir à définir les variables elles-mêmes.\n\n## Variables CI/CD personnalisées\n\n![Les runners peuvent créer deux types de variables CI/CD personnalisées : Type et Fichier.](https://about.gitlab.com/images/blogimages/demystifying-ci-cd-variables/variable_types.jpeg)\n\nLors de la création d'une variable CI/CD dans les paramètres, GitLab offre à l'utilisateur plus d'options pour configurer la variable. Utilisez ces options de configuration supplémentaires pour exercer un contrôle plus strict sur les variables plus sensibles :\n\n**Portée de l'environnement :** si une variable ne doit être utilisée que dans un environnement spécifique, définissez-la pour qu'elle soit disponible uniquement dans cet environnement. Par exemple, vous pouvez définir un jeton de déploiement pour qu'il ne soit disponible que dans l'environnement `production`.\n\n**Variables protégées :** comme pour la portée de l'environnement, vous pouvez définir une variable pour qu'elle ne soit disponible que lorsque le pipeline s'exécute sur une branche protégée, comme votre branche par défaut.\n\n**Type de variable :** certaines applications nécessitent que la configuration leur soit transmise sous la forme d'un fichier. Si une application nécessite cette configuration, définissez simplement le type de variable comme « Fichier ». Cette configuration de la variable CI/CD signifie que lorsque le runner rend la variable disponible dans l'environnement, il l'écrit dans un fichier temporaire et stocke le chemin d'accès au fichier en tant que valeur. Un utilisateur peut ensuite transmettre le chemin d'accès au fichier à toutes les applications qui en ont besoin.\n\nEn plus des éléments énumérés pour définir et utiliser les variables, GitLab a introduit une fonctionnalité qui génère des variables préremplies lorsqu'un pipeline doit être exécuté manuellement. Les variables préremplies réduisent les risques d'erreur et facilitent l'exécution du pipeline.\n\n**Variables masquées :** les [variables masquées](https://docs.gitlab.com/ee/ci/variables/#mask-a-cicd-variable) sont des variables CI qui ont été **cachées dans les job logs** pour empêcher l'affichage de leur valeur.\n\n**Variables masquées et cachées :** introduites dans [GitLab 17.4](https://about.gitlab.com/releases/2024/09/19/gitlab-17-4-released/#hide-cicd-variable-values-in-the-ui), les variables [masquées et cachées](https://docs.gitlab.com/ee/ci/variables/#hide-a-cicd-variable) offrent la même fonctionnalité de masquage des job logs et **gardent la valeur cachée** **dans l'interface utilisateur des paramètres**. Nous ne recommandons pas d'utiliser ces deux types de variables pour les informations sensibles (comme les secrets), car elles peuvent être exposées par inadvertance.\n\n## Secrets\n\nUn secret est un identifiant de connexion sensible qui doit rester confidentiel. Voici des exemples de secrets :\n\n* Mots de passe\n* Clés SSH\n* Jetons d'accès\n* Tout autre type d'identifiants de connexion dont la divulgation pourrait porter préjudice à l'entreprise\n\nGitLab permet actuellement à ses utilisateurs d'[utiliser des secrets externes](https://docs.gitlab.com/ee/ci/secrets/) dans l'[intégration continue (CI)](https://about.gitlab.com/fr-fr/topics/ci-cd/benefits-continuous-integration/ \"Qu'est-ce que l'intégration continue (CI) ?\"), en tirant parti de HashiCorp Vault, Google Cloud Secret Manager et Azure Key Vault pour gérer de manière sécurisée les clés, les tokens et d'autres secrets au niveau du projet. Les utilisateurs peuvent ainsi séparer ces secrets des autres variables CI/CD pour des raisons de sécurité.\n\n### Gestionnaire de secrets de GitLab\n\nEn plus de fournir une assistance pour les secrets externes dans la CI, GitLab prévoit également de proposer une [solution native de gestion des secrets](https://gitlab.com/groups/gitlab-org/-/epics/10108) permettant de stocker les secrets de manière pratique et sécurisée au sein de sa plateforme. Cette solution aidera également les clients à utiliser les secrets stockés dans les composants et les environnements spécifiques à GitLab, ainsi qu'à gérer facilement les accès au niveau des groupes d'espaces de nommage et des projets.\n\nPour en savoir plus sur le gestionnaire de secrets de GitLab, consultez notre article « [Le gestionnaire de secrets natif de GitLab renforce la sécurité de la chaîne d'approvisionnement logicielle](https://about.gitlab.com/blog/gitlab-native-secrets-manager-to-give-software-supply-chain-security-a-boost/) ». \n\n***Avertissement :** cet article de blog contient des informations relatives aux produits, fonctionnalités et caractéristiques à venir. Il est important de noter que les informations contenues dans cet article de blog ne sont fournies qu'à titre informatif. Veuillez ne pas vous fier à ces informations à des fins d'achat ou de planification. Comme pour tout projet, les éléments mentionnés dans cet article sont susceptibles de changer ou d’être retardés. Le développement, la sortie et le calendrier de tout produit ou fonctionnalité restent à la seule discrétion de GitLab.*\n",[786,916,917,785,111,759],"features","inside GitLab","2025-01-28",{"slug":920,"featured":6,"template":686},"demystifying-ci-cd-variables","content:fr-fr:blog:demystifying-ci-cd-variables.yml","Demystifying Ci Cd Variables","fr-fr/blog/demystifying-ci-cd-variables.yml","fr-fr/blog/demystifying-ci-cd-variables",{"_path":926,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":927,"content":933,"config":941,"_id":943,"_type":16,"title":944,"_source":18,"_file":945,"_stem":946,"_extension":21},"/fr-fr/blog/ci-deployment-and-environments",{"title":928,"description":929,"ogTitle":928,"ogDescription":929,"noIndex":6,"ogImage":930,"ogUrl":931,"ogSiteName":723,"ogType":724,"canonicalUrls":931,"schema":932},"Comment déployer du code dans des environnements multiples avec GitLab CI","GitLab CI est à la fois puissant et polyvalent. Découvrez les capacités de cet outil à travers plusieurs scénarios d'utilisation.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662033/Blog/Hero%20Images/intro.jpg","https://about.gitlab.com/blog/ci-deployment-and-environments","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Comment déployer du code dans des environnements multiples avec GitLab CI\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Ivan Nemytchenko\"},{\"@type\":\"Person\",\"name\":\"Cesar Saavedra\"}],\n        \"datePublished\": \"2021-02-05\",\n      }",{"title":928,"description":929,"authors":934,"heroImage":930,"date":937,"body":938,"category":14,"tags":939,"updatedDate":940},[935,936],"Ivan Nemytchenko","Cesar Saavedra","2021-02-05","Imaginez-vous gestionnaire d’un site d'information. Heureusement, le code de\nvotre projet est déjà hébergé sur GitLab.com et vous utilisez [GitLab\nCI/CD](https://docs.gitlab.com/ee/ci/testing/ \"Test avec GitLab CI/CD\") pour\nvos tests. Maintenant, vous souhaitez connaître toutes les possibilités de\n[déploiement](https://about.gitlab.com/fr-fr/blog/how-to-keep-up-with-ci-cd-best-practices/\n\"Meilleures pratiques CI/CD\").\n\n\nPar souci de pertinence, supposons que l'application se compose uniquement\nde fichiers HTML, sans code côté serveur ni compilation sophistiquée des\nactifs JS. La plateforme de destination sera également générique, nous\nutiliserons [Amazon S3](https://aws.amazon.com/fr/s3/ \"Amazon S3\").\n\n\nPlutôt que de fournir des extraits de code à copier-coller, nous allons vous\npartager les principes et les fonctionnalités de GitLab CI, afin que vous\npuissiez les appliquer dans votre propre pile technologique. \n\n\nDéroulons donc notre histoire depuis son commencement, où il n'est pas\nencore question d'intégration continue.\n\n\n## La ligne de départ\n\n\n__Déploiement__ : un ensemble de fichiers HTML devraient apparaître dans\nvotre bucket S3 (déjà configuré pour [héberger un site web\nstatique](https://docs.aws.amazon.com/fr_fr/AmazonS3/latest/userguide/HostingWebsiteOnS3Setup.html\n\"Héberger un site web statique avec Amazon S3\")). Il y a des millions de\nfaçons de procéder. Dans notre cas, nous utiliserons la bibliothèque [AWS\nCLI](https://aws.amazon.com/fr/cli/ \"AWS CLI\") fournie par Amazon. \n\n\nLa commande complète ressemble à ceci :\n\n\n```shell\n\naws s3 cp ./ s3://yourbucket/ --recursive --exclude \"*\" --include \"*.html\"\n\n```\n\n\nLe push du code vers le dépôt et le déploiement sont deux processus\ndistincts.\n\n\n![Déploiement\nmanuel](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674077/Blog/Content%20Images/19-updated.png){:\n.center}\n\n{: .note .text-center}\n\n\nDétail important : la commande nécessite de [fournir les variables\nd'environnement](https://docs.aws.amazon.com/fr_fr/cli/latest/userguide/cli-chap-getting-started.html)\n`AWS_ACCESS_KEY_ID` et `AWS_SECRET_ACCESS_KEY`. Il vous faudra peut-être\naussi spécifier `AWS_DEFAULT_REGION`. \n\n\nEssayons d'automatiser cette procédure avec [l'intégration continue de\nGitLab](https://about.gitlab.com/fr-fr/solutions/continuous-integration/\n\"Intégration continue de GitLab\").\n\n\n## Votre premier déploiement automatisé\n\n\nGitLab CI offre une grande flexibilité dans l'exécution des commandes. Sa\nconfiguration s'adapte à vos besoins, reproduisant l'environnement de votre\nterminal local. Ajoutez votre script dans le fichier .gitlab-ci.yml et\neffectuez un push de votre code : l’outil d'intégration continue de GitLab\ndéclenche un *job* et vos commandes sont exécutées.\n\n\nPrécisons maintenant le contexte d'utilisation de cet exemple : il s'agit\nd'un site de taille modeste, avec une trentaine de visiteurs journaliers, et\nune seule branche principale de dépôt de code. Commençons par spécifier un\n*job* avec la commande précédente dans le fichier `.gitlab-ci.yml` :\n\n\n```yaml\n\ndeploy:\n  script: aws s3 cp ./ s3://yourbucket/ --recursive --exclude \"*\" --include \"*.html\"\n```\n\n\nOups, la commande a échoué :\n\n\n![Message d'erreur lors de l'exécution d'un job\nGitLab.](https://about.gitlab.com/images/blogimages/ci-deployment-and-environments/13.jpg){:\n.shadow}\n\n\nIl fallait d'abord vérifier l'existence d'un exécutable `aws`. Pour\ninstaller `awscli`, nous avons besoin de `pip`, qui est un outil\nd'installation de paquets Python. Spécifions une image Docker avec Python\npréinstallé, qui devrait également contenir `pip` : \n\n\n```yaml\n\ndeploy:\n  image: python:latest\n  script:\n  - pip install awscli\n  - aws s3 cp ./ s3://yourbucket/ --recursive --exclude \"*\" --include \"*.html\"\n```\n\n\n![Déploiement\nautomatisé](https://about.gitlab.com/images/blogimages/ci-deployment-and-environments/fail1.png){:\n.center}\n\n{: .note .text-center}\n\n\nVous effectuez un push de votre code sur GitLab, et il est automatiquement\ndéployé par l’outil CI. \n\n\nL'installation d'`awscli` rallonge le temps d'exécution du job, mais pour\nl'instant ce n'est pas un souci. Pour accélérer le processus, [cherchez une\nimage Docker](https://hub.docker.com/ \"Chercher une image Docker\") avec\n`awscli` préinstallé, ou créez une image vous-même. \n\n\nN’oublions pas les variables d'environnement récupérées depuis la [console\nAWS](https://console.aws.amazon.com/) :\n\n\n```yaml\n\nvariables:\n  AWS_ACCESS_KEY_ID: \"AKIAIOSFODNN7EXAMPLE\"\n  AWS_SECRET_ACCESS_KEY: \"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\"\ndeploy:\n  image: python:latest\n  script:\n  - pip install awscli\n  - aws s3 cp ./ s3://yourbucket/ --recursive --exclude \"*\" --include \"*.html\"\n```\n\n\nCela devrait fonctionner, mais attention : ce n'est jamais une bonne idée de\ndévoiler des clés secrètes de votre code, même dans un dépôt privé.\nRemédions donc à cette situation.\n\n\n### Des secrets bien gardés\n\n\nGitLab dispose d’un endroit spécialement dédié aux variables secrètes :\n__Paramètres > CI/CD > Variables__.\n\n\n![Ajouter une variable secrète dans\nGitLab](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674076/Blog/Content%20Images/add-variable-updated.png)\n\n\nTout ce que vous y mettez se transforme en variables d'environnement. En\ncochant la case « Masquée », vous masquerez la variable dans les job logs.\nEn cochant la case « Protéger la variable », vous n’exporterez la variable\nuniquement vers les pipelines s'exécutant sur des branches et des étiquettes\nprotégées. \n\n\nSeuls les utilisateurs ayant le statut de propriétaire ou de chargé de\nmaintenance sur un projet auront accès à cette section. Nous pourrions\nsupprimer la section `variables` de notre configuration CI, mais nous allons\nl'utiliser à d'autres fins.\n\n\n### Savoir spécifier et utiliser des variables non-secrètes\n\n\nLorsque votre configuration s'agrandit, il devient pratique de conserver\ncertains paramètres sous formes de variables au début de votre\nconfiguration. Le cas présent ne le justifie pas, mais pour les besoins de\ncette démonstration, nous allons définir le nom du compartiment S3 comme\nvariable :\n\n\n```yaml\n\nvariables:\n  S3_BUCKET_NAME: \"yourbucket\"\ndeploy:\n  image: python:latest\n  script:\n  - pip install awscli\n  - aws s3 cp ./ s3://$S3_BUCKET_NAME/ --recursive --exclude \"*\" --include \"*.html\"\n```\n\n\nJusqu'ici, tout va bien :\n\n\n![Compilation GitLab CI sans\nerreur](https://about.gitlab.com/images/blogimages/ci-deployment-and-environments/14.jpg){:\n.shadow.medium.center}\n\n\nDans notre scénario, la fréquentation du site est en hausse, et vous avez\nembauché un développeur pour vous aider. Voyons comment le workflow GitLab\nCI s'adapte au travail en équipe.\n\n\n## Comment utiliser GitLab CI en équipe\n\n\nAvec deux utilisateurs travaillant dans le même dépôt, il n'est plus\npratique d'utiliser la branche principale pour le développement. Vous\ndécidez d'utiliser des branches séparées pour les nouvelles fonctionnalités\net les nouveaux articles, et de les fusionner dans la branche principale\nlorsqu'elles sont prêtes.\n\n\nCependant, votre configuration CI actuelle ne prend pas en charge les\nbranches. Chaque push effectué vers GitLab sera déployé sur S3. La solution\nest simple : il suffit d'ajouter `only: main` au job `deploy`.\n\n\nEn plus de ne pas vouloir déployer chaque branche sur l’environnement de\nproduction, vous souhaiteriez pouvoir prévisualiser vos modifications depuis\nles branches de fonctionnalités. \n\n\n![Déploiement de la branche principale de GitLab vers AWS\nS3](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674076/Blog/Content%20Images/15-updated.png){:\n.center}\n\n{: .note .text-center}  \n\n\n### Comment configurer un environnement de test ?\n\n\nMatteo, votre nouveau développeur, vous propose d'utiliser la fonctionnalité\n[GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/ \"GitLab\nPages\"), idéale pour prévisualiser votre travail en cours. Afin d'[héberger\ndes sites web sur GitLab\nPages](https://docs.gitlab.com/ee/user/project/pages/getting_started/pages_ui.html\n\"Héberger des sites web sur GitLab Pages\"), votre fichier de configuration\nCI doit répondre à trois règles simples :\n\n\n- Le *job* doit être nommé `pages`\n\n- Il doit y avoir une section `artifacts` avec un dossier `public`\n\n- Tout ce que vous souhaitez héberger doit être placé dans le dossier\n`public`\n\n\nLe contenu du dossier public sera hébergé à l'adresse suivante :\n`http://\u003Cusername>.gitlab.io/\u003Cprojectname>/`\n\n\nVoici la configuration complète après avoir appliqué l’[exemple de\nconfiguration pour les sites web en\nHTML](https://gitlab.com/pages/plain-html/-/blob/main/.gitlab-ci.yml\n\"Exemple de configuration pour les sites web en HTML\") :\n\n\n```yaml\n\nvariables:\n  S3_BUCKET_NAME: \"yourbucket\"\n\ndeploy:\n  image: python:latest\n  script:\n  - pip install awscli\n  - aws s3 cp ./ s3://$S3_BUCKET_NAME/ --recursive --exclude \"*\" --include \"*.html\"\n  only:\n  - main\n\npages:\n  image: alpine:latest\n  script:\n  - mkdir -p ./public\n  - cp ./*.html ./public/\n  artifacts:\n    paths:\n    - public\n  except:\n  - main\n```\n\n\nNous avons spécifié deux jobs. L'un d'eux déploie le site web pour vos\nclients sur S3 (`deploy`). L'autre (`pages`) déploie le site web sur GitLab\nPages. Nommons-les « Environnement de production » et « Environnement de\npréproduction ». Toutes les branches seront déployées sur GitLab Pages, à\nl'exception de la branche principale. \n\n\n![Déploiement différencié des branches dans GitLab Pages et\nS3.](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674076/Blog/Content%20Images/16-updated.png){:\n.center}\n\n{: .note .text-center}\n\n\n## Introduction aux environnements\n\n\nGitLab offre la prise en charge de [nombreux\nenvironnements](https://docs.gitlab.com/ee/ci/environments/ \"Environnements\nGitLab\") (dynamiques ou statiques) ; vous devez simplement spécifier\nl'environnement correspondant pour chaque *job* de déploiement :\n\n\n```yaml\n\nvariables:\n  S3_BUCKET_NAME: \"yourbucket\"\n\ndeploy to production:\n  environment: production\n  image: python:latest\n  script:\n  - pip install awscli\n  - aws s3 cp ./ s3://$S3_BUCKET_NAME/ --recursive --exclude \"*\" --include \"*.html\"\n  only:\n  - main\n\npages:\n  image: alpine:latest\n  environment: staging\n  script:\n  - mkdir -p ./public\n  - cp ./*.html ./public/\n  artifacts:\n    paths:\n    - public\n  except:\n  - main\n```\n\n\nGitLab garde une trace de tous vos déploiements. Ainsi, vous savez toujours\nce qui est actuellement déployé sur vos serveurs :\n\n\n![Visualisation des environnements sur GitLab\nCI/CD.](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674076/Blog/Content%20Images/envs-updated.png){:\n.shadow.center}\n\n\nL'historique complet de vos déploiements sur chacun de vos environnements\nactuels vous est aussi fourni :\n\n\n![Historique des déploiements\nGitLab.](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674077/Blog/Content%20Images/staging-env-detail-updated.png){:\n.shadow.center}\n\n\nMaintenant que tout est automatisé et configuré, de nouveaux défis nous\nattendent.\n\n\n## Comment dépanner les déploiements ?\n\n\nOups ! La branche de fonctionnalités que vous avez poussé sur\nl'environnement de préproduction vient d'être remplacée par celle de Matteo,\nqui vient d'effectuer un push de sa propre branche. L'énervement vous gagne,\nc'est la troisième fois que cela arrive aujourd'hui ! \n\n\nEt si vous utilisiez Slack pour notifier vos déploiements, afin d'éviter ce\ngenre de désagrément ?\n\n\n> Recevez des notifications en utilisant l'[application GitLab pour\nSlack](https://docs.gitlab.com/ee/user/project/integrations/gitlab_slack_application.html).\n\n\n## Du travail d'équipe à grande échelle\n\n\nQuelque temps plus tard, et vous voilà à la tête d'un site web très\npopulaire, et d'une équipe de huit personnes. Mais, désormais, les membres\nde votre équipe perdent un temps précieux à attendre de pouvoir\nprévisualiser leur travail. Le déploiement de chaque branche en\npréproduction n'est plus optimal.\n\n\n![File d'attente de branches à examiner en\npréproduction](https://about.gitlab.com/images/blogimages/ci-deployment-and-environments/build.png){:\n.center}\n\n\nIl est temps de perfectionner le système. Vous convenez avec votre équipe de\nfusionner au préalable chaque changement sur la branche de préproduction. La\nmodification du fichier `.gitlab-ci.yml` est minime :\n\n\n```yaml\n\nexcept:\n\n- main\n\n```\n\n\nest remplacé par\n\n\n```yaml\n\nonly:\n\n- staging\n\n```\n\n\n![Dessin de développeurs qui fusionnent leurs changements dans une branche\nde préproduction avant de les déployer sur\nS3](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674077/Blog/Content%20Images/17-updated.png){:\n.center}\n\n{: .note .text-center}\n\n\nVos collaborateurs doivent fusionner leurs branches de fonctionnalités avant\nde prévisualiser leur travail en préproduction. Cela nécessite plus de temps\net d'efforts, mais tout le monde s'accorde à dire que c'est toujours mieux\nque d'attendre.\n\n\n## Comment gérer les urgences ?\n\n\nIl arrive parfois que les choses tournent mal. Quelqu'un a mal fusionné des\nbranches et a effectué un push du résultat directement en production, juste\nau moment où le hashtag de votre site devenait viral sur les réseaux\nsociaux. Des milliers de personnes voient des visuels cassés au lieu de\nvotre page d'accueil habituelle. Heureusement, la fonction __Restaurer\nl’environnement__ a permis de résoudre le problème en moins d'une minute.\n\n\n![Fonctionnalité de restauration sur la plateforme\nGitLab](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674077/Blog/Content%20Images/18-updated.png){:\n.shadow.center}\n\n{: .note .text-center}\n\n\nLa fonction de restauration de l'environnement relance le job précédent avec\nla validation précédente. Vous avez décidé de désactiver le déploiement\nautomatique en production et de passer au déploiement manuel. Pour ce faire,\nvous devez ajouter  `when : manual` à votre *job*. Il n'y aura effectivement\nplus de déploiement automatique en production. Le déploiement manuel\ns'effectue en allant dans __Compilation > Pipelines__, et en cliquant sur\n__« Exécuter des jobs manuels ou différés »__ :\n\n\n![Déploiement manuel sur\nGitLab.](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674077/Blog/Content%20Images/prod-env-rollback-arrow-updated.png){:\n.shadow.center}\n\n\nEffectuons maintenant un bond en avant dans le temps. Votre entreprise est\ndevenue une société de plusieurs centaines d'employés travaillant sur le\nsite web, et les compromis précédents ne fonctionnent plus.\n\n\n### Faire ses premiers pas avec les Review Apps\n\n\nLogiquement, la nouvelle étape consiste à lancer une instance temporaire de\nl'application par branche de fonctionnalités pour la revue. Pour cela, nous\navons configuré un autre bucket S3. Sa seule particularité est que le\ncontenu du site est placé dans un dossier portant le nom de la branche de\ndéveloppement, de sorte que l’URL ressemble à :\n\n\n`http://\u003CREVIEW_S3_BUCKET_NAME>.s3-website-us-east-1.amazonaws.com/\u003Cbranchname>/`\n\n\nVoici le remplacement du *job* `pages` utilisé auparavant :\n\n\n```yaml\n\nreview apps:\n  variables:\n    S3_BUCKET_NAME: \"reviewbucket\"\n  image: python:latest\n  environment: review\n  script:\n  - pip install awscli\n  - mkdir -p ./$CI_BUILD_REF_NAME\n  - cp ./*.html ./$CI_BUILD_REF_NAME/\n  - aws s3 cp ./ s3://$S3_BUCKET_NAME/ --recursive --exclude \"*\" --include \"*.html\"\n```\n\n\nIci, il est bon de connaître l'origine de cette variable\n`$CI_BUILD_REF_NAME`. GitLab prédéfinit de [nombreuses variables\nd'environnement](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html\n\"Variables d'environnement dans GitLab\") à utiliser dans vos jobs. Notez que\nnous avons défini la variable `S3_BUCKET_NAME` à l'intérieur du *job*. Vous\npouvez ainsi réécrire les définitions de niveau supérieur. \n\n\nReprésentation visuelle de la configuration des Review Apps :\n\n\n![Dessin représentant la configuration Review Apps de\nGitLab.](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674076/Blog/Content%20Images/manual-pipeline-arrow-updated.png){:\n.illustration}\n\n\nLes détails de l'implémentation des Review Apps varient selon votre pile\ntechnologique et de votre processus de déploiement. Tout ne sera pas aussi\nsimple qu'avec un site HTML statique. Programmer des instances temporaires à\nla volée avec tous les logiciels et services requis n'est pas chose aisée.\nMais tout cela peut être accompli, notamment à l'aide des conteneurs Docker,\nChef ou Ansible.\n\n\nLe déploiement avec Docker mériterait d'ailleurs un article complet. Et si\nvous regrettez l'absence de scénarios plus complexes qu'un simple\ndéploiement en HTML statique, nous vous recommandons de lire [cet\narticle](https://about.gitlab.com/blog/building-an-elixir-release-into-docker-image-using-gitlab-ci-part-1/\n\"Construire une version d'Elixir dans une image Docker en utilisant GitLab\nCI - Partie 1\"). Abordons maintenant un dernier sujet.\n\n\n### Déployer sur différentes plateformes\n\n\nDans la pratique, nous ne sommes pas limités à S3 et à GitLab Pages. Nous\nhébergeons et déployons nos applications sur différents services. De plus,\nsi vous décidez un jour de passer à une nouvelle plateforme, vous devrez\nalors réécrire tous vos scripts de déploiement. Vous pourrez alors utiliser\nune petite merveille appelée `dpl` pour vous faciliter la tâche.\n\n\nJusqu'ici, nous avons utilisé `awscli` pour livrer du code à un service\ncomme Amazon S3. Quel que soit le système utilisé, le principe reste le même\n: vous exécutez une commande avec certains paramètres et transmettez une clé\nsecrète d'authentification. L'outil de déploiement `dpl` utilise ce principe\net fournit une interface unique pour cette [liste de\nfournisseurs](https://github.com/travis-ci/dpl#supported-providers \"Liste de\nfournisseurs\"). Voici à quoi ressemblerait le déploiement d’un *job* en\nproduction avec `dpl`:\n\n\n```yaml\n\nvariables:\n  S3_BUCKET_NAME: \"yourbucket\"\n\ndeploy to production:\n  environment: production\n  image: ruby:latest\n  script:\n  - gem install dpl\n  - dpl --provider=s3 --bucket=$S3_BUCKET_NAME\n  only:\n  - main\n```\n\n\nEn cas de déploiement sur plusieurs systèmes ou de changements fréquents de\nplateforme de destination, `dpl` vous aide à uniformiser vos scripts de\ndéploiement.\n\n\n## Cinq points clés à retenir\n\n\n1. Un déploiement est une commande (ou un ensemble de commandes)\nrégulièrement exécutée. Il peut donc être exécuté dans GitLab CI.\n\n\n2. La plupart des commandes à exécuter nécessitent de fournir une ou\nplusieurs clés secrètes, que vous stockez dans __Paramètres >\n[CI/CD](https://about.gitlab.com/fr-fr/topics/ci-cd/ \"Qu'est-ce que le CI/CD\n?\") > Variables__.\n\n\n3. Avec GitLab CI, vous pouvez spécifier de façon flexible les branches vers\nlesquelles vous déployez votre code.\n\n\n4. GitLab conserve l'historique des déploiements dans tous vos\nenvironnements, et vous permet de revenir à n'importe quelle version\nprécédente.\n\n\n5. Pour les éléments critiques de votre infrastructure, vous pouvez activer\nle déploiement manuel depuis l'interface de GitLab, au lieu du déploiement\nautomatisé.\n",[785,786,759],"2024-11-21",{"slug":942,"featured":6,"template":686},"ci-deployment-and-environments","content:fr-fr:blog:ci-deployment-and-environments.yml","Ci Deployment And Environments","fr-fr/blog/ci-deployment-and-environments.yml","fr-fr/blog/ci-deployment-and-environments",{"_path":948,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":949,"content":955,"config":963,"_id":965,"_type":16,"title":966,"_source":18,"_file":967,"_stem":968,"_extension":21},"/fr-fr/blog/we-need-to-talk-no-proxy",{"title":950,"description":951,"ogTitle":950,"ogDescription":951,"noIndex":6,"ogImage":952,"ogUrl":953,"ogSiteName":723,"ogType":724,"canonicalUrls":953,"schema":954},"Pouvons-nous standardiser la variable d'environnement NO_PROXY ?","Découvrez notre guide complet sur no_proxy, la configuration des paramètres\ndu proxy, ainsi que les spécificités de no_proxy, http_proxy et https_proxy.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659507/Blog/Hero%20Images/AdobeStock_623844718.jpg","https://about.gitlab.com/blog/we-need-to-talk-no-proxy","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Pouvons-nous standardiser la variable d'environnement NO_PROXY ?\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Stan Hu\"}],\n        \"datePublished\": \"2021-01-27\",\n      }",{"title":950,"description":951,"authors":956,"heroImage":952,"date":957,"body":958,"category":14,"tags":959},[706],"2021-01-27","Si vous avez déjà utilisé un serveur proxy Web, vous êtes probablement familier avec les variables d’environnement `http_proxy` ou `HTTP_PROXY`. Cependant, vous l'êtes peut-être moins avec la variable `no_proxy` qui permet d’exclure le trafic destiné à certains hôtes d'utiliser le proxy. Bien que le protocole HTTP soit standardisé, aucune norme ne précise comment utiliser ces variables. Par conséquent, les clients Web prennent en charge ces variables de manière différente.  \n\nDécouvrez dans cet article tout ce que vous devez savoir sur la variable d’environnement no_proxy, ainsi qu’un cas pratique d’un de nos clients GitLab. \n\n## Comprendre http_proxy, https_proxy et no_proxy\n\nDe nos jours, la plupart des clients Web permettent de se connecter à des serveurs proxy via les variables d'environnement suivantes : \n\n- `http_proxy` / `HTTP_PROXY`\n- `https_proxy` / `HTTPS_PROXY`\n- `no_proxy` / `NO_PROXY`\n\nCes variables indiquent au client l'URL à utiliser pour accéder aux serveurs proxy et quelles exceptions appliquer. \n\nPar exemple, si vous avez un serveur proxy attaché à `http://alice.example.com:8080`, vous pourriez l’utiliser via : \n\n```sh\nexport http_proxy=http://alice.example.com:8080\n```\n\nMais quel serveur proxy sera utilisé si Maxime définit aussi la version en majuscules : `HTTP_PROXY` ?\n\n```sh\nexport HTTP_PROXY=http://maxime.example.com:8080\n```\nAussi surprenant que cela puisse paraître, cela dépend. Dans certains cas, le proxy d'Alice est utilisé, dans d'autres cas, c'est celui de Maxime. Nous y reviendrons plus loin dans cet article. \n\nQue se passe-t-il si vous souhaitez définir des exceptions ? Par exemple, admettons que vous souhaitez utiliser un serveur proxy pour tout, sauf pour `internal.example.com` et `internal2.example.com`. C'est ici que la variable `no_proxy` entre en jeu. Vous paramétrez alors `no_proxy` comme suit : \n\n```sh\nexport no_proxy=internal.example.com,internal2.example.com\n```\n\nEt si vous souhaitez exclure certaines adresses IP ? Faut-il utiliser des astérisques ou des caractères génériques ? Ou bien utiliser des blocs CIDR (comme `192.168.1.1/32`) ? Même réponse : cela dépend.\n\n## L'évolution des variables proxy et no_proxy\n\nEn 1994, la plupart des clients Web utilisaient la bibliothèque logicielle `libwww` du CERN, qui prenait en charge les variables d'environnement `http_proxy` et `no_proxy`. `libwww` utilisait uniquement la forme en minuscules de `http_proxy` et [la syntaxe de `no_proxy` était simple](https://github.com/w3c/libwww/blob/8678b3dcb4191065ca39caea54bb1beba809a617/Library/src/HTAccess.c#L234-L239) : \n\n```\nno_proxy is a comma- or space-separated list of machine\nor domain names, with optional :port part.  If no :port\npart is present, it applies to all ports on that domain.\n\nExample:\n\t\tno_proxy=\"cern.ch,some.domain:8001\"\n```\n\nDe nouveaux clients sont apparus, ajoutant leurs propres implémentations HTTP sans les relier à `libwww`. En janvier 1996, Hrvoje Niksic publie `geturl`, le prédécesseur de ce qu'on connaît aujourd'hui sous le nom de `wget`. Un mois plus tard, [`geturl` prend en charge `http_proxy` dans la version v1.1](https://ftp.sunet.se/mirror/archive/ftp.sunet.se/pub/www/utilities/wget/old-versions/). En mai 1996, `geturl` v1.3 ajoute la prise en charge de `no_proxy`. Tout comme `libwww`, `geturl` n'accepte que les minuscules. \n\nEn janvier 1998, Daniel Stenberg publie `curl` v5.1, [qui prend en charge les variables `http_proxy` et `no_proxy`](https://github.com/curl/curl/blob/ae1912cb0d494b48d514d937826c9fe83ec96c4d/CHANGES#L929-L944). De plus, `curl` accepte désormais les majuscules, `HTTP_PROXY` et `NO_PROXY`.\n\n__Nota Bene :__ en mars 2009, [`curl` v7.19.4](https://github.com/curl/curl/releases/tag/curl-7_19_4) abandonne la prise en compte de la forme en majuscules de `HTTP_PROXY` [en raison de problèmes de sécurité](https://github.com/curl/curl/blob/30e7641d7d2eb46c0b67c0c495a0ea7e52333ee2/lib/url.c#L2250-L2261). Cependant, même si `curl` n'accepte plus `HTTP_PROXY`, `HTTPS_PROXY` fonctionne toujours.\n\n## Gestion des variables du serveur proxy\n\nSuite aux [recherches de notre collègue Nourdin el Bacha](https://gitlab.com/gitlab-com/support/support-team-meta/-/issues/2991), nous comprenons que la gestion des variables du serveur proxy varie en fonction du langage ou de l'outil utilisé. \n\n### http_proxy et https_proxy\n\nDans ce tableau, chaque ligne représente une variable, et chaque colonne correspond à l'outil (comme `curl`) ou au langage (comme `Ruby`) auquel elle s'applique : \n\n|                 | curl      | wget           | Ruby          | Python    | Go        |\n|-----------------|-----------|----------------|---------------|-----------|-----------|\n| `http_proxy`    | Oui       | Oui            | Oui           | Oui       | Oui        |\n| `HTTP_PROXY`    | Non        | Non           | Oui ([Mise en garde](https://github.com/ruby/ruby/blob/0ed71b37fa9af134fdd5a7fd1cebd171eba83541/lib/uri/generic.rb#L1519)) | Oui (si `REQUEST_METHOD` n'est pas dans env)       | Oui       |\n| `https_proxy`   | Oui       | Oui            | Oui           | Oui       | Oui       |\n| `HTTPS_PROXY`   | Oui       | Non             | Oui           | Oui       | Oui       |\n| Casse de caractères | Minuscules | Minuscules uniquement | Minuscules     | Minuscules | Majuscules |\n| Sources       | [source](https://github.com/curl/curl/blob/30e7641d7d2eb46c0b67c0c495a0ea7e52333ee2/lib/url.c#L2250-L2266) | [source](https://github.com/jay/wget/blob/099d8ee3da3a6eea5635581ae517035165f400a5/src/retr.c#L1222-L1239) | [source](https://github.com/ruby/ruby/blob/0ed71b37fa9af134fdd5a7fd1cebd171eba83541/lib/uri/generic.rb#L1474-L1543) | [source](https://github.com/python/cpython/blob/030a713183084594659aefd77b76fe30178e23c8/Lib/urllib/request.py#L2488-L2517) | [source](https://github.com/golang/go/blob/682a1d2176b02337460aeede0ff9e49429525195/src/vendor/golang.org/x/net/http/httpproxy/proxy.go#L82-L97) |\n\nNotez que `http_proxy` et `https_proxy` sont toujours pris en charge, alors que `HTTP_PROXY` ne l'est pas. Python (via `urllib`) ne facilite pas les choses : `HTTP_PROXY` peut être utilisé [tant que `REQUEST_METHOD` n'est pas défini dans l'environnement](https://github.com/python/cpython/blob/030a713183084594659aefd77b76fe30178e23c8/Lib/urllib/request.py#L2504-L2508).\n\nLes variables d'environnement sont normalement définies en majuscules, mais puisque `http_proxy` est apparu en premier, il est devenu de fait la norme. En cas de doute, optez pour la forme en minuscules, car elle est universellement prise en charge.\n\nContrairement à la plupart des implémentations, Go essaie d'abord la forme en majuscules avant revenir à la version en minuscules. Nous verrons plus tard pourquoi cela a causé du tort à notre client GitLab. \n\n### no_proxy\n\nCertains utilisateurs ont signalé le [manque d'indications sur `no_proxy`](https://github.com/curl/curl/issues/1208). Puisque `no_proxy` définit une liste d'exceptions, des questions sur son fonctionnement se posent. \n\nPar exemple, vous configurez votre `no_proxy` comme suit : \n\n```sh\nexport no_proxy=example.com\n```\n\nEst-ce que cela signifie que le domaine doit être une correspondance exacte ou que `subdomain.example.com` corresponde aussi à cette configuration ? \n\nLe tableau suivant présente les différentes configurations. Toutes les implémentations correspondent aux suffixes, comme le montre la ligne « `correspondance des suffixes` ».\n\n|                       | curl      | wget           | Ruby      | Python    | Go        |\n|-----------------------|-----------|----------------|-----------|-----------|-----------|\n| `no_proxy`            | Oui       | Oui          | Oui     | Oui      | Oui      |\n| `NO_PROXY`            | Oui       | Non             | Oui       | Oui       | Oui       |\n| Casse de caractères       | Minuscules | Minuscules uniquement | Minuscules | Minuscules | Majuscules |\n| Correspondance des suffixes ?     | Oui       | Oui            | Oui       | Oui       | Oui       |\n| Points initiaux `.` ?   | Oui       | Non             | Oui       | Oui       | Non        |\n| `*` fait correspondre tous les hôtes| Oui       | Non             | Non        | Oui       | Oui       |\n| Prise en charge des expressions régulières ?     | Non        | Non             | Non        | Non        | Non        |\n| Prise en charge des blocs CIDR ? | Non        | Non             | Oui       | Non        | Oui       |\n| Détection des adresses IP de bouclage ? | Non        | Non             | Non        | Non        | Oui       |\n| Sources            | [source](https://github.com/curl/curl/blob/30e7641d7d2eb46c0b67c0c495a0ea7e52333ee2/lib/url.c#L2152-L2206) | [source](https://github.com/jay/wget/blob/099d8ee3da3a6eea5635581ae517035165f400a5/src/retr.c#L1266-L1274) | [source](https://github.com/ruby/ruby/blob/0ed71b37fa9af134fdd5a7fd1cebd171eba83541/lib/uri/generic.rb#L1545-L1554) | [source](https://github.com/python/cpython/blob/030a713183084594659aefd77b76fe30178e23c8/Lib/urllib/request.py#L2519-L2551)| [source](https://github.com/golang/go/blob/682a1d2176b02337460aeede0ff9e49429525195/src/vendor/golang.org/x/net/http/httpproxy/proxy.go#L170-L206) |\n\nCependant, si `no_proxy` est précédé d'un `.`, cela implique des changements. \n\nPar exemple, `curl` et `wget` se comportent différemment. `curl` supprime le `.` dans la configuration pour se coller au suffixe du domaine. Il contourne ainsi le proxy :\n\n```sh\n$ env https_proxy=http://non.existent/ no_proxy=.gitlab.com curl https://gitlab.com\n\u003Chtml>\u003Cbody>You are being \u003Ca href=\"https://about.gitlab.com/\">redirected\u003C/a>.\u003C/body>\u003C/html>\n```\n\nNéanmoins, `wget` ne supprime pas le `.` et utilise la correspondance exacte avec le nom d'hôte. Par conséquent, `wget` essaie d'utiliser un proxy si un domaine de premier niveau est utilisé : \n\n```sh\n$ env https_proxy=http://non.existent/ no_proxy=.gitlab.com wget https://gitlab.com\nResolving non.existent (non.existent)... failed: Name or service not known.\nwget: unable to resolve host address 'non.existent'\n```\n\nToutes les implémentations ne prennent pas en charge les expressions régulières (regex). Utiliser des regex peut compliquer la configuration puisqu'elles peuvent prendre différentes variantes (comme PCRE ou POSIX). L'utilisation d'expressions régulières entraîne également de potentielles failles de sécurité et de performance. \n\nConfigurer `no_proxy` avec un astérisque (`*`) peut désactiver l'utilisation de proxy pour toutes les adresses, bien que ce principe ne soit pas appliqué tout le temps. \n\nAu moment de décider de l'utilisation d'un proxy, aucune implémentation n'effectue de recherche DNS pour résoudre un nom d'hôte en adresse IP. Il est préférable d'éviter de spécifier les adresses IP dans `no_proxy` à moins que le client ne les utilise explicitement. \n\nIl en va de même pour les blocs CIDR, tels que `18.240.0.1/24`. Ces blocs ne fonctionnent que si la requête est faite directement à une adresse IP. Seuls les environnements de développement Go et Ruby permettent l'utilisation de blocs CIDR. Go désactive même automatiquement l'utilisation d'un proxy si une adresse IP de bouclage est détectée, ce qui n'est pas le cas dans d'autres implémentations.\n\n## Pourquoi les paramètres du proxy sont-ils importants ?\n\nSi votre application est codée en plusieurs langages et doit fonctionner avec un pare-feu avec un serveur proxy, il est important de faire attention à ces différences. \n\nPar exemple, GitLab est composé d'éléments codés en Ruby et d'autres en Go. Un de nos clients a configuré son proxy de la façon suivante : \n\n```yaml\nHTTP_PROXY: http://proxy.company.com\nHTTPS_PROXY: http://proxy.company.com\nNO_PROXY: .correct-company.com\n```\n\nIl a ensuite signalé un problème avec GitLab : \n- Un `git push` à partir de la ligne de commande a fonctionné.\n- Les modifications Git effectuées à partir de l'interface Web ont échoué.\n\nNos ingénieurs ont découvert qu'un problème de configuration de [Kubernetes](https://about.gitlab.com/fr-fr/blog/kubernetes-the-container-orchestration-solution/ \"Kubernetes\") entraînait le maintien de valeurs obsolètes. L'environnement ressemblait à : \n\n```yaml\nHTTP_PROXY: http://proxy.company.com\nHTTPS_PROXY: http://proxy.company.com\nNO_PROXY: .correct-company.com\nno_proxy: .wrong-company.com\n```\n\nLes irrégularités entre `no_proxy` et `NO_PROXY` ont entraîné des alertes. Supprimer l'entrée incorrecte ou uniformiser les variables auraient pu résoudre le problème. Observons ce qu'il s'est passé. \n\nRappelez-vous que : \n- Ruby priorise `no_proxy`.\n- Go priorise `NO_PROXY`.\n\nPar conséquent, les services codées en Go, comme [GitLab Workhorse](https://docs.gitlab.com/ee/development/workhorse/), ont un bon paramétrage du proxy. Un `git push` depuis la ligne de commande a fonctionné car les services Go gèrent cette activité : \n\n```mermaid\nsequenceDiagram\n    autonumber\n    participant C as Client\n    participant W as Workhorse\n    participant G as Gitaly\n    C->>W: git push\n    W->>G: gRPC: PostReceivePack\n    G->>W: OK\n    W->>C: OK\n```\n\nL'appel gRPC de l'étape 2 n'a jamais tenté d'utiliser le proxy car `no_proxy` a été configuré correctement pour se connecter directement à Gitaly.\n\nCependant, lorsqu'un utilisateur effectue une modification dans l'interface utilisateur, Gitaly transmet la requête au service `gitaly-ruby`, qui est écrit en Ruby. `gitaly-ruby` effectue des modifications dans le dépôt et renvoie un rapport via un appel gRPC à son processus parent. Malheureusement, comme le montre l'étape 4 ci-dessous, l'étape de reporting n'a pas eu lieu :\n\n```mermaid\nsequenceDiagram\n    autonumber\n    participant C as Client\n    participant R as Rails\n    participant G as Gitaly\n    participant GR as gitaly-ruby\n    participant P as Proxy\n    C->>R: Change file in UI\n    R->>G: gRPC: UserCommitFiles\n    G->>GR: gRPC: UserCommitFiles\n    GR->>P: CONNECT\n    P->>GR: FAIL\n```\n\nPuisque gRPC utilise HTTP/2 comme mode de transport, `gitaly-ruby` tente de se connecter au proxy (il était connecté à une configuration erronée de `no_proxy`). Le proxy a immédiatement rejeté la requête HTTP, ce qui a entraîné l'erreur du push sur l'interface Web. \n\nAprès la suppression des minuscules `no_proxy` de l'environnement, les pushs depuis l'interface utilisateur ont fonctionné comme prévu. `gitaly-ruby` s'est connecté au processus parent Gitaly. L'étape 4 a donc fonctionné comme suit : \n\n```mermaid\nsequenceDiagram\n    autonumber\n    participant C as Client\n    participant R as Rails\n    participant G as Gitaly\n    participant GR as gitaly-ruby\n    participant P as Proxy\n    C->>R: Change file in UI\n    R->>G: gRPC: UserCommitFiles\n    G->>GR: gRPC: UserCommitFiles\n    GR->>G: OK\n    G->>R: OK\n    R->>C: OK\n```\n\n#### Pourquoi faut-il privilégier un proxy HTTPS ?\n\nNotez que le client a défini `HTTPS_PROXY` sur un proxy HTTP non crypté : `http://` est préféré à `https://`. Bien que ce ne soit pas idéal en termes de sécurité, certaines équipes de développement utilisent cette méthode pour éviter les problèmes de certificats TLS (et donc, des problèmes de connexion pour les utilisateurs finaux). \n\nSi un proxy HTTPS avait été spécifié, nous n’aurions pas rencontré ce problème. Lorsqu'un proxy HTTPS est utilisé, gRPC ignore ce paramètre car [les proxy HTTPS ne sont pas pris en charge](https://github.com/grpc/grpc/issues/20939).\n\n## Le plus petit dénominateur commun\n\nPersonne ne devrait définir des valeurs irrégulières avec des paramètres de proxy en minuscules et en majuscules. Cependant, si vous devez gérer une stack dans plusieurs langages, vous pourrez configurer les paramètres de proxy HTTP selon le plus petit dénominateur commun.\n\n### `http_proxy` et `https_proxy`\n\n`HTTP_PROXY` n'est pas toujours pris en charge ou recommandé. Préférez toujours le format en minuscules et si vous devez absolument utiliser la version en majuscules, vérifiez qu'elles partagent la même valeur.\n\n### `no_proxy`\n\n1. Adoptez le format en minuscules.\n2. Utilisez les valeurs `hostname:port` séparées par des virgules.\n3. Les adresses IP sont acceptables, mais les noms d'hôtes ne sont pas résolus.\n4. Les suffixes correspondent toujours (`example.com` correspondra à `test.example.com`).\n5. Évitez d'utiliser le point initial (`.`) pour les domaines de premier niveau.\n6. Veillez à ne pas utiliser de correspondances de blocs CIDR. Seuls Go et Ruby les prennent en charge. \n\n## Standardiser `no_proxy`\n\nConnaître le plus petit dénominateur commun aide à éviter des problèmes si ces définitions sont copiées pour différents clients Web. Mais est-ce que `no_proxy` et les autres configurations de proxy requièrent une version standard documentée plutôt qu'une convention ad hoc ? \n\nVoici quelques points qui peuvent vous aider : \n\n1. Préférez le format en minuscules aux variantes en majuscules (`http_proxy` devrait être utilisé avant `HTTP_PROXY`).\n2. Utilisez des valeurs `hostname:port` séparées par des virgules (chaque valeur peut inclure des espaces facultatifs.). \n3. Ne faites pas de recherche DNS et évitez les expressions régulières (regex). \n4. Appliquez `*` pour faire correspondre tous les hôtes.\n5. Supprimez les points initiaux (`.`) et faites correspondre les suffixes de domaine. \n6. Prenez en charge la correspondance des blocs CIDR. \n7. Évitez les suppositions sur des adresses IP spéciales (comme les adresses de bouclage dans `no_proxy`).\n\n## Conclusion\n\nPlus de 30 ans se sont écoulés depuis la sortie du premier serveur proxy Web. Depuis, les principes fondamentaux pour configurer un client Web grâce à des variables n'ont pas vraiment changé. Néanmoins, certaines subtilités ont vu le jour. \n\nÀ travers un cas pratique, vous avez découvert qu'une définition erronée des variables `no_proxy` et `NO_PROXY` a entraîné des heures de travail pour résoudre le problème, en raison de différences d'acceptation de configuration entre Ruby et Go. \n\nEn mettant en évidence ces différences, nous espérons vous éviter de futurs problèmes dans votre stack de production. Et qui sait, nous verrons peut-être voir le jour une standardisation au niveau des chargés de maintenance des clients Web. \n",[272,960,961,962],"careers","user stories","startups",{"slug":964,"featured":6,"template":686},"we-need-to-talk-no-proxy","content:fr-fr:blog:we-need-to-talk-no-proxy.yml","We Need To Talk No Proxy","fr-fr/blog/we-need-to-talk-no-proxy.yml","fr-fr/blog/we-need-to-talk-no-proxy",{"_path":970,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":971,"content":977,"config":984,"_id":986,"_type":16,"title":987,"_source":18,"_file":988,"_stem":989,"_extension":21},"/fr-fr/blog/basics-of-gitlab-ci-updated",{"title":972,"description":973,"ogTitle":972,"ogDescription":973,"noIndex":6,"ogImage":974,"ogUrl":975,"ogSiteName":723,"ogType":724,"canonicalUrls":975,"schema":976},"Intégration continue : créez votre premier pipeline CI avec GitLab ","Vous débutez dans l'intégration continue ? Apprenez à créer votre premier pipeline CI avec GitLab. Lisez notre guide complet.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662061/Blog/Hero%20Images/cicdcover.png","https://about.gitlab.com/blog/basics-of-gitlab-ci-updated","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Intégration continue : créez votre premier pipeline CI avec GitLab \",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2020-12-10\",\n      }",{"title":972,"description":973,"authors":978,"heroImage":974,"date":980,"body":981,"category":14,"tags":982,"updatedDate":983},[979],"Itzik Gan Baruch","2020-12-10","Imaginons que vous ne connaissiez rien au concept d’[intégration continue\n(CI)](https://about.gitlab.com/fr-fr/topics/ci-cd/benefits-continuous-integration/\n\"Qu'est-ce que l'intégration continue (CI) ?\") ni à son rôle clé dans le\ncycle de vie du développement logiciel.\n\n\nÀ présent, supposons que vous travaillez sur un projet pour lequel\nl'intégralité du code est répartie dans seulement deux fichiers. Pour\ngarantir le bon fonctionnement de ce projet, il est impératif que la\nconcaténation de ces deux fichiers contienne la phrase « Hello world ».\n\n\nToute la réussite du projet repose sur cette simple phrase, car sans elle,\ntout serait compromis.\n\n\nConscient de cet enjeu, votre meilleur développeur logiciel a décidé de\ncréer un script qui s'exécute dès qu’un nouveau morceau de code est envoyé\naux clients.\n\n\nVoici à quoi cela ressemble  :\n\n\n```bash\n\ncat file1.txt file2.txt | grep -q \"Hello world\"\n\n```\n\n\nMême si, en l'état, ce script permet d'exécuter notre tâche, son\ndéclenchement reste manuel. Et, avec une équipe de développement composée de\n10 personnes, vous n'êtes pas à l'abri d'une erreur humaine qui pourrait\nvous coûter très cher. \n\n\nLa preuve en est, pas plus tard que la semaine dernière, un nouveau membre\nde votre équipe a oublié d'exécuter le script, provoquant des erreurs de\ncompilation pour trois de vos clients.\n\n\nVous prenez donc la décision de résoudre ce problème, une bonne fois pour\ntoutes, en utilisant le pipeline d'[intégration et de livraison\ncontinues](https://about.gitlab.com/fr-fr/solutions/continuous-integration/\n\"Intégration et livraison continues\") de GitLab. Par chance, votre code est\ndéjà sur la plateforme. Il ne vous reste plus qu'à vous lancer.  \n\n\n## Effectuer un premier test dans le pipeline CI de GitLab\n\n\nÀ la lecture de la documentation de GitLab, nous savons qu'il suffit de\nréunir deux lignes de code dans un fichier appelé `.gitlab-ci.yml`:\n\n\n```yaml\n\ntest:\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n```\n\n\nNous le validons et constatons que la compilation s'est déroulée avec succès\n\n\n![Compilation réussie dans le pipeline d’intégration\ncontinue](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/build_succeeded.png)\n\n\nMaintenant, remplaçons « world » par « Africa » dans le deuxième fichier et\nvoyons ce qui se passe :\n\n\n![Échec de compilation dans le pipeline CI\nGitLab](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/build_failed.png)\n\n\nComme nous pouvions le prévoir, la compilation a échoué.\n\n\nNous avons désormais mis en place l'automatisation des tests.  \n\n\nÀ partir de maintenant, [GitLab\nCI](https://about.gitlab.com/fr-fr/blog/ci-deployment-and-environments/\n\"Comment déployer du code dans des environnements multiples avec GitLab CI\")\nexécutera notre script de test dès que nous effectuerons un push du code\nvers le dépôt de code source dans l'environnement\n[DevOps](https://about.gitlab.com/fr-fr/topics/devops/ \"Que signifie DevOps\n?\"). \n\n\nRemarque : dans l'exemple ci-dessus, nous supposons que file1.txt et\nfile2.txt existent sur l'hôte du runner. Pour exécuter cet exemple dans\nGitLab, utilisez le code ci-dessous, qui crée d'abord les fichiers, puis\nexécute le script.\n\n\n```yaml\n\ntest:\n\nbefore_script:\n      - echo \"Hello \" > | tr -d \"\\n\" | > file1.txt\n      - echo \"world\" > file2.txt\nscript: cat file1.txt file2.txt | grep -q 'Hello world'\n\n```\n\n\nPour simplifier notre démonstration, nous partons du principe que ces\nfichiers existent déjà sur l'hôte. Nous n'allons donc pas les créer dans les\nétapes suivantes.\n\n\n## Rendre les résultats des compilations téléchargeables\n\n\nLa prochaine étape consiste à empaqueter le code avant de l'envoyer aux\nclients. Alors, pourquoi ne pas automatiser aussi cette partie du processus\nde développement logiciel ?\n\n\nPour cela, tout ce que nous devons faire est de définir un autre job pour\nl'intégration continue. \n\n\nCommençons par nommer notre job « package » :\n\n\n```yaml\n\ntest:\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n\npackage:\n  script: cat file1.txt file2.txt | gzip > package.gz\n```\n\n\nNous avons maintenant deux onglets : \n\n\n![Deux onglets - générés par deux\njobs](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/two_tabs.png)\n\n\nCependant, nous avons oublié de spécifier que le nouveau fichier est un\nartefact de compilation, afin qu’il puisse être téléchargé. Nous pouvons\ncorriger cela en ajoutant une section `artefacts` :\n\n\n```yaml\n\ntest:\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n\npackage:\n  script: cat file1.txt file2.txt | gzip > packaged.gz\n  artifacts:\n    paths:\n    - packaged.gz\n```\n\n\nVérifions que tout est en place :\n\n\n![Artefact de compilation téléchargeable dans le pipeline CI/CD de\nGitLab](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/artifacts.png)\n\n\nFélicitations ! Tout semble fonctionnel. En revanche, dans la configuration\nactuelle, les jobs s'exécutent en parallèle. Cela signifie que notre\napplication pourra être empaquetée, et ce, même si les tests échouent. Pour\néviter que cela ne se produise, nous allons devoir exécuter les jobs de\nmanière séquentielle.  \n\n\n## Exécuter des jobs de manière séquentielle\n\n\nPour éviter d'empaqueter une application contenant des erreurs, nous allons\nfaire en sorte d'exécuter le job « package » uniquement si les tests sont\npréalablement réussis. Pour commencer, définissons l'ordre d'exécution en\nétablissant des étapes spécifiques  :\n\n\n```yaml\n\nstages:\n  - test\n  - package\n\ntest:\n  stage: test\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n\npackage:\n  stage: package\n  script: cat file1.txt file2.txt | gzip > packaged.gz\n  artifacts:\n    paths:\n    - packaged.gz\n```\n\n\nCela devrait maintenant fonctionner.\n\n\nNous souhaitons également garantir que la compilation (qui est représentée\npar la concaténation dans notre exemple) ne s'exécute qu'une seule fois. En\neffet, cette étape pouvant être chronophage, il serait dommage de l'exécuter\ninutilement.\n\n\nPour éviter cela, définissons une étape supplémentaire :\n\n\n```yaml\n\nstages:\n  - compile\n  - test\n  - package\n\ncompile:\n  stage: compile\n  script: cat file1.txt file2.txt > compiled.txt\n  artifacts:\n    paths:\n    - compiled.txt\n\ntest:\n  stage: test\n  script: cat compiled.txt | grep -q 'Hello world'\n\npackage:\n  stage: package\n  script: cat compiled.txt | gzip > packaged.gz\n  artifacts:\n    paths:\n    - packaged.gz\n```\n\n\nJetons un œil à nos artefacts :\n\n\n![Artefacts de compilation dans le pipeline CI de\nGitLab](https://about.gitlab.com/images/blogimages/the-basics-of-gitlab-ci/clean-artifacts.png)\n\n\nTout a l'air de fonctionner. En revanche, il faudrait éviter de rendre le\nfichier « compile » téléchargeable. Pour cela, nous allons rendre nos\nartefacts temporaires expirables en définissant `expire_in` à « 20 minutes\n».  \n\n\n```yaml\n\ncompile:\n  stage: compile\n  script: cat file1.txt file2.txt > compiled.txt\n  artifacts:\n    paths:\n    - compiled.txt\n    expire_in: 20 minutes\n```\n\n\nMaintenant, notre configuration semble plutôt complète : \n\n- Nous avons trois étapes séquentielles pour compiler, tester et empaqueter\nnotre application. \n\n- Nous transmettons également l'application compilée aux étapes suivantes\npour ne pas exécuter la compilation à deux reprises (ce qui accélère le\nprocessus). \n\n- Et nous stockons une version empaquetée de notre application dans les\nartefacts de compilation pour une utilisation ultérieure.\n\n\n## Savoir quelle image Docker utiliser\n\n\nJusqu'ici, tout va bien. Cependant, en regardant de plus près, nos\ncompilations semblent toujours lentes. Prenons un moment pour regarder les\njournaux (logs) :\n\n\n![Image ruby\n3.1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/ruby-31.png)\n\n\nEn observant de plus près, nous remarquons la mention suivante : `ruby:3.1`.\nCela signifie que GitLab.com utilise des images Docker pour [exécuter nos\ncompilations](https://about.gitlab.com/blog/shared-runners/), et qu’il\nutilise [par\ndéfaut](https://docs.gitlab.com/ee/user/gitlab_com/#shared-runners), l'image\n[`ruby:3.1`](https://hub.docker.com/_/ruby/).\n\n\nCette image contient certainement de nombreux paquets dont nous n'avons pas\nbesoin. Dans un souci d'optimisation de notre pipeline CI, il serait donc\npréférable de changer d'image. Après une courte recherche sur Google, nous\ndécouvrons qu'il existe une image Linux presque vierge appelée\n[`alpine`](https://hub.docker.com/_/alpine/). Nous allons alors l'utiliser.\nPour cela, nous devrons ajouter `image: alpine` au fichier `.gitlab-ci.yml`.\n\n\nEt voilà !  Nous avons maintenant réduit le temps de compilation de presque\ntrois minutes :\n\n\n![Vitesse de compilation améliorée dans le pipeline de\nGitLab](https://about.gitlab.com/images/blogimages/the-basics-of-gitlab-ci/speed.png)\n\n\nVous pouvez également trouver des images libres de droits sur\n[mysql](https://hub.docker.com/_/mysql/),\n[Python](https://hub.docker.com/_/python/),\n[Java](https://hub.docker.com/_/java/) et\n[php](https://hub.docker.com/_/php/). Il est facile, alors, d'en choisir une\npour notre pile technologique. \n\n\nNote : il sera toujours préférable d'utiliser une image qui ne contient\naucun logiciel supplémentaire dont vous n'avez pas besoin, car cela minimise\ngrandement le temps de téléchargement.\n\n\n## Gérer des scénarios complexes \n\n\nImaginons maintenant un scénario un peu plus complexe. Par exemple, un\nnouveau client souhaite que nous empaquetions notre application au format\n`.iso` plutôt qu'en `.gz`. \n\n\nÉtant donné que le pipeline d'intégration continue gère tout le processus,\net que les images ISO peuvent être créées avec la commande `mkisofs`, il\nsuffit d'ajouter un job supplémentaire.\n\n\nVoici à quoi notre configuration devrait ressembler :\n\n\n```yaml\n\nimage: alpine\n\n\nstages:\n  - compile\n  - test\n  - package\n\n# ... \"compile\" and \"test\" jobs are skipped here for the sake of compactness\n\n\npack-gz:\n  stage: package\n  script: cat compiled.txt | gzip > packaged.gz\n  artifacts:\n    paths:\n    - packaged.gz\n\npack-iso:\n  stage: package\n  script:\n  - mkisofs -o ./packaged.iso ./compiled.txt\n  artifacts:\n    paths:\n    - packaged.iso\n```\n\n\nNotez que les noms des jobs ne doivent pas être nécessairement identiques.\nS'ils l'étaient, il serait impossible de faire s'exécuter les jobs en\nparallèle dans la même étape du processus de développement logiciel. \n\n\nAinsi, dans l'exemple qui suit, ignorez le fait que les jobs et étapes\nportent le même nom.\n\n\nQuoi qu'il en soit, la compilation échoue :\n\n\n![Echec de compilation dans le pipeline de\nGitLab](https://about.gitlab.com/images/blogimages/the-basics-of-gitlab-ci/mkisofs.png)\n\n\nLe problème vient de  `mkisofs` qui n'est pas inclus dans l'image `alpine`.\nNous devons donc d'abord l'installer.\n\n\n## Gérer des logiciels et des paquets manquants \n\n\nSelon le [site Web d’Alpine\nLinux](https://pkgs.alpinelinux.org/contents?file=mkisofs&path=&name=&branch=edge&repo=&arch=\n\"Site Web Alpine Linux\"), `mkisofs` fait partie des paquets `xorriso` et\n`cdrkit`. Voici les commandes que nous devons exécuter pour installer un\npaquet :\n\n\n```bash\n\necho \"ipv6\" >> /etc/modules  # enable networking\n\napk update                   # update packages list\n\napk add xorriso              # install package\n\n```\n\n\nCes commandes s'exécutent de la même manière que toute autre commande au\nsein du processus d'intégration continue. La liste complète des commandes\nque nous devons transmettre à la section `script` devrait ressembler à ceci\n:\n\n\n```yml\n\nscript:\n\n- echo \"ipv6\" >> /etc/modules\n\n- apk update\n\n- apk add xorriso\n\n- mkisofs -o ./packaged.iso ./compiled.txt\n\n```\n\n\nCependant, pour des raisons sémantiques, plaçons les commandes liées à\nl'installation du paquet dans `before_script`. \n\n\nNotez que si vous utilisez `before_script` au niveau supérieur d'une\nconfiguration, alors les commandes s'exécuteront avant tous les jobs. Dans\nnotre cas, nous voulons simplement qu'elles s'exécutent avant un job\nspécifique.\n\n\n## Graphes acycliques orientés pour des pipelines CI plus rapides et\nflexibles\n\n\nPlus haut, nous avons configuré des étapes pour que les jobs d'empaquetage\nne s'exécutent qu'à la condition que les tests réussissent. Mais, que se\npasserait-il si nous voulions bouleverser le séquencement des étapes en\nexécutant certains jobs plus tôt qu'initialement prévu ? \n\n\nDans certains cas, le séquencement traditionnel des étapes peut ralentir la\ndurée globale d'exécution du [pipeline\nCI/CD](https://about.gitlab.com/fr-fr/topics/ci-cd/cicd-pipeline/ \"Qu'est-ce\nqu'un pipeline CI/CD ?\"). Pour éviter cela, nous pouvons choisir de\npersonnaliser le séquencement de nos jobs. \n\n\nPar exemple : imaginons que notre étape de test comprenne des tests lourds,\nprenant beaucoup de temps à s'exécuter. Supposons aussi que ces tests ne\nsoient pas nécessairement liés aux jobs d’empaquetage. Dans ce cas, il\nserait préférable que les jobs d’empaquetage puissent démarrer sans attendre\nla fin de ces tests. C'est là qu'interviennent les [graphes acycliques\norientés](https://about.gitlab.com/blog/directed-acyclic-graph/ \"Graphes\nacycliques orientés\"). Ces derniers visent à rompre l'ordre normal\nd'exécution des jobs (ordre séquentiel) grâce à la création de dépendances\nentre certains jobs. Vous pouvez ainsi définir un ordre personnalisé pour\nexécuter les différents jobs de votre pipeline CI.\n\n\nGrâce au mot-clé `needs`, GitLab crée des dépendances entre les jobs et leur\npermet de s'exécuter plus tôt, dès que leurs jobs dépendants sont terminés.\n\n\nDans l'exemple ci-dessous, les jobs d’empaquetage commenceront à s'exécuter\ndès que le test sera terminé. Ainsi, à l'avenir, si quelqu'un ajoute\nd'autres tests à l'étape de test, les jobs d’empaquetage commenceront à\ns'exécuter avant la fin des nouveaux tests :\n\n\n```yaml\n\npack-gz:\n  stage: package\n  script: cat compiled.txt | gzip > packaged.gz\n  needs: [\"test\"]\n  artifacts:\n    paths:\n    - packaged.gz\n\npack-iso:\n  stage: package\n  before_script:\n  - echo \"ipv6\" >> /etc/modules\n  - apk update\n  - apk add xorriso\n  script:\n  - mkisofs -o ./packaged.iso ./compiled.txt\n  needs: [\"test\"]\n  artifacts:\n    paths:\n    - packaged.iso\n```\n\n\nVoici notre version définitive de `.gitlab-ci.yml`:\n\n\n```yaml\n\nimage: alpine\n\n\nstages:\n  - compile\n  - test\n  - package\n\ncompile:\n  stage: compile\n  before_script:\n      - echo \"Hello  \" | tr -d \"\\n\" > file1.txt\n      - echo \"world\" > file2.txt\n  script: cat file1.txt file2.txt > compiled.txt\n  artifacts:\n    paths:\n    - compiled.txt\n    expire_in: 20 minutes\n\ntest:\n  stage: test\n  script: cat compiled.txt | grep -q 'Hello world'\n\npack-gz:\n  stage: package\n  script: cat compiled.txt | gzip > packaged.gz\n  needs: [\"test\"]\n  artifacts:\n    paths:\n    - packaged.gz\n\npack-iso:\n  stage: package\n  before_script:\n  - echo \"ipv6\" >> /etc/modules\n  - apk update\n  - apk add xorriso\n  script:\n  - mkisofs -o ./packaged.iso ./compiled.txt\n  needs: [\"test\"]\n  artifacts:\n    paths:\n    - packaged.iso\n```\n\n\nNous venons de créer un pipeline ! Ainsi, nous avons trois étapes\nséquentielles avec les \n\njobs `pack-gz` et `pack-iso` qui s'exécutent en parallèle à l'intérieur de\nl'étape d'empaquetage :\n\n\n![Représentation d'un artefact de compilation d'un pipeline\nCI](https://about.gitlab.com/images/blogimages/the-basics-of-gitlab-ci/pipeline.png)\n\n\n## Améliorer votre pipeline CI\n\n\nNous allons maintenant découvrir comment améliorer notre pipeline\nd'intégration continue.\n\n\n### Intégrer des tests automatisés dans vos pipelines CI\n\n\nL'objectif clé du développement logiciel avec une approche DevOps est de\nréussir à créer des applications offrant une excellente expérience\nutilisateur. \n\n\nAvec cet objectif en tête, pourquoi ne pas renforcer le cycle de\ndéveloppement logiciel en cherchant à détecter d'éventuels bogues dès le\ndébut du processus ? Pour ce faire, ajoutons des tests à notre pipeline CI.\nDe cette façon, nous pourrons résoudre les problèmes le plus tôt possible.\n\n\nPar chance, le pipeline CI de GitLab nous facilite la tâche en proposant des\ntemplates de tests prêts à l'emploi. Tout ce que nous avons à faire, c'est\nd'inclure ces templates dans la configuration de notre pipeline CI.\n\n\nDans cet exemple, nous allons réaliser des [tests\nd'accessibilité](https://docs.gitlab.com/ee/ci/testing/accessibility_testing.html\n\"Test d'accessibilité\") :\n\n\n```yaml\n\nstages:\n  - accessibility\n\nvariables:\n  a11y_urls: \"https://about.gitlab.com https://www.example.com\"\n\ninclude:\n  - template: \"Verify/Accessibility.gitlab-ci.yml\"\n```\n\n\nPersonnalisez la variable `a11y_urls` pour répertorier les URL des pages web\nà tester avec [Pa11y](https://pa11y.org/ \"Pa11y\") et GitLab [Code\nQuality](https://docs.gitlab.com/ee/ci/testing/code_quality.html \"Code\nQuality\"). \n\n\n```yaml\n   include:\n   - template: Jobs/Code-Quality.gitlab-ci.yml\n```\n\n\nGitLab facilite la consultation du rapport de test directement dans la zone\ndu widget de la [merge\nrequest](https://docs.gitlab.com/ee/user/project/merge_requests/ \"Merge\nrequest\"). Ce widget vous permet de voir la revue de code, l'état du\npipeline et les résultats des tests au même endroit. La capture d'écran\nci-dessous montre à quel point ce widget facilite le travail de vos\néquipes. \n\n\n![Exemple de rapport d'accessibilité dans le pipeline CI/CD de\nGitLab](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-02_at_10.56.41.png)\n\n\u003Ccenter>\u003Ci>Widget pour les merge requests en matière\nd'accessibilité\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\n\n![Exemple de rapport de test sur la qualité du code suite à une merge\nrequest dans\nGitLab](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-02_at_11.00.25.png)\n\n\u003Ccenter>\u003Ci>Widget de merge request pour GitLab Code Quality\u003C/i>\u003C/center>\n\n\n### Matrice des compilations\n\n\nDans certains cas, nous devons tester notre application dans différentes\nconfigurations, versions de systèmes d'exploitation et langages de\nprogrammation. Nous utilisons alors la compilation «\n[parallel:matrix](https://docs.gitlab.com/ee/ci/yaml/#parallelmatrix\n\"parallel:matrix\") ». Cela nous permet de tester notre application à travers\ndiverses combinaisons en parallèle dans un seul job. Maintenant, testons\nnotre code avec différentes versions de Python et avec le mot-clé « matrix\n».\n\n\n```yaml\n\npython-req:\n  image: python:$VERSION\n  stage: lint\n  script:\n    - pip install -r requirements_dev.txt\n    - chmod +x ./build_cpp.sh\n    - ./build_cpp.sh\n  parallel:\n    matrix:\n      - VERSION: ['3.8', '3.9', '3.10', '3.11']   # https://hub.docker.com/_/python\n```\n\n\nLors de l'exécution du pipeline, ce job s'exécute en parallèle quatre fois,\nchaque fois en utilisant une image Python différente comme indiqué\nci-dessous :\n\n\n![Exécution de jobs en parallèle dans le pipeline\nCI/CD](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-02_at_11.12.48.png)\n\n\n### Tests unitaires\n\n\n#### Que sont les tests unitaires ?\n\n\nLes tests unitaires sont des tests ciblés et de petite envergure qui\nvérifient des composants ou des fonctions d'un logiciel. Ces tests\npermettent d'assurer qu'il fonctionne comme prévu. Ils sont essentiels pour\nvérifier que chaque partie du code fonctionne correctement et permettent de\ndétecter les bogues le plus tôt possible dans le processus de développement\nlogiciel. \n\n\nExemple : imaginez que vous développiez une application de calculatrice. Un\ntest unitaire pour la fonction « addition » va vérifier si le résultat d'un\ncalcul comme 2 + 2 est bien égale à 4. Si ce test est concluant, nous avons\nconfirmation que la fonction « addition » fonctionne correctement.\n\n\n#### Tests unitaires : les bonnes pratiques\n\n\nMettre en place des tests unitaires, c'est bien, mais il est possible\nd'aller encore plus loin pour faciliter la vie de vos équipes de\ndéveloppement.\n\n\nPar exemple, lorsqu'un test échoue, vos équipes reçoivent une notification.\nS'engage alors un long processus de vérification des job logs afin de\ntrouver et de corriger les erreurs. Ce processus est long et pourrait être\noptimisé.\n\n\nIl est possible de configurer votre job pour qu'il utilise des [rapports de\ntests\nunitaires](https://docs.gitlab.com/ee/ci/testing/unit_test_reports.html\n\"Rapports de tests unitaires\") (rapports détaillés des erreurs permettant de\nles traiter plus efficacement). GitLab affiche ces rapports dans la merge\nrequest et sur la page de détails des pipelines CI. Cela facilite\nl'identification des échecs, car il n'y a alors plus besoin de consulter\nl'intégralité du journal.\n\n\n#### Rapport de test JUnit\n\n\nCi-dessous un exemple de rapport de test JUnit : \n\n\n![Rapport de test JUnit dans un pipeline d'intégration\ncontinue](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674097/Blog/Content%20Images/pipelines_junit_test_report_v13_10.png){:\n.shadow.center}\n\n\n### Stratégies d'intégration et de tests de bout en bout\n\n\nAfin de s'assurer que toutes les parties de notre code fonctionnent en\nharmonie (y compris les\n[microservices](https://about.gitlab.com/fr-fr/topics/microservices/ \"Que\nsont les microservices ?\"), les tests d'interface utilisateur), il est\ncapital de configurer un pipeline dédié à l'intégration et aux tests de bout\nen bout.\n\n\nCes tests sont exécutés [chaque\nnuit](https://docs.gitlab.com/ee/ci/pipelines/schedules.html) et il est\npossible de configurer le système pour que les [résultats soient\nautomatiquement envoyés vers un canal Slack\ndédié](https://docs.gitlab.com/ee/user/project/integrations/gitlab_slack_application.html#notification-events).\nAinsi, lorsque les équipes de développement arrivent le matin, elles peuvent\nrapidement travailler sur les problèmes identifiés la veille. L'objectif\nétant de détecter et de corriger les problèmes le plus tôt possible dans le\nprocessus de développement logiciel.\n\n\n### Environnement de test\n\n\nDans certains cas, nous avons besoin d'un environnement dédié pour tester\ncorrectement nos applications. On parle alors d'environnement de test. Avec\nle pipeline CI/CD de GitLab, nous pouvons automatiser le déploiement des\nenvironnements de test, et ainsi gagner un temps considérable. \n\n\nComme cet article se concentre principalement sur les pipelines\nd'intégration continue, nous ne nous attarderons pas sur ce point ici. En\nrevanche, libre à vous de consulter la section dédiée à ce sujet dans la\n[documentation\nGitLab](https://docs.gitlab.com/ee/topics/release_your_application.html).\n\n\n## Implémenter des scans de sécurité dans un pipeline CI\n\n\nVoici comment mettre en œuvre des scans de sécurité dans un pipeline CI.\n\n\n### Intégration des SAST et des DAST\n\n\nAvant toute chose, nous souhaitons garder notre code en sécurité. S'il y a\nla moindre vulnérabilité dans nos dernières modifications, nous voulons en\nêtre informés dès que possible. C'est pourquoi il est judicieux d'ajouter\ndes scans de sécurité à votre pipeline CI. \n\nCes scans vérifient le code à chaque commit et vous alertent dès qu'une\nfaille est détectée. \n\n\nIl existe deux types de scan : \n\n- les tests statiques de sécurité des applications\n([SAST](https://docs.gitlab.com/ee/user/application_security/sast/ \"SAST\"))\n\n- les tests dynamiques de sécurité des applications\n([DAST](https://docs.gitlab.com/ee/user/application_security/dast/ \"DAST\"))\n\n\nCi-dessous, consultez notre guide interactif qui vous montre comment ajouter\ndes scans de sécurité à votre pipeline CI. \n\n\nCliquez sur l'image ci-dessous pour commencer. \n\n\n[![Scans product\ntour](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-14_at_13.44.42.png)](https://gitlab.navattic.com/gitlab-scans)\n\n\nGrâce à l'IA et à ses capacités d'analyse, nous pouvons également obtenir\ndes suggestions sur la manière dont les vulnérabilités peuvent être\ncorrigées. Consultez cette démonstration pour plus d'informations.\n\n\nCliquez sur l'image ci-dessous pour commencer. \n\n\n[![product tour explain vulnerability\n](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-14_at_13.50.24.png)](https://tech-marketing.gitlab.io/static-demos/pt-explain-vulnerability.html)\n\n\n## Récapitulatif\n\n\nDans cet article, nous avons volontairement simplifié les exemples afin de\nfaciliter l'intégration des différents concepts de GitLab CI.\n\n\nRésumons rapidement ce que nous avons appris :\n\n1. Pour déléguer certaines tâches à GitLab CI, vous devez définir un ou\nplusieurs [jobs](https://docs.gitlab.com/ee/ci/jobs/) dans `.gitlab-ci.yml`.\n\n2. Les jobs doivent avoir des noms, de préférence facilement identifiables.\n\n3. Chaque job contient un ensemble de règles et d'instructions pour le\npipeline de GitLab. Ces derniers sont définis par des mots-clés spécifiques.\n\n4. Les jobs peuvent s'exécuter de manière séquentielle, en parallèle, ou\ndans l'ordre de votre choix grâce aux graphes acycliques orientés. \n\n5. Vous pouvez transférer des fichiers entre les jobs et les stocker dans\ndes artefacts de compilation afin de pouvoir les télécharger depuis\nl'interface de GitLab CI.\n\n6. Ajoutez [des tests et des scans de\nsécurité](https://docs.gitlab.com/ee/development/integrations/secure.html\n\"Tests et scans de sécurité\") au pipeline CI pour garantir la qualité et la\nsécurité de votre application.\n\n\nCi-dessous se trouvent des descriptions des termes et des mots-clés que nous\navons abordés dans cet article.\n\n\n### Mots-clés, descriptions et documentation\n\n\n{: #keywords}\n\n\n| Mots-clés/termes       | Description |\n\n|---------------|--------------------|\n\n| [.gitlab-ci.yml](https://docs.gitlab.com/ee/ci/yaml/) | Fichier contenant\ntoutes les explications sur la façon dont votre projet doit être construit |\n\n| [script](https://docs.gitlab.com/ee/ci/yaml/#script)        | Définit un\nscript shell à exécuter |\n\n| [before_script](https://docs.gitlab.com/ee/ci/yaml/#before_script) |\nUtilisé pour définir la commande qui doit être exécutée avant tous les jobs\n|\n\n|\n[image](https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#what-is-image)\n| Définit l’image Docker à utiliser |\n\n| [stages](https://docs.gitlab.com/ee/ci/yaml/#stages)         | Définit une\nétape du pipeline CI (par défaut : `test`) |\n\n| [artifacts](https://docs.gitlab.com/ee/ci/yaml/#artifacts)     | Définit\nune liste d'artefacts de compilation |\n\n|\n[artifacts:expire_in](https://docs.gitlab.com/ee/ci/yaml/#artifactsexpire_in)\n| Utilisé pour supprimer les artefacts téléchargés après une durée spécifiée\n|\n\n| [needs](https://docs.gitlab.com/ee/ci/yaml/#needs) | Permet de définir les\ndépendances entre les jobs et permet d'exécuter des jobs dans l'ordre de\nvotre choix |\n\n| [pipelines](https://about.gitlab.com/fr-fr/topics/ci-cd/cicd-pipeline/) |\nUn pipeline est un groupe de compilations exécutées par étapes (batch) |\n\n\n## En savoir plus sur les pipelines CI/CD\n\n\n- [Quelles sont les meilleures pratiques CI/CD à connaître\n?](https://about.gitlab.com/fr-fr/blog/how-to-keep-up-with-ci-cd-best-practices/\n\"Quelles sont les meilleures pratiques CI/CD à connaître ?\")\n\n- [Le guide CI/CD de GitLab pour les\ndébutants](https://about.gitlab.com/blog/beginner-guide-ci-cd/)\n\n- [Obtenez des pipelines plus rapides et plus flexibles avec un graphe\nacyclique orienté](https://about.gitlab.com/blog/directed-acyclic-graph/)\n\n- [Réduisez le temps de compilation avec une image Docker\npersonnalisée](http://beenje.github.io/blog/posts/gitlab-ci-and-conda/)\n\n- [Présentation de la version bêta du catalogue GitLab\nCI/CD](https://about.gitlab.com/blog/introducing-the-gitlab-ci-cd-catalog-beta/)\n\n\n## FAQ sur le pipeline d’intégration continue\n\n\n### Comment choisir entre l'exécution séquentielle et parallèle des jobs\ndans un pipeline CI ?\n\n\nIl y a plusieurs considérations à prendre en compte pour choisir entre\nl'exécution séquentielle et parallèle des jobs dans un pipeline CI. Ainsi,\nil faut considérer les dépendances entre les jobs, la disponibilité des\nressources, les temps d'exécution, les interférences potentielles, la\nstructure de la séquence de tests ou encore les coûts que cela implique. \n\n\nPar exemple, si vous avez un job de compilation qui doit se terminer avant\nqu'un job de déploiement puisse démarrer, vous exécuterez ces jobs de\nmanière séquentielle pour garantir le bon ordre d'exécution. En revanche,\nles tâches telles que les tests unitaires et les tests d'intégration peuvent\ngénéralement s'exécuter en parallèle, car elles ne dépendent pas de\nl'achèvement des autres.\n\n\n### Que sont les graphes acycliques orientés dans GitLab et comment\naméliorent-ils la flexibilité du pipeline CI ?\n\n\nUn graphe acyclique orienté dans un pipeline CI permet d'exécuter des jobs\nen fonction de leurs dépendances, plutôt que dans un ordre strictement\nséquentiel. Ce graphe vous permet ainsi de définir un ordre d'exécution des\njobs pour que ceux des étapes ultérieures commencent dès que les jobs des\nétapes précédentes se terminent. Cela réduit le temps d'exécution global du\npipeline, améliore l'efficacité et laisse même à certains jobs la\npossibilité de se terminer plus tôt que s'ils avaient été exécutés dans un\nordre purement séquentiel (du premier au dernier dans la liste).\n\n\n### Pourquoi est-il important de choisir la bonne image Docker pour les jobs\nd'un pipeline CI GitLab ?\n\n\nGitLab utilise des images Docker pour exécuter des jobs dont l'image par\ndéfaut est ruby 3.1. Pour optimiser votre pipeline CI, il sera cependant\ncrucial de choisir l'image la plus appropriée à vos besoins. Comprenez que\nles jobs téléchargent d'abord l'image Docker spécifiée. Si l'image contient\ndes paquets supplémentaires inutiles, cela augmentera les temps de\ntéléchargement et d'exécution. Il est donc important de s'assurer que\nl'image choisie contient uniquement les paquets essentiels afin d'éviter des\nretards inutiles dans l'exécution des jobs.\n\n\n### Prochaines étapes\n\n\nPour moderniser davantage vos pratiques de développement logiciel, consultez\nle [catalogue GitLab\nCI/CD](https://docs.gitlab.com/ee/architecture/blueprints/ci_pipeline_components/)\npour savoir comment standardiser et réutiliser les composants CI/CD.\n",[785,759],"2025-01-07",{"slug":985,"featured":6,"template":686},"basics-of-gitlab-ci-updated","content:fr-fr:blog:basics-of-gitlab-ci-updated.yml","Basics Of Gitlab Ci Updated","fr-fr/blog/basics-of-gitlab-ci-updated.yml","fr-fr/blog/basics-of-gitlab-ci-updated",{"_path":991,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":992,"content":998,"config":1004,"_id":1006,"_type":16,"title":1007,"_source":18,"_file":1008,"_stem":1009,"_extension":21},"/fr-fr/blog/keep-git-history-clean-with-interactive-rebase",{"title":993,"description":994,"ogTitle":993,"ogDescription":994,"noIndex":6,"ogImage":995,"ogUrl":996,"ogSiteName":723,"ogType":724,"canonicalUrls":996,"schema":997},"Comment conserver un historique Git propre avec le rebase interactif","Le rebase interactif est l'un des outils les plus polyvalents de Git. Découvrez comment l'utiliser pour corriger vos messages de commit, réparer des erreurs et bien plus encore.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662593/Blog/Hero%20Images/title-image.png","https://about.gitlab.com/blog/keep-git-history-clean-with-interactive-rebase","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Comment conserver un historique Git propre avec le rebase interactif\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tobias Günther\"}],\n        \"datePublished\": \"2020-11-23\",\n      }",{"title":993,"description":994,"authors":999,"heroImage":995,"date":1001,"body":1002,"category":14,"tags":1003},[1000],"Tobias Günther","2020-11-23","## Qu'est-ce qu’un rebase interactif ?\n\n\nLe rebase interactif, également connu sous le nom de *Git rebase\ninteractive* en anglais, est un peu le « couteau suisse » de\n[Git](https://about.gitlab.com/fr-fr/blog/what-is-git/ \"Qu'est-ce\nque Git ? \") car il permet d’avoir accès à différents outils pour de\nnombreux usages possibles. Son cas d'utilisation principal restant cependant\nle nettoyage de l'historique des commits locaux.\n\n\nSoulignons bien ici le mot *local*. Le rebase interactif s'utilise\nuniquement pour __nettoyer votre propre historique de commits en local__,\navant par exemple d'intégrer l’une de vos branches de fonctionnalités au\nsein d’une branche d’équipe. \n\n\nEn revanche, le rebase interactif (ou *Git rebase interactive*) ne doit pas\nêtre utilisé sur un historique de commits Git dont le push a déjà été\neffectué et partagé sur un dépôt distant. Le rebase interactif est l’un de\nces outils qui « réécrivent » l'historique Git ; il ne doit donc pas être\nutilisé sur des commits déjà partagés avec d'autres personnes. Passé ce\npetit avertissement, voyons quelques exemples pratiques !\n\n\n## Corriger un ancien message de commit avec le rebase interactif\n\n\nParfois, vous remarquez une coquille dans un vieux message de commit. Ou\nbien, vous oubliez de mentionner quelque chose d'utile dans une description.\nSi l'on parle du tout dernier commit en date, vous pouvez utiliser l'option\n`--amend` de la commande `git commit`. Mais pour les commits plus anciens,\nle *Git rebase interactive* vous permet de les modifier après coup. \n\n\nVoici un exemple de message de commit nécessitant une correction :\n\n\n![Un mauvais message de commit qui nécessite une\ncorrection](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/bad-commit-message@2x.png){:\n.shadow.medium.center}\n\n{: .note.text-center}\n\n\nLa première étape dans toute session de *Git rebase interactive* consiste à\n__déterminer quelle partie de l'historique des commits__ vous souhaitez\nmanipuler. Pour modifier le commit incorrect dans l'exemple précédent, nous\ndevons démarrer la session à partir de son commit parent.\n\n\n![Démarrage de la session de Git rebase\ninteractive](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/start-at-parent-commit@2x.png){:\n.shadow.medium.center}\n\n{: .note.text-center}\n\n\nNous pouvons maintenant transmettre le hash du commit de départ à la\ncommande *Git rebase interactive* :\n\n\n```\n\n$ git rebase -i 0023cddd\n\n```\n\n\nUne fenêtre d’édition va alors s'ouvrir, contenant la liste des commits que\nvous venez de sélectionner. Ne soyez pas surpris s’ils apparaissent dans\nl'ordre inverse. Dans une session de rebase interactif, Git applique les\ncommits élément après élément, du plus ancien au plus récent, ce qui\nsignifie que l'inversion de l'ordre est correcte du point de vue de Git.\n\n\n![Fenêtre d'édition avec les commits\nsélectionnés](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/editor-window-start-ir@2x.png){:\n.shadow.medium.center}\n\n{: .note.text-center}\n\n\nUne chose importante à noter à propos de cette fenêtre d’édition : ce n'est\npas ici que vous effectuez les manipulations réelles ! Dans cet exemple\nconcret, ce n’est pas à cet endroit que vous modifiez le message du commit.\nVous indiquez seulement le commit que vous allez modifier en appliquant un\nmot-clé d'action. Dans notre cas, comme nous voulons changer le message d'un\ncommit, nous entrons la ligne « reword ». Si vous sauvegardez et fermez la\nfenêtre d’édition, une nouvelle fenêtre s'ouvrira, contenant l'ancien\nmessage de commit. \n\n\nIl est temps d'effectuer vos modifications :\n\n\n![Modifications du message du\ncommit](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/correct-commit-message.gif){:\n.shadow.medium.center}\n\n{: .note.text-center}\n\n\nAprès avoir sauvegardé et fermé la fenêtre une fois de plus, la session de\n*Git rebase interactive* est terminée et notre ancien message de commit a\nété corrigé.\n\n\n## Combiner plusieurs commits en un seul avec le rebase interactif\n\n\nAutre cas d'usage du *Git rebase interactive* : lorsque vous souhaitez\n__combiner plusieurs anciens commentaires en un seul__. Bien entendu, la\nrègle d'or du [contrôle de\nversion](https://about.gitlab.com/fr-fr/topics/version-control/ \"Qu'est-ce\nque le contrôle de version ?\") s'applique : il est généralement conseillé de\ncréer plus de petits commits plutôt que quelques gros. Cependant, nous\npouvons parfois nous laisser emporter, et vouloir ensuite fusionner quelques\ncommits en un seul.\n\n\nPrenons un exemple concret, où nous allons entreprendre de combiner les\ncommits suivants :\n\n\n![Combinaison de plusieurs commits en un\nseul](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/squash-selected-commits@2x.png){:\n.shadow.medium.center}\n\n{: .note.text-center}\n\n\nComme dans notre premier cas, nous commençons par démarrer la session de\n*Git rebase interactive* au niveau du commit parent de celui que nous\nvoulons manipuler.\n\n\n```\n\n$ git rebase -i 2b504bee\n\n```\n\n\nUne fois encore, une fenêtre d'édition s'ouvre, listant la partie de notre\nhistorique de [commits\nGit](https://about.gitlab.com/fr-fr/blog/keeping-git-commit-history-clean/\n\"Commits Git\") que nous souhaitons manipuler.\n\n\n![Marquage des lignes avec « squash »\n](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/squash-mark-commit@2x.png){:\n.shadow.medium.center}\n\n{: .note.text-center}\n\n\n### Marquer les lignes avec le mot-clé « squash »\n\n\nLe mot-clé d’action que nous allons utiliser ici s'appelle « squash ». Pour\nbien utiliser cette fonction, retenez que la ligne marquée avec le mot-clé «\nsquash » sera combinée avec la ligne directement au-dessus. Ainsi, comme le\nmontre la capture d'écran ci-dessus, nous avons marqué la ligne #2 avec «\nsquash » afin de la combiner avec le commit de la ligne #1 juste au-dessus.\n\n\nNous pouvons maintenant sauvegarder et fermer la fenêtre d’édition ; une\nnouvelle fenêtre va alors apparaître. Il nous est maintenant demandé de\nfournir un message de commit pour le nouveau commit créé en combinant ces\ndeux anciens.\n\n\n![Ajout d’un nouveau message pour le nouveau commit\nfusionné](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/squash-enter-new-message@2x.png){:\n.shadow.medium.center}\n\n{: .note.text-center}\n\n\nEnfin, sauvegardez et fermez cette fenêtre d’édition. Un nouveau commit est\ncréé, contenant les modifications des deux anciens commits. \n\n\n## Corriger une erreur avec le rebase interactif\n\n\nUn autre cas d’usage du *Git rebase interactive* consiste à corriger une\nerreur identifiée dans l'un de vos commits précédents. La nature exacte de\nl'erreur n'a pas d'importance. Vous pourriez par exemple avoir oublié\nd'ajouter un changement, de supprimer un fichier, ou simplement de corriger\nune faute de frappe.\n\n\nDans une telle situation, nous avons tendance à vouloir créer un nouveau\ncommit pour corriger cette erreur. Cela risque toutefois d'ajouter du\ndésordre à votre historique de commits. Il n'est pas idéal d'ajouter un\ncommit de fortune au commit initial juste pour corriger quelques erreurs.\nVotre historique de commits deviendra rapidement illisible, car jonché de\nmultiples petits commits de correction. \n\n\nC'est là que vous pouvez profiter de « fixup », l'un des outils fournis avec\nle *Git rebase interactive*. « Fixup » applique ce commit de réparation\nrapide et ses changements au commit initial, le corrigeant ainsi. Ensuite,\nil se débarrasse simplement du commit de fortune. \n\n\n![Fonctionnement de « fixup\n»](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/diagram-fixup.png){:\n.medium.center}\n\n{: .note.text-center}\n\n\n### Comment utiliser « fixup » ?\n\n\nUne fois la fonction « fixup » utilisée, c'est comme si notre commit initial\navait toujours été correct. Voyons cela à l'aide d'un exemple. \n\n\nLa première étape consiste à faire le nécessaire pour corriger le problème.\nIl peut s'agir d'ajouter un nouveau fichier, de modifier des fichiers\nexistants ou de supprimer ceux qui sont obsolètes. Vous avez simplement à\neffectuer les modifications qui corrigent l'erreur.\n\n\nL'étape suivante consiste à valider ces modifications au niveau du dépôt,\nmais avec un petit truc en plus. Au moment du commit, nous allons ajouter\n`--fixup` et indiquer à Git le hash de notre mauvais commit :\n\n\n```\n\n$ git add corrections.txt\n\n$ git commit --fixup 2b504bee\n\n```\n\n\nJetez maintenant un coup d'œil à votre historique de commits. Vous\nconstaterez qu'un commit d'apparence ordinaire a été créé. Mais à y voir de\nplus près, il s'est passé quelque chose. Le nouveau commit affiche la\nmention « fixup ! » et il reprend le sujet de notre mauvais commit.\n\n\n![Le commit initial et le commit de\ncorrection](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/fixup_create-fix-commit@2x.png){:\n.shadow.medium.center}\n\n{: .note.text-center}\n\n\nEnfin, la troisième étape consiste à démarrer la session de *Git rebase\ninteractive*. Nous sélectionnons à nouveau le commit parent de notre mauvais\ncommit comme point de départ :\n\n\n```\n\n$ git rebase -i 0023cddd --autosquash\n\n```\n\n\nEt pour conclure, nous utilisons notre botte secrète : `--autosquash`. Cette\noption nous assure de ne rien avoir à faire au sein de la fenêtre d’édition\ndésormais ouverte. Regardons de plus près la situation :\n\n\n![Notre commit de correction est marqué « fixup » et classé à la bonne\nposition](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/fixup_editor@2x.png){:\n.shadow.medium.center}\n\n{: .note.text-center}\n\n\nGit a automatiquement effectué deux choses :\n\n\n1. Le commit de correction de fortune est marqué comme « fixup ». \n\n2. L'ordre des lignes fait apparaître notre commit de correction directement\nsous le mauvais commit. Tout comme « squash », « fixup » combine le commit\navec celui de la ligne supérieure.\n\n\nEnfin, il ne nous reste plus qu'à sauvegarder et à fermer la fenêtre\nd’édition.\n\n\nJetons un coup d'œil à l'historique des commits :\n\n\n![Problème\nrésolu](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/fixup_final-corrected@2x.png){:\n.shadow.medium.center}\n\n{: .note.text-center}\n\n\nAinsi, le mauvais commit initial contient maintenant les changements du\ncommit de secours. Mais en plus de cela, le commit de secours a maintenant\ndisparu de l’historique de commits. Tout beau, tout propre, comme s'il n'y\navait jamais eu le moindre problème !\n\n\n## Découvrez la puissance du rebase interactif\n\n\nVous allez pouvoir utiliser le Git rebase interactive dans de très nombreux\ncas, la plupart du temps afin de corriger des erreurs. Pour une vue\nd'ensemble de toutes les choses utiles à faire avec le rebase interactif,\nnous vous recommandons ce [guide sur\nGit](https://git-scm.com/book/fr/v2/Utilitaires-Git-R%C3%A9%C3%A9crire-l%E2%80%99historique).\n\n\n## FAQ sur le rebase interactif\n\n\n### Quelle est la différence entre rebase et merge ?\n\n\nVoilà une question souvent posée par les développeurs : rebase ou merge ?\nCes commandes permettent d'effectuer des changements d'une branche à\nl'autre. Avec `git merge`, nous créons un commit de merge dans la branche\nlocale. Avec `git rebase`, chaque commit de la branche locale est recréé en\npointe de la branche principale. `Git rebase -i` interactif est similaire à\ngit rebase, mais permet en plus de modifier les commits au moment de les\nenvoyer vers la branche principale.\n\n\n### Quelle est la différence entre le Git rebase interactive et le Git\nrebase ?\n\n\nLorsque l'on ajoute l'option interactive au Git rebase, cela permet d'ouvrir\nune fenêtre d’édition afin d'éditer en amont chaque commit de votre branche\nlocale avant de les rebaser, notamment pour nettoyer votre historique. Les\ncommandes principales sont `reword` (éditer un message de commit), `squash`\n(fusionner deux commits), et `fixup` (amender un commit).\n\n\n### Quelles sont les erreurs à éviter avec le rebase interactif ?\n\n\nLe rebase interactif est généralement conseillé aux utilisateurs plutôt\navancés. Lorsque vous utilisez ces commandes, veillez à éviter les pièges\nsuivants :\n\n\n- __Ordre des commits.__ Conservez la logique du workflow lorsque vous\nréordonnez des commits.\n\n- __Sauvegarde.__ N'oubliez pas de sauvegarder et fermer votre fenêtre\nd'édition en fin de session de rebase interactif.\n\n- __Rebasing sur la branche principale.__ Le rebase s'applique toujours à\ndes commits de votre branche locale vers la branche publique. \n\n\nImage de couverture par David Taljat sur\n[Pexels](https://www.pexels.com/@david-taljat-3748658/).\n",[735,759],{"slug":1005,"featured":6,"template":686},"keep-git-history-clean-with-interactive-rebase","content:fr-fr:blog:keep-git-history-clean-with-interactive-rebase.yml","Keep Git History Clean With Interactive Rebase","fr-fr/blog/keep-git-history-clean-with-interactive-rebase.yml","fr-fr/blog/keep-git-history-clean-with-interactive-rebase",{"_path":1011,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":1012,"content":1018,"config":1029,"_id":1031,"_type":16,"title":1032,"_source":18,"_file":1033,"_stem":1034,"_extension":21},"/fr-fr/blog/using-ansible-and-gitlab-as-infrastructure-for-code",{"ogTitle":1013,"schema":1014,"ogImage":1015,"ogDescription":1016,"ogSiteName":723,"noIndex":6,"ogType":724,"ogUrl":1017,"title":1013,"canonicalUrls":1017,"description":1016},"Créez des pipelines IaC évolutifs avec GitLab","\n                        { \"@context\": \"https://schema.org\", \"@type\": \"Article\", \"headline\": \"How to use GitLab and Ansible to create infrastructure as code\", \"author\": [{\"@type\":\"Person\",\"name\":\"Brad Downey\"},{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}], \"datePublished\": \"2019-07-01\", }","https://res.cloudinary.com/about-gitlab-com/image/upload/f_auto,q_auto,w_820,h_500,c_lfill/v1746211002/zlet4rmfg2z0j6lg16mc.png","Automatisez la gestion de votre infrastructure avec des pipelines CI/CD sécurisés, un scan de sécurité intégré, à l’aide de GitLab, Terraform/OpenTofu, Ansible.","https://about.gitlab.com/blog/using-ansible-and-gitlab-as-infrastructure-for-code",{"heroImage":1015,"body":1019,"authors":1020,"updatedDate":1023,"date":1024,"title":1025,"tags":1026,"description":1028,"category":14},"Les outils d'Infrastructure as Code (IaC), tels que TerraForm/OpenTofu, ou\nde gestion des configurations, tels qu'Ansible, jouent un rôle clé dans de\nnombreux workflows critiques. Ces projets commencent parfois par de simples\nscripts d'automatisations, sans nécessairement suivre les bonnes pratiques\nde développement logiciel ni répondre aux contrôles réglementaires exigés\npour les applications logicielles d'entreprise.\n\n\nSouvent développées par des ingénieurs système ou des ingénieurs d'infrastructure, ces automatisations sont mises en place sans réelle expertise des approches [DevOps](https://about.gitlab.com/fr-fr/topics/devops/ \"Qu'est-ce que le DevOps ?\"), DevSecOps, [CI/CD](https://about.gitlab.com/topics/ci-cd/ \"Qu'est-ce que le CI/CD ?\") et d'automatisation des tests. Dans les grandes entreprises employant de nombreuses équipes d'ingénierie parfois cloisonnées, la situation est encore plus compliquée.\n\n\nChez GitLab, nous maîtrisons l'[approche DevSecOps](https://about.gitlab.com/fr-fr/topics/devsecops/ \"Qu'est-ce que le DevSecOps ?\") depuis plus de 10 ans et utilisons notre plateforme DevSecOps unifiée en interne pour automatiser des tâches critiques à l'échelle de l'entreprise. Nous accompagnons des milliers de clients qui s'appuient sur notre plateforme GitLab pour une variété de processus : Infrastructure as Code (IaC), automatisation, gestion cloud, [ingénierie de plateforme](https://about.gitlab.com/fr-fr/the-source/platform/driving-business-results-with-platform-engineering/ \"Qu'est-ce que l’ingénierie de plateforme ?\") et bien d'autres encore.\n\n\nDécouvrez dans cet article les principales fonctionnalités pour transformer vos puissantes automatisations en pipelines de livraison de logiciels évolutifs et auditables.\n\n\n![Liste d'automatisation](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750433380/oipm6tq8qutoh1ctredd.png)\n\n\n## Mise en œuvre\n\n\n[Ce projet de démonstration](https://gitlab.com/gl-demo-ultimate-saberkan/public/ansible-demo) illustre un workflow DevOps complet qui combine la puissance d'OpenTofu avec les pratiques modernes d'Ansible, le tout orchestré via les [pipelines CI/CD](https://about.gitlab.com/fr-fr/topics/ci-cd/cicd-pipeline/ \"Qu'est-ce qu'un pipeline CI/CD ?\") de GitLab. Il met en scène le provisionnement d'un environnement de test AWS à l'aide de composants OpenTofu intégrés à GitLab, suivi du déploiement d'un serveur web Tomcat à l'aide de la version la plus récente d'Ansible, avec exécution dans un environnement personnalisé et prise en charge des collections.\n\n\nLe projet tire parti de nombreuses fonctionnalités de GitLab :\n\n\n* Création et stockage d'environnements d'exécution Ansible personnalisés dans le [registre de conteneurs de GitLab](https://docs.gitlab.com/user/packages/container_registry/)\n\n* [Scan de sécurité des scripts d'IaC et des conteneurs permettant de détecter des vulnérabilités](https://docs.gitlab.com/user/application_security/iac_scanning/)\n\n* Intégration du [linting Ansible avec GitLab Code Quality](https://docs.gitlab.com/user/application_security/iac_scanning/)\n\n* Stockage des binaires Tomcat dans le [dépôt de paquets génériques](https://docs.gitlab.com/user/packages/generic_packages/)\n\n* Utilisation des [variables d'environnement CI/CD à des fins de configuration](https://docs.gitlab.com/ci/variables/)\n\n\nL'ensemble du workflow est automatisé par le biais d'un [pipeline GitLab](https://docs.gitlab.com/ci/pipelines/) qui gère toutes les étapes, du provisionnement de l'infrastructure au déploiement des applications, en passant par les tests de sécurité.\n\n\n![ Workflow automatisé via un pipeline GitLab ](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750433380/giatmolwn9inusi4cev2.png)\n\n\n### Provisionnement de l'environnement avec OpenTofu\n\n\nLe projet commence par le provisionnement d'un environnement de test AWS à l'aide d'OpenTofu, en s'appuyant sur l'intégration native des [composants OpenTofu de GitLab](https://docs.gitlab.com/user/infrastructure/iac/), qui rationalisent le processus de provisionnement de l'infrastructure. Le pipeline inclut des étapes de validation, de planification et d'application qui garantissent un déploiement approprié de l'infrastructure tout en maintenant les bonnes pratiques IaC de GitLab.\n\n\nCe projet tire parti des capacités de l'[outil de gestion des fichiers d'état de Terraform intégré à GitLab](https://docs.gitlab.com/user/infrastructure/iac/terraform_state/) ainsi que du [Terraform Module Registry](https://docs.gitlab.com/user/packages/terraform_module_registry/), tous deux compatibles avec OpenTofu et HashiCorp Terraform. Il est également possible d'utiliser les composants OpenTofu de GitLab avec HashiCorp Terraform en procédant à une [légère personnalisation](https://gitlab.com/components/opentofu#can-i-use-this-component-with-terraform) : vous devez créer votre propre image incluant un script nommé `gitlab-tofu` pour maintenir sa compatibilité avec les jobs de composants. Vous pouvez ensuite remplacer les commandes `tofu` par les commandes `Terraform` équivalentes.\n\n\nL'exemple de composant « OpenTofu Module Release » montre comment créer un module Terraform et le stocker dans Terraform Module Registry dans GitLab. Ce module est ensuite importé dans le fichier `provision_lab.tf` directement depuis GitLab pour déployer l'environnement de test sur AWS. Ensuite, il génère un fichier d'inventaire contenant l'adresse IP publique de l'instance provisionnée, qui peut être utilisée dans les étapes de gestion des configurations avec Ansible.\n\n\n```\n\n# From .gitlab-ci.yml\n - component: gitlab.com/components/opentofu/module-release@1.1.0\n   inputs:\n     root_dir: tofu\n     as: 🔍 tofu-module-release\n     stage: 🏗️ build-tofu-module\n     module_version: 0.0.1\n     module_system: aws\n     module_name: aws-lab\n     root_dir: tofu/modules/ansible-demo/aws-lab\n     rules:\n       - if: \"$CI_COMMIT_BRANCH\"\n         when: manual\n```\n\n\n```\n\n# From provision_lab.tf\n\nmodule \"aws-lab\" {\n  source = \"https://gitlab.com/api/v4/projects/67604719/packages/terraform/modules/aws-lab/aws/0.0.1\"\n}\n\n```\n\n\nLes composants de validation, de planification et de déploiement sont configurés avec le paramètre `**auto_define_backend: true**`. Ils s'intègrent automatiquement au backend de stockage d’état Terraform intégré à GitLab et éliminent le besoin de configuration manuelle du backend ou de solutions de stockage d'état externes telles que des compartiments S3.\n\n\n```\n\n# From gitlab-ci.yml\n\n- component: gitlab.com/components/opentofu/apply@0.55.0\n  inputs:\n    version: 0.55.0\n    opentofu_version: 1.8.8\n    root_dir: tofu\n    state_name: demo\n    as: ✅ tofu-apply\n    stage: 🏗️ provision-lab\n    auto_define_backend: true\n    rules:\n      - if: \"$CI_COMMIT_BRANCH\"\n        when: manual\n```\n\n\n![Les composants de validation, de planification et de déploiement sont configurés avec le paramètre `auto_define_backend: true`](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750433380/giatmolwn9inusi4cev2.png)\n\n\nLa configuration de l'infrastructure crée une instance EC2 CentOS Stream 9 avec des groupes de sécurité appropriés pour autoriser l'accès SSH depuis les runners GitLab et l'accès HTTP au serveur Tomcat.\n\n\nL'accès SSH et la configuration HTTP sont configurés par le biais des [variables d'environnement GitLab CI/CD](https://docs.gitlab.com/ci/variables/#define-a-cicd-variable-in-the-ui).\n\n\n![Accès SSH et configuration HTTP](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750433381/cmqtzg6ahz8ua5w8ybgs.png)\n\n\nPour un accès sécurisé au cloud, le projet met en œuvre [l'intégration OpenID Connect de GitLab](https://docs.gitlab.com/ci/cloud_services/aws/) avec AWS, en utilisant des identifiants de connexion temporaires via AWS Security Token Service (STS) :\n\n\n```\n\n# From .gitlab-ci.yml\n\n.tofu_aws_setup:\n id_tokens:\n   OIDC_TOKEN:\n     aud: https://gitlab.com\n before_script:\n   - echo \"${OIDC_TOKEN}\" > /tmp/web_identity_token\n   - export AWS_PROFILE=\"\"\n   - export AWS_ROLE_ARN=\"${AWS_ROLE_ARN}\"\n   - export AWS_WEB_IDENTITY_TOKEN_FILE=\"/tmp/web_identity_token\"\n```\n\n\n### Création de l'environnement d'exécution Ansible\n\n\nLes déploiements modernes avec Ansible reposent largement sur l'utilisation d'[environnements d'exécution](https://docs.ansible.com/ansible/latest/getting_started_ee/index.html) : il s'agit de versions conteneurisées qui encapsulent Ansible avec toutes ses dépendances, y compris les rôles et les collections préinstallés nécessaires. Dans ce projet, un environnement d'exécution personnalisé est créé, basé sur Fedora 39, qui inclut ansible-core, ansible-runner ainsi que des collections spécifiques, telle que ansible.posix, requise dans cet exemple pour configurer le pare-feu et SELinux.\n\n\nLes rôles et collections tiers de ce projet sont téléchargés en mode natif à partir du dépôt communautaire Ansible Galaxy. Cette approche s'appuie sur l'écosystème de contenu Ansible réutilisable de la communauté, comme le montre la configuration de l'environnement d'exécution. Bien que cette démonstration utilise des ressources Ansible de la communauté, cette mise en œuvre de pipeline est entièrement compatible avec Red Hat Ansible Automation Platform. La structure du pipeline reste identique ; seules les sources de contenu changent. Ainsi, les entreprises qui utilisent la version Enterprise peuvent simplement rediriger leurs sources de contenu d'automatisation vers leur Automation Hub privé au lieu du dépôt Ansible Galaxy par défaut issu de la communauté. Selon la documentation officielle d'Ansible, vous pouvez réaliser cette opération en [configurant votre serveur Automation Hub privé et votre token d'accès dans le fichier ansible.cfg](https://docs.redhat.com/en/documentation/red_hat_ansible_automation_platform/1.2/html/getting_started_with_red_hat_ansible_automation_hub/proc-configure-automation-hub-server#proc-configure-automation-hub-server).\n\n\n```\n\n# From execution-environment.yml\n\n---\n\nversion: 3\n\n\nimages:\n  base_image:\n    name: quay.io/fedora/fedora:39\n\ndependencies:\n  ansible_core:\n    package_pip: ansible-core\n  ansible_runner:\n    package_pip: ansible-runner\n  system:\n    - openssh-clients\n    - sshpass\n  galaxy:\n    collections:\n    - name: ansible.posix\n      version: \">=2.0.0\"\n```\n\n\n![Environnement d'exécution faisant l'objet d'un push vers le registre de conteneurs de GitLab ](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750433384/dh1o2ojjmb04ru4tfr9k.png)\n\n\nL'environnement d'exécution est défini dans un fichier YAML, généré à l'aide d'ansible-builder, puis faisant l'objet d'un push vers le [registre de conteneurs de GitLab](https://docs.gitlab.com/user/packages/container_registry/). Cette approche garantit des environnements d'exécution cohérents d'un système à l'autre, tout en simplifiant la gestion des dépendances.\n\n\n```\n\n# From gitlab-ci.yml\n\n🔨 ansible-build-ee:\n  stage: 📦 ansible-build-ee\n  image: docker:24.0.5\n  needs: []\n  services:\n    - docker:24.0.5-dind\n  before_script:\n    - apk add --no-cache python3 py3-pip\n    - pip install ansible-builder\n    - cd ansible/execution-environment\n  script:\n    - ansible-builder build -t ${EE_IMAGE_NAME}:${EE_IMAGE_TAG} --container-runtime docker\n    - docker tag ${EE_IMAGE_NAME}:${EE_IMAGE_TAG} ${CI_REGISTRY_IMAGE}/${EE_IMAGE_NAME}:${EE_IMAGE_TAG}\n    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY\n    - docker push ${CI_REGISTRY_IMAGE}/${EE_IMAGE_NAME}:${EE_IMAGE_TAG}\n```\n\n\n### Déploiement de Tomcat avec Ansible\n\n\nUne fois l'infrastructure provisionnée et l'environnement d'exécution construit, le pipeline déploie Tomcat à l'aide d'[Ansible Navigator](https://ansible.readthedocs.io/projects/navigator/). L'environnement d'exécution créé à l'étape précédente est utilisé comme image pour le job de déploiement dans le pipeline GitLab.\n\n\n```\n\n# From gitlab-ci.yml\n\n🚀 ansible-deploy:\n  stage: 🚀 ansible-deploy\n  image: ${CI_REGISTRY_IMAGE}/${EE_IMAGE_NAME}:${EE_IMAGE_TAG}\n  needs:\n    - ✅ tofu-apply\n  extends: [.ssh_private_key_setup, .default_rules]\n  script:\n    - ansible-navigator run ansible/playbook.yml \n      -i ansible/inventory/hosts.ini\n      --execution-environment false\n      --mode stdout \n      --log-level debug\n```\n\n\nCe processus récupère le paquet applicatif depuis le [dépôt de paquets générique de GitLab](https://docs.gitlab.com/user/packages/generic_packages/), configure les utilisateurs et les autorisations système, et définit Tomcat comme service systemd.\n\n\n```\n\n# From playbook.yml\n\n---\n\n- name: Deploy Tomcat Server\n  hosts: all\n  become: true\n  roles:\n      - role: tomcat\n  \n  vars:\n    # Tomcat package and installation\n    tomcat_package: \"https://gitlab.com/api/v4/projects/67604719/packages/generic/apache-tomcat/10.1.39/apache-tomcat-10.1.39.tar.gz\"\n    tomcat_install_dir: \"/opt/tomcat\"\n    java_package: \"java-17-openjdk-devel\"\n```\n\n\n![Registre de paquets de GitLab](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750433381/mynak8i2k7ms9vhdijqg.png)\n\n\n### Scan de sécurité et qualité du code\n\n\nLa sécurité est intégrée tout au long du pipeline avec plusieurs outils de scan. Ce projet utilise le [scanner SAST IaC intégré de GitLab](https://docs.gitlab.com/user/application_security/iac_scanning/) pour détecter les vulnérabilités dans le code Terraform et Ansible. L'[analyse des conteneurs](https://docs.gitlab.com/user/application_security/container_scanning/) est appliquée à l'image de l'environnement d'exécution pour identifier tout problème de sécurité et générer une [nomenclature logicielle (SBOM)](https://about.gitlab.com/fr-fr/blog/the-ultimate-guide-to-sboms/ \"Qu'est-ce qu'une nomenclature logicielle ?\").\n\n\n```\n\n# From gitlab-ci.yml\n\ninclude: \n\n- template: Jobs/SAST-IaC.gitlab-ci.yml \n\n- template: Jobs/Container-Scanning.gitlab-ci.yml\n\n```\n\n\n![La sécurité est intégrée à chaque étape du pipeline avec plusieurs outils de scanning](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750433386/e6ejckcv5kdyhhosej2f.png)\n\n\nDe plus, le projet utilise Ansible Linter et ses résultats sont intégrés à [GitLab Code Quality](https://docs.gitlab.com/ci/testing/code_quality/#import-code-quality-results-from-a-cicd-job). Cette intégration produit des rapports qui sont affichés directement dans l'interface de GitLab, ce qui facilite l'identification et la résolution des anomalies.\n\n\n```\n\n# From gitlab-ci.yml\n\n🔍 ansible-lint:\n  stage: 🚀 ansible-deploy\n  image: ${CI_REGISTRY_IMAGE}/${EE_IMAGE_NAME}:${EE_IMAGE_TAG}\n  needs: []\n  script:\n    - ansible-lint ansible/playbook.yml -f codeclimate | python3 -m json.tool | tee gl-code-quality-report.json || true\n  artifacts:\n    reports:\n      codequality:\n        - gl-code-quality-report.json\n```\n\n\n![Le projet utilise Ansible Linter et ses résultats sont intégrés à GitLab Code Quality](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750433380/gsfpaldra4rmtkseaudo.png)\n\n\n### Vérification de l'état du déploiement\n\n\nAprès le déploiement, le pipeline effectue des vérifications de l'état pour s'assurer que le serveur Tomcat fonctionne correctement. Ce job tente d'établir une connexion au port HTTP du serveur et vérifie qu'il renvoie une réponse confirmant que le service est bien actif. Cette étape garantit que le déploiement s'est correctement terminé et que l'application est accessible.\n\n\nVous pouvez également tester l'accès de votre navigateur à l'instance provisionnée par Tomcat en utilisant l'adresse IP publique de l'instance provisionnée EC2.\n\n\n![Vérification de l'état d'un job](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750433385/uksdkjryydxhu94v1naj.png)\n\n\n## Destruction de l'environnement de test\n\n\nDernière étape du pipeline : le processus de nettoyage détruit l'environnement de test. Cette opération est mise en œuvre à l'aide du composant de destruction OpenTofu, qui garantit que toutes les ressources créées au cours de l'étape de provisionnement sont correctement supprimées.\n\n\n## Récapitulatif\n\n\nGitLab offre une plateforme DevSecOps unifiée et un framework pour gérer, à l'échelle de l'entreprise, les pratiques d'automatisation critiques telles que la gestion des configurations et de l'IaC (Infrastructure as Code). Ce framework inclut le [contrôle de version](https://about.gitlab.com/fr-fr/topics/version-control/ \"Qu'est-ce que le contrôle de version ?\"), la planification de projet, la gestion des tickets, la collaboration entre les équipes, les pipelines CI/CD, la gestion du paquet de binaires et du registre de conteneurs, le scan de sécurité et de nombreuses autres fonctionnalités utiles. Il permet également de renforcer la gouvernance grâce à des contrôles intégrés dans les processus. Si vous cherchez à développer vos pratiques cloud (qu’il s’agisse d’un cloud privé ou public) ou plus généralement, de tout workflow d'automatisation en libre-service doté de règles de gouvernance, envisagez d'utiliser GitLab, TerraForm et Ansible comme les trois piliers d'une plateforme d'automatisation à la fois évolutive et conforme aux exigences de gouvernance.\n\n\n> Lancez-vous avec un [essai gratuit de GitLab Ultimate](http://bout.gitlab.com/free-trial/). Inscrivez-vous dès aujourd'hui !\n",[1021,1022],"George Kichukov","Salahddine Aberkan","2025-07-17","2019-07-01","GitLab DevSecOps : des pipelines IaC au service de votre croissance",[1027,111],"demo","Découvrez comment automatiser la gestion de votre infrastructure pour accompagner la croissance de votre entreprise grâce à des pipelines CI/CD sécurisés et un scan de sécurité intégré, à l'aide de GitLab, Terraform/OpenTofu et Ansible.",{"slug":1030,"featured":6,"template":686},"using-ansible-and-gitlab-as-infrastructure-for-code","content:fr-fr:blog:using-ansible-and-gitlab-as-infrastructure-for-code.yml","Using Ansible And Gitlab As Infrastructure For Code","fr-fr/blog/using-ansible-and-gitlab-as-infrastructure-for-code.yml","fr-fr/blog/using-ansible-and-gitlab-as-infrastructure-for-code",{"_path":1036,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":1037,"content":1043,"config":1050,"_id":1052,"_type":16,"title":1053,"_source":18,"_file":1054,"_stem":1055,"_extension":21},"/fr-fr/blog/keeping-git-commit-history-clean",{"title":1038,"description":1039,"ogTitle":1038,"ogDescription":1039,"noIndex":6,"ogImage":1040,"ogUrl":1041,"ogSiteName":723,"ogType":724,"canonicalUrls":1041,"schema":1042},"Commits Git : comment et pourquoi maintenir un historique propre","L’historique des commits Git peut rapidement devenir désorganisé. Dans cet article, vous découvrirez tous nos conseils pour y remédier.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659457/Blog/Hero%20Images/keep-git-commit-history-clean.jpg","https://about.gitlab.com/blog/keeping-git-commit-history-clean","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Commits Git : comment et pourquoi maintenir un historique propre\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kushal Pandya\"}],\n        \"datePublished\": \"2018-06-07\",\n      }",{"title":1038,"description":1039,"authors":1044,"heroImage":1040,"date":1046,"body":1047,"category":14,"tags":1048,"updatedDate":1049},[1045],"Kushal Pandya","2018-06-07","Les commits Git sont des éléments fondamentaux d’un [dépôt\nGit](https://git-scm.com/book/fr/v2/Les-bases-de-Git-D%C3%A9marrer-un-d%C3%A9p%C3%B4t-Git\n\"Dépôt Git\") (Git Repository), sans oublier les messages de commit qui\nconstituent un véritable journal de bord pour le dépôt. Au fur et à mesure\nque le projet ou le dépôt évolue dans le temps (avec l’ajout de nouvelles\nfonctionnalités, la correction de bugs, la refonte de l’architecture), les\nmessages de commit permettent de suivre et de comprendre les modifications\napportées. Ces messages doivent donc résumer de manière courte et précise\nles changements effectués.\n\n\n## Qu’est-ce qu’un commit Git ?\n\n\nLes messages de commit Git sont les empreintes laissées sur le code que vous\nmodifiez. Lorsque vous consultez votre code un an plus tard, avoir rédigé un\nmessage clair vous aide à comprendre plus facilement et rapidement les\nraisons derrière vos choix de développement. De plus, ces messages\nfacilitent la collaboration avec vos collègues. Avec des commits Git isolés\nen fonction du contexte, il est plus rapide pour les développeurs et\ndéveloppeuses de détecter un bug introduit par un seul commit et d’y revenir\ndessus. \n\n\nDans le cadre de projets d’envergure, où de nombreuses parties sont\najoutées, modifiées ou supprimées constamment, s’assurer que les messages de\ncommit soient correctement maintenus peut parfois être une tâche compliquée,\nparticulièrement sur les projets qui s’étendent sur plusieurs semaines ou\nplusieurs mois. \n\n\nPour vous aider à maintenir un historique de commits Git précis, découvrez\ndans cet article un certain nombre de situations auxquelles les développeurs\net développeuses peuvent être confrontés au quotidien : \n\n\n- Situation 1 : Je dois modifier le commit le plus récent\n\n- Situation 2 : Je dois modifier un commit Git spécifique\n\n- Situation 3 : Je dois ajouter, combiner ou supprimer un commit Git \n\n- Situation 4 : Mon historique de commits Git est incohérent, je veux\nrepartir à zéro\n\n\n__Remarque :__ cet article suppose que vous ayez déjà des connaissances sur\nles fondamentaux de Git comme le fonctionnement des branches, l’ajout de\nmodifications non validées d’une branche à l'étape du staging et la\nvalidation des modifications. Vous souhaitez en savoir plus sur ces éléments\n? Consultez notre\n[documentation](https://docs.gitlab.com/ee/topics/git/index.html\n\"Documentation GitLab sur Git\") avant de continuer la lecture de cet\narticle. \n\n\nAvant d’entrer dans le vif du sujet, regardons brièvement à quoi ressemble\nun workflow de développement dans le cadre d’un projet Ruby on Rails\nhypothétique. \n\n\n## Exemple de commit Git\n\n\nDans cet exemple, nous avons besoin d’ajouter une vue de navigation sur la\npage d’accueil, ce qui implique la mise à jour et l’ajout de nombreux\nfichiers. \n\n\nVoici le déroulement de l’ensemble du processus étape par étape : \n\n\n- Vous commencez à travailler sur une fonctionnalité avec la mise à jour\nd’un fichier que nous appelons `application_controller.rb`\n\n\n- Cette fonctionnalité requiert la mise à jour d’une vue : `index.html.haml`\n\n\n- Vous avez ajouté un partiel utilisé dans la page d’index :\n`_navigation.html.haml`\n\n\n- Les styles de la page doivent également être mis à jour pour refléter le\npartiel ajouté : `styles.css.scss`\n\n\n- La fonctionnalité est maintenant prête avec les modifications souhaitées,\nil est temps de mettre à jour les tests. Les fichiers à mettre à jour sont\n: \n  - `application_controller_spec.rb`\n  - `navigation_spec.rb`\n\n- Les tests sont mis à jour et fonctionnent comme prévu. Désormais, il est\ntemps de valider les changements.\n\n\nPuisque tous les fichiers appartiennent à différentes parties de\nl’architecture, nous validons les modifications de manière isolée les unes\ndes autres afin d’assurer que chaque commit représente un certain contexte\net soit dans le bon ordre. Les changements des commits Git s’ordonnent\ngénéralement comme suit : en commençant par le backend, suivi de la couche\nintermédiaire puis du frontend.\n\n\n1. `application_controller.rb` & `application_controller_spec.rb` ; __Add\nroutes for navigation__.\n\n2. `_navigation.html.haml` & `navigation_spec.rb` ; __Page Navigation\nView__.\n\n3. `index.html.haml` ; __Render navigation partial__.\n\n4. `styles.css.scss` ; __Add styles for navigation__.\n\n\nMaintenant que nos changements sont validés, il est possible de créer une\nmerge request (requête de fusion) avec la branche. Une fois la merge request\nouverte, celle-ci est généralement examinée par un pair avant que les\nchangements ne soient fusionnés dans la branche principale du dépôt Git.\nMaintenant, observons les différentes situations dans lesquelles vous pouvez\nvous trouver lors de la révision du code. \n\n\n## Situation 1 : comment modifier le commit Git le plus récent ?\n\n\nImaginez que le relecteur examine le fichier `styles.css.scss` et suggère\nune modification. Dans ce cas, il est très simple d’effectuer cette\nmodification car les changements de la feuille de style font partie du\ndernier commit sur votre branche. \n\n\nVoici comment s’y prendre : \n\n\n- Vous effectuez directement les changements nécessaires dans\n`styles.css.scss` dans votre branche actuelle. \n\n\n- Une fois les changements effectués, ajoutez ces modifications au staging;\nexécutez `git add styles.css.scss`. \n\n\n- Dès que les changements sont pris en compte, ajoutez-les à votre dernier\ncommit; exécutez la commande `git commit --amend`.\n  - Explication de la commande : Ici, nous demandons à la commande `git commit` d’inclure tout ce qui est présent dans le staging au commit le plus récent.\n\n- Cela ouvrira votre dernier commit dans l’éditeur de texte défini par Git\ncontenant le message de commit « __Add styles for navigation__ ». \n\n\n- Comme nous avons seulement mis à jour la déclaration CSS, nous n’avons pas\nbesoin de modifier le message de commit. À ce stade, vous pouvez simplement\nenregistrer et quitter l’éditeur de texte que Git a ouvert et vos\nchangements apparaîtront dans le commit. \n\n\nPuisque vous avez modifié un commit Git existant, vous devez pousser ces\nchangements vers le dépôt distant (« remote repository ») grâce à la\ncommande : `git push --force-with-lease \u003Cremote_name> \u003Cbranch_name>`.\nCelle-ci va remplacer le commit `Add styles for navigation` sur le dépôt\ndistant, par le commit mis à jour à l’instant dans notre dépôt local.\n\n\nGardez en tête que lorsque vous travaillez à plusieurs sur la même branche,\nle fait de pousser un commit de force peut causer des problèmes pour les\nautres utilisateurs. En effet, ces derniers peuvent rencontrer des\ndifficultés au moment de pousser normalement leurs changements sur une\nbranche distante contenant de nouveaux commits poussés de force. Par\nconséquent, utilisez cette fonctionnalité avec prudence. Apprenez-en\ndavantage sur les [Git Push](https://git-scm.com/docs/git-push/fr \"Git\nPush\") dans la documentation de Git. \n\n\n## Situation 2 : comment modifier les changements d’un commit Git spécifique\n?\n\n\nDans l’exemple précédent, le changement du commit Git était plutôt simple\ncar vous deviez seulement modifier le dernier commit Git. Maintenant,\nimaginons que le relecteur avait suggéré de modifier un élément dans\n`_navigation.html.haml`. Dans cette situation, la modification doit se faire\nau niveau du deuxième commit en partant du haut. Il est donc nécessaire\nd’employer une autre méthode pour le changer. \n\n\nChaque fois qu’un commit est effectué dans une branche, il est identifié par\nune chaîne de caractères représentant un hachage SHA-1. Cet identifiant\nunique permet de distinguer un commit d’un autre. Vous pouvez voir tous les\ncommits précédents, ainsi que leurs hachages SHA-1 dans une branche en\nexécutant la commande `git log`. \n\n\nVous obtiendrez alors un résultat qui ressemble à peu près à une liste où\nles commits les plus récents sont en haut :\n\n\n```\n\ncommit aa0a35a867ed2094da60042062e8f3d6000e3952 (HEAD ->\nadd-page-navigation)\n\nAuthor: Kushal Pandya \u003Ckushal@gitlab.com>\n\nDate: Wed May 2 15:24:02 2024 +0530\n\n    Add styles for navigation\n\ncommit c22a3fa0c5cdc175f2b8232b9704079d27c619d0\n\nAuthor: Kushal Pandya \u003Ckushal@gitlab.com>\n\nDate: Wed May 2 08:42:52 2024 +0000\n\n    Render navigation partial\n\ncommit 4155df1cdc7be01c98b0773497ff65c22ba1549f\n\nAuthor: Kushal Pandya \u003Ckushal@gitlab.com>\n\nDate: Wed May 2 08:42:51 2024 +0000\n\n    Page Navigation View\n\ncommit 8d74af102941aa0b51e1a35b8ad731284e4b5a20\n\nAuthor: Kushal Pandya \u003Ckushal@gitlab.com>\n\nDate: Wed May 2 08:12:20 2024 +0000\n\n    Add routes for navigation\n```\n\n\nC’est ici que la commande `git rebase` entre en jeu. Chaque fois que vous\nsouhaitez modifier un commit spécifique avec la commande `git rebase`, vous\ndevez d’abord rebaser votre branche en déplaçant le HEAD juste avant le\ncommit que vous souhaitez modifier. Dans le cas présent, nous devons changer\nle commit `Page Navigation View`.\n\n\n![Commit\nLog](https://about.gitlab.com/images/blogimages/keeping-git-commit-history-clean/GitRebase.png){:\n.shadow.center.medium}\n\n\nNotez ici le hachage du commit qui se trouve juste avant celui que nous\nsouhaitons modifier. \n\n\nCopiez le hachage et effectuez les étapes suivantes : \n\n\n- Rebasez la branche pour vous positionner sur le commit précédant votre\ncommit cible. Exécutez `git rebase -i\n8d74af102941aa0b51e1a35b8ad731284e4b5a20`.\n  - Explication de la commande Git : ici, vous exécutez la commande `rebase` de Git en mode interactif avec le hachage SHA-1 comme commit sur lequel se rebaser.\n- Votre éditeur de texte s’ouvre et affiche tous vos commits effectués après\nle commit sur lequel vous vous rebasez. \n\n\nCe qui va correspondre à : \n\n\n```\n\npick 4155df1cdc7 Page Navigation View\n\npick c22a3fa0c5c Render navigation partial\n\npick aa0a35a867e Add styles for navigation\n\n\n# Rebase 8d74af10294..aa0a35a867e onto 8d74af10294 (3 commands)\n\n#\n\n# Commands:\n\n# p, pick = use commit\n\n# r, reword = use commit, but edit the commit message\n\n# e, edit = use commit, but stop for amending\n\n# s, squash = use commit, but meld into previous commit\n\n# f, fixup = like \"squash\", but discard this commit's log message\n\n# x, exec = run command (the rest of the line) using shell\n\n# d, drop = remove Git commit\n\n#\n\n# These lines can be re-ordered; they are executed from top to bottom.\n\n#\n\n# If you remove a line here THAT COMMIT WILL BE LOST.\n\n#\n\n# However, if you remove everything, the rebase will be aborted.\n\n#\n\n# Note that empty commits are commented out\n\n```\n\nChaque commit est précédé du mot `pick`. Ci-dessous, vous retrouverez tous\nles mots-clés disponibles. Pour éditer un commit, vous devez changer `pick\n4155df1cdc7 Page Navigation View` en `edit 4155df1cdc7 Page Navigation\nView`. Sauvegardez les changements et quittez l’éditeur. \n\n\nVotre branche est désormais rebasée à l’endroit précédent le commit qui\nincluait `_navigation.html.haml`. Ouvrez le fichier et effectuez les\nmodifications souhaitées selon les retours de vos pairs. Une fois les\nchangements terminés, intégrez-les en exécutant `git add\n_navigation.html.haml`.\n\n\nMaintenant que les changements sont intégrés, il est temps de ramener la\nbranche HEAD au commit initial (en incluant les modifications apportées).\nExécutez `git rebase -–continue`. \n\n\nVotre éditeur par défaut s’ouvrira dans le terminal et affichera le message\nde commit modifié lors du rebasage : `Page Navigation View`. Vous pouvez\nmodifier ce message si vous le souhaitez. Néanmoins, il est préférable de le\nlaisser tel quel. Enregistrez et quittez l’éditeur. \n\n\nÀ ce stade, Git réexécutera tous les commits qui ont suivi après le commit\nque vous venez de modifier et maintenant la branche HEAD est de retour au\ncommit supérieur que vous aviez initialement. Il inclut également les\nnouveaux changements que vous avez apportés à l’un des commits. \n\n\nPuisque vous avez modifié un commit déjà présent dans le dépôt distant, vous\ndevez à nouveau pousser de force cette branche en exécutant : `git push\n--force-with-lease \u003Cremote_name> \u003Cbranch_name>`.\n\n\n## Situation 3 : comment ajouter, combiner ou supprimer des commits Git ?\n\n\nIl arrive régulièrement que l'on ajoute plusieurs commits pour corriger des\néléments déjà validés. Il est possible de les réduire tout en les combinant\navec les commits initiaux. \n\n\nPour cela, commencez le rebase interactif comme vous le feriez dans d’autres\nscénarios : \n\n\n```\n\npick 4155df1cdc7 Page Navigation View\n\npick c22a3fa0c5c Render navigation partial\n\npick aa0a35a867e Add styles for navigation\n\npick 62e858a322 Fix a typo\n\npick 5c25eb48c8 Ops another fix\n\npick 7f0718efe9 Fix 2\n\npick f0ffc19ef7 Argh Another fix!\n\n```\n\n\nSi vous souhaitez combiner toutes ces modifications dans `c22a3fa0c5c Render\nnavigation partial`, vous devez : \n\n\n- Déplacer les corrections afin de les placer juste en-dessous du commit que\nvous désirez garder à la fin.\n\n\n- Changer `pick` en `squash` ou `fixup` pour chacune des modifications. \n\n\n*Remarque:* `squash` conserve les messages de commit des corrections dans la\ndescription. `Fixup` oublie les messages de commit des corrections et\nconserve l’original. \n\n\nVous obtenez donc : \n\n\n```\n\npick 4155df1cdc7 Page Navigation View\n\npick c22a3fa0c5c Render navigation partial\n\nfixup 62e858a322 Fix a typo\n\nfixup 5c25eb48c8 Ops another fix\n\nfixup 7f0718efe9 Fix 2\n\nfixup f0ffc19ef7 Argh Another fix!\n\npick aa0a35a867e Add styles for navigation\n\n```\n\n\nEnregistrez les changements et quittez l’éditeur. Voici le résultat : \n\n\n```\n\npick 4155df1cdc7 Page Navigation View\n\npick 96373c0bcf Render navigation partial\n\npick aa0a35a867e Add styles for navigation\n\n```\n\n\nComme précédemment, vous avez juste besoin d’exécuter `git push\n--force-with-lease \u003Cremote_name> \u003Cbranch_name>` et les changements sont\nappliqués.\n\n\nSi vous souhaitez supprimer un commit Git de la branche, utilisez plutôt la\ncommande `drop` ou effacez la ligne. Nous conseillons d’éviter les commandes\n`squash` et `fixup` pour cela.\n\n\n### Comment éviter les conflits entre commits ?\n\n\nPour éviter tout conflit, assurez-vous que les commits que vous faites\nremonter n’impactent pas de fichiers modifiés par des commits suivants.\n\n\n```\n\npick 4155df1cdc7 Page Navigation View\n\npick c22a3fa0c5c Render navigation partial\n\nfixup 62e858a322 Fix a typo                 # this changes styles.css\n\nfixup 5c25eb48c8 Ops another fix            # this changes image/logo.svg\n\nfixup 7f0718efe9 Fix 2                      # this changes styles.css\n\nfixup f0ffc19ef7 Argh Another fix!          # this changes styles.css\n\npick aa0a35a867e Add styles for navigation  # this changes index.html (no\nconflict)\n\n```\n\n\n## Situation 4 : mon historique de commits Git est incohérent, comment\nrepartir à zéro ?\n\n\nPour une fonctionnalité importante, il est courant d'avoir plusieurs\ncorrections et révisions fréquemment validées. Au lieu de rebaser\nconstamment la branche, vous pouvez retarder le nettoyage des commits\njusqu'à la fin du développement. \n\n\nC'est là que la création de fichiers patch s’avère très utile. En fait, les\nfichiers patch étaient le moyen principal de partager du code par e-mail\nlors de la collaboration sur de grands projets open source avant que des\nservices basés sur Git comme GitLab ne soient disponibles pour les\ndéveloppeurs et les développeuses. \n\n\nImaginez que vous avez une branche (par exemple `add-page-navigation`) où il\ny a des tonnes de commits qui ne transmettent pas clairement les changements\nsous-jacents. Voici comment vous pouvez créer un fichier patch pour tous les\nchangements apportés dans cette branche :\n\n\n- La première étape pour créer ce fichier patch est de s’assurer que votre\nbranche possède bien tous les changements présents dans la branche `master`\net n’a pas de conflits avec celle-ci. \n\n\n- Vous pouvez exécuter `git rebase master` ou `git merge master` pendant que\nvous êtes dans la branche `add-page-navigation` pour obtenir tous les\nchangements de la branche master sur votre branche. \n\n\n- Maintenant, créez le fichier patch. Pour ce faire, exécutez `git diff\nmaster add-page-navigation > ~/add_page_navigation.patch`.\n  - Explication de la commande : nous utilisons la fonctionnalité diff de Git. Nous demandons une diff entre la branche `master` et la branche `add-page-navigation`. Nous redirigeons le résultat (via le symbole `>`) vers un fichier nommé `add_page_navigation.patch` dans notre répertoire personnel (typiquement `~/` dans les systèmes d'exploitation *nix).\n\n- Vous pouvez spécifier n'importe quel chemin où vous souhaitez conserver ce\nfichier et choisir le nom et l’extension de ce fichier selon vos envies.\n\n\n- Une fois que la commande est exécutée et que vous ne voyez aucune erreur,\nvotre fichier patch a bien été généré.\n\n\n- Maintenant, vérifiez la branche `master`. Exécutez `git checkout master`.\n\n\n- Supprimez la branche `add-page-navigation` du dépôt local. Exécutez `git\nbranch -D add-page-navigation`. Souvenez-vous que nous avons déjà effectué\nles modifications sur cette branche avec la création d’un fichier patch. \n\n\n- Créez une nouvelle branche avec le même nom (pendant que la branche\n`master` est sélectionnée). Exécutez `git checkout -b add-page-navigation`.\n\n\n- À ce stade, c'est une nouvelle branche qui n'a aucun de vos changements.\n\n\n- Enfin, appliquez vos changements à partir du fichier patch `git apply\n~/add_page_navigation.patch`.\n\n\n- Tous vos changements sont appliqués dans une branche et ils apparaîtront\ncomme non validés, comme si toutes vos modifications avaient été faites,\nmais aucune d’entre elles n'avait été validées dans la branche.\n\n\n- Vous pouvez maintenant valider des fichiers individuels ou des fichiers\ngroupés par zone d'impact dans l'ordre que vous souhaitez, avec de courts\nmessages de commit.\n\n\nComme dans les situations précédentes, nous avons essentiellement modifié\ntoute la branche. Il est donc temps de la pousser de force. \n\n\n## Conclusion sur l'historique des commits Git\n\n\nBien que nous ayons couvert la plupart des situations qui surviennent dans\nun workflow avec Git, la réécriture de l’historique Git reste un vaste\nsujet. Au fur et à mesure que vous vous familiarisez avec les astuces\nmentionnées ci-dessus, vous pourrez apprendre des concepts plus avancés sur\nce sujet dans la [documentation officielle de\nGit](https://git-scm.com/book/fr/v2/Utilitaires-Git-R%C3%A9%C3%A9crire-l%E2%80%99historique\n\"Documentation officielle de Git\"). \n\n\n*Photo par pan xiaozhen sur Unsplash.*\n",[735,871],"2024-07-11",{"slug":1051,"featured":6,"template":686},"keeping-git-commit-history-clean","content:fr-fr:blog:keeping-git-commit-history-clean.yml","Keeping Git Commit History Clean","fr-fr/blog/keeping-git-commit-history-clean.yml","fr-fr/blog/keeping-git-commit-history-clean",2,[693,716,744,769,793,814,836,857,880],1758326254762]