[{"data":1,"prerenderedAt":3210},["ShallowReactive",2],{"/fr-fr/blog/basics-of-gitlab-ci-updated":3,"navigation-fr-fr":2428,"banner-fr-fr":2862,"footer-fr-fr":2870,"blog-post-authors-fr-fr-Itzik Gan Baruch":3108,"blog-related-posts-fr-fr-basics-of-gitlab-ci-updated":3122,"blog-promotions-fr-fr":3147,"next-steps-fr-fr":3201},{"id":4,"title":5,"authors":6,"body":8,"category":2407,"date":2408,"description":2409,"extension":2410,"externalUrl":2411,"faq":2411,"featured":2412,"heroImage":2413,"meta":2414,"navigation":261,"path":2415,"seo":2416,"slug":2420,"stem":2421,"tags":2422,"template":2425,"updatedDate":2426,"__hash__":2427},"blogPosts/fr-fr/blog/basics-of-gitlab-ci-updated.md","Intégration continue : créez votre premier pipeline CI avec GitLab ",[7],"Itzik Gan Baruch",{"type":9,"value":10,"toc":2378},"minimark",[11,23,26,29,32,35,75,78,81,91,96,103,132,135,142,145,151,154,157,174,177,222,225,229,232,235,238,279,282,288,295,358,361,367,370,374,377,481,484,487,490,647,650,656,663,718,721,734,738,741,747,779,796,799,805,831,834,838,848,855,858,1008,1011,1014,1017,1023,1032,1036,1055,1101,1107,1148,1153,1159,1163,1166,1169,1179,1189,1196,1199,1341,1346,1639,1647,1653,1657,1660,1665,1668,1671,1674,1683,1745,1763,1786,1796,1802,1809,1815,1820,1824,1833,1938,1941,1947,1951,1956,1959,1962,1966,1969,1972,1982,1986,1989,1996,2000,2010,2025,2029,2032,2040,2044,2047,2051,2054,2057,2060,2079,2082,2085,2095,2098,2100,2110,2114,2117,2120,2156,2159,2163,2166,2289,2293,2330,2334,2338,2341,2344,2347,2351,2354,2357,2361,2364,2367,2371,2374],[12,13,14,15,22],"p",{},"Imaginons que vous ne connaissiez rien au concept d’",[16,17,21],"a",{"href":18,"rel":19,"title":20},"https://about.gitlab.com/fr-fr/topics/ci-cd/benefits-continuous-integration/",[],"Qu'est-ce que l'intégration continue (CI) ?","intégration continue (CI)"," ni à son rôle clé dans le cycle de vie du développement logiciel.",[12,24,25],{},"À présent, supposons que vous travaillez sur un projet pour lequel l'intégralité du code est répartie dans seulement deux fichiers. Pour garantir le bon fonctionnement de ce projet, il est impératif que la concaténation de ces deux fichiers contienne la phrase « Hello world ».",[12,27,28],{},"Toute la réussite du projet repose sur cette simple phrase, car sans elle, tout serait compromis.",[12,30,31],{},"Conscient de cet enjeu, votre meilleur développeur logiciel a décidé de créer un script qui s'exécute dès qu’un nouveau morceau de code est envoyé aux clients.",[12,33,34],{},"Voici à quoi cela ressemble  :",[36,37,42],"pre",{"className":38,"code":39,"language":40,"meta":41,"style":41},"language-bash shiki shiki-themes github-light","cat file1.txt file2.txt | grep -q \"Hello world\"\n","bash","",[43,44,45],"code",{"__ignoreMap":41},[46,47,50,54,58,61,65,68,72],"span",{"class":48,"line":49},"line",1,[46,51,53],{"class":52},"s7eDp","cat",[46,55,57],{"class":56},"sYBdl"," file1.txt",[46,59,60],{"class":56}," file2.txt",[46,62,64],{"class":63},"sD7c4"," |",[46,66,67],{"class":52}," grep",[46,69,71],{"class":70},"sYu0t"," -q",[46,73,74],{"class":56}," \"Hello world\"\n",[12,76,77],{},"Même si, en l'état, ce script permet d'exécuter notre tâche, son déclenchement reste manuel. Et, avec une équipe de développement composée de 10 personnes, vous n'êtes pas à l'abri d'une erreur humaine qui pourrait vous coûter très cher.",[12,79,80],{},"La preuve en est, pas plus tard que la semaine dernière, un nouveau membre de votre équipe a oublié d'exécuter le script, provoquant des erreurs de compilation pour trois de vos clients.",[12,82,83,84,90],{},"Vous prenez donc la décision de résoudre ce problème, une bonne fois pour toutes, en utilisant le pipeline d'",[16,85,89],{"href":86,"rel":87,"title":88},"https://about.gitlab.com/fr-fr/solutions/continuous-integration/",[],"Intégration et livraison continues","intégration et de livraison continues"," de GitLab. Par chance, votre code est déjà sur la plateforme. Il ne vous reste plus qu'à vous lancer.",[92,93,95],"h2",{"id":94},"effectuer-un-premier-test-dans-le-pipeline-ci-de-gitlab","Effectuer un premier test dans le pipeline CI de GitLab",[12,97,98,99,102],{},"À la lecture de la documentation de GitLab, nous savons qu'il suffit de réunir deux lignes de code dans un fichier appelé ",[43,100,101],{},".gitlab-ci.yml",":",[36,104,108],{"className":105,"code":106,"language":107,"meta":41,"style":41},"language-yaml shiki shiki-themes github-light","test:\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n","yaml",[43,109,110,120],{"__ignoreMap":41},[46,111,112,116],{"class":48,"line":49},[46,113,115],{"class":114},"shJU0","test",[46,117,119],{"class":118},"sgsFI",":\n",[46,121,123,126,129],{"class":48,"line":122},2,[46,124,125],{"class":114},"  script",[46,127,128],{"class":118},": ",[46,130,131],{"class":56},"cat file1.txt file2.txt | grep -q 'Hello world'\n",[12,133,134],{},"Nous le validons et constatons que la compilation s'est déroulée avec succès",[12,136,137],{},[138,139],"img",{"alt":140,"src":141},"Compilation réussie dans le pipeline d’intégration continue","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/build_succeeded.png",[12,143,144],{},"Maintenant, remplaçons « world » par « Africa » dans le deuxième fichier et voyons ce qui se passe :",[12,146,147],{},[138,148],{"alt":149,"src":150},"Échec de compilation dans le pipeline CI\nGitLab","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/build_failed.png",[12,152,153],{},"Comme nous pouvions le prévoir, la compilation a échoué.",[12,155,156],{},"Nous avons désormais mis en place l'automatisation des tests.",[12,158,159,160,166,167,173],{},"À partir de maintenant, ",[16,161,165],{"href":162,"rel":163,"title":164},"https://about.gitlab.com/fr-fr/blog/ci-deployment-and-environments/",[],"Comment déployer du code dans des environnements multiples avec GitLab CI","GitLab\nCI","\nexécutera notre script de test dès que nous effectuerons un push du code vers le dépôt de code source dans l'environnement ",[16,168,172],{"href":169,"rel":170,"title":171},"https://about.gitlab.com/fr-fr/topics/devops/",[],"Que signifie DevOps\n?","DevOps",".",[12,175,176],{},"Remarque : dans l'exemple ci-dessus, nous supposons que file1.txt et file2.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 exécute le script.",[36,178,180],{"className":105,"code":179,"language":107,"meta":41,"style":41},"test:\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",[43,181,182,188,195,204,212],{"__ignoreMap":41},[46,183,184,186],{"class":48,"line":49},[46,185,115],{"class":114},[46,187,119],{"class":118},[46,189,190,193],{"class":48,"line":122},[46,191,192],{"class":114},"before_script",[46,194,119],{"class":118},[46,196,198,201],{"class":48,"line":197},3,[46,199,200],{"class":118},"      - ",[46,202,203],{"class":56},"echo \"Hello \" > | tr -d \"\\n\" | > file1.txt\n",[46,205,207,209],{"class":48,"line":206},4,[46,208,200],{"class":118},[46,210,211],{"class":56},"echo \"world\" > file2.txt\n",[46,213,215,218,220],{"class":48,"line":214},5,[46,216,217],{"class":114},"script",[46,219,128],{"class":118},[46,221,131],{"class":56},[12,223,224],{},"Pour simplifier notre démonstration, nous partons du principe que ces fichiers existent déjà sur l'hôte. Nous n'allons donc pas les créer dans les étapes suivantes.",[92,226,228],{"id":227},"rendre-les-résultats-des-compilations-téléchargeables","Rendre les résultats des compilations téléchargeables",[12,230,231],{},"La prochaine étape consiste à empaqueter le code avant de l'envoyer aux clients. Alors, pourquoi ne pas automatiser aussi cette partie du processus de développement logiciel ?",[12,233,234],{},"Pour cela, tout ce que nous devons faire est de définir un autre job pour l'intégration continue.",[12,236,237],{},"Commençons par nommer notre job « package » :",[36,239,241],{"className":105,"code":240,"language":107,"meta":41,"style":41},"test:\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n\npackage:\n  script: cat file1.txt file2.txt | gzip > package.gz\n",[43,242,243,249,257,263,270],{"__ignoreMap":41},[46,244,245,247],{"class":48,"line":49},[46,246,115],{"class":114},[46,248,119],{"class":118},[46,250,251,253,255],{"class":48,"line":122},[46,252,125],{"class":114},[46,254,128],{"class":118},[46,256,131],{"class":56},[46,258,259],{"class":48,"line":197},[46,260,262],{"emptyLinePlaceholder":261},true,"\n",[46,264,265,268],{"class":48,"line":206},[46,266,267],{"class":114},"package",[46,269,119],{"class":118},[46,271,272,274,276],{"class":48,"line":214},[46,273,125],{"class":114},[46,275,128],{"class":118},[46,277,278],{"class":56},"cat file1.txt file2.txt | gzip > package.gz\n",[12,280,281],{},"Nous avons maintenant deux onglets :",[12,283,284],{},[138,285],{"alt":286,"src":287},"Deux onglets - générés par deux jobs","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/two_tabs.png",[12,289,290,291,294],{},"Cependant, nous avons oublié de spécifier que le nouveau fichier est un artefact de compilation, afin qu’il puisse être téléchargé. Nous pouvons corriger cela en ajoutant une section ",[43,292,293],{},"artefacts"," :",[36,296,298],{"className":105,"code":297,"language":107,"meta":41,"style":41},"test:\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",[43,299,300,306,314,318,324,333,341,349],{"__ignoreMap":41},[46,301,302,304],{"class":48,"line":49},[46,303,115],{"class":114},[46,305,119],{"class":118},[46,307,308,310,312],{"class":48,"line":122},[46,309,125],{"class":114},[46,311,128],{"class":118},[46,313,131],{"class":56},[46,315,316],{"class":48,"line":197},[46,317,262],{"emptyLinePlaceholder":261},[46,319,320,322],{"class":48,"line":206},[46,321,267],{"class":114},[46,323,119],{"class":118},[46,325,326,328,330],{"class":48,"line":214},[46,327,125],{"class":114},[46,329,128],{"class":118},[46,331,332],{"class":56},"cat file1.txt file2.txt | gzip > packaged.gz\n",[46,334,336,339],{"class":48,"line":335},6,[46,337,338],{"class":114},"  artifacts",[46,340,119],{"class":118},[46,342,344,347],{"class":48,"line":343},7,[46,345,346],{"class":114},"    paths",[46,348,119],{"class":118},[46,350,352,355],{"class":48,"line":351},8,[46,353,354],{"class":118},"    - ",[46,356,357],{"class":56},"packaged.gz\n",[12,359,360],{},"Vérifions que tout est en place :",[12,362,363],{},[138,364],{"alt":365,"src":366},"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",[12,368,369],{},"Félicitations ! Tout semble fonctionnel. En revanche, dans la configuration actuelle, les jobs s'exécutent en parallèle. Cela signifie que notre application pourra être empaquetée, et ce, même si les tests échouent. Pour éviter que cela ne se produise, nous allons devoir exécuter les jobs de manière séquentielle.",[92,371,373],{"id":372},"exécuter-des-jobs-de-manière-séquentielle","Exécuter des jobs de manière séquentielle",[12,375,376],{},"Pour éviter d'empaqueter une application contenant des erreurs, nous allons faire en sorte d'exécuter le job « package » uniquement si les tests sont préalablement réussis. Pour commencer, définissons l'ordre d'exécution en établissant des étapes spécifiques  :",[36,378,380],{"className":105,"code":379,"language":107,"meta":41,"style":41},"stages:\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",[43,381,382,389,397,404,408,414,423,431,435,442,451,460,467,474],{"__ignoreMap":41},[46,383,384,387],{"class":48,"line":49},[46,385,386],{"class":114},"stages",[46,388,119],{"class":118},[46,390,391,394],{"class":48,"line":122},[46,392,393],{"class":118},"  - ",[46,395,396],{"class":56},"test\n",[46,398,399,401],{"class":48,"line":197},[46,400,393],{"class":118},[46,402,403],{"class":56},"package\n",[46,405,406],{"class":48,"line":206},[46,407,262],{"emptyLinePlaceholder":261},[46,409,410,412],{"class":48,"line":214},[46,411,115],{"class":114},[46,413,119],{"class":118},[46,415,416,419,421],{"class":48,"line":335},[46,417,418],{"class":114},"  stage",[46,420,128],{"class":118},[46,422,396],{"class":56},[46,424,425,427,429],{"class":48,"line":343},[46,426,125],{"class":114},[46,428,128],{"class":118},[46,430,131],{"class":56},[46,432,433],{"class":48,"line":351},[46,434,262],{"emptyLinePlaceholder":261},[46,436,438,440],{"class":48,"line":437},9,[46,439,267],{"class":114},[46,441,119],{"class":118},[46,443,445,447,449],{"class":48,"line":444},10,[46,446,418],{"class":114},[46,448,128],{"class":118},[46,450,403],{"class":56},[46,452,454,456,458],{"class":48,"line":453},11,[46,455,125],{"class":114},[46,457,128],{"class":118},[46,459,332],{"class":56},[46,461,463,465],{"class":48,"line":462},12,[46,464,338],{"class":114},[46,466,119],{"class":118},[46,468,470,472],{"class":48,"line":469},13,[46,471,346],{"class":114},[46,473,119],{"class":118},[46,475,477,479],{"class":48,"line":476},14,[46,478,354],{"class":118},[46,480,357],{"class":56},[12,482,483],{},"Cela devrait maintenant fonctionner.",[12,485,486],{},"Nous souhaitons également garantir que la compilation (qui est représentée par la concaténation dans notre exemple) ne s'exécute qu'une seule fois. En effet, cette étape pouvant être chronophage, il serait dommage de l'exécuter inutilement.",[12,488,489],{},"Pour éviter cela, définissons une étape supplémentaire :",[36,491,493],{"className":105,"code":492,"language":107,"meta":41,"style":41},"stages:\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",[43,494,495,501,508,514,520,524,531,539,548,554,560,567,571,577,585,595,600,607,616,626,633,640],{"__ignoreMap":41},[46,496,497,499],{"class":48,"line":49},[46,498,386],{"class":114},[46,500,119],{"class":118},[46,502,503,505],{"class":48,"line":122},[46,504,393],{"class":118},[46,506,507],{"class":56},"compile\n",[46,509,510,512],{"class":48,"line":197},[46,511,393],{"class":118},[46,513,396],{"class":56},[46,515,516,518],{"class":48,"line":206},[46,517,393],{"class":118},[46,519,403],{"class":56},[46,521,522],{"class":48,"line":214},[46,523,262],{"emptyLinePlaceholder":261},[46,525,526,529],{"class":48,"line":335},[46,527,528],{"class":114},"compile",[46,530,119],{"class":118},[46,532,533,535,537],{"class":48,"line":343},[46,534,418],{"class":114},[46,536,128],{"class":118},[46,538,507],{"class":56},[46,540,541,543,545],{"class":48,"line":351},[46,542,125],{"class":114},[46,544,128],{"class":118},[46,546,547],{"class":56},"cat file1.txt file2.txt > compiled.txt\n",[46,549,550,552],{"class":48,"line":437},[46,551,338],{"class":114},[46,553,119],{"class":118},[46,555,556,558],{"class":48,"line":444},[46,557,346],{"class":114},[46,559,119],{"class":118},[46,561,562,564],{"class":48,"line":453},[46,563,354],{"class":118},[46,565,566],{"class":56},"compiled.txt\n",[46,568,569],{"class":48,"line":462},[46,570,262],{"emptyLinePlaceholder":261},[46,572,573,575],{"class":48,"line":469},[46,574,115],{"class":114},[46,576,119],{"class":118},[46,578,579,581,583],{"class":48,"line":476},[46,580,418],{"class":114},[46,582,128],{"class":118},[46,584,396],{"class":56},[46,586,588,590,592],{"class":48,"line":587},15,[46,589,125],{"class":114},[46,591,128],{"class":118},[46,593,594],{"class":56},"cat compiled.txt | grep -q 'Hello world'\n",[46,596,598],{"class":48,"line":597},16,[46,599,262],{"emptyLinePlaceholder":261},[46,601,603,605],{"class":48,"line":602},17,[46,604,267],{"class":114},[46,606,119],{"class":118},[46,608,610,612,614],{"class":48,"line":609},18,[46,611,418],{"class":114},[46,613,128],{"class":118},[46,615,403],{"class":56},[46,617,619,621,623],{"class":48,"line":618},19,[46,620,125],{"class":114},[46,622,128],{"class":118},[46,624,625],{"class":56},"cat compiled.txt | gzip > packaged.gz\n",[46,627,629,631],{"class":48,"line":628},20,[46,630,338],{"class":114},[46,632,119],{"class":118},[46,634,636,638],{"class":48,"line":635},21,[46,637,346],{"class":114},[46,639,119],{"class":118},[46,641,643,645],{"class":48,"line":642},22,[46,644,354],{"class":118},[46,646,357],{"class":56},[12,648,649],{},"Jetons un œil à nos artefacts :",[12,651,652],{},[138,653],{"alt":654,"src":655},"Artefacts de compilation dans le pipeline CI de\nGitLab","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782399213/blog/Content%20Images/the-basics-of-gitlab-ci/clean-artifacts.png",[12,657,658,659,662],{},"Tout a l'air de fonctionner. En revanche, il faudrait éviter de rendre le fichier « compile » téléchargeable. Pour cela, nous allons rendre nos artefacts temporaires expirables en définissant ",[43,660,661],{},"expire_in"," à « 20 minutes\n».",[36,664,666],{"className":105,"code":665,"language":107,"meta":41,"style":41},"compile:\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",[43,667,668,674,682,690,696,702,708],{"__ignoreMap":41},[46,669,670,672],{"class":48,"line":49},[46,671,528],{"class":114},[46,673,119],{"class":118},[46,675,676,678,680],{"class":48,"line":122},[46,677,418],{"class":114},[46,679,128],{"class":118},[46,681,507],{"class":56},[46,683,684,686,688],{"class":48,"line":197},[46,685,125],{"class":114},[46,687,128],{"class":118},[46,689,547],{"class":56},[46,691,692,694],{"class":48,"line":206},[46,693,338],{"class":114},[46,695,119],{"class":118},[46,697,698,700],{"class":48,"line":214},[46,699,346],{"class":114},[46,701,119],{"class":118},[46,703,704,706],{"class":48,"line":335},[46,705,354],{"class":118},[46,707,566],{"class":56},[46,709,710,713,715],{"class":48,"line":343},[46,711,712],{"class":114},"    expire_in",[46,714,128],{"class":118},[46,716,717],{"class":56},"20 minutes\n",[12,719,720],{},"Maintenant, notre configuration semble plutôt complète :",[722,723,724,728,731],"ul",{},[725,726,727],"li",{},"Nous avons trois étapes séquentielles pour compiler, tester et empaqueter\nnotre application.",[725,729,730],{},"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 processus).",[725,732,733],{},"Et nous stockons une version empaquetée de notre application dans les\nartefacts de compilation pour une utilisation ultérieure.",[92,735,737],{"id":736},"savoir-quelle-image-docker-utiliser","Savoir quelle image Docker utiliser",[12,739,740],{},"Jusqu'ici, tout va bien. Cependant, en regardant de plus près, nos compilations semblent toujours lentes. Prenons un moment pour regarder les journaux (logs) :",[12,742,743],{},[138,744],{"alt":745,"src":746},"Image ruby 3.1","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/ruby-31.png",[12,748,749,750,753,754,760,761,766,767,772,773,173],{},"En observant de plus près, nous remarquons la mention suivante : ",[43,751,752],{},"ruby:3.1",".\nCela signifie que GitLab.com utilise des images ",[16,755,759],{"href":756,"rel":757,"title":758},"https://about.gitlab.com/fr-fr/blog/what-is-docker-comprehensive-guide/",[],"Qu'est-ce que Docker ?","Docker"," pour ",[16,762,765],{"href":763,"rel":764},"https://about.gitlab.com/blog/shared-runners/",[],"exécuter nos compilations",", et qu’il utilise ",[16,768,771],{"href":769,"rel":770},"https://docs.gitlab.com/user/gitlab_com/#shared-runners",[],"par défaut",", l'image ",[16,774,777],{"href":775,"rel":776},"https://hub.docker.com/_/ruby/",[],[43,778,752],{},[12,780,781,782,789,790,793,794,173],{},"Cette image contient certainement de nombreux paquets dont nous n'avons pas besoin. Dans un souci d'optimisation de notre pipeline CI, il serait donc préférable de changer d'image. Après une courte recherche sur Google, nous découvrons qu'il existe une image Linux presque vierge appelée ",[16,783,786],{"href":784,"rel":785},"https://hub.docker.com/_/alpine/",[],[43,787,788],{},"alpine",". Nous allons alors l'utiliser.\nPour cela, nous devrons ajouter ",[43,791,792],{},"image: alpine"," au fichier ",[43,795,101],{},[12,797,798],{},"Et voilà !  Nous avons maintenant réduit le temps de compilation de presque trois minutes :",[12,800,801],{},[138,802],{"alt":803,"src":804},"Vitesse de compilation améliorée dans le pipeline de\nGitLab","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782399214/blog/Content%20Images/the-basics-of-gitlab-ci/speed.png",[12,806,807,808,813,814,813,819,824,825,830],{},"Vous pouvez également trouver des images libres de droits sur ",[16,809,812],{"href":810,"rel":811},"https://hub.docker.com/_/mysql/",[],"mysql",", ",[16,815,818],{"href":816,"rel":817},"https://hub.docker.com/_/python/",[],"Python",[16,820,823],{"href":821,"rel":822},"https://hub.docker.com/_/java/",[],"Java"," et ",[16,826,829],{"href":827,"rel":828},"https://hub.docker.com/_/php/",[],"php",". Il est facile, alors, d'en choisir une pour notre pile technologique.",[12,832,833],{},"Note : il sera toujours préférable d'utiliser une image qui ne contient aucun logiciel supplémentaire dont vous n'avez pas besoin, car cela minimise grandement le temps de téléchargement.",[92,835,837],{"id":836},"gérer-des-scénarios-complexes","Gérer des scénarios complexes",[12,839,840,841,844,845,173],{},"Imaginons maintenant un scénario un peu plus complexe. Par exemple, un nouveau client souhaite que nous empaquetions notre application au format ",[43,842,843],{},".iso"," plutôt qu'en ",[43,846,847],{},".gz",[12,849,850,851,854],{},"Étant donné que le pipeline d'intégration continue gère tout le processus, et que les images ISO peuvent être créées avec la commande ",[43,852,853],{},"mkisofs",", il suffit d'ajouter un job supplémentaire.",[12,856,857],{},"Voici à quoi notre configuration devrait ressembler :",[36,859,861],{"className":105,"code":860,"language":107,"meta":41,"style":41},"image: alpine\n\nstages:\n  - compile\n  - test\n  - package\n\n# ... \"compile\" and \"test\" jobs are skipped here for the sake of compactness\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",[43,862,863,873,877,883,889,895,901,905,911,915,922,930,938,944,950,956,960,967,975,981,988,994,1000],{"__ignoreMap":41},[46,864,865,868,870],{"class":48,"line":49},[46,866,867],{"class":114},"image",[46,869,128],{"class":118},[46,871,872],{"class":56},"alpine\n",[46,874,875],{"class":48,"line":122},[46,876,262],{"emptyLinePlaceholder":261},[46,878,879,881],{"class":48,"line":197},[46,880,386],{"class":114},[46,882,119],{"class":118},[46,884,885,887],{"class":48,"line":206},[46,886,393],{"class":118},[46,888,507],{"class":56},[46,890,891,893],{"class":48,"line":214},[46,892,393],{"class":118},[46,894,396],{"class":56},[46,896,897,899],{"class":48,"line":335},[46,898,393],{"class":118},[46,900,403],{"class":56},[46,902,903],{"class":48,"line":343},[46,904,262],{"emptyLinePlaceholder":261},[46,906,907],{"class":48,"line":351},[46,908,910],{"class":909},"sAwPA","# ... \"compile\" and \"test\" jobs are skipped here for the sake of compactness\n",[46,912,913],{"class":48,"line":437},[46,914,262],{"emptyLinePlaceholder":261},[46,916,917,920],{"class":48,"line":444},[46,918,919],{"class":114},"pack-gz",[46,921,119],{"class":118},[46,923,924,926,928],{"class":48,"line":453},[46,925,418],{"class":114},[46,927,128],{"class":118},[46,929,403],{"class":56},[46,931,932,934,936],{"class":48,"line":462},[46,933,125],{"class":114},[46,935,128],{"class":118},[46,937,625],{"class":56},[46,939,940,942],{"class":48,"line":469},[46,941,338],{"class":114},[46,943,119],{"class":118},[46,945,946,948],{"class":48,"line":476},[46,947,346],{"class":114},[46,949,119],{"class":118},[46,951,952,954],{"class":48,"line":587},[46,953,354],{"class":118},[46,955,357],{"class":56},[46,957,958],{"class":48,"line":597},[46,959,262],{"emptyLinePlaceholder":261},[46,961,962,965],{"class":48,"line":602},[46,963,964],{"class":114},"pack-iso",[46,966,119],{"class":118},[46,968,969,971,973],{"class":48,"line":609},[46,970,418],{"class":114},[46,972,128],{"class":118},[46,974,403],{"class":56},[46,976,977,979],{"class":48,"line":618},[46,978,125],{"class":114},[46,980,119],{"class":118},[46,982,983,985],{"class":48,"line":628},[46,984,393],{"class":118},[46,986,987],{"class":56},"mkisofs -o ./packaged.iso ./compiled.txt\n",[46,989,990,992],{"class":48,"line":635},[46,991,338],{"class":114},[46,993,119],{"class":118},[46,995,996,998],{"class":48,"line":642},[46,997,346],{"class":114},[46,999,119],{"class":118},[46,1001,1003,1005],{"class":48,"line":1002},23,[46,1004,354],{"class":118},[46,1006,1007],{"class":56},"packaged.iso\n",[12,1009,1010],{},"Notez 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 parallèle dans la même étape du processus de développement logiciel.",[12,1012,1013],{},"Ainsi, dans l'exemple qui suit, ignorez le fait que les jobs et étapes portent le même nom.",[12,1015,1016],{},"Quoi qu'il en soit, la compilation échoue :",[12,1018,1019],{},[138,1020],{"alt":1021,"src":1022},"Echec de compilation dans le pipeline de\nGitLab","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782399214/blog/Content%20Images/the-basics-of-gitlab-ci/mkisofs.png",[12,1024,1025,1026,1028,1029,1031],{},"Le problème vient de  ",[43,1027,853],{}," qui n'est pas inclus dans l'image ",[43,1030,788],{},".\nNous devons donc d'abord l'installer.",[92,1033,1035],{"id":1034},"gérer-des-logiciels-et-des-paquets-manquants","Gérer des logiciels et des paquets manquants",[12,1037,1038,1039,813,1045,1047,1048,824,1051,1054],{},"Selon le ",[16,1040,1044],{"href":1041,"rel":1042,"title":1043},"https://pkgs.alpinelinux.org/contents?file=mkisofs&path=&name=&branch=edge&repo=&arch=",[],"Site Web Alpine Linux","site Web d’Alpine\nLinux",[43,1046,853],{}," fait partie des paquets ",[43,1049,1050],{},"xorriso",[43,1052,1053],{},"cdrkit",". Voici les commandes que nous devons exécuter pour installer un paquet :",[36,1056,1058],{"className":38,"code":1057,"language":40,"meta":41,"style":41},"echo \"ipv6\" >> /etc/modules  # enable networking\napk update                   # update packages list\napk add xorriso              # install package\n",[43,1059,1060,1077,1088],{"__ignoreMap":41},[46,1061,1062,1065,1068,1071,1074],{"class":48,"line":49},[46,1063,1064],{"class":70},"echo",[46,1066,1067],{"class":56}," \"ipv6\"",[46,1069,1070],{"class":63}," >>",[46,1072,1073],{"class":56}," /etc/modules",[46,1075,1076],{"class":909},"  # enable networking\n",[46,1078,1079,1082,1085],{"class":48,"line":122},[46,1080,1081],{"class":52},"apk",[46,1083,1084],{"class":56}," update",[46,1086,1087],{"class":909},"                   # update packages list\n",[46,1089,1090,1092,1095,1098],{"class":48,"line":197},[46,1091,1081],{"class":52},[46,1093,1094],{"class":56}," add",[46,1096,1097],{"class":56}," xorriso",[46,1099,1100],{"class":909},"              # install package\n",[12,1102,1103,1104,1106],{},"Ces commandes s'exécutent de la même manière que toute autre commande au sein du processus d'intégration continue. La liste complète des commandes que nous devons transmettre à la section ",[43,1105,217],{}," devrait ressembler à ceci\n:",[36,1108,1112],{"className":1109,"code":1110,"language":1111,"meta":41,"style":41},"language-yml shiki shiki-themes github-light","script:\n- echo \"ipv6\" >> /etc/modules\n- apk update\n- apk add xorriso\n- mkisofs -o ./packaged.iso ./compiled.txt\n","yml",[43,1113,1114,1120,1128,1135,1142],{"__ignoreMap":41},[46,1115,1116,1118],{"class":48,"line":49},[46,1117,217],{"class":114},[46,1119,119],{"class":118},[46,1121,1122,1125],{"class":48,"line":122},[46,1123,1124],{"class":118},"- ",[46,1126,1127],{"class":56},"echo \"ipv6\" >> /etc/modules\n",[46,1129,1130,1132],{"class":48,"line":197},[46,1131,1124],{"class":118},[46,1133,1134],{"class":56},"apk update\n",[46,1136,1137,1139],{"class":48,"line":206},[46,1138,1124],{"class":118},[46,1140,1141],{"class":56},"apk add xorriso\n",[46,1143,1144,1146],{"class":48,"line":214},[46,1145,1124],{"class":118},[46,1147,987],{"class":56},[12,1149,1150,1151,173],{},"Cependant, pour des raisons sémantiques, plaçons les commandes liées à l'installation du paquet dans ",[43,1152,192],{},[12,1154,1155,1156,1158],{},"Notez que si vous utilisez ",[43,1157,192],{}," au niveau supérieur d'une configuration, alors les commandes s'exécuteront avant tous les jobs. Dans notre cas, nous voulons simplement qu'elles s'exécutent avant un job spécifique.",[92,1160,1162],{"id":1161},"graphes-acycliques-orientés-pour-des-pipelines-ci-plus-rapides-et","Graphes acycliques orientés pour des pipelines CI plus rapides et",[12,1164,1165],{},"flexibles",[12,1167,1168],{},"Plus haut, nous avons configuré des étapes pour que les jobs d'empaquetage ne s'exécutent qu'à la condition que les tests réussissent. Mais, que se passerait-il si nous voulions bouleverser le séquencement des étapes en exécutant certains jobs plus tôt qu'initialement prévu ?",[12,1170,1171,1172,1178],{},"Dans certains cas, le séquencement traditionnel des étapes peut ralentir la durée globale d'exécution du ",[16,1173,1177],{"href":1174,"rel":1175,"title":1176},"https://about.gitlab.com/fr-fr/topics/ci-cd/cicd-pipeline/",[],"Qu'est-ce qu'un pipeline CI/CD ?","pipeline\nCI/CD",". Pour éviter cela, nous pouvons choisir de personnaliser le séquencement de nos jobs.",[12,1180,1181,1182,1188],{},"Par exemple : imaginons que notre étape de test comprenne des tests lourds, prenant beaucoup de temps à s'exécuter. Supposons aussi que ces tests ne soient pas nécessairement liés aux jobs d’empaquetage. Dans ce cas, il serait préférable que les jobs d’empaquetage puissent démarrer sans attendre la fin de ces tests. C'est là qu'interviennent les ",[16,1183,1187],{"href":1184,"rel":1185,"title":1186},"https://about.gitlab.com/blog/directed-acyclic-graph/",[],"Graphes acycliques orientés","graphes acycliques orientés",". Ces derniers visent à rompre l'ordre normal d'exécution des jobs (ordre séquentiel) grâce à la création de dépendances entre certains jobs. Vous pouvez ainsi définir un ordre personnalisé pour exécuter les différents jobs de votre pipeline CI.",[12,1190,1191,1192,1195],{},"Grâce au mot-clé ",[43,1193,1194],{},"needs",", GitLab crée des dépendances entre les jobs et leur permet de s'exécuter plus tôt, dès que leurs jobs dépendants sont terminés.",[12,1197,1198],{},"Dans l'exemple ci-dessous, les jobs d’empaquetage commenceront à s'exécuter dès que le test sera terminé. Ainsi, à l'avenir, si quelqu'un ajoute d'autres tests à l'étape de test, les jobs d’empaquetage commenceront à s'exécuter avant la fin des nouveaux tests :",[36,1200,1202],{"className":105,"code":1201,"language":107,"meta":41,"style":41},"pack-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",[43,1203,1204,1210,1218,1226,1240,1246,1252,1258,1262,1268,1276,1283,1289,1295,1301,1307,1313,1323,1329,1335],{"__ignoreMap":41},[46,1205,1206,1208],{"class":48,"line":49},[46,1207,919],{"class":114},[46,1209,119],{"class":118},[46,1211,1212,1214,1216],{"class":48,"line":122},[46,1213,418],{"class":114},[46,1215,128],{"class":118},[46,1217,403],{"class":56},[46,1219,1220,1222,1224],{"class":48,"line":197},[46,1221,125],{"class":114},[46,1223,128],{"class":118},[46,1225,625],{"class":56},[46,1227,1228,1231,1234,1237],{"class":48,"line":206},[46,1229,1230],{"class":114},"  needs",[46,1232,1233],{"class":118},": [",[46,1235,1236],{"class":56},"\"test\"",[46,1238,1239],{"class":118},"]\n",[46,1241,1242,1244],{"class":48,"line":214},[46,1243,338],{"class":114},[46,1245,119],{"class":118},[46,1247,1248,1250],{"class":48,"line":335},[46,1249,346],{"class":114},[46,1251,119],{"class":118},[46,1253,1254,1256],{"class":48,"line":343},[46,1255,354],{"class":118},[46,1257,357],{"class":56},[46,1259,1260],{"class":48,"line":351},[46,1261,262],{"emptyLinePlaceholder":261},[46,1263,1264,1266],{"class":48,"line":437},[46,1265,964],{"class":114},[46,1267,119],{"class":118},[46,1269,1270,1272,1274],{"class":48,"line":444},[46,1271,418],{"class":114},[46,1273,128],{"class":118},[46,1275,403],{"class":56},[46,1277,1278,1281],{"class":48,"line":453},[46,1279,1280],{"class":114},"  before_script",[46,1282,119],{"class":118},[46,1284,1285,1287],{"class":48,"line":462},[46,1286,393],{"class":118},[46,1288,1127],{"class":56},[46,1290,1291,1293],{"class":48,"line":469},[46,1292,393],{"class":118},[46,1294,1134],{"class":56},[46,1296,1297,1299],{"class":48,"line":476},[46,1298,393],{"class":118},[46,1300,1141],{"class":56},[46,1302,1303,1305],{"class":48,"line":587},[46,1304,125],{"class":114},[46,1306,119],{"class":118},[46,1308,1309,1311],{"class":48,"line":597},[46,1310,393],{"class":118},[46,1312,987],{"class":56},[46,1314,1315,1317,1319,1321],{"class":48,"line":602},[46,1316,1230],{"class":114},[46,1318,1233],{"class":118},[46,1320,1236],{"class":56},[46,1322,1239],{"class":118},[46,1324,1325,1327],{"class":48,"line":609},[46,1326,338],{"class":114},[46,1328,119],{"class":118},[46,1330,1331,1333],{"class":48,"line":618},[46,1332,346],{"class":114},[46,1334,119],{"class":118},[46,1336,1337,1339],{"class":48,"line":628},[46,1338,354],{"class":118},[46,1340,1007],{"class":56},[12,1342,1343,1344,102],{},"Voici notre version définitive de ",[43,1345,101],{},[36,1347,1349],{"className":105,"code":1348,"language":107,"meta":41,"style":41},"image: alpine\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",[43,1350,1351,1359,1363,1369,1375,1381,1387,1391,1397,1405,1411,1418,1424,1432,1438,1444,1450,1458,1462,1468,1476,1484,1488,1494,1503,1512,1523,1530,1537,1544,1549,1556,1565,1572,1579,1586,1593,1600,1607,1618,1625,1632],{"__ignoreMap":41},[46,1352,1353,1355,1357],{"class":48,"line":49},[46,1354,867],{"class":114},[46,1356,128],{"class":118},[46,1358,872],{"class":56},[46,1360,1361],{"class":48,"line":122},[46,1362,262],{"emptyLinePlaceholder":261},[46,1364,1365,1367],{"class":48,"line":197},[46,1366,386],{"class":114},[46,1368,119],{"class":118},[46,1370,1371,1373],{"class":48,"line":206},[46,1372,393],{"class":118},[46,1374,507],{"class":56},[46,1376,1377,1379],{"class":48,"line":214},[46,1378,393],{"class":118},[46,1380,396],{"class":56},[46,1382,1383,1385],{"class":48,"line":335},[46,1384,393],{"class":118},[46,1386,403],{"class":56},[46,1388,1389],{"class":48,"line":343},[46,1390,262],{"emptyLinePlaceholder":261},[46,1392,1393,1395],{"class":48,"line":351},[46,1394,528],{"class":114},[46,1396,119],{"class":118},[46,1398,1399,1401,1403],{"class":48,"line":437},[46,1400,418],{"class":114},[46,1402,128],{"class":118},[46,1404,507],{"class":56},[46,1406,1407,1409],{"class":48,"line":444},[46,1408,1280],{"class":114},[46,1410,119],{"class":118},[46,1412,1413,1415],{"class":48,"line":453},[46,1414,200],{"class":118},[46,1416,1417],{"class":56},"echo \"Hello  \" | tr -d \"\\n\" > file1.txt\n",[46,1419,1420,1422],{"class":48,"line":462},[46,1421,200],{"class":118},[46,1423,211],{"class":56},[46,1425,1426,1428,1430],{"class":48,"line":469},[46,1427,125],{"class":114},[46,1429,128],{"class":118},[46,1431,547],{"class":56},[46,1433,1434,1436],{"class":48,"line":476},[46,1435,338],{"class":114},[46,1437,119],{"class":118},[46,1439,1440,1442],{"class":48,"line":587},[46,1441,346],{"class":114},[46,1443,119],{"class":118},[46,1445,1446,1448],{"class":48,"line":597},[46,1447,354],{"class":118},[46,1449,566],{"class":56},[46,1451,1452,1454,1456],{"class":48,"line":602},[46,1453,712],{"class":114},[46,1455,128],{"class":118},[46,1457,717],{"class":56},[46,1459,1460],{"class":48,"line":609},[46,1461,262],{"emptyLinePlaceholder":261},[46,1463,1464,1466],{"class":48,"line":618},[46,1465,115],{"class":114},[46,1467,119],{"class":118},[46,1469,1470,1472,1474],{"class":48,"line":628},[46,1471,418],{"class":114},[46,1473,128],{"class":118},[46,1475,396],{"class":56},[46,1477,1478,1480,1482],{"class":48,"line":635},[46,1479,125],{"class":114},[46,1481,128],{"class":118},[46,1483,594],{"class":56},[46,1485,1486],{"class":48,"line":642},[46,1487,262],{"emptyLinePlaceholder":261},[46,1489,1490,1492],{"class":48,"line":1002},[46,1491,919],{"class":114},[46,1493,119],{"class":118},[46,1495,1497,1499,1501],{"class":48,"line":1496},24,[46,1498,418],{"class":114},[46,1500,128],{"class":118},[46,1502,403],{"class":56},[46,1504,1506,1508,1510],{"class":48,"line":1505},25,[46,1507,125],{"class":114},[46,1509,128],{"class":118},[46,1511,625],{"class":56},[46,1513,1515,1517,1519,1521],{"class":48,"line":1514},26,[46,1516,1230],{"class":114},[46,1518,1233],{"class":118},[46,1520,1236],{"class":56},[46,1522,1239],{"class":118},[46,1524,1526,1528],{"class":48,"line":1525},27,[46,1527,338],{"class":114},[46,1529,119],{"class":118},[46,1531,1533,1535],{"class":48,"line":1532},28,[46,1534,346],{"class":114},[46,1536,119],{"class":118},[46,1538,1540,1542],{"class":48,"line":1539},29,[46,1541,354],{"class":118},[46,1543,357],{"class":56},[46,1545,1547],{"class":48,"line":1546},30,[46,1548,262],{"emptyLinePlaceholder":261},[46,1550,1552,1554],{"class":48,"line":1551},31,[46,1553,964],{"class":114},[46,1555,119],{"class":118},[46,1557,1559,1561,1563],{"class":48,"line":1558},32,[46,1560,418],{"class":114},[46,1562,128],{"class":118},[46,1564,403],{"class":56},[46,1566,1568,1570],{"class":48,"line":1567},33,[46,1569,1280],{"class":114},[46,1571,119],{"class":118},[46,1573,1575,1577],{"class":48,"line":1574},34,[46,1576,393],{"class":118},[46,1578,1127],{"class":56},[46,1580,1582,1584],{"class":48,"line":1581},35,[46,1583,393],{"class":118},[46,1585,1134],{"class":56},[46,1587,1589,1591],{"class":48,"line":1588},36,[46,1590,393],{"class":118},[46,1592,1141],{"class":56},[46,1594,1596,1598],{"class":48,"line":1595},37,[46,1597,125],{"class":114},[46,1599,119],{"class":118},[46,1601,1603,1605],{"class":48,"line":1602},38,[46,1604,393],{"class":118},[46,1606,987],{"class":56},[46,1608,1610,1612,1614,1616],{"class":48,"line":1609},39,[46,1611,1230],{"class":114},[46,1613,1233],{"class":118},[46,1615,1236],{"class":56},[46,1617,1239],{"class":118},[46,1619,1621,1623],{"class":48,"line":1620},40,[46,1622,338],{"class":114},[46,1624,119],{"class":118},[46,1626,1628,1630],{"class":48,"line":1627},41,[46,1629,346],{"class":114},[46,1631,119],{"class":118},[46,1633,1635,1637],{"class":48,"line":1634},42,[46,1636,354],{"class":118},[46,1638,1007],{"class":56},[12,1640,1641,1642,824,1644,1646],{},"Nous venons de créer un pipeline ! Ainsi, nous avons trois étapes séquentielles avec les jobs ",[43,1643,919],{},[43,1645,964],{}," qui s'exécutent en parallèle à l'intérieur de l'étape d'empaquetage :",[12,1648,1649],{},[138,1650],{"alt":1651,"src":1652},"Représentation d'un artefact de compilation d'un pipeline\nCI","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782399214/blog/Content%20Images/the-basics-of-gitlab-ci/pipeline.png",[92,1654,1656],{"id":1655},"améliorer-votre-pipeline-ci","Améliorer votre pipeline CI",[12,1658,1659],{},"Nous allons maintenant découvrir comment améliorer notre pipeline d'intégration continue.",[1661,1662,1664],"h3",{"id":1663},"intégrer-des-tests-automatisés-dans-vos-pipelines-ci","Intégrer des tests automatisés dans vos pipelines CI",[12,1666,1667],{},"L'objectif clé du développement logiciel avec une approche DevOps est de réussir à créer des applications offrant une excellente expérience utilisateur.",[12,1669,1670],{},"Avec cet objectif en tête, pourquoi ne pas renforcer le cycle de développement logiciel en cherchant à détecter d'éventuels bogues dès le dé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.",[12,1672,1673],{},"Par chance, le pipeline CI de GitLab nous facilite la tâche en proposant des templates de tests prêts à l'emploi. Tout ce que nous avons à faire, c'est d'inclure ces templates dans la configuration de notre pipeline CI.",[12,1675,1676,1677,294],{},"Dans cet exemple, nous allons réaliser des ",[16,1678,1682],{"href":1679,"rel":1680,"title":1681},"https://docs.gitlab.com/ci/testing/accessibility_testing/",[],"Test d'accessibilité","tests d'accessibilité",[36,1684,1686],{"className":105,"code":1685,"language":107,"meta":41,"style":41},"stages:\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",[43,1687,1688,1694,1701,1705,1712,1722,1726,1733],{"__ignoreMap":41},[46,1689,1690,1692],{"class":48,"line":49},[46,1691,386],{"class":114},[46,1693,119],{"class":118},[46,1695,1696,1698],{"class":48,"line":122},[46,1697,393],{"class":118},[46,1699,1700],{"class":56},"accessibility\n",[46,1702,1703],{"class":48,"line":197},[46,1704,262],{"emptyLinePlaceholder":261},[46,1706,1707,1710],{"class":48,"line":206},[46,1708,1709],{"class":114},"variables",[46,1711,119],{"class":118},[46,1713,1714,1717,1719],{"class":48,"line":214},[46,1715,1716],{"class":114},"  a11y_urls",[46,1718,128],{"class":118},[46,1720,1721],{"class":56},"\"https://about.gitlab.com https://www.example.com\"\n",[46,1723,1724],{"class":48,"line":335},[46,1725,262],{"emptyLinePlaceholder":261},[46,1727,1728,1731],{"class":48,"line":343},[46,1729,1730],{"class":114},"include",[46,1732,119],{"class":118},[46,1734,1735,1737,1740,1742],{"class":48,"line":351},[46,1736,393],{"class":118},[46,1738,1739],{"class":114},"template",[46,1741,128],{"class":118},[46,1743,1744],{"class":56},"\"Verify/Accessibility.gitlab-ci.yml\"\n",[12,1746,1747,1748,1751,1752,1757,1758,173],{},"Personnalisez la variable ",[43,1749,1750],{},"a11y_urls"," pour répertorier les URL des pages web à tester avec ",[16,1753,1756],{"href":1754,"rel":1755,"title":1756},"https://pa11y.org/",[],"Pa11y"," et GitLab ",[16,1759,1762],{"href":1760,"rel":1761,"title":1762},"https://docs.gitlab.com/ci/testing/code_quality/",[],"Code\nQuality",[36,1764,1766],{"className":105,"code":1765,"language":107,"meta":41,"style":41},"    include:\n    - template: Jobs/Code-Quality.gitlab-ci.yml\n",[43,1767,1768,1775],{"__ignoreMap":41},[46,1769,1770,1773],{"class":48,"line":49},[46,1771,1772],{"class":114},"    include",[46,1774,119],{"class":118},[46,1776,1777,1779,1781,1783],{"class":48,"line":122},[46,1778,354],{"class":118},[46,1780,1739],{"class":114},[46,1782,128],{"class":118},[46,1784,1785],{"class":56},"Jobs/Code-Quality.gitlab-ci.yml\n",[12,1787,1788,1789,1795],{},"GitLab facilite la consultation du rapport de test directement dans la zone du widget de la ",[16,1790,1794],{"href":1791,"rel":1792,"title":1793},"https://docs.gitlab.com/user/project/merge_requests/",[],"Merge request","merge request",". Ce widget vous permet de voir la revue de code, l'état du pipeline et les résultats des tests au même endroit. La capture d'écran ci-dessous montre à quel point ce widget facilite le travail de vos équipes.",[12,1797,1798],{},[138,1799],{"alt":1800,"src":1801},"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",[1803,1804,1805],"center",{},[1806,1807,1808],"i",{},"Widget pour les merge requests en matière d'accessibilité",[12,1810,1811],{},[138,1812],{"alt":1813,"src":1814},"Exemple de rapport de test sur la qualité du code suite à une merge request dans\nGitLab","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-02_at_11.00.25.png",[1803,1816,1817],{},[1806,1818,1819],{},"Widget de merge request pour GitLab Code Quality",[1661,1821,1823],{"id":1822},"matrice-des-compilations","Matrice des compilations",[12,1825,1826,1827,1832],{},"Dans certains cas, nous devons tester notre application dans différentes configurations, versions de systèmes d'exploitation et langages de programmation. Nous utilisons alors la compilation « ",[16,1828,1831],{"href":1829,"rel":1830,"title":1831},"https://docs.gitlab.com/ci/yaml/#parallelmatrix",[],"parallel:matrix"," ». Cela nous permet de tester notre application à travers diverses combinaisons en parallèle dans un seul job. Maintenant, testons notre code avec différentes versions de Python et avec le mot-clé « matrix\n».",[36,1834,1836],{"className":105,"code":1835,"language":107,"meta":41,"style":41},"python-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",[43,1837,1838,1845,1855,1864,1870,1877,1884,1891,1898,1905],{"__ignoreMap":41},[46,1839,1840,1843],{"class":48,"line":49},[46,1841,1842],{"class":114},"python-req",[46,1844,119],{"class":118},[46,1846,1847,1850,1852],{"class":48,"line":122},[46,1848,1849],{"class":114},"  image",[46,1851,128],{"class":118},[46,1853,1854],{"class":56},"python:$VERSION\n",[46,1856,1857,1859,1861],{"class":48,"line":197},[46,1858,418],{"class":114},[46,1860,128],{"class":118},[46,1862,1863],{"class":56},"lint\n",[46,1865,1866,1868],{"class":48,"line":206},[46,1867,125],{"class":114},[46,1869,119],{"class":118},[46,1871,1872,1874],{"class":48,"line":214},[46,1873,354],{"class":118},[46,1875,1876],{"class":56},"pip install -r requirements_dev.txt\n",[46,1878,1879,1881],{"class":48,"line":335},[46,1880,354],{"class":118},[46,1882,1883],{"class":56},"chmod +x ./build_cpp.sh\n",[46,1885,1886,1888],{"class":48,"line":343},[46,1887,354],{"class":118},[46,1889,1890],{"class":56},"./build_cpp.sh\n",[46,1892,1893,1896],{"class":48,"line":351},[46,1894,1895],{"class":114},"  parallel",[46,1897,119],{"class":118},[46,1899,1900,1903],{"class":48,"line":437},[46,1901,1902],{"class":114},"    matrix",[46,1904,119],{"class":118},[46,1906,1907,1909,1912,1914,1917,1919,1922,1924,1927,1929,1932,1935],{"class":48,"line":444},[46,1908,200],{"class":118},[46,1910,1911],{"class":114},"VERSION",[46,1913,1233],{"class":118},[46,1915,1916],{"class":56},"'3.8'",[46,1918,813],{"class":118},[46,1920,1921],{"class":56},"'3.9'",[46,1923,813],{"class":118},[46,1925,1926],{"class":56},"'3.10'",[46,1928,813],{"class":118},[46,1930,1931],{"class":56},"'3.11'",[46,1933,1934],{"class":118},"]   ",[46,1936,1937],{"class":909},"# https://hub.docker.com/_/python\n",[12,1939,1940],{},"Lors de l'exécution du pipeline, ce job s'exécute en parallèle quatre fois, chaque fois en utilisant une image Python différente comme indiqué ci-dessous :",[12,1942,1943],{},[138,1944],{"alt":1945,"src":1946},"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",[1661,1948,1950],{"id":1949},"tests-unitaires","Tests unitaires",[1952,1953,1955],"h4",{"id":1954},"que-sont-les-tests-unitaires","Que sont les tests unitaires ?",[12,1957,1958],{},"Les tests unitaires sont des tests ciblés et de petite envergure qui vérifient des composants ou des fonctions d'un logiciel. Ces tests permettent d'assurer qu'il fonctionne comme prévu. Ils sont essentiels pour vérifier que chaque partie du code fonctionne correctement et permettent de détecter les bogues le plus tôt possible dans le processus de développement logiciel.",[12,1960,1961],{},"Exemple : imaginez que vous développiez une application de calculatrice. Un test unitaire pour la fonction « addition » va vérifier si le résultat d'un calcul comme 2 + 2 est bien égale à 4. Si ce test est concluant, nous avons confirmation que la fonction « addition » fonctionne correctement.",[1952,1963,1965],{"id":1964},"tests-unitaires-les-bonnes-pratiques","Tests unitaires : les bonnes pratiques",[12,1967,1968],{},"Mettre en place des tests unitaires, c'est bien, mais il est possible d'aller encore plus loin pour faciliter la vie de vos équipes de développement.",[12,1970,1971],{},"Par 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 trouver et de corriger les erreurs. Ce processus est long et pourrait être optimisé.",[12,1973,1974,1975,1981],{},"Il est possible de configurer votre job pour qu'il utilise des ",[16,1976,1980],{"href":1977,"rel":1978,"title":1979},"https://docs.gitlab.com/ci/testing/unit_test_reports/",[],"Rapports de tests unitaires","rapports de tests unitaires"," (rapports détaillés des erreurs permettant de les traiter plus efficacement). GitLab affiche ces rapports dans la merge request et sur la page de détails des pipelines CI. Cela facilite l'identification des échecs, car il n'y a alors plus besoin de consulter l'intégralité du journal.",[1952,1983,1985],{"id":1984},"rapport-de-test-junit","Rapport de test JUnit",[12,1987,1988],{},"Ci-dessous un exemple de rapport de test JUnit :",[12,1990,1991,1995],{},[138,1992],{"alt":1993,"src":1994},"Rapport de test JUnit dans un pipeline d'intégration continue","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674097/Blog/Content%20Images/pipelines_junit_test_report_v13_10.png","{:\n.shadow.center}",[1661,1997,1999],{"id":1998},"stratégies-dintégration-et-de-tests-de-bout-en-bout","Stratégies d'intégration et de tests de bout en bout",[12,2001,2002,2003,2009],{},"Afin de s'assurer que toutes les parties de notre code fonctionnent en harmonie (y compris les ",[16,2004,2008],{"href":2005,"rel":2006,"title":2007},"https://about.gitlab.com/fr-fr/topics/microservices/",[],"Que sont les microservices ?","microservices",", les tests d'interface utilisateur), il est capital de configurer un pipeline dédié à l'intégration et aux tests de bout en bout.",[12,2011,2012,2013,2018,2019,2024],{},"Ces tests sont exécutés ",[16,2014,2017],{"href":2015,"rel":2016},"https://docs.gitlab.com/ci/pipelines/schedules/",[],"chaque nuit"," et il est possible de configurer le système pour que les ",[16,2020,2023],{"href":2021,"rel":2022},"https://docs.gitlab.com/user/project/integrations/gitlab_slack_application/#notification-events",[],"résultats soient automatiquement envoyés vers un canal Slack dédié",".\nAinsi, lorsque les équipes de développement arrivent le matin, elles peuvent rapidement travailler sur les problèmes identifiés la veille. L'objectif étant de détecter et de corriger les problèmes le plus tôt possible dans le processus de développement logiciel.",[1661,2026,2028],{"id":2027},"environnement-de-test","Environnement de test",[12,2030,2031],{},"Dans certains cas, nous avons besoin d'un environnement dédié pour tester correctement nos applications. On parle alors d'environnement de test. Avec le pipeline CI/CD de GitLab, nous pouvons automatiser le déploiement des environnements de test, et ainsi gagner un temps considérable.",[12,2033,2034,2035,173],{},"Comme cet article se concentre principalement sur les pipelines d'intégration continue, nous ne nous attarderons pas sur ce point ici. En revanche, libre à vous de consulter la section dédiée à ce sujet dans la ",[16,2036,2039],{"href":2037,"rel":2038},"https://docs.gitlab.com/topics/release_your_application/",[],"documentation\nGitLab",[92,2041,2043],{"id":2042},"implémenter-des-scans-de-sécurité-dans-un-pipeline-ci","Implémenter des scans de sécurité dans un pipeline CI",[12,2045,2046],{},"Voici comment mettre en œuvre des scans de sécurité dans un pipeline CI.",[1661,2048,2050],{"id":2049},"intégration-des-sast-et-des-dast","Intégration des SAST et des DAST",[12,2052,2053],{},"Avant toute chose, nous souhaitons garder notre code en sécurité. S'il y a la moindre vulnérabilité dans nos dernières modifications, nous voulons en être informés dès que possible. C'est pourquoi il est judicieux d'ajouter des scans de sécurité à votre pipeline CI.",[12,2055,2056],{},"Ces scans vérifient le code à chaque commit et vous alertent dès qu'une faille est détectée.",[12,2058,2059],{},"Il existe deux types de scan :",[722,2061,2062,2071],{},[725,2063,2064,2065,2070],{},"les tests statiques de sécurité des applications\n(",[16,2066,2069],{"href":2067,"rel":2068,"title":2069},"https://docs.gitlab.com/user/application_security/sast/",[],"SAST",")",[725,2072,2073,2074,2070],{},"les tests dynamiques de sécurité des applications\n(",[16,2075,2078],{"href":2076,"rel":2077,"title":2078},"https://docs.gitlab.com/user/application_security/dast/",[],"DAST",[12,2080,2081],{},"Ci-dessous, consultez notre guide interactif qui vous montre comment ajouter des scans de sécurité à votre pipeline CI.",[12,2083,2084],{},"Cliquez sur l'image ci-dessous pour commencer.",[12,2086,2087],{},[16,2088,2091],{"href":2089,"rel":2090},"https://gitlab.navattic.com/gitlab-scans",[],[138,2092],{"alt":2093,"src":2094},"Scans product tour","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-14_at_13.44.42.png",[12,2096,2097],{},"Grâce à l'IA et à ses capacités d'analyse, nous pouvons également obtenir des suggestions sur la manière dont les vulnérabilités peuvent être corrigées. Consultez cette démonstration pour plus d'informations.",[12,2099,2084],{},[12,2101,2102],{},[16,2103,2106],{"href":2104,"rel":2105},"https://tech-marketing.gitlab.io/static-demos/pt-explain-vulnerability.html",[],[138,2107],{"alt":2108,"src":2109},"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",[92,2111,2113],{"id":2112},"récapitulatif","Récapitulatif",[12,2115,2116],{},"Dans cet article, nous avons volontairement simplifié les exemples afin de faciliter l'intégration des différents concepts de GitLab CI.",[12,2118,2119],{},"Résumons rapidement ce que nous avons appris :",[2121,2122,2123,2134,2137,2140,2143,2146],"ol",{},[725,2124,2125,2126,2131,2132,173],{},"Pour déléguer certaines tâches à GitLab CI, vous devez définir un ou\nplusieurs ",[16,2127,2130],{"href":2128,"rel":2129},"https://docs.gitlab.com/ci/jobs/",[],"jobs"," dans ",[43,2133,101],{},[725,2135,2136],{},"Les jobs doivent avoir des noms, de préférence facilement identifiables.",[725,2138,2139],{},"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.",[725,2141,2142],{},"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.",[725,2144,2145],{},"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 l'interface de GitLab CI.",[725,2147,2148,2149,2155],{},"Ajoutez ",[16,2150,2154],{"href":2151,"rel":2152,"title":2153},"https://docs.gitlab.com/development/integrations/secure/",[],"Tests et scans de sécurité","des tests et des scans de\nsécurité"," au pipeline CI pour garantir la qualité et la sécurité de votre application.",[12,2157,2158],{},"Ci-dessous se trouvent des descriptions des termes et des mots-clés que nous avons abordés dans cet article.",[1661,2160,2162],{"id":2161},"mots-clés-descriptions-et-documentation","Mots-clés, descriptions et documentation",[12,2164,2165],{},"{: #keywords}",[2167,2168,2169,2182],"table",{},[2170,2171,2172],"thead",{},[2173,2174,2175,2179],"tr",{},[2176,2177,2178],"th",{},"Mots-clés/termes",[2176,2180,2181],{},"Description",[2183,2184,2185,2197,2208,2219,2230,2243,2255,2267,2278],"tbody",{},[2173,2186,2187,2194],{},[2188,2189,2190],"td",{},[16,2191,101],{"href":2192,"rel":2193},"https://docs.gitlab.com/ci/yaml/",[],[2188,2195,2196],{},"Fichier contenant toutes les explications sur la façon dont votre projet doit être construit",[2173,2198,2199,2205],{},[2188,2200,2201],{},[16,2202,217],{"href":2203,"rel":2204},"https://docs.gitlab.com/ci/yaml/#script",[],[2188,2206,2207],{},"Définit un script shell à exécuter",[2173,2209,2210,2216],{},[2188,2211,2212],{},[16,2213,192],{"href":2214,"rel":2215},"https://docs.gitlab.com/ci/yaml/#before_script",[],[2188,2217,2218],{},"Utilisé pour définir la commande qui doit être exécutée avant tous les jobs",[2173,2220,2221,2227],{},[2188,2222,2223],{},[16,2224,867],{"href":2225,"rel":2226},"https://docs.gitlab.com/ci/docker/using_docker_images/#what-is-image",[],[2188,2228,2229],{},"Définit l’image Docker à utiliser",[2173,2231,2232,2238],{},[2188,2233,2234],{},[16,2235,386],{"href":2236,"rel":2237},"https://docs.gitlab.com/ci/yaml/#stages",[],[2188,2239,2240,2241,2070],{},"Définit une étape du pipeline CI (par défaut : ",[43,2242,115],{},[2173,2244,2245,2252],{},[2188,2246,2247],{},[16,2248,2251],{"href":2249,"rel":2250},"https://docs.gitlab.com/ci/yaml/#artifacts",[],"artifacts",[2188,2253,2254],{},"Définit une liste d'artefacts de compilation",[2173,2256,2257,2264],{},[2188,2258,2259],{},[16,2260,2263],{"href":2261,"rel":2262},"https://docs.gitlab.com/ci/yaml/#artifactsexpire_in",[],"artifacts:expire_in",[2188,2265,2266],{},"Utilisé pour supprimer les artefacts téléchargés après une durée spécifiée",[2173,2268,2269,2275],{},[2188,2270,2271],{},[16,2272,1194],{"href":2273,"rel":2274},"https://docs.gitlab.com/ci/yaml/#needs",[],[2188,2276,2277],{},"Permet de définir les dépendances entre les jobs et permet d'exécuter des jobs dans l'ordre de votre choix",[2173,2279,2280,2286],{},[2188,2281,2282],{},[16,2283,2285],{"href":1174,"rel":2284},[],"pipelines",[2188,2287,2288],{},"Un pipeline est un groupe de compilations exécutées par étapes (batch)",[92,2290,2292],{"id":2291},"en-savoir-plus-sur-les-pipelines-cicd","En savoir plus sur les pipelines CI/CD",[722,2294,2295,2303,2310,2316,2323],{},[725,2296,2297],{},[16,2298,2302],{"href":2299,"rel":2300,"title":2301},"https://about.gitlab.com/fr-fr/blog/how-to-keep-up-with-ci-cd-best-practices/",[],"Quelles sont les meilleures pratiques CI/CD à connaître ?","Quelles sont les meilleures pratiques CI/CD à connaître\n?",[725,2304,2305],{},[16,2306,2309],{"href":2307,"rel":2308},"https://about.gitlab.com/blog/beginner-guide-ci-cd/",[],"Le guide CI/CD de GitLab pour les\ndébutants",[725,2311,2312],{},[16,2313,2315],{"href":1184,"rel":2314},[],"Obtenez des pipelines plus rapides et plus flexibles avec un graphe\nacyclique orienté",[725,2317,2318],{},[16,2319,2322],{"href":2320,"rel":2321},"http://beenje.github.io/blog/posts/gitlab-ci-and-conda/",[],"Réduisez le temps de compilation avec une image Docker\npersonnalisée",[725,2324,2325],{},[16,2326,2329],{"href":2327,"rel":2328},"https://about.gitlab.com/blog/introducing-the-gitlab-ci-cd-catalog-beta/",[],"Présentation de la version bêta du catalogue GitLab\nCI/CD",[92,2331,2333],{"id":2332},"faq-sur-le-pipeline-dintégration-continue","FAQ sur le pipeline d’intégration continue",[1661,2335,2337],{"id":2336},"comment-choisir-entre-lexécution-séquentielle-et-parallèle-des-jobs","Comment choisir entre l'exécution séquentielle et parallèle des jobs",[12,2339,2340],{},"dans un pipeline CI ?",[12,2342,2343],{},"Il y a plusieurs considérations à prendre en compte pour choisir entre l'exécution séquentielle et parallèle des jobs dans un pipeline CI. Ainsi, il faut considérer les dépendances entre les jobs, la disponibilité des ressources, les temps d'exécution, les interférences potentielles, la structure de la séquence de tests ou encore les coûts que cela implique.",[12,2345,2346],{},"Par exemple, si vous avez un job de compilation qui doit se terminer avant qu'un job de déploiement puisse démarrer, vous exécuterez ces jobs de manière séquentielle pour garantir le bon ordre d'exécution. En revanche, les tâches telles que les tests unitaires et les tests d'intégration peuvent généralement s'exécuter en parallèle, car elles ne dépendent pas de l'achèvement des autres.",[1661,2348,2350],{"id":2349},"que-sont-les-graphes-acycliques-orientés-dans-gitlab-et-comment","Que sont les graphes acycliques orientés dans GitLab et comment",[12,2352,2353],{},"améliorent-ils la flexibilité du pipeline CI ?",[12,2355,2356],{},"Un graphe acyclique orienté dans un pipeline CI permet d'exécuter des jobs en fonction de leurs dépendances, plutôt que dans un ordre strictement séquentiel. Ce graphe vous permet ainsi de définir un ordre d'exécution des jobs pour que ceux des étapes ultérieures commencent dès que les jobs des étapes précédentes se terminent. Cela réduit le temps d'exécution global du pipeline, améliore l'efficacité et laisse même à certains jobs la possibilité de se terminer plus tôt que s'ils avaient été exécutés dans un ordre purement séquentiel (du premier au dernier dans la liste).",[1661,2358,2360],{"id":2359},"pourquoi-est-il-important-de-choisir-la-bonne-image-docker-pour-les-jobs","Pourquoi est-il important de choisir la bonne image Docker pour les jobs",[12,2362,2363],{},"d'un pipeline CI GitLab ?",[12,2365,2366],{},"GitLab utilise des images Docker pour exécuter des jobs dont l'image par défaut est ruby 3.1. Pour optimiser votre pipeline CI, il sera cependant crucial de choisir l'image la plus appropriée à vos besoins. Comprenez que les jobs téléchargent d'abord l'image Docker spécifiée. Si l'image contient des paquets supplémentaires inutiles, cela augmentera les temps de téléchargement et d'exécution. Il est donc important de s'assurer que l'image choisie contient uniquement les paquets essentiels afin d'éviter des retards inutiles dans l'exécution des jobs.",[1661,2368,2370],{"id":2369},"prochaines-étapes","Prochaines étapes",[12,2372,2373],{},"Pour moderniser davantage vos pratiques de développement logiciel, consultez le catalogue GitLab\nCI/CD\npour savoir comment standardiser et réutiliser les composants CI/CD.",[2375,2376,2377],"style",{},"html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .shJU0, html code.shiki .shJU0{--shiki-default:#22863A}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}",{"title":41,"searchDepth":122,"depth":122,"links":2379},[2380,2381,2382,2383,2384,2385,2386,2387,2394,2397,2400,2401],{"id":94,"depth":122,"text":95},{"id":227,"depth":122,"text":228},{"id":372,"depth":122,"text":373},{"id":736,"depth":122,"text":737},{"id":836,"depth":122,"text":837},{"id":1034,"depth":122,"text":1035},{"id":1161,"depth":122,"text":1162},{"id":1655,"depth":122,"text":1656,"children":2388},[2389,2390,2391,2392,2393],{"id":1663,"depth":197,"text":1664},{"id":1822,"depth":197,"text":1823},{"id":1949,"depth":197,"text":1950},{"id":1998,"depth":197,"text":1999},{"id":2027,"depth":197,"text":2028},{"id":2042,"depth":122,"text":2043,"children":2395},[2396],{"id":2049,"depth":197,"text":2050},{"id":2112,"depth":122,"text":2113,"children":2398},[2399],{"id":2161,"depth":197,"text":2162},{"id":2291,"depth":122,"text":2292},{"id":2332,"depth":122,"text":2333,"children":2402},[2403,2404,2405,2406],{"id":2336,"depth":197,"text":2337},{"id":2349,"depth":197,"text":2350},{"id":2359,"depth":197,"text":2360},{"id":2369,"depth":197,"text":2370},"engineering","2020-12-10","Vous débutez dans l'intégration continue ? Apprenez à créer votre premier pipeline CI avec GitLab. Lisez notre guide complet.","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662061/Blog/Hero%20Images/cicdcover.png",{},"/fr-fr/blog/basics-of-gitlab-ci-updated",{"ogTitle":5,"ogImage":2413,"ogDescription":2409,"ogSiteName":2417,"noIndex":2412,"ogType":2418,"ogUrl":2419,"title":5,"canonicalUrls":2419,"description":2409},"https://about.gitlab.com","article","https://about.gitlab.com/blog/basics-of-gitlab-ci-updated","basics-of-gitlab-ci-updated","fr-fr/blog/basics-of-gitlab-ci-updated",[2423,2424],"CI","tutorial","BlogPost","2025-01-07","_NzyDUdNXxjH9MCEpYRO0O_BYszEmnh2q6Z1NTYJIM8",{"logo":2429,"freeTrial":2434,"sales":2439,"login":2444,"items":2449,"search":2777,"minimal":2813,"duo":2832,"switchNav":2841,"pricingDeployment":2852},{"config":2430},{"href":2431,"dataGaName":2432,"dataGaLocation":2433},"/fr-fr/","gitlab logo","header",{"text":2435,"config":2436},"Commencer un essai gratuit",{"href":2437,"dataGaName":2438,"dataGaLocation":2433},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/fr-fr&glm_content=default-saas-trial/","free trial",{"text":2440,"config":2441},"Demander une démo",{"href":2442,"dataGaName":2443,"dataGaLocation":2433},"/fr-fr/sales/?contact-topic=request-demo","sales",{"text":2445,"config":2446},"Connexion",{"href":2447,"dataGaName":2448,"dataGaLocation":2433},"https://gitlab.com/users/sign_in/","sign in",[2450,2479,2581,2586,2700,2755],{"text":2451,"config":2452,"menu":2454},"Plateforme",{"dataNavLevelOne":2453},"platform",{"type":2455,"columns":2456},"cards",[2457,2463,2471],{"title":2451,"description":2458,"link":2459},"La plateforme d'orchestration intelligente pour le DevSecOps",{"text":2460,"config":2461},"Explorer notre plateforme",{"href":2462,"dataGaName":2453,"dataGaLocation":2433},"/fr-fr/platform/",{"title":2464,"description":2465,"link":2466},"GitLab Duo Agent Platform","L'IA agentique pour l'ensemble du cycle de développement logiciel",{"text":2467,"config":2468},"Découvrir GitLab Duo",{"href":2469,"dataGaName":2470,"dataGaLocation":2433},"/fr-fr/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":2472,"description":2473,"link":2474},"Pourquoi GitLab ?","Découvrez les principales raisons pour lesquelles les entreprises choisissent GitLab",{"text":2475,"config":2476},"En savoir plus",{"href":2477,"dataGaName":2478,"dataGaLocation":2433},"/fr-fr/why-gitlab/","why gitlab",{"text":2480,"left":261,"config":2481,"menu":2483},"Produit",{"dataNavLevelOne":2482},"solutions",{"type":2484,"link":2485,"columns":2489,"feature":2560},"lists",{"text":2486,"config":2487},"Voir toutes les solutions",{"href":2488,"dataGaName":2482,"dataGaLocation":2433},"/fr-fr/solutions/",[2490,2515,2538],{"title":2491,"description":2492,"link":2493,"items":2498},"Automatisation","CI/CD et automatisation pour accélérer le déploiement",{"config":2494},{"icon":2495,"href":2496,"dataGaName":2497,"dataGaLocation":2433},"AutomatedCodeAlt","/fr-fr/solutions/delivery-automation/","automated software delivery",[2499,2503,2506,2511],{"text":2500,"config":2501},"CI/CD",{"href":2502,"dataGaLocation":2433,"dataGaName":2500},"/fr-fr/solutions/continuous-integration/",{"text":2464,"config":2504},{"href":2469,"dataGaLocation":2433,"dataGaName":2505},"gitlab duo agent platform - product menu",{"text":2507,"config":2508},"Gestion du code source",{"href":2509,"dataGaLocation":2433,"dataGaName":2510},"/fr-fr/solutions/source-code-management/","Source Code Management",{"text":2512,"config":2513},"Livraison de logiciels automatisée",{"href":2496,"dataGaLocation":2433,"dataGaName":2514},"Automated software delivery",{"title":2516,"description":2517,"link":2518,"items":2523},"Sécurité","Livrez du code plus rapidement sans compromettre la sécurité",{"config":2519},{"href":2520,"dataGaName":2521,"dataGaLocation":2433,"icon":2522},"/fr-fr/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[2524,2528,2533],{"text":2525,"config":2526},"Tests de sécurité des applications",{"href":2520,"dataGaName":2527,"dataGaLocation":2433},"Application security testing",{"text":2529,"config":2530},"Sécurité de la chaîne d'approvisionnement logicielle",{"href":2531,"dataGaLocation":2433,"dataGaName":2532},"/fr-fr/solutions/supply-chain/","Software supply chain security",{"text":2534,"config":2535},"Conformité logicielle",{"href":2536,"dataGaName":2537,"dataGaLocation":2433},"/fr-fr/solutions/software-compliance/","software compliance",{"title":2539,"link":2540,"items":2545},"Mesures",{"config":2541},{"icon":2542,"href":2543,"dataGaName":2544,"dataGaLocation":2433},"DigitalTransformation","/fr-fr/solutions/visibility-measurement/","visibility and measurement",[2546,2550,2555],{"text":2547,"config":2548},"Visibilité et mesures",{"href":2543,"dataGaLocation":2433,"dataGaName":2549},"Visibility and Measurement",{"text":2551,"config":2552},"Gestion de la chaîne de valeur",{"href":2553,"dataGaLocation":2433,"dataGaName":2554},"/fr-fr/solutions/value-stream-management/","Value Stream Management",{"text":2556,"config":2557},"Analyses et informations",{"href":2558,"dataGaLocation":2433,"dataGaName":2559},"/fr-fr/solutions/analytics-and-insights/","Analytics and insights",{"title":2561,"type":2484,"items":2562},"GitLab",[2563,2569,2575],{"text":2564,"config":2565},"Entreprises",{"icon":2566,"href":2567,"dataGaLocation":2433,"dataGaName":2568},"Building","/fr-fr/enterprise/","enterprise",{"text":2570,"config":2571},"Pour les PME",{"icon":2572,"href":2573,"dataGaLocation":2433,"dataGaName":2574},"Work","/fr-fr/small-business/","small business",{"text":2576,"config":2577},"Pour le secteur public",{"icon":2578,"href":2579,"dataGaLocation":2433,"dataGaName":2580},"Organization","/fr-fr/solutions/public-sector/","public sector",{"text":2582,"config":2583},"Tarifs",{"href":2584,"dataGaName":2585,"dataGaLocation":2433,"dataNavLevelOne":2585},"/fr-fr/pricing/","pricing",{"text":2587,"config":2588,"menu":2590},"Ressources",{"dataNavLevelOne":2589},"resources",{"type":2484,"link":2591,"columns":2595,"feature":2689},{"text":2592,"config":2593},"Afficher toutes les ressources",{"href":2594,"dataGaName":2589,"dataGaLocation":2433},"/fr-fr/resources/",[2596,2629,2656],{"title":2597,"items":2598},"Premiers pas",[2599,2604,2609,2614,2619,2624],{"text":2600,"config":2601},"Installation",{"href":2602,"dataGaName":2603,"dataGaLocation":2433},"/fr-fr/install/","install",{"text":2605,"config":2606},"Guides de démarrage",{"href":2607,"dataGaName":2608,"dataGaLocation":2433},"/fr-fr/get-started/","quick setup checklists",{"text":2610,"config":2611},"Apprentissage",{"href":2612,"dataGaLocation":2433,"dataGaName":2613},"https://university.gitlab.com/","learn",{"text":2615,"config":2616},"Documentation",{"href":2617,"dataGaName":2618,"dataGaLocation":2433},"https://docs.gitlab.com/","product documentation",{"text":2620,"config":2621},"Vidéos sur les bonnes pratiques",{"href":2622,"dataGaName":2623,"dataGaLocation":2433},"/fr-fr/getting-started-videos/","best practice videos",{"text":2625,"config":2626},"Intégrations",{"href":2627,"dataGaName":2628,"dataGaLocation":2433},"/fr-fr/integrations/","integrations",{"title":2630,"items":2631},"Découvrir",[2632,2637,2642,2647,2651],{"text":2633,"config":2634},"Témoignages clients",{"href":2635,"dataGaName":2636,"dataGaLocation":2433},"/fr-fr/customers/","customer success stories",{"text":2638,"config":2639},"Blog",{"href":2640,"dataGaName":2641,"dataGaLocation":2433},"/fr-fr/blog/","blog",{"text":2643,"config":2644},"Demo Hub",{"href":2645,"dataGaName":2646,"dataGaLocation":2433},"/fr-fr/demo-hub/","demo hub",{"text":2648,"config":2649},"The Source",{"href":2650,"dataGaName":2641,"dataGaLocation":2433},"/fr-fr/the-source/",{"text":2652,"config":2653},"Travail à distance",{"href":2654,"dataGaName":2655,"dataGaLocation":2433},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":2657,"items":2658},"Connecter",[2659,2664,2669,2674,2679,2684],{"text":2660,"config":2661},"Services GitLab",{"href":2662,"dataGaName":2663,"dataGaLocation":2433},"/fr-fr/services/","services",{"text":2665,"config":2666},"Contribuer",{"href":2667,"dataGaName":2668,"dataGaLocation":2433},"https://contributors.gitlab.com","contribute",{"text":2670,"config":2671},"Communauté",{"href":2672,"dataGaName":2673,"dataGaLocation":2433},"/community/","community",{"text":2675,"config":2676},"Forum",{"href":2677,"dataGaName":2678,"dataGaLocation":2433},"https://forum.gitlab.com/","forum",{"text":2680,"config":2681},"Événements",{"href":2682,"dataGaName":2683,"dataGaLocation":2433},"/events/","events",{"text":2685,"config":2686},"Partenaires",{"href":2687,"dataGaName":2688,"dataGaLocation":2433},"/fr-fr/partners/","partners",{"config":2690,"title":2693,"text":2694,"link":2695},{"background":2691,"textColor":2692},"url('https://res.cloudinary.com/about-gitlab-com/image/upload/v1777322348/qpq8yrgn8knii57omj0c.png')","#000","Nouveautés de GitLab","Découvrez les dernières fonctionnalités et améliorations.",{"text":2696,"config":2697},"Lire les articles les plus récents",{"href":2698,"dataGaName":2699,"dataGaLocation":2433},"/fr-fr/whats-new/","whats new",{"text":2701,"config":2702,"menu":2704},"Société",{"dataNavLevelOne":2703},"company",{"type":2484,"columns":2705},[2706],{"items":2707},[2708,2713,2718,2720,2725,2730,2735,2740,2745,2750],{"text":2709,"config":2710},"À propos",{"href":2711,"dataGaName":2712,"dataGaLocation":2433},"/fr-fr/company/","about",{"text":2714,"config":2715,"footerGa":2717},"Carrières",{"href":2716,"dataGaName":2130,"dataGaLocation":2433},"/jobs/",{"dataGaName":2130},{"text":2680,"config":2719},{"href":2682,"dataGaName":2683,"dataGaLocation":2433},{"text":2721,"config":2722},"Leadership",{"href":2723,"dataGaName":2724,"dataGaLocation":2433},"/company/team/e-group/","leadership",{"text":2726,"config":2727},"Manuel",{"href":2728,"dataGaName":2729,"dataGaLocation":2433},"https://handbook.gitlab.com/","handbook",{"text":2731,"config":2732},"Relations avec les investisseurs",{"href":2733,"dataGaName":2734,"dataGaLocation":2433},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":2736,"config":2737},"Trust Center",{"href":2738,"dataGaName":2739,"dataGaLocation":2433},"/fr-fr/security/","trust center",{"text":2741,"config":2742},"Centre pour la transparence de l'IA",{"href":2743,"dataGaName":2744,"dataGaLocation":2433},"/fr-fr/ai-transparency-center/","ai transparency center",{"text":2746,"config":2747},"Newsletter",{"href":2748,"dataGaName":2749,"dataGaLocation":2433},"/company/contact/#contact-forms","newsletter",{"text":2751,"config":2752},"Presse",{"href":2753,"dataGaName":2754,"dataGaLocation":2433},"/press/","press",{"text":2756,"config":2757,"menu":2758},"Nous contacter",{"dataNavLevelOne":2703},{"type":2484,"columns":2759},[2760],{"items":2761},[2762,2767,2772],{"text":2763,"config":2764},"Contacter l'équipe commerciale",{"href":2765,"dataGaName":2766,"dataGaLocation":2433},"/fr-fr/sales/","talk to sales",{"text":2768,"config":2769},"Assistance GitLab",{"href":2770,"dataGaName":2771,"dataGaLocation":2433},"https://support.gitlab.com/hc/en-us","support portal",{"text":2773,"config":2774},"Portail clients GitLab",{"href":2775,"dataGaName":2776,"dataGaLocation":2433},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":2778,"login":2779,"suggestions":2786},"Fermer",{"text":2780,"link":2781},"Pour rechercher des dépôts et des projets, connectez-vous à",{"text":2782,"config":2783},"GitLab.com",{"href":2447,"dataGaName":2784,"dataGaLocation":2785},"search login","search",{"text":2787,"default":2788},"Suggestions",[2789,2792,2797,2799,2804,2809],{"text":2464,"config":2790},{"href":2469,"dataGaName":2791,"dataGaLocation":2785},"GitLab Duo Agent Platform",{"text":2793,"config":2794},"Suggestions de code (IA)",{"href":2795,"dataGaName":2796,"dataGaLocation":2785},"/fr-fr/solutions/code-suggestions/","Code Suggestions (AI)",{"text":2500,"config":2798},{"href":2502,"dataGaName":2500,"dataGaLocation":2785},{"text":2800,"config":2801},"GitLab sur AWS",{"href":2802,"dataGaName":2803,"dataGaLocation":2785},"/fr-fr/partners/technology-partners/aws/","GitLab on AWS",{"text":2805,"config":2806},"GitLab sur Google Cloud",{"href":2807,"dataGaName":2808,"dataGaLocation":2785},"/fr-fr/partners/technology-partners/google-cloud-platform/","GitLab on Google Cloud",{"text":2810,"config":2811},"Pourquoi utiliser GitLab ?",{"href":2477,"dataGaName":2812,"dataGaLocation":2785},"Why GitLab?",{"freeTrial":2814,"mobileIcon":2819,"desktopIcon":2824,"secondaryButton":2827},{"text":2815,"config":2816},"Commencer votre essai gratuit",{"href":2817,"dataGaName":2438,"dataGaLocation":2818},"https://gitlab.com/-/trials/new/","nav",{"altText":2820,"config":2821},"Icône GitLab",{"src":2822,"dataGaName":2823,"dataGaLocation":2818},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":2820,"config":2825},{"src":2826,"dataGaName":2823,"dataGaLocation":2818},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":2828,"config":2829},"Commencer",{"href":2830,"dataGaName":2831,"dataGaLocation":2818},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/fr-fr/get-started/","get started",{"freeTrial":2833,"mobileIcon":2837,"desktopIcon":2839},{"text":2834,"config":2835},"En savoir plus sur GitLab Duo",{"href":2469,"dataGaName":2836,"dataGaLocation":2818},"gitlab duo",{"altText":2820,"config":2838},{"src":2822,"dataGaName":2823,"dataGaLocation":2818},{"altText":2820,"config":2840},{"src":2826,"dataGaName":2823,"dataGaLocation":2818},{"button":2842,"mobileIcon":2847,"desktopIcon":2849},{"text":2843,"config":2844},"/switch",{"href":2845,"dataGaName":2846,"dataGaLocation":2818},"#contact","switch",{"altText":2820,"config":2848},{"src":2822,"dataGaName":2823,"dataGaLocation":2818},{"altText":2820,"config":2850},{"src":2851,"dataGaName":2823,"dataGaLocation":2818},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":2853,"mobileIcon":2858,"desktopIcon":2860},{"text":2854,"config":2855},"Retour aux tarifs",{"href":2584,"dataGaName":2856,"dataGaLocation":2818,"icon":2857},"back to pricing","GoBack",{"altText":2820,"config":2859},{"src":2822,"dataGaName":2823,"dataGaLocation":2818},{"altText":2820,"config":2861},{"src":2826,"dataGaName":2823,"dataGaLocation":2818},{"title":2863,"button":2864,"config":2868},"GitLab Orbit est arrivé : la couche de contexte pour les agents d'IA.",{"text":2475,"config":2865},{"href":2866,"dataGaName":2867,"dataGaLocation":2433},"/fr-fr/gitlab-orbit/","orbit",{"layout":2869,"disabled":2412},"release",{"data":2871},{"text":2872,"source":2873,"edit":2879,"contribute":2884,"config":2888,"items":2893,"minimal":3100},"Git est une marque déposée de Software Freedom Conservancy et notre utilisation de « GitLab » est sous licence.",{"text":2874,"config":2875},"Afficher le code source de la page",{"href":2876,"dataGaName":2877,"dataGaLocation":2878},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":2880,"config":2881},"Modifier cette page",{"href":2882,"dataGaName":2883,"dataGaLocation":2878},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":2665,"config":2885},{"href":2886,"dataGaName":2887,"dataGaLocation":2878},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":2889,"facebook":2890,"youtube":2891,"linkedin":2892},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[2894,2940,2992,3035,3067],{"title":2582,"links":2895,"subMenu":2910},[2896,2900,2905],{"text":2897,"config":2898},"Voir les forfaits",{"href":2584,"dataGaName":2899,"dataGaLocation":2878},"view plans",{"text":2901,"config":2902},"GitLab Premium",{"href":2903,"dataGaName":2904,"dataGaLocation":2878},"/fr-fr/pricing/premium/","why premium",{"text":2906,"config":2907},"GitLab Ultimate",{"href":2908,"dataGaName":2909,"dataGaLocation":2878},"/fr-fr/pricing/ultimate/","why ultimate",[2911],{"title":2756,"links":2912},[2913,2915,2917,2920,2925,2930,2935],{"text":2763,"config":2914},{"href":2765,"dataGaName":2443,"dataGaLocation":2878},{"text":2768,"config":2916},{"href":2770,"dataGaName":2771,"dataGaLocation":2878},{"text":2918,"config":2919},"Portail clients",{"href":2775,"dataGaName":2776,"dataGaLocation":2878},{"text":2921,"config":2922},"Statut",{"href":2923,"dataGaName":2924,"dataGaLocation":2878},"https://status.gitlab.com/","status",{"text":2926,"config":2927},"Conditions d'utilisation",{"href":2928,"dataGaName":2929,"dataGaLocation":2878},"/terms/","terms of use",{"text":2931,"config":2932},"Politique de confidentialité",{"href":2933,"dataGaName":2934,"dataGaLocation":2878},"/fr-fr/privacy/","privacy statement",{"text":2936,"config":2937},"Gestion des cookies",{"dataGaName":2938,"dataGaLocation":2878,"id":2939,"isOneTrustButton":261},"cookie preferences","ot-sdk-btn",{"title":2480,"links":2941,"subMenu":2950},[2942,2946],{"text":2943,"config":2944},"Plateforme DevSecOps",{"href":2462,"dataGaName":2945,"dataGaLocation":2878},"devsecops platform",{"text":2947,"config":2948},"Développement assisté par l'IA",{"href":2469,"dataGaName":2949,"dataGaLocation":2878},"ai-assisted development",[2951],{"title":2952,"links":2953},"Thèmes",[2954,2958,2963,2967,2972,2977,2982,2987],{"text":2500,"config":2955},{"href":2956,"dataGaName":2957,"dataGaLocation":2878},"/fr-fr/topics/ci-cd/","cicd",{"text":2959,"config":2960},"GitOps",{"href":2961,"dataGaName":2962,"dataGaLocation":2878},"/fr-fr/topics/gitops/","gitops",{"text":172,"config":2964},{"href":2965,"dataGaName":2966,"dataGaLocation":2878},"/fr-fr/topics/devops/","devops",{"text":2968,"config":2969},"Contrôle de version",{"href":2970,"dataGaName":2971,"dataGaLocation":2878},"/fr-fr/topics/version-control/","version control",{"text":2973,"config":2974},"DevSecOps",{"href":2975,"dataGaName":2976,"dataGaLocation":2878},"/fr-fr/topics/devsecops/","devsecops",{"text":2978,"config":2979},"Cloud-native",{"href":2980,"dataGaName":2981,"dataGaLocation":2878},"/fr-fr/topics/cloud-native/","cloud native",{"text":2983,"config":2984},"IA pour la programmation",{"href":2985,"dataGaName":2986,"dataGaLocation":2878},"/fr-fr/topics/devops/ai-for-coding/","ai for coding",{"text":2988,"config":2989},"IA agentique",{"href":2990,"dataGaName":2991,"dataGaLocation":2878},"/fr-fr/topics/agentic-ai/","agentic ai",{"title":2993,"links":2994},"Solutions",[2995,2998,3000,3005,3008,3011,3014,3017,3019,3022,3025,3030],{"text":2525,"config":2996},{"href":2520,"dataGaName":2997,"dataGaLocation":2878},"Application Security Testing",{"text":2512,"config":2999},{"href":2496,"dataGaName":2497,"dataGaLocation":2878},{"text":3001,"config":3002},"Développement Agile",{"href":3003,"dataGaName":3004,"dataGaLocation":2878},"/fr-fr/solutions/agile-delivery/","agile delivery",{"text":2507,"config":3006},{"href":2509,"dataGaName":3007,"dataGaLocation":2878},"source code management",{"text":2500,"config":3009},{"href":2502,"dataGaName":3010,"dataGaLocation":2878},"continuous integration & delivery",{"text":2551,"config":3012},{"href":2553,"dataGaName":3013,"dataGaLocation":2878},"value stream management",{"text":2959,"config":3015},{"href":3016,"dataGaName":2962,"dataGaLocation":2878},"/fr-fr/solutions/gitops/",{"text":2564,"config":3018},{"href":2567,"dataGaName":2568,"dataGaLocation":2878},{"text":3020,"config":3021},"PME",{"href":2573,"dataGaName":2574,"dataGaLocation":2878},{"text":3023,"config":3024},"Secteur public",{"href":2579,"dataGaName":2580,"dataGaLocation":2878},{"text":3026,"config":3027},"Éducation",{"href":3028,"dataGaName":3029,"dataGaLocation":2878},"/fr-fr/solutions/education/","education",{"text":3031,"config":3032},"Services financiers",{"href":3033,"dataGaName":3034,"dataGaLocation":2878},"/fr-fr/solutions/finance/","financial services",{"title":2587,"links":3036},[3037,3039,3041,3043,3046,3048,3051,3053,3055,3057,3059,3061,3063,3065],{"text":2600,"config":3038},{"href":2602,"dataGaName":2603,"dataGaLocation":2878},{"text":2605,"config":3040},{"href":2607,"dataGaName":2608,"dataGaLocation":2878},{"text":2610,"config":3042},{"href":2612,"dataGaName":2613,"dataGaLocation":2878},{"text":2615,"config":3044},{"href":2617,"dataGaName":3045,"dataGaLocation":2878},"docs",{"text":2638,"config":3047},{"href":2640,"dataGaName":2641,"dataGaLocation":2878},{"text":3049,"config":3050},"Nouveautés",{"href":2698,"dataGaName":2699,"dataGaLocation":2878},{"text":2633,"config":3052},{"href":2635,"dataGaName":2636,"dataGaLocation":2878},{"text":2652,"config":3054},{"href":2654,"dataGaName":2655,"dataGaLocation":2878},{"text":2660,"config":3056},{"href":2662,"dataGaName":2663,"dataGaLocation":2878},{"text":2665,"config":3058},{"href":2667,"dataGaName":2668,"dataGaLocation":2878},{"text":2670,"config":3060},{"href":2672,"dataGaName":2673,"dataGaLocation":2878},{"text":2675,"config":3062},{"href":2677,"dataGaName":2678,"dataGaLocation":2878},{"text":2680,"config":3064},{"href":2682,"dataGaName":2683,"dataGaLocation":2878},{"text":2685,"config":3066},{"href":2687,"dataGaName":2688,"dataGaLocation":2878},{"title":2701,"links":3068},[3069,3071,3073,3075,3077,3079,3084,3089,3091,3093,3095],{"text":2709,"config":3070},{"href":2711,"dataGaName":2703,"dataGaLocation":2878},{"text":2714,"config":3072},{"href":2716,"dataGaName":2130,"dataGaLocation":2878},{"text":2721,"config":3074},{"href":2723,"dataGaName":2724,"dataGaLocation":2878},{"text":2726,"config":3076},{"href":2728,"dataGaName":2729,"dataGaLocation":2878},{"text":2731,"config":3078},{"href":2733,"dataGaName":2734,"dataGaLocation":2878},{"text":3080,"config":3081},"Développement durable",{"href":3082,"dataGaName":3083,"dataGaLocation":2878},"/sustainability/","Sustainability",{"text":3085,"config":3086},"Diversité, inclusion et appartenance (DIB)",{"href":3087,"dataGaName":3088,"dataGaLocation":2878},"/fr-fr/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":2736,"config":3090},{"href":2738,"dataGaName":2739,"dataGaLocation":2878},{"text":2746,"config":3092},{"href":2748,"dataGaName":2749,"dataGaLocation":2878},{"text":2751,"config":3094},{"href":2753,"dataGaName":2754,"dataGaLocation":2878},{"text":3096,"config":3097},"Déclaration de transparence sur l'esclavage moderne",{"href":3098,"dataGaName":3099,"dataGaLocation":2878},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":3101},[3102,3104,3106],{"text":2926,"config":3103},{"href":2928,"dataGaName":2929,"dataGaLocation":2878},{"text":2936,"config":3105},{"dataGaName":2938,"dataGaLocation":2878,"id":2939,"isOneTrustButton":261},{"text":2931,"config":3107},{"href":2933,"dataGaName":2934,"dataGaLocation":2878},[3109],{"id":3110,"title":7,"body":2411,"config":3111,"content":3113,"description":2411,"extension":1111,"meta":3117,"navigation":261,"path":3118,"seo":3119,"stem":3120,"__hash__":3121},"blogAuthors/en-us/blog/authors/itzik-gan-baruch.yml",{"template":3112},"BlogAuthor",{"name":7,"config":3114},{"headshot":3115,"ctfId":3116},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749658921/Blog/Author%20Headshots/iganbaruch-headshot.jpg","iganbaruch",{},"/en-us/blog/authors/itzik-gan-baruch",{},"en-us/blog/authors/itzik-gan-baruch","bz9VMiTQ1ixvnoxUFk0jiUcnLG3oQsymgXNCqyRqfsk",[3123,3131,3139],{"title":3124,"description":3125,"heroImage":3126,"category":2407,"date":3127,"authors":3128,"slug":3130,"externalUrl":2411},"Green DevOps : l'importance de mesurer le bilan carbone de vos pipelines CI/CD","Les pipelines CI/CD ont un bilan carbone caché. Découvrez pourquoi il est crucial de le mesurer et comment vous lancer avec Eco CI et Carmen dans GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1765809212/noh0mdfn9o94ry9ykura.png","2026-07-22",[3129],"Lysanne Pinto","green-devops-carbon-measurement-cicd-pipeline",{"title":3132,"description":3133,"heroImage":3134,"category":2407,"date":3135,"authors":3136,"slug":3138,"externalUrl":2411},"Comment mettre en place l'observabilité CI/CD à grande échelle","Ce guide pratique consacré à l'analyse des pipelines GitLab aide les utilisateurs de GitLab Self-Managed à obtenir des indicateurs opérationnels exploitables grâce à Prometheus et Grafana.","https://res.cloudinary.com/about-gitlab-com/image/upload/f_auto,q_auto,c_lfill/v1774465167/n5hlvrsrheadeccyr1oz.png","2026-05-18",[3137],"Paul Meresanu","how-to-build-ci-cd-observability-at-scale",{"title":3140,"description":3141,"heroImage":3142,"category":2407,"date":3143,"authors":3144,"slug":3146,"externalUrl":2411},"5 modèles de pipeline GitLab pour résoudre vos enjeux d'ingénierie","Découvrez comment faire évoluer votre approche CI/CD avec des modèles composables pour les monorepos, les microservices, les environnements et la gouvernance.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1772721753/frfsm1qfscwrmsyzj1qn.png","2026-05-06",[3145],"Omid Khan","5-ways-gitlab-pipeline-logic-solves-real-engineering-problems",{"promotions":3148},[3149,3163,3175,3187],{"id":3150,"categories":3151,"header":3153,"text":3154,"button":3155,"image":3160},"ai-modernization",[3152],"ai","L'IA tient-elle ses promesses à grande échelle ?","Le questionnaire ne prendra pas plus de 5 minutes.",{"text":3156,"config":3157},"Obtenez votre score de maturité IA",{"href":3158,"dataGaName":3159,"dataGaLocation":2641},"/fr-fr/assessments/ai-modernization-assessment/","modernization assessment",{"config":3161},{"src":3162},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":3164,"categories":3165,"header":3167,"text":3154,"button":3168,"image":3172},"devops-modernization",[3166,2976],"product","Vous contentez-vous de gérer des outils ou de livrer des innovations ?",{"text":3169,"config":3170},"Obtenez votre score de maturité DevOps",{"href":3171,"dataGaName":3159,"dataGaLocation":2641},"/fr-fr/assessments/devops-modernization-assessment/",{"config":3173},{"src":3174},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":3176,"categories":3177,"header":3179,"text":3154,"button":3180,"image":3184},"security-modernization",[3178],"security","Faut-il sacrifier la rapidité pour garantir la sécurité ?",{"text":3181,"config":3182},"Obtenez votre score de maturité en matière de sécurité",{"href":3183,"dataGaName":3159,"dataGaLocation":2641},"/fr-fr/assessments/security-modernization-assessment/",{"config":3185},{"src":3186},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":3188,"paths":3189,"header":3192,"text":3193,"button":3194,"image":3199},"github-azure-migration",[3190,3191],"migration-from-azure-devops-to-gitlab","integrating-azure-devops-scm-and-gitlab","Votre équipe est-elle prête pour la migration de GitHub vers Azure ?","GitHub a déjà commencé sa migration vers Azure. Découvrez ce que cela signifie pour vous.",{"text":3195,"config":3196},"Découvrez les différences entre GitLab et GitHub",{"href":3197,"dataGaName":3198,"dataGaLocation":2641},"/fr-fr/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":3200},{"src":3174},{"header":3202,"blurb":3203,"button":3204,"secondaryButton":3208},"Commencez à développer plus rapidement dès aujourd'hui","Découvrez ce que votre équipe peut accomplir avec la plateforme d'orchestration intelligente pour le DevSecOps.\n",{"text":2435,"config":3205},{"href":3206,"dataGaName":2438,"dataGaLocation":3207},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/fr-fr/","feature",{"text":2763,"config":3209},{"href":2765,"dataGaName":2443,"dataGaLocation":3207},1786803762947]