<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>CI/CD on The Cloud Optimist</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/categories/ci/cd/</link>
        <description>Recent content in CI/CD on The Cloud Optimist</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>fr-FR</language>
        <lastBuildDate>Tue, 17 Feb 2026 07:30:00 +0100</lastBuildDate><atom:link href="https://antoinedelia.github.io/cloud-optimist/pr-144/fr/categories/ci/cd/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Le jour où j&#39;ai accidentellement supprimé une API, et ce que cela m&#39;a appris sur le DevOps</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2026/the-day-i-accidentally-deleted-an-api-and-what-it-taught-me-about-devops/</link>
        <pubDate>Tue, 17 Feb 2026 07:30:00 +0100</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2026/the-day-i-accidentally-deleted-an-api-and-what-it-taught-me-about-devops/</guid>
        <description>&lt;img src="https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2026/the-day-i-accidentally-deleted-an-api-and-what-it-taught-me-about-devops/deleted_api.png" alt="Featured image of post Le jour où j&#39;ai accidentellement supprimé une API, et ce que cela m&#39;a appris sur le DevOps" /&gt;&lt;p&gt;La journée du 4 avril 2024 avait bien commencé. Un petit café en main, un VS Code en plein ébullition, et de la douce musique électro dans les oreilles, tant de facteurs positifs qui ne pouvaient présager de la catastrophe à venir.&lt;/p&gt;
&lt;p&gt;Aujourd&amp;rsquo;hui, j&amp;rsquo;aimerai vous raconter comment une journée en apparence tranquille est devenue un moment marquant de ma carrière de DevOps !&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/the-day-i-accidentally-deleted-an-api-and-what-it-taught-me-about-devops/calm_before_storm.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Le calme avant la tempête&#34;
	
	
&gt;&lt;/p&gt;
&lt;h1 id=&#34;incident&#34;&gt;&lt;a href=&#34;#incident&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Incident
&lt;/h1&gt;&lt;h2 id=&#34;le-contexte&#34;&gt;&lt;a href=&#34;#le-contexte&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Le contexte
&lt;/h2&gt;&lt;p&gt;Je travaillais alors dans une équipe avec pour but de mettre à disposition une API Gateway globale sur AWS, avec plusieurs endpoints managés par différentes équipes. Concrètement, la mise en place de cette API Gateway était l&amp;rsquo;étape initiale du projet. Cela comprenait un record DNS qui pointait vers cette API, l&amp;rsquo;API Gateway elle-même, ainsi qu&amp;rsquo;un Cognito Authorizer configuré avec plusieurs clients.&lt;/p&gt;
&lt;p&gt;Une fois cette API prête, des équipes externes pouvaient alors déployer leurs propres endpoints sur cette API. Pour cela, une pipeline CI/CD était mise en place, et via CloudFormation, les endpoints se rattachaient directement à l&amp;rsquo;API déjà créée.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Je simplifie au maximum, si des détails techniques vous intéressent, n&amp;rsquo;hésitez pas à me contacter !&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;De mon côté, en plus d&amp;rsquo;être responsable de l&amp;rsquo;infrastrcture globale de l&amp;rsquo;API, il m&amp;rsquo;arrivait de travailler ou de troubleshooter certains services.&lt;/p&gt;
&lt;h2 id=&#34;le-début-du-drame&#34;&gt;&lt;a href=&#34;#le-d%c3%a9but-du-drame&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Le début du drame
&lt;/h2&gt;&lt;p&gt;Si vous avez déjà travaillé avec CloudFormation, vous êtes peut-être familier avec le terme &lt;code&gt;UPDATE_ROLLBACK_FAILED&lt;/code&gt;. C&amp;rsquo;est ce qui arrive lorsque vous essayez de mettre à jour une stack CloudFormation, mais que celle-ci a rencontré un problème. Elle essaiera donc de faire un rollback. Mais si ce rollback n&amp;rsquo;aboutit pas, votre stack sera alors en &lt;code&gt;UPDATE_ROLLBACK_FAILED&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Et ce &lt;code&gt;UPDATE_ROLLBACK_FAILED&lt;/code&gt; est bien embêtant, car vous ne pouvez plus relancer de déploiements tant que vous n&amp;rsquo;avez pas résolu le problème.&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est exactement ce qui s&amp;rsquo;est passé ce fameux 4 avril 2024. Un de nos services s&amp;rsquo;est retrouvé dans cet état, et j&amp;rsquo;ai commencé à investiguer le pourquoi du comment.&lt;/p&gt;
&lt;p&gt;Après quelques minutes, j&amp;rsquo;ai constaté que le problème venait de la ressource API elle-même. Sans trop réfléchir, et dans une optique de débloquer le problème rapidement, je me suis rendu directement sur la console AWS, sur le service API Gateway. J&amp;rsquo;ai cherché la ressource en question, et me suis empressé de la supprimer.&lt;/p&gt;
&lt;p&gt;À ce moment précis, quelque chose de très étrange s&amp;rsquo;est produit. Un comportement inattendu qui m&amp;rsquo;a glacé le sang. Au lieu de me retrouver sur la même page, AWS m&amp;rsquo;a renvoyé sur la page principale du service API Gateway. Cette même page qui liste vos APIs disponibles, et qui affichait maintenant le nombre &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai ainsi réalisé que je n&amp;rsquo;avais pas supprimé la ressource API, mais bien l&amp;rsquo;API Gateway dans sa totalité.&lt;/p&gt;
&lt;h2 id=&#34;les-détails-dun-échec&#34;&gt;&lt;a href=&#34;#les-d%c3%a9tails-dun-%c3%a9chec&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Les détails d&amp;rsquo;un échec
&lt;/h2&gt;&lt;p&gt;Jamais je n&amp;rsquo;aurais pensé commettre une telle bêtise. Et j&amp;rsquo;imagine que vous lisant ces lignes, vous vous dites la même chose.&lt;/p&gt;
&lt;p&gt;Car pour se tromper, &lt;strong&gt;il fallait le faire !&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Laissez-moi vous faire une reconstitution de la scène du crime. Voici ce que j&amp;rsquo;ai vu au moment où j&amp;rsquo;ai pris la décision de supprimer une ressource de l&amp;rsquo;API Gateway.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/the-day-i-accidentally-deleted-an-api-and-what-it-taught-me-about-devops/api_gateway_view.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Vue de la ressource API Gateway&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Toute ressemblance avec une situation réelle est totalement fortuite&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Dans ma situation, sur quel bouton auriez-vous cliqué ? Facile ! Le bouton &lt;em&gt;Delete&lt;/em&gt; juste à droite de la ressource !&lt;/p&gt;
&lt;p&gt;Pour ma part (et je ne sais toujours pas ce qui m&amp;rsquo;a poussé à faire cela), j&amp;rsquo;ai préféré cliquer sur le bouton &lt;em&gt;API actions&lt;/em&gt;. Après tout, je voulais en effet faire une action !&lt;/p&gt;
&lt;p&gt;Et que se passe-t-il quand on clique sur ce bouton ?&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/the-day-i-accidentally-deleted-an-api-and-what-it-taught-me-about-devops/api_actions.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Menu déroulant du bouton API Actions&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Oula ! De suite, on voit que ce n&amp;rsquo;est pas du tout ce qu&amp;rsquo;on veut faire. Mais pensez-vous que cela m&amp;rsquo;a découragé ? Absolument pas ! J&amp;rsquo;étais venu pour supprimer une ressource, et quand j&amp;rsquo;ai vu le mot &lt;em&gt;Delete&lt;/em&gt;, je n&amp;rsquo;ai pas réfléchi plus longtemps ! J&amp;rsquo;aurais dû, car ainsi, j&amp;rsquo;aurais sûrement vu le mot &lt;em&gt;API&lt;/em&gt; juste à côté.&lt;/p&gt;
&lt;p&gt;Heureusement, nos amis de chez AWS ont pensé à tout ! Lorsque vous cliquez sur &lt;em&gt;Delete API&lt;/em&gt;, on va tout de même vous demander si vous êtes bel et bien certain de vouloir supprimer cette API. Un beau message s&amp;rsquo;affiche, vous indiquant le nom de l&amp;rsquo;API en question, et vous demandant de taper le mot &lt;em&gt;confirm&lt;/em&gt; pour valider cette opération.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/the-day-i-accidentally-deleted-an-api-and-what-it-taught-me-about-devops/delete_api_dialog.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Demande de confirmation de suppression de l’API&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Tout ça, c&amp;rsquo;est bien beau, mais les ingénieurs d&amp;rsquo;AWS ont sous-estimé mon impatience. À ce moment-là, cette demande de confirmation n&amp;rsquo;était pas une mise en garde, mais un obstacle à mon but de supprimer ma ressource. Ni une ni deux, j&amp;rsquo;ai entré le mot &lt;em&gt;confirm&lt;/em&gt;, et validé l&amp;rsquo;opération.&lt;/p&gt;
&lt;p&gt;Voici donc la dernière chose que j&amp;rsquo;ai vue avant de finalement réaliser l&amp;rsquo;erreur que j&amp;rsquo;avais commise.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/the-day-i-accidentally-deleted-an-api-and-what-it-taught-me-about-devops/successfully_deleted_api.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;L’API a été supprimée avec succès&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Une vision d&amp;rsquo;horreur&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Je voulais absolument vous retracer ce petit parcours pour vous faire comprendre une chose : vous aurez beau mettre en place toutes les sécurités possibles, &lt;strong&gt;vous ne pourrez jamais rien faire contre un individu impatient&lt;/strong&gt;, car ce dernier ne saura pas lire vos avertissements.&lt;/p&gt;
&lt;p&gt;Alors, la prochaine fois que vous devrez faire une action somme toute inoffensive, prenez bien le temps de lire et de vous assurer que vous êtes bel et bien sur le bon chemin.&lt;/p&gt;
&lt;p&gt;Cela étant dit, passons maintenant à une étape cruciale : la résolution de cet incident !&lt;/p&gt;
&lt;h1 id=&#34;résolution&#34;&gt;&lt;a href=&#34;#r%c3%a9solution&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Résolution
&lt;/h1&gt;&lt;h2 id=&#34;le-déclic&#34;&gt;&lt;a href=&#34;#le-d%c3%a9clic&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Le déclic
&lt;/h2&gt;&lt;p&gt;Revenons donc sur le moment du drame. Après avoir réalisé ce qui était arrivé, j&amp;rsquo;ai eu comme un électrochoc, un éclair de génie (aucune poudre blanche n&amp;rsquo;ayant pourtant été consommée). Je savais maintenant ce que je devais faire : résoudre l&amp;rsquo;incident, mais surtout, documenter les actions que j&amp;rsquo;allais entreprendre.&lt;/p&gt;
&lt;p&gt;Car quelques semaines plus tôt, je m&amp;rsquo;étais intéressé à &lt;a class=&#34;link&#34; href=&#34;https://about.gitlab.com/blog/postmortem-of-database-outage-of-january-31/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;l&amp;rsquo;incident GitLab de 2017&lt;/a&gt;, celui ayant interrompu le service pendant plusieurs heures, et résultant d&amp;rsquo;une perte de données pour certains utilisateurs. J&amp;rsquo;ai ainsi découvert le terme de &lt;strong&gt;Post-Morten&lt;/strong&gt;, et leur intérêt dans ce genre de situation. Mais je garde ça pour la prochaine section de cet article.&lt;/p&gt;
&lt;p&gt;En attendant, si vous êtes intéressés par ces sujets-là, je vous conseille la très bonne &lt;a class=&#34;link&#34; href=&#34;https://www.youtube.com/@kevinfaang/videos&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;chaîne Youtube de Kevin Fang&lt;/a&gt; qui je le cite : &amp;ldquo;lit des postmortems et en fait des vidéos de piètre qualité&amp;rdquo;.&lt;/p&gt;
&lt;h2 id=&#34;rollback-impact-et-communication&#34;&gt;&lt;a href=&#34;#rollback-impact-et-communication&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Rollback, impact, et communication
&lt;/h2&gt;&lt;p&gt;La première chose que je me suis dite, c&amp;rsquo;est qu&amp;rsquo;il était peut-être possible de faire une sorte de rollback directement depuis AWS, et d&amp;rsquo;ainsi réduire au maximum l&amp;rsquo;impact sur les utilisateurs. Si j&amp;rsquo;avais correctement lu le message d&amp;rsquo;avertissement plus haut, j&amp;rsquo;aurais tout de suite compris que cela était impossible (mais si je l&amp;rsquo;avais lu, je n&amp;rsquo;aurais de toute façon pas été dans cette situation).&lt;/p&gt;
&lt;p&gt;N&amp;rsquo;ayant aucun moyen rapide et simple de revenir en arrière, j&amp;rsquo;étais maintenant confiant que j&amp;rsquo;étais face à un véritable incident ayant un impact global. J&amp;rsquo;ai donc dans un premier temps pris soin de comprendre tous les impacts que cette suppression d&amp;rsquo;API allait avoir. Dans mon cas, non seulement l&amp;rsquo;API n&amp;rsquo;était plus disponible (merci Captain Obvious), mais en plus de cela, aucun nouveau déploiement n&amp;rsquo;était possible jusqu&amp;rsquo;à ce que l&amp;rsquo;API soit de nouveau opérationnelle.&lt;/p&gt;
&lt;p&gt;Finalement, j&amp;rsquo;ai fait en sorte d&amp;rsquo;avertir toute notre équipe interne de la situation. Ainsi, ils étaient au courant de l&amp;rsquo;incident en cours, et que j&amp;rsquo;étais en train de travailler à sa résolution.&lt;/p&gt;
&lt;h2 id=&#34;analyse-et-découverte-de-problèmes&#34;&gt;&lt;a href=&#34;#analyse-et-d%c3%a9couverte-de-probl%c3%a8mes&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Analyse et découverte de problèmes
&lt;/h2&gt;&lt;p&gt;Il était maintenant temps de se retrousser les manches et de trouver un moyen de redéployer cette API Gateway.&lt;/p&gt;
&lt;p&gt;En premier lieu, je me suis rendu dans le service CloudFormation, car j&amp;rsquo;avais souvenir que cette API avait été initialement déployée via ce service. J&amp;rsquo;ai d&amp;rsquo;abord essayé de mettre à jour la stack, en pensant que cela pourrait faire revenir ma chère API comme par magie.&lt;/p&gt;
&lt;p&gt;Évidemment, cela n&amp;rsquo;allait pas être aussi simple. La mise à jour de cette stack était maintenant impossible, car la suppression manuelle de l&amp;rsquo;API avait fait rentrer la stack dans un état &amp;ldquo;hybride&amp;rdquo; dont elle n&amp;rsquo;arrivait pas à se sortir.&lt;/p&gt;
&lt;p&gt;La mise à jour de cette stack étant impossible, la suite logique était de la supprimer afin de la déployer à nouveau proprement. Et c&amp;rsquo;est là que les ennuis ont commencé. Cette fameuse stack CloudFormation produisait plusieurs Outputs. &lt;strong&gt;Deux de ces outputs étaient nécessaires à toutes les stacks &amp;ldquo;enfants&amp;rdquo;&lt;/strong&gt; qui avaient jusqu&amp;rsquo;alors déployé leurs endpoints sur cette API. Ainsi, CloudFormation m&amp;rsquo;interdisait de supprimer ma stack, car elle pourrait impacter toutes les autres.&lt;/p&gt;
&lt;p&gt;Après plusieurs minutes de réflexion pour essayer de trouver d&amp;rsquo;autres alternatives, cette forte interdépendance m&amp;rsquo;amena à prendre une décision difficile : supprimer toutes les stacks &amp;ldquo;enfants&amp;rdquo; de CloudFormation, pour un total de 81 stacks.&lt;/p&gt;
&lt;p&gt;Pour couronner le tout, ces stacks &amp;ldquo;enfants&amp;rdquo; n&amp;rsquo;avaient pas de tags identifiables qui auraient pu nous permettre d&amp;rsquo;automatiser cette suppression. Heureusement, la plupart d&amp;rsquo;entre elles avaient un nom avec un préfixe reconnaissable, ce qui m&amp;rsquo;a permis de faire un bon coup de ménage sur la plupart d&amp;rsquo;entre elles.&lt;/p&gt;
&lt;p&gt;Je vous ai parlé &lt;strong&gt;d&amp;rsquo;interdépendances&lt;/strong&gt; ? Parce que ce n&amp;rsquo;est pas fini ! Certaines stacks avaient déployé des buckets S3. Et devinez quoi ? CloudFormation ne voudra pas supprimer votre stack, si votre bucket S3 n&amp;rsquo;est pas vide ! Et bien sûr, 14 stacks se sont retrouvées dans l&amp;rsquo;état &lt;code&gt;DELETE_FAILED&lt;/code&gt; à cause de cela. Heureusement, le problème se résout assez facilement : après avoir fait un backup de chaque bucket, il suffit de les vider et de relancer la suppression de la stack.&lt;/p&gt;
&lt;h2 id=&#34;déploiement-de-lapi--le-bout-du-tunnel-&#34;&gt;&lt;a href=&#34;#d%c3%a9ploiement-de-lapi--le-bout-du-tunnel-&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Déploiement de l&amp;rsquo;API : Le bout du tunnel ?
&lt;/h2&gt;&lt;p&gt;Étant venu à bout de toutes ces interdépendances, il était maintenant temps de supprimer la stack CloudFormation de l&amp;rsquo;API Gateway, et de la déployer à nouveau.&lt;/p&gt;
&lt;p&gt;La suppression se passa sans plus de problème (Dieu merci), mais évidemment, cela ne fût pas le cas pour sa création.&lt;/p&gt;
&lt;p&gt;Déjà, parlons de la stack elle-même. Un fichier YML existait dans un repo GitHub, mais &lt;strong&gt;celui-ci n&amp;rsquo;avait pas été mis à jour depuis des lustres&lt;/strong&gt;, et je savais que je ferais mieux d&amp;rsquo;utiliser la définition de la stack présente dans CloudFormation (et oui, je l&amp;rsquo;ai quand même gardée, pas fou le gars).&lt;/p&gt;
&lt;p&gt;Cette stack ne déployait pas uniquement l&amp;rsquo;API Gateway, mais plusieurs ressources AWS (je ne rentrerai pas dans les détails du pourquoi nous avions besoin de ces ressources dans cet article), dont des Lambdas. Ces dernières se basaient encore sur Python 3.7, version avec laquelle &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html#runtimes-deprecated&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;il était impossible de se servir pour créer de nouvelles Lambdas&lt;/a&gt;. Heureusement, un petit upgrade en Python 3.12 sera suffisant pour qu&amp;rsquo;AWS nous laisse tranquille.&lt;/p&gt;
&lt;p&gt;Et, à ma grande surprise, la stack se déployait maintenant sans souci !&lt;/p&gt;
&lt;p&gt;Mais je vous la fait courte, il restait encore du pain sur la planche ! En effet, il manquait à la stack CloudFormation plusieurs ressources critiques à la bonne exécution de notre API. Des ressources qui avaient été créées à la main dans AWS directement, faisant fi de toute bonne pratique d&amp;rsquo;Infrastructure as Code (&lt;em&gt;pleure en Terraform&lt;/em&gt;). Dans un souci de rétablissement du service le plus rapidement possible (on est DevOps, ou on ne l&amp;rsquo;est pas !), ces ressources seront donc créées une nouvelle fois à la main.&lt;/p&gt;
&lt;p&gt;Pour finir, plusieurs composants clés faisaient référence à l&amp;rsquo;ARN de l&amp;rsquo;ancienne API en dur. Il fallait ainsi faire tout un travail d&amp;rsquo;archéologie pour trouver tous les endroits où une mise à jour vers la nouvelle API s&amp;rsquo;imposait.&lt;/p&gt;
&lt;p&gt;Finalement, après plusieurs heures de troubleshooting, l&amp;rsquo;API était de nouveau opérationnelle, et les développeurs pouvaient à nouveau déployer leurs projets.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cet incident aura démarré le 4 avril 2024 à 15h24 et se sera conclu le 5 avril 2024 à 08h46.&lt;/strong&gt;&lt;/p&gt;
&lt;h1 id=&#34;post-mortem-et-lessons-learned&#34;&gt;&lt;a href=&#34;#post-mortem-et-lessons-learned&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Post-Mortem et Lessons Learned
&lt;/h1&gt;&lt;p&gt;Pendant cet incident, j&amp;rsquo;ai réalisé une prise de note intensive sur les actions menées. J&amp;rsquo;avais déjà entendu parler du principe de &lt;strong&gt;Post-Mortem&lt;/strong&gt;, et je pensais que cet incident serait le parfait candidat.&lt;/p&gt;
&lt;p&gt;Si vous ignorez le principe d&amp;rsquo;un Post-Mortem, il agit comme un document retraçant les étapes de résolution d&amp;rsquo;un incident, couvrant les impacts, et la root cause, mais surtout — et à mon sens le plus intéressant — comporte une section appellée &lt;strong&gt;Lessons Learned&lt;/strong&gt;. Cette section, si vous la prenez au sérieux, sera votre meilleure alliée pour construire une architecture plus robuste et plus durable.&lt;/p&gt;
&lt;p&gt;Concrètement, vous allez noter dans cette section trois points clés : ce qui s&amp;rsquo;est bien passé, ce qui s&amp;rsquo;est mal passé, et là où vous avez eu de la chance. Et surtout, &lt;strong&gt;soyez honnêtes&lt;/strong&gt; ! Même si certains points vous paraissent bêtes, ou vous font passer pour un incompétent (et je vous dis ça alors que j&amp;rsquo;ai manuellement supprimé une API, donc prenez-le avec légèreté), le but n&amp;rsquo;est pas de pointer du doigt (ce qu&amp;rsquo;on appelle aussi la blameless culture), mais de comprendre les failles dans notre système, afin de les améliorer.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;« The cost of failure is education. » — Devin Carraway (&lt;a class=&#34;link&#34; href=&#34;https://sre.google/sre-book/postmortem-culture/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Cela vous paraît peut-être encore un peu flou, alors laissez-moi vous montrer mes lessons learned de cet incident.&lt;/p&gt;
&lt;h2 id=&#34;what-went-well&#34;&gt;&lt;a href=&#34;#what-went-well&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;What went well
&lt;/h2&gt;&lt;p&gt;Pendant cet incident, &lt;strong&gt;deux choses se sont bien passées&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;D&amp;rsquo;abord, la résolution s&amp;rsquo;est faite par &lt;strong&gt;un membre de l&amp;rsquo;équipe qui connaissait en profondeur cette architecture&lt;/strong&gt;, ce qui a permis de comprendre rapidement ce qui devait être remis en place pour restaurer le service.&lt;/p&gt;
&lt;p&gt;Enfin, il y a eu &lt;strong&gt;une bonne communication tout au long de cet incident&lt;/strong&gt;. Lorsque le problème s&amp;rsquo;est présenté, il n&amp;rsquo;a pas essayé d&amp;rsquo;être dissimulé, et des mises à jour fréquentes ont été annoncées pour avertir de l&amp;rsquo;avancement de sa résolution. C&amp;rsquo;est un point très important, car non seulement vous donnez de la visibilité sur vos actions, mais par la communication, vous pouvez aussi acquérir des informations utiles à la résolution de votre incident (un collègue pourra par exemple vous pointer vers une documentation dont vous n&amp;rsquo;avez pas connaissance, ou vous donner un coup de main si nécessaire).&lt;/p&gt;
&lt;h2 id=&#34;what-went-wrong&#34;&gt;&lt;a href=&#34;#what-went-wrong&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;What went wrong
&lt;/h2&gt;&lt;p&gt;Ici, c&amp;rsquo;est la partie qui fait mal. Comme je vous l&amp;rsquo;ai dit, il faut ravaler sa fierté, et mettre en lumière tout ce qui aurait pu être mieux exécuté.&lt;/p&gt;
&lt;p&gt;Pour cet incident, &lt;strong&gt;quatre choses ne se sont pas bien passées&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Pour commencer, &lt;strong&gt;l&amp;rsquo;infrastrucutre de cette API n&amp;rsquo;était non seulement pas consolidée dans un seul et même fichier&lt;/strong&gt; (ou dossier), mais était en plus disséminée dans plusieurs repos GitHub. Il était ainsi très compliqué d&amp;rsquo;avoir une vue d&amp;rsquo;ensemble de ce qui était nécessaire au bon fonctionnement de cette API.&lt;/p&gt;
&lt;p&gt;Ensuite, un gros problème résidait dans ce qu&amp;rsquo;on appelle le &lt;strong&gt;drift&lt;/strong&gt;. Ce sont toutes les différences que vous avez entre votre infrastructure réelle, et votre infrastructure telle qu&amp;rsquo;elle est définie dans votre code. Idéalement, aucune modification manuelle ne doit avoit lieu, et tout doit passer par votre fichier d&amp;rsquo;Infrastructure as Code. Si cela avait était le cas, un simple redéploiement aurait permi une remise en service instantanée.&lt;/p&gt;
&lt;p&gt;Un autre problème résidait dans &lt;strong&gt;la forte interdépendance de toutes les ressources&lt;/strong&gt;. Beaucoup par exemple se basaient sur un output de la stack CloudFormation. Si vous enlevez cette stack, vous enlevez ainsi la possibilité de déployer la suite de votre infrastructure.&lt;/p&gt;
&lt;p&gt;Enfin, l&amp;rsquo;identification des ressources liées à notre infrastructure était difficile. &lt;strong&gt;Notre stack déployait les ressources sans aucun tag associé&lt;/strong&gt;, ce qui rendait compliqué la recherche de toutes les ressources nécessaires à notre API.&lt;/p&gt;
&lt;h2 id=&#34;where-we-got-lucky&#34;&gt;&lt;a href=&#34;#where-we-got-lucky&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Where we got lucky
&lt;/h2&gt;&lt;p&gt;Cette partie peut ressembler à du positif, mais il n&amp;rsquo;en est rien ! Car vous allez ici parler des élément qui se sont bien passés, mais UNIQUEMENT car vous avez eu de la chance. Comprenez qu&amp;rsquo;à tout moment, cela aurait pû être un autre point à mettre dans la catégorie &amp;ldquo;What went wrong&amp;rdquo;. Donc soyez heureux pour cette fois, mais ne baissez pas votre garde pour autant !&lt;/p&gt;
&lt;p&gt;Pour cet incident, &lt;strong&gt;trois choses se sont bien passées par chance&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Tout d&amp;rsquo;abord, l&amp;rsquo;incident a été &lt;strong&gt;immédiatement identifié&lt;/strong&gt; (c&amp;rsquo;est au moins l&amp;rsquo;avantage quand on fait une boulette pareille). Mais cela aurait pû être bien pire ! Car si cette API avait été supprimée par tout autre moyen (un script d&amp;rsquo;automatisation par exemple), nous n&amp;rsquo;avions aucun monitoring en place capable de nous prévenir d&amp;rsquo;une telle chose.&lt;/p&gt;
&lt;p&gt;Ensuite, il se trouve que la personne qui a supprimé cette API avait une excellente connaissance du projet et de l&amp;rsquo;infrastructure (je parle de moi oui, il faut bien s&amp;rsquo;envoyer quelques fleurs). Cela a permis de très vite enchaîner sur la résolution de l&amp;rsquo;incident, mais cela aurait pu se passer autrement.&lt;/p&gt;
&lt;p&gt;Enfin, cette API était en fait &lt;strong&gt;notre API de dev&lt;/strong&gt;. L&amp;rsquo;API de prod, elle, allait très bien (détail que j&amp;rsquo;ai volontairement gardé pour la fin, il paraît que c&amp;rsquo;est du storytelling). Alors certes, l&amp;rsquo;impact fût minime, mais l&amp;rsquo;incident aurait tout de même pû arriver en production, avec les mêmes problématiques de remise en service. Et cela aurait pû coûter bien plus cher.&lt;/p&gt;
&lt;h2 id=&#34;préparer-le-futur&#34;&gt;&lt;a href=&#34;#pr%c3%a9parer-le-futur&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Préparer le futur
&lt;/h2&gt;&lt;p&gt;Maintenant que vous avez pu lister les problèmes rencontrés lors de la résolution de cet incident, en tant que bon DevOps, vous vous devez d&amp;rsquo;en tirer les leçons. Notez bien tout ce qui pourrait être amélioré, mais surtout, fixez-vous un plan ! Sinon, ce ne seront que de vastes phrases sans utilité.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;« Tout objectif sans plan n&amp;rsquo;est qu&amp;rsquo;un souhait. » — Antoine de Saint-Exupéry&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Dans mon cas, les trois leçons clés ont été les suivantes :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Consolidation de l&amp;rsquo;Infrastructure as Code :&lt;/strong&gt; tout doit pouvoir être déployé en un clin d&amp;rsquo;oeil. C&amp;rsquo;est un chantier que je serai amené à compléter dans les mois qui suivirent (mais cette histoire, c&amp;rsquo;est pour une prochaine fois).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Amélioration du monitoring et de l&amp;rsquo;alerting :&lt;/strong&gt; si cet incident devait de nouveau arriver, il nous faut être averti rapidement afin de réagir en vitesse.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Documentation plus claire et cohérente :&lt;/strong&gt; n&amp;rsquo;importe quel membre de l&amp;rsquo;équipe doit pouvoir faire face à un tel incident, et cela commence par une documentation fiable et compréhensible.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Toutes ces leçons seront ensuite trackées en tant qu&amp;rsquo;issues GitHub, et je m&amp;rsquo;appliquerai à les compléter dans les mois qui suivirent (mais cette histoire, c&amp;rsquo;est pour une prochaine fois).&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;&lt;a href=&#34;#conclusion&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Conclusion
&lt;/h1&gt;&lt;p&gt;Vous l&amp;rsquo;aurez compris, un accident ça arrive. L&amp;rsquo;essentiel est qu&amp;rsquo;il soit bénéfique pour vous, et l&amp;rsquo;ensemble de votre organisation. Servez-vous en comme d&amp;rsquo;une opportunité d&amp;rsquo;apprendre et de consolider des failles qui n&amp;rsquo;était jusqu&amp;rsquo;alors pas détectées (certaines entreprises s&amp;rsquo;amusent d&amp;rsquo;ailleurs même à &lt;a class=&#34;link&#34; href=&#34;https://en.wikipedia.org/wiki/Chaos_engineering&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;volontairement créer ce chaos&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Merci de m&amp;rsquo;avoir lu jusqu&amp;rsquo;au bout ! Je vous laisse ici, car j&amp;rsquo;ai d&amp;rsquo;autres infrastructures à supprimer !&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Comment j&#39;ai automatisé la création de mon blog dans le Cloud</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/how-i-automated-my-blog-to-the-cloud/</link>
        <pubDate>Tue, 04 Mar 2025 07:30:00 +0100</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/how-i-automated-my-blog-to-the-cloud/</guid>
        <description>&lt;img src="https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/how-i-automated-my-blog-to-the-cloud/automated-blog.jpeg" alt="Featured image of post Comment j&#39;ai automatisé la création de mon blog dans le Cloud" /&gt;&lt;h1 id=&#34;le-commencement-et-la-fin&#34;&gt;&lt;a href=&#34;#le-commencement-et-la-fin&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Le commencement et la fin
&lt;/h1&gt;&lt;p&gt;Quand j&amp;rsquo;ai envisagé de créer un blog pour la première fois, j&amp;rsquo;étais encore étudiant dans mon école d&amp;rsquo;ingénieurs. Et le monde des sites internets et des blogs était encore quelque chose de nouveau pour moi. Et lorsque je me suis finalement lancé dans l&amp;rsquo;aventure du blogging, c&amp;rsquo;est tout naturellement que je me suis tourné vers ce qui semblait être la meilleure solution à l&amp;rsquo;époque : WordPress.&lt;/p&gt;
&lt;p&gt;Quoi que l&amp;rsquo;on en dise, &lt;strong&gt;WordPress est une solution relativement simple d&amp;rsquo;usage&lt;/strong&gt; pour les débutants qui souhaitent créer leur premier site internet. Et ça tombe bien, car j&amp;rsquo;en faisais parti !&lt;/p&gt;
&lt;p&gt;Alors, armé d&amp;rsquo;un tout nouveau compte chez OVH, j&amp;rsquo;ai pû mettre en ligne mon &lt;a class=&#34;link&#34; href=&#34;https://blog.antoinedelia.fr&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;blog personnel&lt;/a&gt; en quelques cliques !&lt;/p&gt;
&lt;p&gt;Et puis, quelques années plus tard, quand me vint l&amp;rsquo;idée de publier un blog dédié à des sujets professionels, là encore, j&amp;rsquo;ai fait appel à mon bon vieil ami WordPress.&lt;/p&gt;
&lt;p&gt;Les mois passèrent, et l&amp;rsquo;idyle que je vivais avec WordPress commençait petit à petit à se ternir. Certes, rajouter des articles à travers l&amp;rsquo;UI de WordPress était pratique, mais pour ce qui était de gérer les backups, c&amp;rsquo;était une autre paire de manches. En plus, WordPress requiert une base de données pour fonctionner, ce qui rendait le tout très volumineux pour quelques articles, sans compter la facture qui venait avec.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/how-i-automated-my-blog-to-the-cloud/struggling_blog.jpeg&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Les galères avec WordPress&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Je me rendais alors compte que, pour un blog aussi simple, et avec si peu de visites, il y avait certainement un moyen d&amp;rsquo;améliorer les choses.&lt;/p&gt;
&lt;h1 id=&#34;le-début-dun-nouveau-plan&#34;&gt;&lt;a href=&#34;#le-d%c3%a9but-dun-nouveau-plan&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Le début d&amp;rsquo;un nouveau plan
&lt;/h1&gt;&lt;p&gt;Je vais vous raconter ici le cheminement qui m&amp;rsquo;a amené au renouveau de mon blog sur lequel vous vous trouvez aujourd&amp;rsquo;hui. Si vous êtes seulement intéressé par les détails techniques, vous pouvez &lt;a class=&#34;link&#34; href=&#34;#c%c3%b4t%c3%a9-technique--l%c3%a9tat-actuel-des-choses&#34; &gt;avancer à la prochain section&lt;/a&gt;. Sinon, bonne lecture !&lt;/p&gt;
&lt;h2 id=&#34;la-découverte-dhugo&#34;&gt;&lt;a href=&#34;#la-d%c3%a9couverte-dhugo&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;La découverte d&amp;rsquo;Hugo
&lt;/h2&gt;&lt;p&gt;Avant de me mettre en quête d&amp;rsquo;un nouvel outil pour mon blog, j&amp;rsquo;ai d&amp;rsquo;abord réfléchi à ce dont j&amp;rsquo;avais réelement besoin.&lt;/p&gt;
&lt;p&gt;Mon blog était en fait assez rudimentaire : une page d&amp;rsquo;accueil qui listait les différents articles, pas de JavaScript tarabiscoté dans les parages, et aucun besoin d&amp;rsquo;un backend pour gérer une API. Au final, &lt;strong&gt;l&amp;rsquo;utilisation d&amp;rsquo;une base de données était-elle nécessaire ?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Il y avait aussi une chose importante à garder en mémoire. Je suis un ingénieur, ce qui fait de moi par définition, un bien piètre designer. Je voulais à tout prix éviter d&amp;rsquo;avoir à gérer le CSS de mon blog : je voualais me concenter sur le contenu, plutôt que sur le style.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai donc commencé mes recherches, dans l&amp;rsquo;espoir de trouver un outil qui répondrait à ces critères. Et il ne m&amp;rsquo;a pas fallu bien longtemps avant de tomber sur la perle rare : &lt;a class=&#34;link&#34; href=&#34;https://gohugo.io/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Hugo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/how-i-automated-my-blog-to-the-cloud/hugo.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Hugo logo&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;À peine eus-je atterri sur le site d&amp;rsquo;Hugo que je fus accueilli par cet intriguant message : &lt;strong&gt;Le framework le plus rapide du monde pour générer des sites web&lt;/strong&gt;. On peut dire que cela a piqué ma curiosité, et je me pressa d&amp;rsquo;aller fouiller dans la documentation. Et je n&amp;rsquo;allais pas être déçu.&lt;/p&gt;
&lt;p&gt;Hugo se charge de convertir des articles au format markdown (comme l&amp;rsquo;on trouve sur les README de GitHub par exemple) vers le format HTML. Qui plus est, il existe une &lt;a class=&#34;link&#34; href=&#34;https://themes.gohugo.io/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;miriade de thèmes&lt;/a&gt; mis à disposition, ce qui me laissait l&amp;rsquo;embarras du choix, sans avoir besoin de designer quoi que ce soit !&lt;/p&gt;
&lt;p&gt;Sans perdre une seconde, je m&amp;rsquo;empressai de convertir mon blog WordPress vers un site Hugo (j&amp;rsquo;ai utilisé pour ça un super petit script intitulé &lt;a class=&#34;link&#34; href=&#34;https://github.com/SchumacherFM/wordpress-to-hugo-exporter&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;wordpress-to-hugo-exporter&lt;/a&gt; qui convertit une base de données WordPress en fichiers markdown avec l&amp;rsquo;arborescence requise pour Hugo).&lt;/p&gt;
&lt;p&gt;Mon site Hugo était désormais prêt ! Il fallait maintenant trouver un moyen de l&amp;rsquo;héberger quelque part.&lt;/p&gt;
&lt;h2 id=&#34;un-hébergeur-à-la-hauteur--aws&#34;&gt;&lt;a href=&#34;#un-h%c3%a9bergeur-%c3%a0-la-hauteur--aws&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Un hébergeur à la hauteur : AWS
&lt;/h2&gt;&lt;p&gt;En même temps que je me creusais la tête pour trouver une alternative pour mon blog, j&amp;rsquo;ai eu une opportunité professionnelle qui m&amp;rsquo;a amené à travailler dans une entreprise spécialisée dans le Cloud, et plus particulièrement &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/how-i-automated-my-blog-to-the-cloud/aws.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;AWS logo&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;À l&amp;rsquo;époque, le Cloud était tout nouveau pour moi. Mais j&amp;rsquo;en entendais tellement parler, que je voulais connaître la raison de cet engouement. Était-ce vraiment un &amp;ldquo;game-changer&amp;rdquo;, comme certains le disaient, ou était-ce encore un de ces mots-clés techniques qui faisait le buzz ?&lt;/p&gt;
&lt;p&gt;Pour vous la faire courte, &lt;strong&gt;AWS était (et est toujours) absolument incroyable !&lt;/strong&gt; Ce n&amp;rsquo;était pas seulement la découverte d&amp;rsquo;un nouvel outil, il s&amp;rsquo;agissait là d&amp;rsquo;un changement de paradigme qui ne me ferait plus jamais aborder un problème de la même manière (si vous ne connaissez pas AWS et pensez que j&amp;rsquo;en fais trop, attendez de vous y mettre&amp;hellip;).&lt;/p&gt;
&lt;p&gt;Plus j&amp;rsquo;en apprenais sur AWS et la multitude de services qui le composait, plus je me disais : &lt;strong&gt;n&amp;rsquo;y a-t-il pas un moyen pour moi d&amp;rsquo;utiliser le Cloud pour mon blog ?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Avec cette idée en tête, je commençais à me renseigner sur toutes les options qu&amp;rsquo;offrait AWS. Et compte tenu de ma récente découverte d&amp;rsquo;Hugo, mon site n&amp;rsquo;avait ni besoin de PHP, ni d&amp;rsquo;une base de données pour fonctionner. Il s&amp;rsquo;agissait maintenant d&amp;rsquo;un site statique qui, à première vue, pouvait très bien être déployé dans un bucket S3.&lt;/p&gt;
&lt;p&gt;Et non seulement AWS offre une &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteHosting.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;documentation sur l&amp;rsquo;hébergement d&amp;rsquo;un site statique dans un bucket S3&lt;/a&gt;, mais &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/s3/pricing/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;le coût de stockage d&amp;rsquo;un site si léger ne représentait que quelques centimes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;avais trouvé là une manière simple et peu coûteuse d&amp;rsquo;héberger mon site.&lt;/p&gt;
&lt;p&gt;Le dernier point qui me chiffonait, est que pour mettre en place tout cela, je devais créer un bucket AWS S3, le configurer convenablement, rajouter le CDN AWS CloudFront, prendre en compte les certificats via AWS ACM, et finalement créer une entrée DNS dans AWS Route53. Tant d&amp;rsquo;actions qui, si réalisées manuellement, pouvaient être difficiles à reproduire si jamais je venais à accidentellement supprimer mon compte AWS.&lt;/p&gt;
&lt;p&gt;Il me fallait donc maintenant un moyen simple et robuste de configurer cette infrastructure.&lt;/p&gt;
&lt;h2 id=&#34;terraform-à-la-rescousse&#34;&gt;&lt;a href=&#34;#terraform-%c3%a0-la-rescousse&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Terraform à la rescousse
&lt;/h2&gt;&lt;p&gt;Quand vous commencez à apprendre le Cloud, vous allez généralement entendre parler d&amp;rsquo;&lt;a class=&#34;link&#34; href=&#34;https://fr.wikipedia.org/wiki/Infrastructure_as_code&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Infrastructure as Code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Le principe est simple : décrire son infrastructure Cloud avec&amp;hellip; du code ! (oui, comme son nom l&amp;rsquo;indique).&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;avantage d&amp;rsquo;utiliser un outil d&amp;rsquo;IaC, c&amp;rsquo;est que vous allez pouvoir garder en mémoire les changements effectués sur votre infrastructure, et pouvoir ainsi avoir un historique de toutes les modifications effectuées (un peu comme vous pouvez le faire avec du code classique sur GitHub).&lt;/p&gt;
&lt;p&gt;Imaginons par exemple que quelqu&amp;rsquo;un décide de changer la configuration d&amp;rsquo;un service AWS. Cette personne se connecte sur la console AWS et effectue ces modifications. Mais après plusieurs essais infructueux, cette personne décide de laisser tomber pour le moment, et de revenir en arrière. Mais voilà, elle n&amp;rsquo;est plus vraiment sûr de la manière dont le service était configuré au départ ! Et à moins d&amp;rsquo;avoir pris note de l&amp;rsquo;état initial, cette personne n&amp;rsquo;a plus qu&amp;rsquo;à deviner à coups de plusieurs essais l&amp;rsquo;état dans lequel remettre ce service.&lt;/p&gt;
&lt;p&gt;Tout cela aurait pû être évité si le service avait initialement été configuré avec un outil d&amp;rsquo;Infrastructure as Code. Si tel avait été le cas, un petit coup de déploiement automatique aurait fait l&amp;rsquo;affaire !&lt;/p&gt;
&lt;p&gt;Des outils d&amp;rsquo;IaC, il en existe un paquet. Mais comment ne pas parler du plus populaire, de celui qui a rendu cette pratique commune dans le milieu du Cloud : &lt;a class=&#34;link&#34; href=&#34;https://www.terraform.io/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Terraform&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/how-i-automated-my-blog-to-the-cloud/terraform.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Terraform logo&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Terraform est donc un outil d&amp;rsquo;Infrastructure as Code avec une approche déclarative, ce qui signifie que c&amp;rsquo;est à vous de déclarer l&amp;rsquo;état dans lequel vous souhaitez déployer votre infrastructure. Pour cela, il faut utiliser un langage bien particulier : le hcl (pour HashiCorp Configuration Language). Voici par exemple la création d&amp;rsquo;un bucket S3 via Terraform.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-terraform&#34; data-lang=&#34;terraform&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;resource&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;aws_s3_bucket&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;example&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;bucket&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;my-tf-test-bucket&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;tags&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;Name&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;My bucket&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;Environment&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Dev&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Revenons maintenant à mon blog ! Terraform me semblait l&amp;rsquo;outil parfait pour configurer mon infrastructure qui accueillerait mon blog. Je n&amp;rsquo;avais plus qu&amp;rsquo;à passer par une étape d&amp;rsquo;architecture pour savoir de quels services AWS j&amp;rsquo;aurais besoin et comment les connecter entre eux, avant de mettre la main dans le code pour définir tout cela en langage Terraform.&lt;/p&gt;
&lt;p&gt;Voici d&amp;rsquo;ailleurs le diagramme d&amp;rsquo;architecture que j&amp;rsquo;ai initialement crée pour l&amp;rsquo;occasion.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/how-i-automated-my-blog-to-the-cloud/blog_architecture_diagram.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Diagramme d’architecture de mon blog sur AWS, déployé par Terraform&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Tout cela était parfait, mais je me rendis vite compte d&amp;rsquo;une chose. À chaque fois que j&amp;rsquo;allais rajouter un article, ou que je devais modifier mon infrastructure, il me fallait cloner le projet sur mon ordinateur, et effectuer tout un tas d&amp;rsquo;opérations manuelles.&lt;/p&gt;
&lt;p&gt;Autant vous dire que cela ne me plaisait pas du tout, et je comptais bien y remédier !&lt;/p&gt;
&lt;h2 id=&#34;oubliez-les-copier-coller-avec-github-actions&#34;&gt;&lt;a href=&#34;#oubliez-les-copier-coller-avec-github-actions&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Oubliez les copier-coller avec GitHub Actions
&lt;/h2&gt;&lt;p&gt;Comme je le disais juste au-dessus, mon site était fin prêt. La dernière étape qui me manquait concernait &lt;strong&gt;le déploiement&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Pour l&amp;rsquo;instant, quand je voulais créer un nouvel article, il me fallait build le site Hugo à la main, et déplacer les fichiers générés dans mon bucket S3. Quel terrible gâchis de temps et d&amp;rsquo;énergie !&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai donc creusé le sujet des pipelines CI/CD afin de me rendre la vie plus simple (si le sujet vous intéresse, je vous conseille &lt;a class=&#34;link&#34; href=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/how-we-built-a-cicd-strategy-that-onboards-100-python-projects-in-under-a-minute/&#34; &gt;mon article sur la mise en place d&amp;rsquo;une stratégie CI/CD&lt;/a&gt;). Et bien que Jenkins essayait à tout prix de se distinguer, je suis parti sur ce qui semblait être le plus logique : &lt;a class=&#34;link&#34; href=&#34;https://github.com/features/actions&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;GitHub Actions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/how-i-automated-my-blog-to-the-cloud/github_actions.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;GitHub Actions logo&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Les GitHub Actions sont en fait des pipelines CI/CD qui sont définies directement dans votre repository GitHub. Le gros avantage, est que vous n&amp;rsquo;avez pas besoin de créer un compte supplémentaire ou d&amp;rsquo;installer quoi que ce soit, tout est inclus ! En plus de ça, GitHub Actions utilise une syntaxe YAML très facile à comprendre (contrairement à Jenkins et son groovy des enfers !).&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est donc assez facilement que j&amp;rsquo;ai pû créer une pipeline qui me reconfigure Terraform si mon infrastructure a été modifiée, et qui me build et deploy automatiquement mon blog sur mon bucket S3 en cas de modifications ou ajout d&amp;rsquo;un article.&lt;/p&gt;
&lt;p&gt;Toutes les steps de la pipeline sont au vert, mission accomplie !&lt;/p&gt;
&lt;h1 id=&#34;côté-technique--létat-actuel-des-choses&#34;&gt;&lt;a href=&#34;#c%c3%b4t%c3%a9-technique--l%c3%a9tat-actuel-des-choses&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Côté technique : L&amp;rsquo;état actuel des choses
&lt;/h1&gt;&lt;p&gt;Mon blog est désormais automatisé et se déploie sur AWS automatiquement !&lt;/p&gt;
&lt;p&gt;Si vous voulez plonger directement dedans, tout est publique sur mon repository GitHub : &lt;a class=&#34;link&#34; href=&#34;https://github.com/antoinedelia/cloud-optimist&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/antoinedelia/cloud-optimist&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Mais laissez-moi détailler un peu tout ça.&lt;/p&gt;
&lt;h2 id=&#34;structure-du-projet&#34;&gt;&lt;a href=&#34;#structure-du-projet&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Structure du projet
&lt;/h2&gt;&lt;p&gt;La structure de mon projet est comme suit :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cloud-optimist/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── .github/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   └── workflows/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│       └── main.yml  &lt;span class=&#34;c1&#34;&gt;# GitHub Actions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── cloud/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   └── ...  &lt;span class=&#34;c1&#34;&gt;# Mon blog Hugo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── terraform/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   └── ...  &lt;span class=&#34;c1&#34;&gt;# La configuration Terraform&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;└── README.md
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Comme vous le voyez, je sépare ce projet en trois dossiers clés :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.github&lt;/code&gt; : contient le fichier &lt;code&gt;main.yml&lt;/code&gt; qui définit les étapes CI/CD de la GitHub Actions&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cloud&lt;/code&gt; : contient mon blog Hugo&lt;/li&gt;
&lt;li&gt;&lt;code&gt;terraform&lt;/code&gt; : contient toute l&amp;rsquo;infrastructure Terraform&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;la-github-actions&#34;&gt;&lt;a href=&#34;#la-github-actions&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;La GitHub Actions
&lt;/h2&gt;&lt;p&gt;Ma GitHub Actions est assez simple, et se décompose en plusieurs étapes.&lt;/p&gt;
&lt;h3 id=&#34;les-étapes-de-préparation&#34;&gt;&lt;a href=&#34;#les-%c3%a9tapes-de-pr%c3%a9paration&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Les étapes de préparation
&lt;/h3&gt;&lt;p&gt;Regardons d&amp;rsquo;abord le haut du fichier.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Build and Deploy&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;on&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;push&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;branches&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;master&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;pull_request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;jobs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;build-and-deploy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Build &amp;amp; Deploy&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;runs-on&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;ubuntu-latest&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;environment&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;production&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;defaults&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;shell&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;bash&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;working-directory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;cloud&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Ici, je dis à GitHub de lancer la pipeline uniquement sur la branch &lt;code&gt;master&lt;/code&gt;, ou s&amp;rsquo;il s&amp;rsquo;agit d&amp;rsquo;une Pull Request. Je vous rassure, je ne déplois rien en production via une Pull Request. Vous verrez un peu plus bas, que cela me permet uniquement de build mon blog afin de tester que tout va bien, mais le déploiement ne sera effectué qu&amp;rsquo;une fois les changements mergés sur la branch &lt;code&gt;master&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;indique également à GitHub d&amp;rsquo;utiliser &lt;code&gt;bash&lt;/code&gt;, et de se baser par défaut dans le dossier &lt;code&gt;cloud&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Voyons maintenant la suite :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;steps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;uses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;actions/checkout@v3&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;uses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;dorny/paths-filter@v2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;filter&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;with&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;filters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sd&#34;&gt;          web:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sd&#34;&gt;            - &amp;#39;cloud/**&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sd&#34;&gt;          terraform:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sd&#34;&gt;            - &amp;#39;terraform/**&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Cette première étape est cruciale si vous voulez accélérer vos temps de CI/CD ainsi qu&amp;rsquo;économiser de l&amp;rsquo;argent.&lt;/p&gt;
&lt;p&gt;Je me sers de l&amp;rsquo;actions &lt;a class=&#34;link&#34; href=&#34;https://github.com/dorny/paths-filter&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;dorny/paths-filter&lt;/a&gt; qui me permet de &lt;strong&gt;détecter quels fichiers ont été modifiés lors du dernier commit&lt;/strong&gt;. Dans mon cas, je regarde en particulier les dossiers &lt;code&gt;cloud&lt;/code&gt; et &lt;code&gt;terraform&lt;/code&gt;. Ainsi, si je ne détecte pas de changements côté Terraform, aucun besoin de lancer l&amp;rsquo;étape qui va reconfigurer mon infrastructure. Idem, si le dossier &lt;code&gt;cloud&lt;/code&gt; est intact, inutile de build et deploy le blog. Cela vous sauvera quelques centimes liés au coût de transfert de fichiers vers AWS (pas la peine de me remercier !).&lt;/p&gt;
&lt;p&gt;La section suivante parle d&amp;rsquo;elle-même.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# Checkout the repository to the GitHub Actions runner&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Checkout&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;uses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;actions/checkout@v2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Update Git Submodules&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;working-directory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;./&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;git submodule update --init --recursive&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Je viens récupérer le contenu de mon repository et m&amp;rsquo;assure de mettre à jour les submodules. Cette dernière étape me servait du temps où j&amp;rsquo;utilisais les submodules pour mes thèmes Hugo. J&amp;rsquo;utilise désormais les &lt;a class=&#34;link&#34; href=&#34;https://gohugo.io/hugo-modules/use-modules/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Hugo Modules&lt;/a&gt;, et je pourrais donc zapper cette étape.&lt;/p&gt;
&lt;h3 id=&#34;les-étapes-terraform&#34;&gt;&lt;a href=&#34;#les-%c3%a9tapes-terraform&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Les étapes Terraform
&lt;/h3&gt;&lt;p&gt;Passons à la partie Terraform :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# Install the latest version of Terraform CLI and configure the Terraform CLI configuration file with a Terraform Cloud user API token&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Setup Terraform&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;steps.filter.outputs.terraform == &amp;#39;true&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;uses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;hashicorp/setup-terraform@v1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;with&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;cli_config_credentials_token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;${{ secrets.TF_API_TOKEN }}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# Initialize a new or existing Terraform working directory by creating initial files, loading any remote state, downloading modules, etc.&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Terraform Init&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;steps.filter.outputs.terraform == &amp;#39;true&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;working-directory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;./terraform&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;terraform init&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# Checks that all Terraform configuration files adhere to a canonical format&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Terraform Format&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;steps.filter.outputs.terraform == &amp;#39;true&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;working-directory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;./terraform&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;terraform fmt -check&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# Generates an execution plan for Terraform&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Terraform Plan&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;steps.filter.outputs.terraform == &amp;#39;true&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;working-directory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;./terraform&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;terraform plan&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# On push to master, build or change infrastructure according to Terraform configuration files&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Terraform Apply&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;working-directory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;./terraform&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;steps.filter.outputs.terraform == &amp;#39;true&amp;#39; &amp;amp;&amp;amp; github.ref == &amp;#39;refs/heads/master&amp;#39; &amp;amp;&amp;amp; github.event_name == &amp;#39;push&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;terraform apply -auto-approve&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;C&amp;rsquo;est déjà bien plus long ! Analysons ça étape par étape.&lt;/p&gt;
&lt;p&gt;La première chose qui devrait attirer votre attention, c&amp;rsquo;est cette ligne :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;steps.filter.outputs.terraform == &amp;#39;true&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Vous vous rappelez, c&amp;rsquo;est ce qui permet de dire si des fichiers ont été modifiés dans le dossier &lt;code&gt;terraform&lt;/code&gt;. Je vérifie donc ici si j&amp;rsquo;ai besoin de lancer ces étapes ou non.&lt;/p&gt;
&lt;p&gt;Ensuite, je lance quelques commandes basiques de Terraform : un &lt;code&gt;terraform init&lt;/code&gt; pour initialiser mon projet, un &lt;code&gt;terraform fmt -check&lt;/code&gt; pour m&amp;rsquo;assurer que mon code est tout joli, et enfin un &lt;code&gt;terraform plan&lt;/code&gt; pour voir les changements à effectuer.&lt;/p&gt;
&lt;p&gt;Reste une dernière étape, et pas des moindres : le &lt;code&gt;terraform apply -auto-approve&lt;/code&gt;, qui permettra de déployer les changements. Mais si vous êtes attentifs, vous remarquerez que j&amp;rsquo;ai rajouté deux conditions :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;l&#34;&gt;github.ref == &amp;#39;refs/heads/master&amp;#39; &amp;amp;&amp;amp; github.event_name == &amp;#39;push&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Cela me garantit que &lt;strong&gt;cette étape ne sera uniquement lancée si l&amp;rsquo;action est un &lt;code&gt;push&lt;/code&gt; sur la branch &lt;code&gt;master&lt;/code&gt;&lt;/strong&gt;. Ainsi, aucun risque de déploiement inopportun si je décide de travailler sur une autre branch ou sur une Pull Request. Ouf !&lt;/p&gt;
&lt;h3 id=&#34;les-étapes-hugo-et-aws&#34;&gt;&lt;a href=&#34;#les-%c3%a9tapes-hugo-et-aws&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Les étapes Hugo et AWS
&lt;/h3&gt;&lt;p&gt;Maintenant que mon infrastructure est au point, il est temps de publier mon blog !&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Build&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;uses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;actions/setup-node@v2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;steps.filter.outputs.web == &amp;#39;true&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;sudo wget https://github.com/gohugoio/hugo/releases/download/v0.142.0/hugo_extended_0.142.0_linux-amd64.deb -O hugo.deb&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;sudo dpkg --install ./hugo.deb&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;hugo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Deploy to AWS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;uses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;jakejarvis/s3-sync-action@master&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;steps.filter.outputs.web == &amp;#39;true&amp;#39; &amp;amp;&amp;amp; github.ref == &amp;#39;refs/heads/master&amp;#39; &amp;amp;&amp;amp; github.event_name == &amp;#39;push&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;with&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--&lt;span class=&#34;l&#34;&gt;acl public-read --follow-symlinks --delete&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;env&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;AWS_S3_BUCKET&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;${{ secrets.AWS_S3_BUCKET }}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;${{ secrets.AWS_ACCESS_KEY_ID }}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;${{ secrets.AWS_SECRET_ACCESS_KEY }}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;AWS_REGION&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;eu-west-1&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;SOURCE_DIR&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;cloud/public/&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Comme pour Terraform, nous vérifions si des modifications ont été effectuées au niveau du blog.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;steps.filter.outputs.web == &amp;#39;true&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Ensuite, je récupère une version extended d&amp;rsquo;Hugo directement depuis la release GitHub, ici la version v0.142.0. Je l&amp;rsquo;installe et build mon site en lançant la commande &lt;code&gt;hugo&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Cette étape pourrait être simplifiée avec l&amp;rsquo;utilisation de l&amp;rsquo;actions &lt;a class=&#34;link&#34; href=&#34;https://github.com/peaceiris/actions-hugo&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;peaceiris/actions-hugo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Enfin, j&amp;rsquo;utilise l&amp;rsquo;actions &lt;a class=&#34;link&#34; href=&#34;https://github.com/jakejarvis/s3-sync-action&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;jakejarvis/s3-sync-action&lt;/a&gt; (je me rends compte en écrivant cet article que cette actions a été archivée quelques jours plus tôt, aïe ! &amp;ndash; je rajouterai un edit plus tard pour parler d&amp;rsquo;une alternative) pour déplacer mon blog vers mon bucket S3.&lt;/p&gt;
&lt;p&gt;Bien sûr, il vous faudra stocker vos credentials au niveau de votre repository GitHub pour autoriser cette opération vers AWS, mais rien de bien sorcier !&lt;/p&gt;
&lt;h2 id=&#34;la-partie-terraform&#34;&gt;&lt;a href=&#34;#la-partie-terraform&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;La partie Terraform
&lt;/h2&gt;&lt;p&gt;Concernant la partie Terraform, je vais essayer d&amp;rsquo;être bref, car il n&amp;rsquo;y a rien de bien compliqué.&lt;/p&gt;
&lt;p&gt;Une particularité dans mon cas, c&amp;rsquo;est que &lt;strong&gt;j&amp;rsquo;aime séparer mes fichiers &lt;code&gt;.tf&lt;/code&gt; en fonction des services AWS utilisés&lt;/strong&gt;, plutôt que d&amp;rsquo;avoir un unique fichier &lt;code&gt;main.tf&lt;/code&gt; qui peut vite devenir difficile à lire. J&amp;rsquo;ai donc un fichier &lt;code&gt;s3.tf&lt;/code&gt; pour les ressources liées au service S3, un &lt;code&gt;cloudfront.tf&lt;/code&gt; pour tout ce qui est lié au service CloudFront, etc.&lt;/p&gt;
&lt;p&gt;Un détail important, c&amp;rsquo;est qu&amp;rsquo;&lt;strong&gt;il est nécessaire de définir à minima la region &lt;code&gt;us-east-1&lt;/code&gt;&lt;/strong&gt;, car c&amp;rsquo;est dans cette region que vous devez créer vos certificats ACM. Pour le reste, toutes mes ressources sont créées dans la region &lt;code&gt;eu-west-1&lt;/code&gt;. J&amp;rsquo;utilise pour cela les &lt;a class=&#34;link&#34; href=&#34;https://developer.hashicorp.com/terraform/language/providers/configuration#alias-multiple-provider-configurations&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;alias Terraform&lt;/a&gt;. Voici un exemple :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-terraform&#34; data-lang=&#34;terraform&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# La configuration par défaut : les ressources qui commencent par `aws_` utiliseront ce provider
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;provider&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;aws&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;region&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;eu-west-1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;provider&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;aws&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;region&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;us-east-1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;alias&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;us_east_1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;resource&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;aws_s3_bucket&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;site&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;bucket&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;bucket_name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;force_destroy&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;resource&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;aws_acm_certificate&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;cert&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;provider&lt;/span&gt;                  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;aws&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;us_east_1&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;  # Utilise le provider AWS dans us-east-1 via son alias
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;domain_name&lt;/span&gt;               &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;domain_name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;subject_alternative_names&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;*.&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;domain_name&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;validation_method&lt;/span&gt;         &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;DNS&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;la-partie-hugo&#34;&gt;&lt;a href=&#34;#la-partie-hugo&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;La partie Hugo
&lt;/h2&gt;&lt;p&gt;Mon blog Hugo se base sur le theme &lt;a class=&#34;link&#34; href=&#34;https://themes.gohugo.io/themes/hugo-theme-stack/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Stack&lt;/a&gt;. Il existe d&amp;rsquo;ailleurs un &lt;a class=&#34;link&#34; href=&#34;https://github.com/CaiJimmy/hugo-theme-stack-starter&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;template GitHub&lt;/a&gt; qui vous permet en un clic de récupérer le squelette du blog, et de l&amp;rsquo;adapter selon vos envies, ou de tout simplement vous concentrer directement sur vos articles.&lt;/p&gt;
&lt;p&gt;Pas grande chose de plus à dire sur cette partie, si ce n&amp;rsquo;est que je vous encourage à voir le fonctionnement des &lt;a class=&#34;link&#34; href=&#34;https://gohugo.io/hugo-modules/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Hugo Modules&lt;/a&gt;, ce qui vous évitera de gérer vos thèmes via un submodule (et qui vous simplifiera la vie lors de la mise à jour du thème).&lt;/p&gt;
&lt;h1 id=&#34;pistes-daméliorations&#34;&gt;&lt;a href=&#34;#pistes-dam%c3%a9liorations&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Pistes d&amp;rsquo;améliorations
&lt;/h1&gt;&lt;p&gt;Bien que je sois très satisfait du résultat final, j&amp;rsquo;ai noté quelques points qui pourraient être améliorés dans le futur.&lt;/p&gt;
&lt;p&gt;D&amp;rsquo;abord, j&amp;rsquo;ai vu qu&amp;rsquo;Hugo dispose d&amp;rsquo;une commande &lt;code&gt;deploy&lt;/code&gt; qui est capable de déployer directement un blog sur un bucket S3. Parfait ! Je dois donc creuser le sujet de &lt;a class=&#34;link&#34; href=&#34;https://gohugo.io/hosting-and-deployment/hugo-deploy/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Hugo Deploy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Enfin, même si l&amp;rsquo;hébergement dans AWS est peu coûteux (moins de 2$ par mois), il n&amp;rsquo;en est pas moins gratuit. Or, il serait tout à fait possible d&amp;rsquo;utiliser les &lt;a class=&#34;link&#34; href=&#34;https://pages.github.com/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;GitHub Pages&lt;/a&gt; pour rendre ce blog accessible, et profiter de GitHub comme hébergement (là-dessus, je suis un peu moins emballé, car je ne pourrais plus me la péter avec mes jolis diagrammes AWS&amp;hellip;).&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;&lt;a href=&#34;#conclusion&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Conclusion
&lt;/h1&gt;&lt;p&gt;Et voilà, vous savez tout !&lt;/p&gt;
&lt;p&gt;De mes débuts avec WordPress, qui, bien que pratique, présentait des faiblesses du point de vue backup, maintenance et déploiement.&lt;/p&gt;
&lt;p&gt;De mes recherches pour trouver une stack technique parfaite : AWS, Terraform, Hugo et GitHub Actions, tout ça pour permettre un déploiement rapide et à moindre coût !&lt;/p&gt;
&lt;p&gt;Quand je compare avec ce que j&amp;rsquo;avais à l&amp;rsquo;époque, je ne suis que trop heureux d&amp;rsquo;avoir sauté le pas !&lt;/p&gt;
&lt;p&gt;Et vous aussi, vous avez maintenant toutes les informations pour créer un blog à vous, et déployer tout ça en un clin d&amp;rsquo;oeil !&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Happy blogging !&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/how-i-automated-my-blog-to-the-cloud/happy_blog.jpeg&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Réussite de la migration de mon blog vers le Cloud&#34;
	
	
&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Comment mettre en place une stratégie CI/CD pour onboarder plus de 100 projets Python en moins d&#39;une minute</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/how-we-built-a-cicd-strategy-that-onboards-100-python-projects-in-under-a-minute/</link>
        <pubDate>Sun, 19 Jan 2025 16:45:00 +0200</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/how-we-built-a-cicd-strategy-that-onboards-100-python-projects-in-under-a-minute/</guid>
        <description>&lt;img src="https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/how-we-built-a-cicd-strategy-that-onboards-100-python-projects-in-under-a-minute/ci-cd-strategy.jpeg" alt="Featured image of post Comment mettre en place une stratégie CI/CD pour onboarder plus de 100 projets Python en moins d&#39;une minute" /&gt;&lt;p&gt;Nous savons tous que les pipelines CI/CD sont importantes. Il semble même impossible d&amp;rsquo;imaginer un monde où l’on déploie un projet en production sans vérifier la qualité de son code et sans s&amp;rsquo;assurer que des tests ont été effectués. De plus, pour permettre aux développeurs de se concentrer sur le développement, tout cela devrait être automatisé.&lt;/p&gt;
&lt;p&gt;Eh bien, les choses ne sont pas toujours aussi simples.&lt;/p&gt;
&lt;p&gt;Aujourd&amp;rsquo;hui, je vais vous partager comment nous sommes passés de l&amp;rsquo;absence de stratégie CI/CD à l&amp;rsquo;intégration de plus de 100 projets Python en moins d&amp;rsquo;une minute.&lt;/p&gt;
&lt;h1 id=&#34;la-réalité&#34;&gt;&lt;a href=&#34;#la-r%c3%a9alit%c3%a9&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;La réalité
&lt;/h1&gt;&lt;p&gt;Lorsque j&amp;rsquo;ai rejoint mon entreprise actuelle, j&amp;rsquo;ai constaté que nous gérions un grand nombre de projets Python. Mais quand j&amp;rsquo;ai essayé de vérifier la CI/CD de ces projets, c’était un peu le bazar. Certains projets avaient une configuration CI/CD, mais pas beaucoup. Et ceux qui en avaient une n’utilisaient pas les mêmes règles pour vérifier la conformité du code. Il était clair que la mise en place d’une CI/CD pour chaque projet était traitée comme un effort de dernier recours. Et, pour être honnête, cela se comprend.&lt;/p&gt;
&lt;p&gt;En effet, bien que les pipelines CI/CD soient largement reconnues pour leur efficacité, leur mise en place s&amp;rsquo;avère souvent difficile.&lt;/p&gt;
&lt;p&gt;Mais je savais que nous pouvions changer cela d&amp;rsquo;une manière ou d&amp;rsquo;une autre. Avant de sauter dans une stratégie à mettre en place, je voulais comprendre ce qui avait empêché cette mise en place en premier lieu.&lt;/p&gt;
&lt;h2 id=&#34;manque-de-permissions&#34;&gt;&lt;a href=&#34;#manque-de-permissions&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Manque de permissions
&lt;/h2&gt;&lt;p&gt;La première chose que j&amp;rsquo;ai réalisée, c&amp;rsquo;est que tous les développeurs n&amp;rsquo;avaient pas le même niveau d&amp;rsquo;accès à notre instance Jenkins. Tandis que certains pouvaient créer de nouvelles pipelines pour leurs projets, d&amp;rsquo;autres ne le pouvaient pas. Dans les grandes entreprises, ce genre de scénario n&amp;rsquo;est pas rare.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Leçon apprise : un manque de permissions ne devrait pas être un obstacle pour utiliser une pipeline CI/CD.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;manque-de-connaissances&#34;&gt;&lt;a href=&#34;#manque-de-connaissances&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Manque de connaissances
&lt;/h2&gt;&lt;p&gt;Lorsque les développeurs avaient la possibilité de créer un pipeline, certains ne le faisaient pas, simplement parce qu&amp;rsquo;ils n&amp;rsquo;avaient pas les connaissances nécessaires. Il faut préciser que notre entreprise utilise une instance Jenkins comme outil officiel de CI/CD. Cet outil, bien qu&amp;rsquo;ayant fait ses preuves, reste pour le moins difficile d&amp;rsquo;usage, notamment pour les jeunes développeurs qui sont souvent familiers avec d&amp;rsquo;autres outils CI/CD (comme GitHub Actions ou CircleCI). De plus, nous n&amp;rsquo;avions pas de documentation claire sur le processus à suivre pour créer une nouvelle pipeline. Ainsi certains développeurs, de peur de casser quelque chose, préféraient ne pas prendre de risques en évitant de toucher à Jenkins.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Leçon apprise : nous devons nous assurer que les personnes sans connaissances sur Jenkins puissent utiliser un pipeline CI/CD.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;manque-de-temps&#34;&gt;&lt;a href=&#34;#manque-de-temps&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Manque de temps
&lt;/h2&gt;&lt;p&gt;Mettre en place une pipeline CI/CD au début d&amp;rsquo;un projet demande du temps, chose qui peut être négligée par les chefs de projets qui veulent expédier un produit aussi rapidement que possible. De plus, il est parfois difficile de quantifier le retour sur investissement d’une pipeline CI/CD. Et si cela est difficile à prouver comme étant bénéfique pour l’entreprise, cela finit dans la boîte &amp;ldquo;on s&amp;rsquo;en occupera plus tard&amp;rdquo;. Et nous savons tous que les tâches qui finissent dans cette boîte ne verront plus jamais la lumière du jour.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Leçon apprise : la mise en place d’une pipeline CI/CD doit être rapide et simple.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;manque-de-guidelines-claires&#34;&gt;&lt;a href=&#34;#manque-de-guidelines-claires&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Manque de guidelines claires
&lt;/h2&gt;&lt;p&gt;Enfin, j&amp;rsquo;ai jeté un œil aux projets qui &lt;em&gt;eux&lt;/em&gt; avaient une pipeline CI/CD. Ils fonctionnaient bien, mais je pouvais clairement voir qu&amp;rsquo;ils manquaient d&amp;rsquo;une vision commune. Certains utilisaient le même formateur de code (black), mais pas toujours avec la même longueur de ligne. Certains incluaient une étape de test, d&amp;rsquo;autres non. Nous avions donc des projets n&amp;rsquo;ayant pas la même qualité et conformité de code. Et cela pouvait potentiellement créer de la confusion pour un nouveau développeur, ne sachant pas quel standard suivre.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Leçon apprise : des guidelines claires de CI/CD doivent être mises en place.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&#34;la-vision-globale&#34;&gt;&lt;a href=&#34;#la-vision-globale&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;La vision globale
&lt;/h1&gt;&lt;p&gt;Après avoir analysé ce qui pouvait poser problème, il est maintenant important de penser à une solution qui puisse résoudre tous ces points, tout en respectant les meilleures pratiques de l&amp;rsquo;entreprise et en utilisant les outils à notre disposition.&lt;/p&gt;
&lt;h2 id=&#34;formatting&#34;&gt;&lt;a href=&#34;#formatting&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Formatting
&lt;/h2&gt;&lt;p&gt;La première étape serait d&amp;rsquo;utiliser un formateur pour s&amp;rsquo;assurer que chaque ligne de code dans notre base de code soit uniforme. Cela permet d’éviter que nous ayons des standards de code différents à travers nos projets.&lt;/p&gt;
&lt;p&gt;Auparavant, nous utilisions &lt;code&gt;black&lt;/code&gt; comme formateur. Mais après avoir entendu beaucoup de bien sur le nouvel outil à la mode, nous avons décidé de passer à &lt;code&gt;ruff&lt;/code&gt;, offrant les mêmes avantages que &lt;code&gt;black&lt;/code&gt;, mais avec une exécution plus rapide (entre autres).&lt;/p&gt;
&lt;h2 id=&#34;linting&#34;&gt;&lt;a href=&#34;#linting&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Linting
&lt;/h2&gt;&lt;p&gt;L&amp;rsquo;étape suivante serait d&amp;rsquo;utiliser un linter pour détecter les problèmes potentiels dans notre code. Cela nous permet d&amp;rsquo;éviter la complexité dans notre code, ainsi que de repérer les mauvaises pratiques ou les problèmes de sécurité.&lt;/p&gt;
&lt;p&gt;Dans le passé, j’utilisais beaucoup &lt;code&gt;flake8&lt;/code&gt;. Mais étant donné que nous utilisions déjà &lt;code&gt;ruff&lt;/code&gt;, et que celui-ci peut également agir comme un linter, la question ne se posait plus.&lt;/p&gt;
&lt;p&gt;Il existe de nombreuses règles que &lt;code&gt;ruff&lt;/code&gt; peut appliquer. Nous avons décidé d&amp;rsquo;en utiliser certaines par défaut, tout en laissant une certaine liberté aux développeurs selon les projets.&lt;/p&gt;
&lt;h2 id=&#34;tests-unitaires&#34;&gt;&lt;a href=&#34;#tests-unitaires&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Tests unitaires
&lt;/h2&gt;&lt;p&gt;Les tests sont une partie critique du développement de tout projet. Ils assurent que nous livrons un code de qualité en production, tout en nous permettant de nous assurer que notre code fonctionnera correctement.&lt;/p&gt;
&lt;p&gt;Nous avons décidé d’utiliser &lt;code&gt;pytest&lt;/code&gt; pour exécuter ces tests. Le répertoire de code par défaut devrait s&amp;rsquo;appeler &lt;code&gt;src&lt;/code&gt;, et tous les tests devraient être dans un dossier &lt;code&gt;tests&lt;/code&gt;, avec des fichiers préfixés par &lt;code&gt;test_&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;code-coverage&#34;&gt;&lt;a href=&#34;#code-coverage&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Code Coverage
&lt;/h2&gt;&lt;p&gt;Étroitement liée aux tests unitaires, le code coverage nous permet de savoir jusqu&amp;rsquo;où notre code a été testé. Cela peut nous indiquer rapidement si nous avons suffisamment testé notre code, ainsi que nous indiquer les lignes restantes à couvrir.&lt;/p&gt;
&lt;p&gt;Comme nous utilisions &lt;code&gt;pytest&lt;/code&gt;, nous avons décidé d&amp;rsquo;utiliser &lt;code&gt;pytest-cov&lt;/code&gt; pour générer un coverage report, car il s&amp;rsquo;intègre parfaitement avec &lt;code&gt;pytest&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Nous avons fixé le seuil de couverture minimale à 50 %. En dessous, cela risquerait de négliger des portions importantes du code, tandis qu’au-dessus, cela pourrait décourager les développeurs d&amp;rsquo;écrire les tests nécessaires.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/how-we-built-a-cicd-strategy-that-onboards-100-python-projects-in-under-a-minute/detailed-view-of-the-code-coverage-step.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Detailed view of the code coverage step&#34;
	
	
&gt;&lt;/p&gt;
&lt;h2 id=&#34;jenkins-organization-folders&#34;&gt;&lt;a href=&#34;#jenkins-organization-folders&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Jenkins Organization Folders
&lt;/h2&gt;&lt;p&gt;Les étapes de notre futur pipeline étaient prêtes. Il nous restait à trouver un moyen d&amp;rsquo;appliquer globalement cette pipeline à nos repositories Python. J’ai alors cherché un moyen de le faire facilement via Jenkins.&lt;/p&gt;
&lt;p&gt;C’est là que je suis tombé sur les &lt;a class=&#34;link&#34; href=&#34;https://www.jenkins.io/doc/book/using/best-practices/#use-organization-folders&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Organization Folders&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Les Organization Folders sont conçus pour des scénarios comme le nôtre : scanner automatiquement une organisation (comme une organisation GitHub), filtrer les repositories que vous voulez et appliquer une pipeline Jenkins à ces derniers.&lt;/p&gt;
&lt;p&gt;Dans notre exemple, nous pouvons rechercher tous les repositories avec le topic &amp;ldquo;python&amp;rdquo; et les identifier comme projets Python. Ils seront alors automatiquement build par Jenkins. Si un nouveau repository est créé avec ce topic, il sera également pris en charge par Jenkins.&lt;/p&gt;
&lt;p&gt;Ainsi, en moins de 5 secondes, votre projet peut être intégré, sans avoir à le créer dans Jenkins. Tout est fait automatiquement pour que vous puissiez vous concentrer sur votre code.&lt;/p&gt;
&lt;h2 id=&#34;exemples-et-documentation&#34;&gt;&lt;a href=&#34;#exemples-et-documentation&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Exemples et documentation
&lt;/h2&gt;&lt;p&gt;Tout cela était génial, mais je redoutais un dernier obstacle. Que se passerait-il si les développeurs essayaient cette pipeline CI/CD, tout ça pour se rendre compte que leur projet ne passaient pas ces étapes ? Sans documentation claire pour résoudre ces problèmes, ils abandonneraient ou essaieraient de corriger ces erreurs plus tard, ce qui détruirait notre objectif initial.&lt;/p&gt;
&lt;p&gt;Je savais donc que pour embarquer les gens dans ce processus, il fallait fournir une documentation claire avec des exemples concrets, pour qu&amp;rsquo;ils puissent avoir les clés pour résoudre ces erreurs.&lt;/p&gt;
&lt;p&gt;En particulier pour l&amp;rsquo;étape des tests unitaires, car je ne sais que trop bien que cela représente une tâche décourageante à démarrer. J’ai donc préparé un projet à l&amp;rsquo;avance avec des tests unitaires déjà prêts. N&amp;rsquo;importe qui pouvait ainsi s&amp;rsquo;en inspirer, ou direcement recopier certaines parties complexes (par exemple, le mock des appels API boto3).&lt;/p&gt;
&lt;p&gt;La dernière étape serait de faire une présentation sur tout ce que je viens d&amp;rsquo;évoquer. Cela était essentiel pour expliquer et donner du sens à ce projet, pour que les développeurs comprennent réellement l&amp;rsquo;intérêt de tout cela, tout en s’assurant qu&amp;rsquo;ils aient toutes les clés pour être autonomes. Enfin, cela serait également l&amp;rsquo;occasion de répondre à de nombreuses questions, et assurer que tout le monde comprenne le fonctionnement de cette nouvelle pipeline.&lt;/p&gt;
&lt;h1 id=&#34;ce-que-nous-avons-aujourdhui&#34;&gt;&lt;a href=&#34;#ce-que-nous-avons-aujourdhui&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Ce que nous avons aujourd&amp;rsquo;hui
&lt;/h1&gt;&lt;p&gt;Du point de vue d’un développeur, tout ce qu&amp;rsquo;il doit faire pour ajouter une pipeline CI/CD à son projet Python est d’ajouter le topic &lt;code&gt;python&lt;/code&gt; à son repository et de s&amp;rsquo;assurer qu&amp;rsquo;un fichier &lt;code&gt;pyproject.toml&lt;/code&gt; est bien créé à la racine du projet.&lt;/p&gt;
&lt;p&gt;Ces deux exigences permettent à Jenkins de savoir quels projets il doit prendre en compte. Le fichier &lt;code&gt;pyproject.toml&lt;/code&gt; est en effet indispensable pour les étapes de &lt;code&gt;ruff&lt;/code&gt; dans la pipeline.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/how-we-built-a-cicd-strategy-that-onboards-100-python-projects-in-under-a-minute/two-simple-steps-to-get-onboarded-with-cicd-pipelines.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Two simple steps to get onboarded with CI/CD pipelines&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Une fois cela fait, le projet Python vérifiera maintenant les problèmes de formatage, les erreurs de linting, la validation des tests unitaires et la couverture du code.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/how-we-built-a-cicd-strategy-that-onboards-100-python-projects-in-under-a-minute/jenkins-python-cicd-pipeline.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Jenkins Python CI/CD pipeline&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Au final, nous pouvons maintenant mettre en place des pipelines CI/CD en moins d&amp;rsquo;une minute, que ce soit pour un nouveau projet ou un projet existant !&lt;/p&gt;
&lt;h1 id=&#34;quelques-défauts&#34;&gt;&lt;a href=&#34;#quelques-d%c3%a9fauts&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Quelques défauts
&lt;/h1&gt;&lt;p&gt;Bien que cela simplifie beaucoup de choses, il reste encore des améliorations possibles.&lt;/p&gt;
&lt;h2 id=&#34;la-pipeline-ne-peut-pas-être-imposée&#34;&gt;&lt;a href=&#34;#la-pipeline-ne-peut-pas-%c3%aatre-impos%c3%a9e&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;La pipeline ne peut pas être imposée
&lt;/h2&gt;&lt;p&gt;Actuellement, cette pipeline CI/CD ne peut pas être imposée, car les développeurs peuvent simplement retirer le topic &lt;code&gt;python&lt;/code&gt;. Et bien que cela soit acceptable au début (car nous ne voulons pas bloquer les développeurs dans leur travail), l&amp;rsquo;objectif reste de s’assurer que nous appliquons les mêmes bonnes pratiques à tous les projets Python.&lt;/p&gt;
&lt;p&gt;Cela pourrait être résolu à l&amp;rsquo;avenir par l&amp;rsquo;utilisation des &lt;a class=&#34;link&#34; href=&#34;https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/about-rulesets&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;GitHub Rulesets&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ces règles fonctionnent à peu près de la même manière que les règles de protection des branches, sauf que vous définissez ces règles au niveau de votre organisation GitHub.&lt;/p&gt;
&lt;p&gt;De cette manière, nous pourrions protéger nos branches principales pour tous nos repositories qui matchent à des &amp;ldquo;custom properties&amp;rdquo; et ainsi exiger qu&amp;rsquo;ils valident leur pipeline CI/CD avant de pouvoir merger.&lt;/p&gt;
&lt;h2 id=&#34;les-étapes-de-la-pipeline-peuvent-être-ignorées&#34;&gt;&lt;a href=&#34;#les-%c3%a9tapes-de-la-pipeline-peuvent-%c3%aatre-ignor%c3%a9es&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Les étapes de la pipeline peuvent être ignorées
&lt;/h2&gt;&lt;p&gt;Le fichier &lt;code&gt;pyproject.toml&lt;/code&gt; est utilisé pour dire à &lt;code&gt;ruff&lt;/code&gt; quel format il doit appliquer ou quelles règles suivre.&lt;/p&gt;
&lt;p&gt;Et comme nous utilisons actuellement le &lt;code&gt;pyproject.toml&lt;/code&gt; dans chaque repository, un développeur pourrait simplement enlever ces règles, contournant ainsi toutes les directives que nous essayions d&amp;rsquo;appliquer au départ.&lt;/p&gt;
&lt;p&gt;Encore une fois, bien que nous permettions cela pour l&amp;rsquo;instant afin de prendre en compte les nombreuses corrections à apporter, à terme, nous aimerions vouloir empêcher cela.&lt;/p&gt;
&lt;p&gt;Nous pourrions soit utiliser un fichier &lt;code&gt;pyproject.toml&lt;/code&gt; commun et fixe, soit l’ajouter dans le fichier &lt;code&gt;CODEOWNERS&lt;/code&gt; de GitHub pour nous assurer qu&amp;rsquo;il ne puisse être modifié sans une approbation stricte.&lt;/p&gt;
&lt;h1 id=&#34;et-après-&#34;&gt;&lt;a href=&#34;#et-apr%c3%a8s-&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Et après ?
&lt;/h1&gt;&lt;p&gt;Avec tout cela en place, nous pouvons maintenant penser à l’évolution de cette pipeline.&lt;/p&gt;
&lt;p&gt;Par exemple, notre entreprise dispose d’une instance SonarQube. Nous serions intéressés d’ajouter une étape qui pourrait analyser chaque projet à la recherche de mauvaises pratiques.&lt;/p&gt;
&lt;p&gt;Nous explorons aussi l’utilisation de &lt;code&gt;mkdocs&lt;/code&gt;, pour que les projets puissent partager un style commun pour la documentation.&lt;/p&gt;
&lt;p&gt;Et une de mes évolutions préférées, nous pourrions explorer l’utilisation de &lt;code&gt;uv&lt;/code&gt; pour installer les dépendances, car il est beaucoup plus rapide que ce bon vieux pip !&lt;/p&gt;
&lt;p&gt;Vous avez également peut-être remarqué que, bien que j&amp;rsquo;aie parlé de CI/CD tout au long de cet article, à aucun moment nous avons parlé d&amp;rsquo;une étape qui, eh bien, &lt;strong&gt;déploie&lt;/strong&gt; quelque chose (ce qui nous laisse avec une pipeline CI). Nous réfléchissons déjà à un moyen de build/deploy des packages Python vers notre gestionnaire de dépôt Artifactory, ce qui en ferait enfin une vraie pipeline CI/CD !&lt;/p&gt;
&lt;p&gt;Enfin, nous n’avons abordé que Python dans cet article, mais la même logique pourrait s&amp;rsquo;appliquer à d&amp;rsquo;autres types de projets. Par exemple, nous travaillons également sur une pipeline CI/CD pour Terraform.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;&lt;a href=&#34;#conclusion&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Conclusion
&lt;/h1&gt;&lt;p&gt;En abordant les problèmes de permissions, les lacunes en matière de connaissances Jenkins et l&amp;rsquo;absence de guidelignes, nous avons construit une stratégie CI/CD unifiée qui prend désormais en charge plus de 100 projets Python. Cela prouve qu’avec la bonne approche, l&amp;rsquo;automatisation est réalisable pour toute organisation.&lt;/p&gt;
&lt;p&gt;Cela a été un long mais enrichissant parcours !&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;espère que cet article a montré la valeur des pipelines CI/CD, vous a aidé à comprendre ce qui pourrait empêcher son application et vous a donné quelques idées sur la manière de mettre en place une stratégie similaire dans votre organisation !&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
