<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>The Cloud Optimist</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/</link>
        <description>Recent content on The Cloud Optimist</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>fr-FR</language>
        <lastBuildDate>Sun, 17 May 2026 07:30:00 +0100</lastBuildDate><atom:link href="https://antoinedelia.github.io/cloud-optimist/pr-144/fr/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Cloud Souverain : Comment démarrer avec Scaleway</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2026/cloud-sovereignty-getting-started-with-scaleway/</link>
        <pubDate>Sun, 17 May 2026 07:30:00 +0100</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2026/cloud-sovereignty-getting-started-with-scaleway/</guid>
        <description>&lt;img src="https://antoinedelia.github.io/cloud-optimist/pr-144/scaleway.png" alt="Featured image of post Cloud Souverain : Comment démarrer avec Scaleway" /&gt;&lt;h1 id=&#34;pourquoi-le-cloud-souverain-&#34;&gt;&lt;a href=&#34;#pourquoi-le-cloud-souverain-&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Pourquoi le Cloud Souverain ?
&lt;/h1&gt;&lt;p&gt;Ces dernières semaines, le concept de &amp;ldquo;Cloud Souverain&amp;rdquo; était partout, comme une évidence. Et pourtant, quand j&amp;rsquo;ai commencé à m&amp;rsquo;intéresser au Cloud il y a plusieurs années, personne n&amp;rsquo;en parlait. C&amp;rsquo;était déjà une prouesse de comprendre et utiliser le Cloud, alors qu&amp;rsquo;il soit souverain ou non, franchement, tout le monde s&amp;rsquo;en fichait.&lt;/p&gt;
&lt;p&gt;Mais avec le climat géopolitique actuel, tout le monde s&amp;rsquo;est souvenu que les trois grands acteurs du Cloud que sont AWS, Azure et GCP sont américains, et que cela pourrait potentiellement poser des problèmes, notamment avec le Cloud Act, qui permet au gouvernement américain d&amp;rsquo;accéder aux données stockées sur les serveurs de ces entreprises, même s&amp;rsquo;ils sont situés en dehors des États-Unis.&lt;/p&gt;
&lt;p&gt;Ainsi, vous aurez beau dire : &amp;ldquo;non mais chez nous on utilise la région AWS &lt;code&gt;eu-west-1&lt;/code&gt; en Irlande, donc c&amp;rsquo;est complètement souverain !&amp;rdquo;, ça ne changera rien au fait que vos données sont potentiellement accessibles par le gouvernement américain. Et beaucoup d&amp;rsquo;entreprises ont commencé à en prendre conscience, et à se demander s&amp;rsquo;il n&amp;rsquo;était pas temps de chercher une alternative plus &lt;em&gt;souveraine&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Et même si on observe des initiatives de la part des Big Three (je pense notamment à AWS avec son initiative &lt;a class=&#34;link&#34; href=&#34;https://www.aboutamazon.fr/actualites/aws/aws-lance-laws-european-sovereign-cloud-et-annonce-son-expansion-en-europe&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;em&gt;AWS European Sovereign Cloud&lt;/em&gt;&lt;/a&gt;), on observe une montée en popularité de solutions alternatives, comme Scaleway, qui a su se positionner rapidement comme un acteur majeur du Cloud Souverain en Europe.&lt;/p&gt;
&lt;p&gt;Aujourd&amp;rsquo;hui, j&amp;rsquo;aimerai donc tester avec vous Scaleway, du point de vue de quelqu&amp;rsquo;un qui a toujours été habitué à AWS. Serais-je agréablement surpris ? Découvrons-le ensemble !&lt;/p&gt;
&lt;h1 id=&#34;premiers-pas-avec-scaleway&#34;&gt;&lt;a href=&#34;#premiers-pas-avec-scaleway&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Premiers pas avec Scaleway
&lt;/h1&gt;&lt;h2 id=&#34;aperçu-de-la-console&#34;&gt;&lt;a href=&#34;#aper%c3%a7u-de-la-console&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Aperçu de la console
&lt;/h2&gt;&lt;p&gt;Je vous passerai toute la partie de création de compte. C&amp;rsquo;est assez simple, et je n&amp;rsquo;ai pas rencontré de problèmes particuliers.&lt;/p&gt;
&lt;p&gt;Maintenant, comme la première impression est importante, voyons voir à quoi ressemble la console d&amp;rsquo;administration de Scaleway dès notre arrivée.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/scaleway_console.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Console d’administration de Scaleway&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Ma première bonne surprise, est la notion de projets. Là où chez AWS, pour un même compte, toutes vos ressources co-habitent au même endroit (ce qui peut rendre la recherche de ressources compliquée), chez Scaleway, vous pouvez créer des projets qui viendront grouper vos ressources. Un premier projet &amp;ldquo;Default&amp;rdquo; existe déjà, et j&amp;rsquo;imagine qu&amp;rsquo;il servira aux ressources &amp;ldquo;communes&amp;rdquo; à plusieurs projets.&lt;/p&gt;
&lt;p&gt;Au niveau de l&amp;rsquo;interface utilisateur, sans pour autant révolutionner la navigation (et après tout, ce n&amp;rsquo;est pas forcément ce qu&amp;rsquo;on attend), Scaleway utilise une sidebar plutôt épurée, avec un groupement de services en fonction de leur fonction. Qui plus est, chaque service a un nom clair, ce qui permet de rapidement savoir où on veut aller (là où AWS aime bien les noms de services cryptiques).&lt;/p&gt;
&lt;p&gt;Allez, fini de rêvasser, et entrons dans le vif du sujet !&lt;/p&gt;
&lt;h2 id=&#34;création-dune-fonction&#34;&gt;&lt;a href=&#34;#cr%c3%a9ation-dune-fonction&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Création d&amp;rsquo;une fonction
&lt;/h2&gt;&lt;p&gt;Le premier test que j&amp;rsquo;aimerai faire, c&amp;rsquo;est de déployer une simple function (aka une AWS Lambda) pour voir les similitudes et différences avec AWS.&lt;/p&gt;
&lt;p&gt;Je me rends donc dans Serverless Compute &amp;ndash;&amp;gt; Functions. Et je suis déjà perplexe : Scaleway me parle de &amp;ldquo;namespaces&amp;rdquo; pour me permettre de grouper mes fonctions. J&amp;rsquo;ai d&amp;rsquo;abord pensé à une redite des &amp;ldquo;projets&amp;rdquo; vu plus haut, mais les &amp;ldquo;namespaces&amp;rdquo; permettent en plus de partager des variables d&amp;rsquo;environnement entre plusieurs fonctions. Des groupes dans des groupes donc.&lt;/p&gt;
&lt;p&gt;Passons là-dessus pour l&amp;rsquo;instant, et commençons à créer notre première fonction.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/scaleway_create_function.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Création d’une fonction dans Scaleway&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Pour commencer, je trouve l&amp;rsquo;interface très clair, et j&amp;rsquo;apprécie particulièrement les petites docs glissées à certains endroits, ainsi que la mention &amp;ldquo;Deprecated&amp;rdquo; sur les versions des runtimes. Idem pour les coûts estimés dans la colonne de droite, une bonne indication rapide pour voir si on n&amp;rsquo;est pas en train de faire n&amp;rsquo;importe quoi ! Au final, cela ressemble beaucoup à du AWS, mais en plus &amp;ldquo;clean&amp;rdquo; et plus ordonné.&lt;/p&gt;
&lt;p&gt;Il y a tout de même des points qui me chiffonnent un peu :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;La request timeout indique un maximum de 900, mais le slider peut monter à 3600&lt;/li&gt;
&lt;li&gt;L&amp;rsquo;input &amp;ldquo;Average request duration&amp;rdquo; qui n&amp;rsquo;a pas l&amp;rsquo;air de pouvoir être rempli&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Une fois que tout est bon, je finis par créer ma fonction. Et là encore, je suis un peu déçu. Il aura fallu plus d&amp;rsquo;une minute pour déployer cette fonction qui ne contient qu&amp;rsquo;un simple &amp;ldquo;Hello World&amp;rdquo;. J&amp;rsquo;ai notamment été intrigué par l&amp;rsquo;étape numéro 3 : &amp;ldquo;function image is being pushed to container registry&amp;rdquo;. J&amp;rsquo;ai trouvé ça assez curieux que Scaleway stocke une image de ma pauvre fonction Hello World. Je suis donc allé voir dans le service &amp;ldquo;Container Registry&amp;rdquo; et suprise ! Mon image était bien là, mais avec une taille de 337MB !!! Sachant que le stockage des images sur Scaleway est facturé, je trouve ça un peu fort de café de devoir déjà payé 0.06€ pour un bête Hello World.&lt;/p&gt;
&lt;p&gt;Mais revenons à nos fonctions. Un autre point noir concerne l&amp;rsquo;éditeur de code. Là où chez AWS, on nous offre une expérience proche d&amp;rsquo;un Visual Studio Code, chez Scaleway, vous n&amp;rsquo;aurez droit qu&amp;rsquo;à un simple textarea, avec un seul fichier. Je vous entends déjà dire &amp;ldquo;de toute façon, modifier du code dans la console, c&amp;rsquo;est une hérésie !&amp;rdquo;, et je suis d&amp;rsquo;accord avec vous. Mais cela montre le retard de Scaleway sur ce point.&lt;/p&gt;
&lt;p&gt;En contrepartie, la navigation est quant à elle bien plus agréable et facile pour s&amp;rsquo;y retrouver. J&amp;rsquo;apprécie tout particulièrement la partie &amp;ldquo;Test&amp;rdquo; qui nous offre une commande curl prête à l&amp;rsquo;usage (dommage cependant qu&amp;rsquo;il ne soit pas possible de tester directement depuis la console).&lt;/p&gt;
&lt;h2 id=&#34;même-exercice-avec-terraform&#34;&gt;&lt;a href=&#34;#m%c3%aame-exercice-avec-terraform&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Même exercice avec Terraform
&lt;/h2&gt;&lt;p&gt;Comme je le disais plus haut, la console c&amp;rsquo;est bien, mais si on veut se lancer sérieusement dans un provider cloud, alors il faudra passer par la case Infrastructure as Code. Et ici, mon chouchou reste Terraform. Je suis donc curieux de voir comment se passe le déploiement d&amp;rsquo;une fonction sur Scaleway avec Terraform.&lt;/p&gt;
</description>
        </item>
        <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 migrer son State de Terraform Cloud vers AWS S3 ?</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/moving-away-from-terraform-cloud/</link>
        <pubDate>Wed, 17 Dec 2025 07:30:00 +0200</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/moving-away-from-terraform-cloud/</guid>
        <description>&lt;img src="https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/moving-away-from-terraform-cloud/terraform.png" alt="Featured image of post Comment migrer son State de Terraform Cloud vers AWS S3 ?" /&gt;&lt;h1 id=&#34;introduction&#34;&gt;&lt;a href=&#34;#introduction&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Introduction
&lt;/h1&gt;&lt;p&gt;Quand j&amp;rsquo;ai commencé à utiliser Terraform (notamment pour &lt;a class=&#34;link&#34; href=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/how-i-automated-my-blog-to-the-cloud/&#34; &gt;le déploiement de mon blog&lt;/a&gt;), je me suis tourné vers l&amp;rsquo;utilisation de &lt;strong&gt;Terraform Cloud&lt;/strong&gt; (ce nom a ensuite été modifié en HCP Terraform).&lt;/p&gt;
&lt;h1 id=&#34;terraform-et-le-state&#34;&gt;&lt;a href=&#34;#terraform-et-le-state&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Terraform et le State
&lt;/h1&gt;&lt;p&gt;Si vous connaissez un peu Terraform, vous êtes sûrement familier avec le terme &lt;a class=&#34;link&#34; href=&#34;https://developer.hashicorp.com/terraform/language/state&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;em&gt;State&lt;/em&gt;&lt;/a&gt;, qui correspond en fait à l&amp;rsquo;état actuel de votre infrastructure, et qui permet à Terraform de savoir quelles modifications seront à prévoir si vous venez à modifier vos fichiers Terraform. Ce &lt;em&gt;State&lt;/em&gt; est représenté par un fichier : &lt;strong&gt;terraform.tfstate&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Par défaut, Terraform stocke ce fichier en local sur votre machine, mais recommande d&amp;rsquo;utiliser un &lt;em&gt;backend storage&lt;/em&gt; (comprenez : &amp;ldquo;stockez ce fichier ailleurs bon sang !&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;Évidemment, Terraform vous propose en premier la solution HashiCorp : Terraform Cloud. En créant un compte, vous pourrez gratuitement utiliser leur backend pour stocker vos fichiers de state. C&amp;rsquo;est tout naturellement ce que j&amp;rsquo;ai fait il y a quelques années.&lt;/p&gt;
&lt;h1 id=&#34;la-fin-de-terraform-cloud&#34;&gt;&lt;a href=&#34;#la-fin-de-terraform-cloud&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;La fin de Terraform Cloud
&lt;/h1&gt;&lt;p&gt;Jusqu&amp;rsquo;à cette semaine, où j&amp;rsquo;ai reçu ce mail d&amp;rsquo;HashiCorp.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/moving-away-from-terraform-cloud/terraform-mail-free-plan-expiration.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Mail de Terraform annonçant la fin du plan Free de Terraform Cloud&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Aïe ! Il fallait s&amp;rsquo;en douter, toutes les bonnes choses ont une fin ! L&amp;rsquo;option gratuite de l&amp;rsquo;époque n&amp;rsquo;existera bientôt plus, et il me faut donc faire un choix : mettre à jour mon &amp;ldquo;plan&amp;rdquo; HashiCorp, ou aller stocker mes states ailleurs.&lt;/p&gt;
&lt;p&gt;En regardant de plus près &lt;a class=&#34;link&#34; href=&#34;https://developer.hashicorp.com/terraform/cloud-docs/overview&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;leurs offres actuelles&lt;/a&gt;, HashiCorp propose encore une version gratuite, bien que limitée dans le nombre de ressources pouvant être déployées (500 aujourd&amp;rsquo;hui). C&amp;rsquo;est une offre assez généreuse, mais ne sachant pas comment celle-ci pourra évoluer, je prends la décision de déménager mes States une bonne fois pour toutes.&lt;/p&gt;
&lt;p&gt;Adieu, Terraform Cloud !&lt;/p&gt;
&lt;h1 id=&#34;une-alternative-pour-stocker-vos-states&#34;&gt;&lt;a href=&#34;#une-alternative-pour-stocker-vos-states&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Une alternative pour stocker vos states
&lt;/h1&gt;&lt;p&gt;Heureusement pour moi, il existe bien des moyens pour stocker son state Terraform, et ce grâce au &lt;a class=&#34;link&#34; href=&#34;https://developer.hashicorp.com/terraform/language/state/remote&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Remote State&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Pour faire simple, il suffit de dire à Terraform où sera stocké votre fichier de state. On utilise pour cela &lt;a class=&#34;link&#34; href=&#34;https://developer.hashicorp.com/terraform/language/backend&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;le block &lt;code&gt;backend&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Il en existe une bonne poignée, mais possédant un compte AWS sur lequel je déploie toutes mes ressources, je me dirige tout naturellement vers le backend S3.&lt;/p&gt;
&lt;p&gt;Voici par exemple comment configurer un backend S3 avec 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;/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;nx&#34;&gt;terraform&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;backend&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;s3&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;mybucket&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;key&lt;/span&gt;    &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;path/to/my/key/terraform.tfstate&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;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 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;Maintenant qu&amp;rsquo;une alternative a été trouvée, il est temps de passer à la migration !&lt;/p&gt;
&lt;h1 id=&#34;migration-du-state-vers-s3&#34;&gt;&lt;a href=&#34;#migration-du-state-vers-s3&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Migration du state vers S3
&lt;/h1&gt;&lt;p&gt;Je vais prendre en exemple la migration du state dont je me sers pour déployer ce blog.&lt;/p&gt;
&lt;p&gt;Actuellement, si on regarde &lt;a class=&#34;link&#34; href=&#34;https://github.com/antoinedelia/cloud-optimist/blob/4f8f95c177c490e3383c8b554e8d8ca4b3df249b/.github/workflows/main.yml#L28-L33&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;mon workflow GitHub Actions de déploiement&lt;/a&gt;, on voit que je m&amp;rsquo;authentifie avec un token à mon compte Terraform Cloud. Cette partie-là n&amp;rsquo;aura plus de raison d&amp;rsquo;exister (du  moins pour les credentials, il faudra toujours initialiser la CLI Terraform).&lt;/p&gt;
&lt;p&gt;Ensuite, il va falloir créer un bucket S3 qui contiendra les futurs fichiers de state.&lt;/p&gt;
&lt;p&gt;Enfin, il faudra rajouter un block &lt;code&gt;backend&lt;/code&gt; à mon projet afin d&amp;rsquo;indiquer à Terraform de ne plus utiliser Terraform Cloud, mais bien S3 lorsqu&amp;rsquo;il viendra utiliser le state.&lt;/p&gt;
&lt;p&gt;Attention, nous n&amp;rsquo;avons pas encore fini ! Car si je laisse ce bucket vide, la prochaine fois que j&amp;rsquo;essaierai de déployer mon blog, Terraform viendra se baser sur un state&amp;hellip; inexistant ! Et pensera donc qu&amp;rsquo;aucune ressource n&amp;rsquo;a encore été déployée sur mon compte AWS. Terraform essaiera ainsi de recréer des ressources déjà existantes.&lt;/p&gt;
&lt;p&gt;La dernière étape sera donc de récupérer le fichier de state de mon projet de blog, et de le déplacer dans mon bucket S3.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/moving-away-from-terraform-cloud/downloading_terraform_state.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Téléchargement du Terraform State dans Terraform Cloud&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Je dois ensuite m&amp;rsquo;assurer que les informations que j&amp;rsquo;ai fournies dans le block &lt;code&gt;backend&lt;/code&gt; correspondent bien à la réalité.&lt;/p&gt;
&lt;p&gt;Une fois tout cela prêt, il est temps de tester et de déployer tout ça !&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;ai volontairement omis quelques étapes de cette migration (des variables de workspace à migrer, l&amp;rsquo;utilisation de GitHub Secrets pour le nom du bucket S3, l&amp;rsquo;ajout des credentials AWS dans la GitHub Actions, &amp;hellip;) pour rendre cet article plus concis. Si vous voulez en voir plus, rendez-vous dans la &lt;a class=&#34;link&#34; href=&#34;https://github.com/antoinedelia/cloud-optimist/pull/116&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Pull Request que j&amp;rsquo;ai ouverte&lt;/a&gt; pour réaliser cette migration.&lt;/p&gt;
&lt;p&gt;Si tout s&amp;rsquo;est passé comme prévu, vous devriez voir apparaitre la phrase &lt;code&gt;No changes. Your infrastructure matches the configuration.&lt;/code&gt; lors de votre &lt;code&gt;terraform plan&lt;/code&gt; !&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;Il est toujours pénible de devoir réaliser des migrations sur des infrastructures qui sont déjà en place. Mais avec un peu de temps, et avec une bonne volonté, c&amp;rsquo;est le genre de tâche qui ne prend au final que quelques heures.&lt;/p&gt;
&lt;p&gt;Alors, n&amp;rsquo;attendez pas le dernier moment, et lancez-vous !&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Comment et pourquoi configurer AWS IAM Identity Center sur votre compte AWS</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/how-and-why-to-set-up-aws-iam-identity-center-on-your-aws-account/</link>
        <pubDate>Wed, 19 Nov 2025 07:30:00 +0200</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/how-and-why-to-set-up-aws-iam-identity-center-on-your-aws-account/</guid>
        <description>&lt;img src="https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/how-and-why-to-set-up-aws-iam-identity-center-on-your-aws-account/iam-identity-center.jpg" alt="Featured image of post Comment et pourquoi configurer AWS IAM Identity Center sur votre compte AWS" /&gt;&lt;h1 id=&#34;introduction&#34;&gt;&lt;a href=&#34;#introduction&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Introduction
&lt;/h1&gt;&lt;p&gt;Si vous jonglez avec plusieurs comptes AWS, ou même un seul compte avec différents utilisateurs, vous savez à quel point la gestion des accès peut devenir un véritable casse-tête. Créer des utilisateurs IAM individuels dans chaque compte, gérer leurs permissions, s&amp;rsquo;assurer que tout le monde utilise le MFA&amp;hellip; Ouf, rien que d&amp;rsquo;y penser, ça peut donner des sueurs froides ! Et si je vous disais qu&amp;rsquo;il existe une solution élégante, centralisée et bien plus sécurisée pour gérer tout ça ? Mesdames et Messieurs, laissez-moi vous présenter &lt;strong&gt;IAM Identity Center&lt;/strong&gt; !&lt;/p&gt;
&lt;p&gt;Depuis que j&amp;rsquo;ai découvert et mis en place IAM Identity Center (que certains connaissent peut-être sous son ancien nom, AWS Single Sign-On ou AWS SSO), ma vie d&amp;rsquo;administrateur Cloud a radicalement changé. C&amp;rsquo;est le genre d&amp;rsquo;outil qui, une fois adopté, vous fait vous demander comment vous avez pu vivre sans.&lt;/p&gt;
&lt;p&gt;Alors, qu&amp;rsquo;est-ce que c&amp;rsquo;est exactement, et pourquoi est-ce si génial ? C&amp;rsquo;est ce qu&amp;rsquo;on va voir ensemble.&lt;/p&gt;
&lt;h1 id=&#34;iam-identity-center--késako-&#34;&gt;&lt;a href=&#34;#iam-identity-center--k%c3%a9sako-&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;IAM Identity Center : Késako ?
&lt;/h1&gt;&lt;p&gt;En termes simples, IAM Identity Center est un service AWS qui vous permet de gérer de manière centralisée l&amp;rsquo;accès à tous vos comptes AWS et à vos applications Cloud. Que vous ayez une poignée de comptes ou une organisation AWS tentaculaire avec des dizaines, voire des centaines de comptes, IAM Identity Center est là pour vous simplifier la tâche.&lt;/p&gt;
&lt;p&gt;Il vous offre un point d&amp;rsquo;entrée unique (un portail d&amp;rsquo;accès web) pour vos utilisateurs, leur permettant d&amp;rsquo;accéder aux rôles et aux comptes auxquels ils ont droit, le tout avec une seule authentification.&lt;/p&gt;
&lt;h1 id=&#34;les-avantages-diam-identity-center&#34;&gt;&lt;a href=&#34;#les-avantages-diam-identity-center&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Les avantages d&amp;rsquo;IAM Identity Center
&lt;/h1&gt;&lt;p&gt;Si je suis aussi enthousiaste, c&amp;rsquo;est parce que les bénéfices sont nombreux et significatifs. Pour vous citer les plus importants :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Single Sign-On (SSO) :&lt;/strong&gt; Vos utilisateurs se connectent une seule fois via le portail AWS (ou via votre fournisseur d&amp;rsquo;identité existant si vous en avez un) et accèdent ensuite à tous les comptes et rôles qui leur sont assignés, sans avoir à se ré-authentifier pour chaque compte.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gestion Centralisée :&lt;/strong&gt; Vous gérez tous vos utilisateurs, groupes et leurs permissions (via des &lt;em&gt;Permission Sets&lt;/em&gt;) depuis un seul endroit, même s&amp;rsquo;ils doivent accéder à des dizaines de comptes AWS différents.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Identifiants Temporaires :&lt;/strong&gt; C&amp;rsquo;est l&amp;rsquo;un des points les plus importants ! Lorsque les utilisateurs accèdent à un compte via IAM Identity Center, ils obtiennent des identifiants temporaires à durée de vie limitée. Adieu les &lt;em&gt;Access Keys&lt;/em&gt; IAM qui traînent et qui représentent un risque de sécurité majeur.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MFA (Multi-Factor Authentication) :&lt;/strong&gt; Vous pouvez (et devriez !) imposer l&amp;rsquo;utilisation du MFA directement au niveau de la connexion à IAM Identity Center.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Si j&amp;rsquo;ai piqué votre curiosité et que vous souhaitez en savoir plus, je vous laisse consulter la &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;documentation AWS sur IAM Identity Center&lt;/a&gt;. Pour ceux qui sont déjà convaincus, continuons ensemble !&lt;/p&gt;
&lt;h1 id=&#34;se-lancer-avec-iam-identity-center&#34;&gt;&lt;a href=&#34;#se-lancer-avec-iam-identity-center&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Se Lancer avec IAM Identity Center
&lt;/h1&gt;&lt;p&gt;Mettre en place IAM Identity Center est étonnamment simple, surtout si vous utilisez l&amp;rsquo;annuaire intégré d&amp;rsquo;Identity Center comme source d&amp;rsquo;identité. Voici les étapes clés pour démarrer :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Configuration initiale :&lt;/strong&gt; Rendez-vous dans la console AWS, et cherchez &lt;em&gt;IAM Identity Center&lt;/em&gt;. Attention, choisissez bien votre région AWS pour héberger IAM Identity Center dès le départ, car il est actuellement complexe de changer la région d&amp;rsquo;IAM Identity Center une fois configuré. La configuration initiale est souvent guidée et rapide. Vous choisirez votre source d&amp;rsquo;identité (l&amp;rsquo;annuaire Identity Center, AWS Managed Microsoft AD, ou un fournisseur externe).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Création de groupes et d&amp;rsquo;utilisateurs :&lt;/strong&gt; Définissez des groupes pertinents pour votre organisation (ex: Developers, Administrators, &amp;hellip;). Créez ensuite vos utilisateurs et assignez-les à ces groupes. Si vous utilisez un IdP externe, cette étape consistera plutôt à synchroniser vos utilisateurs et groupes existants.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Création des &lt;em&gt;Permission Sets&lt;/em&gt; :&lt;/strong&gt; Un &lt;em&gt;Permission Set&lt;/em&gt; est un ensemble de permissions (similaire à une policy IAM) que vous allez pouvoir réutiliser. Vous pouvez partir de policies managées par AWS (ex: &lt;em&gt;AdministratorAccess&lt;/em&gt; ou &lt;em&gt;ReadOnlyAccess&lt;/em&gt;) ou créer les vôtres.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Assignation des accès :&lt;/strong&gt; C&amp;rsquo;est ici que la magie opère. Vous assignez un groupe (ou un utilisateur) à un ou plusieurs comptes AWS, en leur donnant le droit d&amp;rsquo;utiliser un &lt;em&gt;Permission Set&lt;/em&gt; spécifique sur ces comptes. Par exemple, le groupe Developers peut avoir le &lt;em&gt;Permission Set&lt;/em&gt; &lt;code&gt;PowerUserAccess&lt;/code&gt; sur les comptes AWS de développement.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Imposer le MFA :&lt;/strong&gt; Dans les paramètres d&amp;rsquo;IAM Identity Center, configurez le MFA pour qu&amp;rsquo;il soit obligatoire pour tous vos utilisateurs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Partager l&amp;rsquo;URL d&amp;rsquo;accès AWS :&lt;/strong&gt; Chaque configuration IAM Identity Center a une URL unique pour le portail d&amp;rsquo;accès (ex: &lt;code&gt;d-xxxxxxxxxx.awsapps.com/start&lt;/code&gt;). C&amp;rsquo;est cette URL que vos utilisateurs mettront en favori pour se connecter.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/how-and-why-to-set-up-aws-iam-identity-center-on-your-aws-account/aws-iam-identity-center-dashboard.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;AWS IAM Identity Center Dashboard&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Une fois connectés au portail, les utilisateurs verront la liste des comptes AWS et des rôles (définis par les &lt;em&gt;Permission Sets&lt;/em&gt;) auxquels ils ont accès. Un clic, et ils sont dans la console du compte AWS choisi avec les bonnes permissions !&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/how-and-why-to-set-up-aws-iam-identity-center-on-your-aws-account/aws-iam-identity-center-access-portal.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;AWS IAM Identity Center Access Portal&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Ils peuvent aussi obtenir des identifiants temporaires pour la CLI. Mais d&amp;rsquo;ailleurs, comment faire pour se connecter à un compte AWS en CLI via IAM Identity Center ? Voyons ça ensemble !&lt;/p&gt;
&lt;h1 id=&#34;configurer-les-accès-cli&#34;&gt;&lt;a href=&#34;#configurer-les-acc%c3%a8s-cli&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Configurer les accès CLI
&lt;/h1&gt;&lt;p&gt;La &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;documentation d&amp;rsquo;AWS pour configurer l&amp;rsquo;authentification CLI avec IAM Identity Center&lt;/a&gt; est assez claire, mais je vais tout de même vous décrire les étapes. Je pars du principe que vous avez déjà installé votre &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/cli/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS CLI&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;La commande pour initier la configuration est la suivante :&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-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;aws configure sso
&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, vous allez devoir rentrer quelques informations propres à votre IAM Identity Center. Le plus important étant le &lt;em&gt;SSO start URL&lt;/em&gt; (que vous pouvez trouver dans IAM Identity Center sous le nom de &lt;em&gt;AWS access portal URL&lt;/em&gt;, URL qui finit par &lt;code&gt;/start&lt;/code&gt;). Il faut ensuite rentrer la région dans laquelle se trouve votre configuration, quant au &lt;em&gt;SSO registration scopes&lt;/em&gt;, vous pouvez laisser la valeur par défaut.&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;/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;SSO session name &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;Recommended&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;: default
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SSO start URL &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;None&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: https://xxxxxxxxxxxx.awsapps.com/start
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SSO region &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;None&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: eu-west-1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SSO registration scopes &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;sso:account:access&lt;span class=&#34;o&#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;Si tout se passe bien, une fenêtre devrait s&amp;rsquo;ouvrir dans votre navigateur pour valider votre identité. Une fois cela fait, retournez dans votre terminal.&lt;/p&gt;
&lt;p&gt;Dans mon cas, je ne possède qu&amp;rsquo;un seul compte AWS, et IAM Identity Center me le sélectionne par défaut. Mais vous aurez peut-être le choix dans le compte AWS à sélectionner. Idem pour le role.&lt;/p&gt;
&lt;p&gt;Enfin, choisissez un nom de profil à utiliser pour vos futurs appels API. Je vous conseille d&amp;rsquo;utiliser &lt;code&gt;default&lt;/code&gt;, ce qui vous permettra de ne pas avoir à rajouter &lt;code&gt;--profile my-aws-profile&lt;/code&gt; à la fin de chacune de vos commandes.&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;/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;The only AWS account available to you is: xxxxxxxxxxxx
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Using the account ID xxxxxxxxxxxx
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;The only role available to you is: AdministratorAccess
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Using the role name &lt;span class=&#34;s2&#34;&gt;&amp;#34;AdministratorAccess&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;Default client Region &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;None&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: eu-west-1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;CLI default output format &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;json &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; not specified&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;None&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: json
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Profile name &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;AdministratorAccess-xxxxxxxxxxxx&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: default
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;The AWS CLI is now configured to use the default profile.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Run the following &lt;span class=&#34;nb&#34;&gt;command&lt;/span&gt; to verify your configuration:
&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;aws sts get-caller-identity
&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;Et voilà, le tour est joué !&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, je suis un grand fan d&amp;rsquo;AWS IAM Identity Center. Il apporte une couche de sécurité indispensable tout en simplifiant considérablement la gestion des accès, que ce soit pour les administrateurs ou pour les utilisateurs.&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est un véritable pilier pour une infrastructure AWS bien gérée et sécurisée. Si vous ne l&amp;rsquo;utilisez pas encore, je vous encourage vivement à explorer sa mise en place. C&amp;rsquo;est un investissement en temps minime pour des gains en sécurité et en efficacité énormes.&lt;/p&gt;
&lt;p&gt;Votre infrastructure (et vos équipes de sécurité) vous diront merci !&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Sur la piste de la ressource perdue - Mon enquête avec Athena et CloudTrail</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/on-the-trail-of-the-lost-resource-my-investigation-with-athena-and-cloudtrail/</link>
        <pubDate>Wed, 09 Jul 2025 12:30:00 +0200</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/on-the-trail-of-the-lost-resource-my-investigation-with-athena-and-cloudtrail/</guid>
        <description>&lt;img src="https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/on-the-trail-of-the-lost-resource-my-investigation-with-athena-and-cloudtrail/aws_lost_resource.jpeg" alt="Featured image of post Sur la piste de la ressource perdue - Mon enquête avec Athena et CloudTrail" /&gt;&lt;h1 id=&#34;introduction&#34;&gt;&lt;a href=&#34;#introduction&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Introduction
&lt;/h1&gt;&lt;p&gt;Récemment, j&amp;rsquo;ai dû jouer les détectives sur notre compte AWS.&lt;/p&gt;
&lt;p&gt;Une ressource était là (un Cognito User Pool), bien présente, mais personne ne se souvenait de son origine. Et évidemment, pas de tags pour nous aider (si seulement ils avaient lu &lt;a class=&#34;link&#34; href=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/why-tagging-your-aws-resources-is-a-must/&#34; &gt;mon article sur le tagging des ressources AWS&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Ma mission, si je l&amp;rsquo;acceptais : découvrir qui l&amp;rsquo;avait créée. Le problème ? L&amp;rsquo;événement datait d&amp;rsquo;il y a environ quatre mois.&lt;/p&gt;
&lt;p&gt;Mon premier réflexe a été de me tourner vers AWS CloudTrail. Et là, premier mur : &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/awscloudtrail/latest/userguide/view-cloudtrail-events.html#event-history-limitations&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;l&amp;rsquo;historique des événements n&amp;rsquo;est consultable que sur les 90 derniers jours&lt;/a&gt;. Raté !&lt;/p&gt;
&lt;p&gt;Heureusement, je savais que nos logs CloudTrail étaient archivés dans un bucket S3. Mon premier réflexe : télécharger manuellement les archives du bon mois, décompresser des dizaines de fichiers JSON, et lancer un &lt;kbd&gt;Ctrl+F&lt;/kbd&gt; en priant très fort. Autant vous dire que ce n&amp;rsquo;est ni efficace, ni agréable, ni rapide.&lt;/p&gt;
&lt;p&gt;Je me suis donc demandé s&amp;rsquo;il n&amp;rsquo;y avait pas un moyen plus simple de chercher dans cet amas de logs, et j&amp;rsquo;ai finalement trouvé la solution parfaite : &lt;strong&gt;AWS Athena&lt;/strong&gt;.&lt;/p&gt;
&lt;h1 id=&#34;interroger-vos-logs-s3-avec-athena&#34;&gt;&lt;a href=&#34;#interroger-vos-logs-s3-avec-athena&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Interroger vos logs S3 avec Athena
&lt;/h1&gt;&lt;p&gt;Pour ceux qui ne connaissent pas, &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/athena/latest/ug/what-is.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS Athena&lt;/a&gt; est un service de requête interactif qui facilite l&amp;rsquo;analyse de données directement dans Amazon S3 en utilisant du SQL standard. En gros, vous pouvez faire des requêtes sur des fichiers (JSON, CSV, &amp;hellip;) comme s&amp;rsquo;il s&amp;rsquo;agissait d&amp;rsquo;une base de données traditionnelle. Plus besoin de télécharger quoi que ce soit !&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;idée est donc de &amp;ldquo;mapper&amp;rdquo; nos logs CloudTrail stockés dans S3 à une table dans Athena. Pour cela, on utilise une seule requête &lt;code&gt;CREATE EXTERNAL TABLE&lt;/code&gt;. En suivant &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/athena/latest/ug/create-cloudtrail-table-partition-projection.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;la documentation d&amp;rsquo;AWS sur le sujet&lt;/a&gt;, j&amp;rsquo;ai lancé la requête suivante dans la console Athena.&lt;/p&gt;
&lt;p&gt;Cette requête crée une table et utilise une fonctionnalité très pratique appelée &amp;ldquo;partition projection&amp;rdquo;. Cela permet à Athena de déduire l&amp;rsquo;emplacement des logs en fonction de la date, sans avoir à gérer manuellement les partitions. C&amp;rsquo;est d&amp;rsquo;autant plus pratique quand la structure est bien standardisée comme c&amp;rsquo;est le cas avec AWS CloudTrail.&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;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&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-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;EXTERNAL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;TABLE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cloudtrail_logs_pp&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;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;n&#34;&gt;eventversion&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&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;n&#34;&gt;useridentity&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRUCT&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&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;n&#34;&gt;arn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&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;o&#34;&gt;&amp;gt;&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;n&#34;&gt;eventtime&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&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;n&#34;&gt;eventsource&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&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;n&#34;&gt;eventname&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&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;n&#34;&gt;awsregion&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&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;n&#34;&gt;requestparameters&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&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;n&#34;&gt;responseelements&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&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;n&#34;&gt;additionaleventdata&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&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;n&#34;&gt;requestid&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&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;n&#34;&gt;eventid&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&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;n&#34;&gt;resources&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;ARRAY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRUCT&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&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;n&#34;&gt;arn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&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;n&#34;&gt;accountid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&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;k&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&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;o&#34;&gt;&amp;gt;&amp;gt;&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;n&#34;&gt;eventtype&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&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;n&#34;&gt;eventcategory&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&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;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;n&#34;&gt;PARTITIONED&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&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;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;o&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;timestamp&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;string&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;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;k&#34;&gt;ROW&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FORMAT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SERDE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;org.apache.hive.hcatalog.data.JsonSerDe&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;n&#34;&gt;STORED&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;INPUTFORMAT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;com.amazon.emr.cloudtrail.CloudTrailInputFormat&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;n&#34;&gt;OUTPUTFORMAT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat&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;k&#34;&gt;LOCATION&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;s3://BUCKET-NAME/AWSLogs/ACCOUNT-ID/CloudTrail/REGION&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;-- Remplacez par le chemin de votre bucket S3
&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;n&#34;&gt;TBLPROPERTIES&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;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;s1&#34;&gt;&amp;#39;projection.enabled&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;true&amp;#39;&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;s1&#34;&gt;&amp;#39;projection.timestamp.format&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;yyyy/MM/dd&amp;#39;&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;s1&#34;&gt;&amp;#39;projection.timestamp.interval&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;1&amp;#39;&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;s1&#34;&gt;&amp;#39;projection.timestamp.interval.unit&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;DAYS&amp;#39;&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;s1&#34;&gt;&amp;#39;projection.timestamp.range&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2024/01/01,NOW&amp;#39;&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;c1&#34;&gt;-- Remplacez par la date de début
&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;s1&#34;&gt;&amp;#39;projection.timestamp.type&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;date&amp;#39;&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;s1&#34;&gt;&amp;#39;storage.location.template&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;s3://BUCKET-NAME/AWSLogs/ACCOUNT-ID/CloudTrail/REGION/${timestamp}&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;-- Remplacez par le chemin de votre bucket S3
&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 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;&lt;strong&gt;Attention :&lt;/strong&gt; N&amp;rsquo;oubliez pas de remplacer les URLs &lt;code&gt;s3://...&lt;/code&gt; par le chemin exact de votre bucket S3 où sont stockés vos logs CloudTrail, et d&amp;rsquo;ajuster la propriété &lt;code&gt;projection.timestamp.range&lt;/code&gt; à la période qui vous intéresse.&lt;/p&gt;
&lt;h1 id=&#34;lheure-de-lenquête--trouver-linformation&#34;&gt;&lt;a href=&#34;#lheure-de-lenqu%c3%aate--trouver-linformation&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;L&amp;rsquo;Heure de l&amp;rsquo;Enquête : Trouver l&amp;rsquo;Information
&lt;/h1&gt;&lt;p&gt;Une fois la table créée (ce qui ne prend que quelques secondes), le plus dur est fait ! Mon enquête pouvait enfin commencer.&lt;/p&gt;
&lt;p&gt;Je cherchais à savoir qui avait créé un &lt;code&gt;UserPoolClient&lt;/code&gt; pour Cognito à une date précise. Ma requête SQL ressemblait donc à ça :&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-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;SELECT&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;n&#34;&gt;eventTime&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;n&#34;&gt;eventName&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;n&#34;&gt;userIdentity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;arn&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;k&#34;&gt;FROM&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;n&#34;&gt;cloudtrail_logs_pp&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;k&#34;&gt;WHERE&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;k&#34;&gt;timestamp&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2025/02/25&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;k&#34;&gt;AND&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eventName&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;CreateUserPoolClient&amp;#39;&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;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;En quelques secondes, Athena a scanné les logs du jour demandé et m&amp;rsquo;a retourné le résultat.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/on-the-trail-of-the-lost-resource-my-investigation-with-athena-and-cloudtrail/running_the_athena_query.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Athena query to search CloudTrail logs in S3&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;avais l&amp;rsquo;heure exacte, l&amp;rsquo;événement, et surtout, l&amp;rsquo;ARN de l&amp;rsquo;utilisateur qui avait effectué l&amp;rsquo;action. Mission accomplie !&lt;/p&gt;
&lt;h1 id=&#34;le-verdict-et-le-coupable&#34;&gt;&lt;a href=&#34;#le-verdict-et-le-coupable&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Le Verdict&amp;hellip; et le Coupable
&lt;/h1&gt;&lt;p&gt;Le plus drôle dans cette histoire ?&lt;/p&gt;
&lt;p&gt;Après avoir mis en place cette solution et retrouvé l&amp;rsquo;information si facilement, j&amp;rsquo;ai découvert que le &amp;ldquo;coupable&amp;rdquo; qui avait créé cette ressource il y a quatre mois&amp;hellip; &lt;strong&gt;c&amp;rsquo;était moi&lt;/strong&gt;. J&amp;rsquo;avais complètement oublié !&lt;/p&gt;
&lt;p&gt;Au-delà de l&amp;rsquo;anecdote, cette expérience m&amp;rsquo;a confirmé une chose : prendre quelques minutes pour configurer Athena sur vos logs CloudTrail est un investissement incroyablement rentable. Vous vous offrez une capacité d&amp;rsquo;audit et de recherche sur le long terme qui vous sauvera des heures de recherche manuelle le jour où vous en aurez vraiment besoin. Ne faites pas comme moi, n&amp;rsquo;attendez pas d&amp;rsquo;être coincé pour le mettre en place !&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Pourquoi taguer vos ressources AWS est indispensable ?</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/why-tagging-your-aws-resources-is-a-must/</link>
        <pubDate>Tue, 24 Jun 2025 07:30:00 +0200</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/why-tagging-your-aws-resources-is-a-must/</guid>
        <description>&lt;img src="https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/why-tagging-your-aws-resources-is-a-must/aws_tagging.jpeg" alt="Featured image of post Pourquoi taguer vos ressources AWS est indispensable ?" /&gt;&lt;h1 id=&#34;introduction&#34;&gt;&lt;a href=&#34;#introduction&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Introduction
&lt;/h1&gt;&lt;p&gt;Plus on déploie de services sur AWS, plus on commence à s&amp;rsquo;y perdre. Au début, on connaît par coeur tous les services qu&amp;rsquo;on utilise, le nombre de Lambdas ou d&amp;rsquo;EC2 qui sont lancées. Mais petit à petit, il est facile de ne plus savoir où donner de la tête, surtout lorsque différents projets s&amp;rsquo;accumulent. Retrouver rapidement quelles ressources appartiennent à quel projet, ou identifier celles qui n&amp;rsquo;ont pas été correctement nettoyées après un PoC, tout cela peut vite devenir un casse-tête. Et c&amp;rsquo;est sans parler de la vision des coûts !&lt;/p&gt;
&lt;p&gt;Heureusement, il existe une pratique simple mais incroyablement puissante : &lt;strong&gt;le tagging&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Dans cet article, j&amp;rsquo;aimerais vous montrer qu&amp;rsquo;une bonne stratégie de tags est &lt;strong&gt;cruciale pour votre organisation, votre gestion des coûts, et pour la sécurité&lt;/strong&gt; de votre compte AWS.&lt;/p&gt;
&lt;p&gt;À vos marques. Prêts ? Taguez !&lt;/p&gt;
&lt;h1 id=&#34;pourquoi-les-tags-sont-ils-utiles-&#34;&gt;&lt;a href=&#34;#pourquoi-les-tags-sont-ils-utiles-&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Pourquoi les tags sont-ils utiles ?
&lt;/h1&gt;&lt;p&gt;Imaginez des étiquettes sur des boîtes de déménagement. Sans elles, impossible de savoir ce qu&amp;rsquo;il y a dedans ou à quelle pièce elles appartiennent. Les tags sur AWS, c&amp;rsquo;est pareil ! Un tag est une &lt;strong&gt;information&lt;/strong&gt; (sous la forme clé-valeur) que vous assignez à vos ressources (instances EC2, buckets S3, bases de données RDS, etc.).&lt;/p&gt;
&lt;p&gt;Une bonne stratégie de tagging vous permet notamment de :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Identifier des ressources orphelines&lt;/strong&gt; : C&amp;rsquo;est le grand classique. Une ressource sans tag &lt;code&gt;Project&lt;/code&gt; ou &lt;code&gt;Owner&lt;/code&gt; ? Il y a de fortes chances qu&amp;rsquo;elle ait été oubliée et qu&amp;rsquo;elle consomme des ressources (et donc de l&amp;rsquo;argent) pour rien. Lister les ressources non taguées (ou mal taguées) est une première étape essentielle pour faire le ménage.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ventiler les coûts&lt;/strong&gt; : En taguant vos ressources avec un identifiant de projet, de centre de coût, ou d&amp;rsquo;équipe, vous pouvez ensuite utiliser AWS Cost Explorer pour filtrer vos dépenses et comprendre précisément quels projets consomment le plus. Indispensable pour la refacturation interne ou simplement pour optimiser votre budget.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automatiser des actions&lt;/strong&gt; : Les tags peuvent servir de déclencheurs pour des scripts d&amp;rsquo;automatisation (par exemple, sauvegarder toutes les instances EC2 avec le tag &lt;code&gt;Backup=Daily&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gérer les accès et la sécurité&lt;/strong&gt; : Le service &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/iam&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS IAM&lt;/a&gt; peut utiliser les tags pour accorder des permissions granulaires.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Bref, taguer, c&amp;rsquo;est la base d&amp;rsquo;une &lt;strong&gt;bonne gouvernance Cloud&lt;/strong&gt;. Pour plus de détails, je vous invite à consulter le &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/solutions/guidance/tagging-on-aws/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;guide de tagging proposé par AWS&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;On peut fort heureusement associer plusieurs tags à une même ressource. Mais cela pose la question : combien de tags sont nécessaires ?&lt;/p&gt;
&lt;p&gt;Cela va dépendre de votre entreprise et de chaque projet, mais globalement, il y a des tags qui ne font pas de mal, peu importe votre situation :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Project&lt;/strong&gt; : Le nom du projet lié à la ressource. Généralement, le nom du repository GitHub fait l&amp;rsquo;affaire&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Environment&lt;/strong&gt; : L&amp;rsquo;environnement désiré (dev, val, prod, &amp;hellip;). Même si vous avez des comptes AWS cloisonnés, cela vous permettra d&amp;rsquo;identifier si une ressource s&amp;rsquo;est perdue durant un déploiement&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Owner&lt;/strong&gt; : L&amp;rsquo;owner de la ressource. Cela pourrait être une personne, mais plus idéalement une équipe (frontend, backend, security, &amp;hellip;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Selon votre usage, vous aurez sûrement d&amp;rsquo;autres idées de tags, mais avec ceux-ci, ce sera déjà un bon début ! Et dans le doute, n&amp;rsquo;hésitez pas à consulter les &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/tag-editor/latest/userguide/best-practices-and-strats.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;best practices de tagging recommandées par AWS&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Voyons maintenant quelques cas concrets de l&amp;rsquo;utilité des tags dans AWS.&lt;/p&gt;
&lt;h2 id=&#34;aws-cost-explorer--suivre-les-coûts-grâce-aux-tags&#34;&gt;&lt;a href=&#34;#aws-cost-explorer--suivre-les-co%c3%bbts-gr%c3%a2ce-aux-tags&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;AWS Cost Explorer : Suivre les coûts grâce aux tags
&lt;/h2&gt;&lt;p&gt;L&amp;rsquo;un des avantages les plus concrets du tagging est la &lt;strong&gt;visibilité qu&amp;rsquo;il apporte sur vos dépenses&lt;/strong&gt;. &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/aws-cost-management/aws-cost-explorer/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS Cost Explorer&lt;/a&gt; est l&amp;rsquo;outil de prédilection pour cela.&lt;/p&gt;
&lt;p&gt;Une fois vos ressources correctement taguées (par exemple, avec le tag &lt;code&gt;Project&lt;/code&gt;), vous devez activer ces tags pour l&amp;rsquo;allocation des coûts dans la console de gestion de la facturation AWS (Billing and Cost Management -&amp;gt; Cost Organization -&amp;gt; Cost Allocation Tags). Attention, il peut y avoir un délai avant que les tags activés n&amp;rsquo;apparaissent dans Cost Explorer.&lt;/p&gt;
&lt;p&gt;Une fois activés, vous pouvez :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Filtrer par tag&lt;/strong&gt; : Dans Cost Explorer, vous pouvez filtrer vos coûts par la valeur d&amp;rsquo;un tag spécifique.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Grouper par tag&lt;/strong&gt; : Vous pouvez également choisir de grouper vos dépenses par tag. Cela vous donnera une vue d&amp;rsquo;ensemble de la répartition des coûts entre les différents projets, environnements, etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Créer des budgets basés sur les tags&lt;/strong&gt; : Avec AWS Budgets, vous pouvez définir des seuils d&amp;rsquo;alerte pour les coûts associés à des tags spécifiques, vous aidant à éviter les mauvaises surprises.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/why-tagging-your-aws-resources-is-a-must/cost_explorer_tag_filtering.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Exemple de filtrage par tag&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Exemple de filtrage par tag pour mon blog : les coûts sont minimes, suis-je un expert FinOps ?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Cette capacité à disséquer votre facture AWS par tags transforme la gestion des coûts d&amp;rsquo;une corvée obscure en un exercice transparent et contrôlable. C&amp;rsquo;est un must pour toute organisation soucieuse de son budget Cloud. Vous pourrez désormais rajouter &lt;em&gt;FinOps&lt;/em&gt; dans votre bio LinkedIn !&lt;/p&gt;
&lt;h2 id=&#34;aws-resource-explorer--garder-un-œil-sur-les-ressources-déployées&#34;&gt;&lt;a href=&#34;#aws-resource-explorer--garder-un-%c5%93il-sur-les-ressources-d%c3%a9ploy%c3%a9es&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;AWS Resource Explorer : Garder un œil sur les ressources déployées
&lt;/h2&gt;&lt;p&gt;Maintenant que l&amp;rsquo;on est convaincu de l&amp;rsquo;utilité des tags, comment fait-on pour &lt;strong&gt;lister toutes les ressources qui utilisent un tag précis ?&lt;/strong&gt; Nous allons le voir ensemble avec une partie dans la console AWS, et une partie qui se passera dans le terminal (pour tous les geeks qui lisent cet article !).&lt;/p&gt;
&lt;h3 id=&#34;lexploration-visuelle-dans-la-console-aws&#34;&gt;&lt;a href=&#34;#lexploration-visuelle-dans-la-console-aws&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;L&amp;rsquo;exploration visuelle dans la console AWS
&lt;/h3&gt;&lt;p&gt;Si vous n&amp;rsquo;êtes pas encore familier avec &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/resourceexplorer/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS Resource Explorer&lt;/a&gt;, c&amp;rsquo;est le moment de le découvrir ! Ce service, relativement récent, vous permet de rechercher et de découvrir vos ressources AWS à travers toutes les régions de votre compte, en utilisant une interface simple, un peu comme un moteur de recherche.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;avantage principal de Resource Explorer est sa capacité à vous donner une vue unifiée. Plus besoin de sauter de région en région. Vous activez l&amp;rsquo;indexation, et ensuite, vous pouvez rechercher vos ressources par nom, ID, et bien sûr&amp;hellip; par tag !&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est un excellent outil pour :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Avoir une vue d&amp;rsquo;ensemble rapide.&lt;/li&gt;
&lt;li&gt;Explorer visuellement les ressources associées à un tag spécifique.&lt;/li&gt;
&lt;li&gt;Identifier rapidement des ressources sans avoir à coder quoi que ce soit.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pour l&amp;rsquo;utiliser, activez-le dans les régions souhaitées (ou toutes), laissez-le indexer vos ressources, puis utilisez la barre de recherche avec une syntaxe comme &lt;code&gt;tag.key:Project tag.value:Cloud*&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/why-tagging-your-aws-resources-is-a-must/resource_explorer_search_tags.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Recherche des ressources par tag&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Exemple de recherche par tag pour mon blog : seulement trois ressources permettent de gérer ce blog !&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;une-approche-plus-technique-avec-aws-cli&#34;&gt;&lt;a href=&#34;#une-approche-plus-technique-avec-aws-cli&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Une approche plus technique avec AWS CLI
&lt;/h3&gt;&lt;p&gt;Pour ceux qui, comme moi, aiment avoir la main via la ligne de commande, ou qui ont besoin d&amp;rsquo;automatiser ces recherches, l&amp;rsquo;&lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/cli/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS CLI&lt;/a&gt; reste une alliée de choix. Plus précisément, c&amp;rsquo;est le service &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/cli/latest/reference/resourcegroupstaggingapi/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;resourcegroupstaggingapi&lt;/a&gt; qui va nous intéresser.&lt;/p&gt;
&lt;p&gt;La commande clé est &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/cli/latest/reference/resourcegroupstaggingapi/get-resources.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;get-resources&lt;/a&gt;. Voici un exemple typique pour lister les ARN de toutes les ressources ayant le tag Project avec la valeur &amp;ldquo;Cloud Antoine Delia&amp;rdquo; :&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;/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;aws resourcegroupstaggingapi get-resources &lt;span class=&#34;se&#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;    --tag-filters &lt;span class=&#34;s2&#34;&gt;&amp;#34;Key=Project,Values=Cloud Antoine Delia&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#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; jq &lt;span class=&#34;s2&#34;&gt;&amp;#34;[.ResourceTagMappingList[].ResourceARN]&amp;#34;&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;Ce qui nous donne :&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;/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-json&#34; data-lang=&#34;json&#34;&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;s2&#34;&gt;&amp;#34;arn:aws:s3:::antoiXXXXXXXXXXXXX&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;p&gt;Décortiquons un peu :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;aws resourcegroupstaggingapi get-resources&lt;/code&gt; : C&amp;rsquo;est l&amp;rsquo;appel à l&amp;rsquo;API, jusqu&amp;rsquo;ici, tout va bien.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--tag-filters &amp;quot;Key=Project,Values=Cloud Antoine Delia&amp;quot;&lt;/code&gt; : C&amp;rsquo;est ici qu&amp;rsquo;on spécifie notre filtre. On cherche le tag Project qui a la valeur &amp;ldquo;Cloud Antoine Delia&amp;rdquo;. Vous pouvez ajouter plusieurs filtres.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;| jq &amp;quot;[.ResourceTagMappingList[].ResourceARN]&amp;quot;&lt;/code&gt; : &lt;a class=&#34;link&#34; href=&#34;https://jqlang.org/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;jq&lt;/a&gt; est un outil formidable pour manipuler du JSON en ligne de commande. Ici, on l&amp;rsquo;utilise pour extraire proprement la liste des ARN des ressources trouvées (vous pouvez vous en passer, mais pourquoi se compliquer la vie ?).&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Eh attends une minute ! Dans la console, tu nous montres trois ressources, et là il n&amp;rsquo;y en a plus qu&amp;rsquo;une ! Elle est où l&amp;rsquo;arnaque ?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Habilement remarqué ! Il faut savoir que lorsque vous faites votre appel à l&amp;rsquo;API, vous utilisez une &lt;strong&gt;region par défaut&lt;/strong&gt;. Or, si vous avez des ressources dans diverses régions, il faudra le spécifier. Ainsi, si l&amp;rsquo;on ajoute &lt;code&gt;--region us-east-1&lt;/code&gt; juste avant le pipe jq, on obtient bien nos deux ressources manquantes.&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;/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-json&#34; data-lang=&#34;json&#34;&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;s2&#34;&gt;&amp;#34;arn:aws:acm:us-east-1:6XXXXXXXXXXX0:certificate/f4ca3b13-XXXXXXXXXXXXX&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;s2&#34;&gt;&amp;#34;arn:aws:cloudfront::6XXXXXXXXXXX0:distribution/ERSXXXXXXXXXX&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;p&gt;Outre ce détail qu&amp;rsquo;il ne vous faudra pas oublier, cette commande est extrêmement puissante car vous pouvez l&amp;rsquo;intégrer dans des scripts pour :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Générer des rapports réguliers sur les ressources par projet.&lt;/li&gt;
&lt;li&gt;Détecter automatiquement les ressources qui ne respectent pas votre politique de tagging.&lt;/li&gt;
&lt;li&gt;Combiner avec d&amp;rsquo;autres commandes AWS CLI pour effectuer des actions sur les ressources listées.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Par exemple, vous pourriez ainsi lister toutes vos ressources d&amp;rsquo;un certain type (ex: toutes vos instances EC2) et de vérifier celles à qui il manque des tags essentiels.&lt;/p&gt;
&lt;p&gt;Et si vous vous demandez si AWS n&amp;rsquo;offre pas déjà un service pour ça&amp;hellip; C&amp;rsquo;est le cas ! Mais nous en parlerons dans un futur article (pour les curieux, je veux parler d&amp;rsquo;&lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/config/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS Config&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id=&#34;aws-iam--sécuriser-lutilisation-de-vos-ressources&#34;&gt;&lt;a href=&#34;#aws-iam--s%c3%a9curiser-lutilisation-de-vos-ressources&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;AWS IAM : Sécuriser l&amp;rsquo;utilisation de vos ressources
&lt;/h2&gt;&lt;p&gt;Vos ressources sont déployées dans AWS, et vous souhaitez maintenant donner à une équipe la permission de gérer tout cela.&lt;/p&gt;
&lt;p&gt;Seulement voilà, dans votre compte AWS, vous avez aussi des ressources critiques qui ne doivent surtout pas être compromises.&lt;/p&gt;
&lt;p&gt;AWS IAM est là pour vous ! À l&amp;rsquo;aide d&amp;rsquo;une simple policy, vous pouvez spécifier que &lt;strong&gt;seules les ressources comportant un certain tag peuvent être modifiées&lt;/strong&gt; par un utilisateur ou un groupe.&lt;/p&gt;
&lt;p&gt;Prenons par exemple le cas suivant : vous aimeriez la possibilité à une équipe de démarrer ou stopper certaines instances EC2, mais de les empêcher d&amp;rsquo;accidentellement stopper une instance EC2 critique !&lt;/p&gt;
&lt;p&gt;Il vous suffit d&amp;rsquo;ajouter la policy suivante à vos utilisateurs :&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;/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-json&#34; data-lang=&#34;json&#34;&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;nt&#34;&gt;&amp;#34;Version&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;2012-10-17&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;nt&#34;&gt;&amp;#34;Statement&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#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;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;nt&#34;&gt;&amp;#34;Sid&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;AllowStartStopEC2IfProjectCloud&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;nt&#34;&gt;&amp;#34;Effect&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Allow&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;nt&#34;&gt;&amp;#34;Action&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#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;s2&#34;&gt;&amp;#34;ec2:StartInstances&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;s2&#34;&gt;&amp;#34;ec2:StopInstances&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;nt&#34;&gt;&amp;#34;Resource&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;arn:aws:ec2:*:*:instance/*&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;nt&#34;&gt;&amp;#34;Condition&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#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;nt&#34;&gt;&amp;#34;StringEquals&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#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;nt&#34;&gt;&amp;#34;aws:ResourceTag/Project&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Cloud Antoine Delia&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;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;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;Sid&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;AllowDescribeToSeeInstances&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;nt&#34;&gt;&amp;#34;Effect&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Allow&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;nt&#34;&gt;&amp;#34;Action&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;ec2:DescribeInstances&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;nt&#34;&gt;&amp;#34;Resource&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;*&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;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;Ainsi, vos utilisateurs seront autonomes dans l&amp;rsquo;utilisation de leurs ressources, sans pour autant avoir la possibilité d&amp;rsquo;impacter d&amp;rsquo;autres ressources.&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, une stratégie de tagging rigoureuse &lt;strong&gt;n&amp;rsquo;est pas une option, c&amp;rsquo;est une nécessité&lt;/strong&gt; pour opérer sereinement sur AWS. Que ce soit sur le plan organisationnel, financier, ou encore dans la gestion de la sécurité, AWS vous donne les moyens de tirer pleinement parti de vos tags.&lt;/p&gt;
&lt;p&gt;Alors, un petit conseil : si ce n&amp;rsquo;est pas déjà fait, &lt;strong&gt;définissez une politique de tagging claire&lt;/strong&gt; dans votre organisation, appliquez-la, et utilisez ces outils pour vérifier régulièrement que tout est en ordre. Vous m&amp;rsquo;en remercierez plus tard !&lt;/p&gt;
</description>
        </item>
        <item>
        <title>uv : La meilleure chose qui soit arrivée à Python - et pourquoi vous devriez l&#39;utiliser</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/uv-the-best-thing-that-happened-to-python-and-why-you-should-use-it/</link>
        <pubDate>Mon, 26 May 2025 07:30:00 +0200</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/uv-the-best-thing-that-happened-to-python-and-why-you-should-use-it/</guid>
        <description>&lt;img src="https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/uv-the-best-thing-that-happened-to-python-and-why-you-should-use-it/uv.jpg" alt="Featured image of post uv : La meilleure chose qui soit arrivée à Python - et pourquoi vous devriez l&#39;utiliser" /&gt;&lt;h1 id=&#34;introduction&#34;&gt;&lt;a href=&#34;#introduction&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Introduction
&lt;/h1&gt;&lt;p&gt;Python est sûrement mon langage de programmation préféré. Sa simplicité permet en un rien de temps de développer des scripts, des backends, voire même des sites internet, sans pour autant se faire des nœuds au cerveau.&lt;/p&gt;
&lt;p&gt;Mais il y a toujours eu une chose qui me déplaisait chez Python : ses outils de packaging. Pendant longtemps, je me suis tenu à l&amp;rsquo;écart de tous ces outils comme Poetry, car bien franchement, je n&amp;rsquo;y comprenais rien !&lt;/p&gt;
&lt;p&gt;Et puis, j&amp;rsquo;ai fait une découverte qui, non seulement m&amp;rsquo;a montré que packager son code Python est une tâche toute simple, mais qui en plus a complètement changé toutes mes habitudes.&lt;/p&gt;
&lt;p&gt;Je veux parler de &lt;a class=&#34;link&#34; href=&#34;https://docs.astral.sh/uv&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;strong&gt;uv&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Créé par la même équipe talentueuse de chez Astral (qui nous avait déjà régalé avec leur outil &lt;a class=&#34;link&#34; href=&#34;https://astral.sh/ruff&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;ruff&lt;/a&gt;), uv est présenté comme un installateur et résolveur de paquets Python &amp;ldquo;extrêmement rapide&amp;rdquo;. Cet outil est ce qu&amp;rsquo;on pourrait appeler un &lt;strong&gt;game-changer&lt;/strong&gt; : une fois que vous y avez goûté, impossible de revenir en arrière !&lt;/p&gt;
&lt;p&gt;Alors, qu&amp;rsquo;est-ce que &lt;strong&gt;uv&lt;/strong&gt; a de si spécial ? Pourquoi cet engouement ? C&amp;rsquo;est ce que nous allons décortiquer ensemble. Accrochez-vous, vous pourriez bien avoir un nouveau coup de foudre !&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ce guide se base sur mon expérience avec uv et les exemples ont été testés avec la version 0.7.3. Selon votre configuration, notamment derrière certains proxys d&amp;rsquo;entreprise, vous pourriez avoir besoin d&amp;rsquo;ajouter l&amp;rsquo;option &lt;code&gt;--native-tls&lt;/code&gt; à certaines commandes uv si vous rencontrez des soucis de connexion SSL.)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&#34;uv-cest-quoi-au-juste-&#34;&gt;&lt;a href=&#34;#uv-cest-quoi-au-juste-&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;uv, c&amp;rsquo;est quoi au juste ?
&lt;/h1&gt;&lt;p&gt;En quelques mots, uv est un outil en ligne de commande qui ambitionne de remplacer pip, pip-tools, venv, pyenv, et même une partie de virtualenv et pipx, tout en étant beaucoup, &lt;em&gt;beaucoup&lt;/em&gt; plus rapide. Oui, rien que ça !&lt;/p&gt;
&lt;p&gt;Comme nombre de nouveaux outils à la mode, il est écrit en Rust. Pardon, je devrais dire, il est écrit en ✨ &lt;em&gt;Rust&lt;/em&gt; ✨. Ce qui explique en grande partie ses performances fulgurantes.&lt;/p&gt;
&lt;h2 id=&#34;préambule&#34;&gt;&lt;a href=&#34;#pr%c3%a9ambule&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Préambule
&lt;/h2&gt;&lt;p&gt;Avant de nous lancer tête la première dans uv et son fonctionnement, j&amp;rsquo;aimerais en premier lieu vous indiquer la façon dont uv gère les dépendances, les environnements virtuels, et l&amp;rsquo;installation des versions de Python. Cela m&amp;rsquo;a plutôt dérouté la première fois que j&amp;rsquo;y ai été confronté, et je pense donc qu&amp;rsquo;il est important de le mentionner avant toute chose.&lt;/p&gt;
&lt;h3 id=&#34;gestion-des-dépendances&#34;&gt;&lt;a href=&#34;#gestion-des-d%c3%a9pendances&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Gestion des dépendances
&lt;/h3&gt;&lt;p&gt;uv base toute sa configuration sur votre fichier &lt;code&gt;pyproject.toml&lt;/code&gt;. Si vous aviez l&amp;rsquo;habitude d&amp;rsquo;utiliser un &lt;code&gt;requirements.txt&lt;/code&gt; par exemple, sachez que uv l&amp;rsquo;ignorera complètement.&lt;/p&gt;
&lt;p&gt;Comme je suis sympa, je vous mets ici un gist d&amp;rsquo;un template de &lt;code&gt;pyproject.toml&lt;/code&gt; que j&amp;rsquo;utilise à chaque fois pour démarrer un nouveau projet Python.&lt;/p&gt;
&lt;details&gt;
    &lt;summary&gt;pyproject.toml&lt;/summary&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;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;45
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;46
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;47
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;48
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;49
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;50
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;51
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;52
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;53
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;54
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;55
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;56
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;57
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;58
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;59
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;60
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;61
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;62
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;63
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;64
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;65
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;66
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;67
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;68
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;69
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;70
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;71
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;72
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;73
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;74
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;75
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;76
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;77
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;78
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;79
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;80
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;81
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;82
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;83
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;84
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;85
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;86
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;87
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;88
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;89
&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-toml&#34; data-lang=&#34;toml&#34;&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 class=&#34;nx&#34;&gt;project&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;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;project-name&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;version&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;0.1.0&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;description&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Project description&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;readme&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;README.md&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;requires-python&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;gt;=3.12&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;p&#34;&gt;[[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;tool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;uv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;index&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;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;votre-index&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;url&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://mon-artifactory.corp/api/pypi/mon-repo-virtual&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;publish-url&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://mon-artifactory.corp/api/pypi/mon-repo-local&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;default&lt;/span&gt; &lt;span class=&#34;p&#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&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 class=&#34;nx&#34;&gt;tool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ruff&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;c&#34;&gt;# Exclude common directories that are typically not part of the source code or are generated by tools.&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;exclude&lt;/span&gt; &lt;span class=&#34;p&#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;s2&#34;&gt;&amp;#34;.bzr&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;s2&#34;&gt;&amp;#34;.cache&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;s2&#34;&gt;&amp;#34;.direnv&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;s2&#34;&gt;&amp;#34;.eggs&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;s2&#34;&gt;&amp;#34;.git&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;s2&#34;&gt;&amp;#34;.git-rewrite&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;s2&#34;&gt;&amp;#34;.hg&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;s2&#34;&gt;&amp;#34;.mypy_cache&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;s2&#34;&gt;&amp;#34;.nox&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;s2&#34;&gt;&amp;#34;.pants.d&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;s2&#34;&gt;&amp;#34;.pytype&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;s2&#34;&gt;&amp;#34;.ruff_cache&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;s2&#34;&gt;&amp;#34;.svn&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;s2&#34;&gt;&amp;#34;.tox&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;s2&#34;&gt;&amp;#34;.venv&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;s2&#34;&gt;&amp;#34;__pypackages__&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;s2&#34;&gt;&amp;#34;_build&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;s2&#34;&gt;&amp;#34;buck-out&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;s2&#34;&gt;&amp;#34;build&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;s2&#34;&gt;&amp;#34;dist&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;s2&#34;&gt;&amp;#34;node_modules&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;s2&#34;&gt;&amp;#34;venv&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;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;c&#34;&gt;# Set the maximum line length to 127 characters.&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;line-length&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;127&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;c&#34;&gt;# Define the number of spaces used for indentation, aligning with Black&amp;#39;s style.&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;indent-width&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&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;c&#34;&gt;# The minimum Python version to target, e.g., when considering automatic code upgrades,&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;c&#34;&gt;# like rewriting type annotations&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;target-version&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;py312&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;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;tool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ruff&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;lint&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;c&#34;&gt;# Enable Pyflakes (F) and a subset of the pycodestyle (E) codes by default.&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;c&#34;&gt;# pycodestyle warnings (W)&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;c&#34;&gt;# Activate Security Rules (S) to replace bandit&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;c&#34;&gt;# Enable the isort rules (I) to replace isort&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;c&#34;&gt;# flake8-bugbear (B)&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;c&#34;&gt;# flake8-simplify (SIM)&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;select&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;F&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;E4&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;E7&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;E9&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;W&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;S&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;I&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;B&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;SIM&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;PGH004&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;ignore&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;# List any rules to be ignored, currently empty.&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;c&#34;&gt;# Allow auto-fixing of all enabled rules when using the `--fix` option.&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;fixable&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;ALL&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;unfixable&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;# Specify rules that cannot be auto-fixed, if any.&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;c&#34;&gt;# Define a regex pattern for allowed unused variables (typically underscore-prefixed).&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;dummy-variable-rgx&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$&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;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;tool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ruff&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;format&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;c&#34;&gt;# Enforce double quotes for strings, following Black&amp;#39;s style.&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;quote-style&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;double&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;c&#34;&gt;# Use spaces for indentation, in line with Black&amp;#39;s formatting style.&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;indent-style&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;space&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;c&#34;&gt;# Keep magic trailing commas, a feature of Black&amp;#39;s formatting.&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;skip-magic-trailing-comma&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&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;c&#34;&gt;# Automatically detect and use the appropriate line ending style.&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;line-ending&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;auto&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;c&#34;&gt;# Update this with your package name or directory to be scanned by pytest-cov&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 class=&#34;nx&#34;&gt;tool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;pytest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ini_options&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;addopts&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;-s --no-header --cov=src --cov-fail-under=50&amp;#34;&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;# force cmd flags&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;testpaths&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;# what directories contain tests&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;s2&#34;&gt;&amp;#34;tests&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;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;pythonpath&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;c&#34;&gt;# what to add to the python path&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;s2&#34;&gt;&amp;#34;.&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;/details&gt;
&lt;p&gt;Au lieu d&amp;rsquo;ajouter vos dépendances à la main, vous pouvez maintenant utiliser &lt;code&gt;uv add &amp;lt;package_name&amp;gt;&lt;/code&gt;, et celui-ci sera ajouté à votre &lt;code&gt;pyproject.toml&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Attention cependant, car certains outils externes se basent toujours sur un fichier &lt;code&gt;requirements.txt&lt;/code&gt;. Vous aurez donc peut-être besoin de lancer la commande &lt;code&gt;uv pip compile -o requirements.txt&lt;/code&gt; dans votre pipeline CI/CD.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;environnement-virtuel&#34;&gt;&lt;a href=&#34;#environnement-virtuel&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Environnement virtuel
&lt;/h3&gt;&lt;p&gt;Comme moi, vous aviez peut-être l&amp;rsquo;habitude d&amp;rsquo;utiliser la commande &lt;code&gt;source .venv/bin/activate&lt;/code&gt; pour activer votre environnement virtuel. Avec uv, c&amp;rsquo;est un peu différent. Votre &lt;code&gt;.venv&lt;/code&gt; sera toujours créé, mais en utilisant uv, il se mettra par défaut dans votre environnement virtuel. Prenons un exemple.&lt;/p&gt;
&lt;p&gt;Là où à l&amp;rsquo;époque vous auriez dû faire ce genre de commandes pour lancer votre script.&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;/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;python -m venv .venv
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;source&lt;/span&gt; .venv/bin/activate
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install requests
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;python main.py
&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;Désormais, uv enlève la gestion de l&amp;rsquo;environnement virtuel de votre travail. Ainsi, les commandes ci-dessus seront remplacées par celles-ci.&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;/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;uv add requests
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv run main.py
&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;Lorsque vous ajoutez un nouveau paquet à votre projet (avec la commande &lt;code&gt;uv add&lt;/code&gt;), uv se charge automatiquement de créer un environnement virtuel s&amp;rsquo;il n&amp;rsquo;existe pas déjà.&lt;/p&gt;
&lt;p&gt;Ensuite, en lançant votre script via &lt;code&gt;uv run&lt;/code&gt;, uv se mettra automatiquement dans votre environnement virtuel.&lt;/p&gt;
&lt;h3 id=&#34;installation-de-python&#34;&gt;&lt;a href=&#34;#installation-de-python&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Installation de Python
&lt;/h3&gt;&lt;p&gt;Vous utilisiez peut-être pyenv pour installer vos différentes versions de Python. Avec uv, tout cela est de l&amp;rsquo;histoire ancienne !&lt;/p&gt;
&lt;p&gt;Lorsque vous souhaitez lancer un projet avec une version de Python bien spécifique, vous avez plusieurs moyens de faire :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Utiliser le fichier &lt;code&gt;.python-version&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Créer un environnement virtuel : &lt;code&gt;uv venv --python 3.11.6&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Lancer une version de Python spécifique : &lt;code&gt;uvx python@3.12&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ce que vous devez retenir, c&amp;rsquo;est que uv ne s&amp;rsquo;appuie pas sur une version globale de Python installée, mais essaiera toujours d&amp;rsquo;utiliser la version spécifique à votre projet.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Bon, je crois que vous en savez assez pour commencer votre initiation. Allons-y !&lt;/p&gt;
&lt;h1 id=&#34;installation&#34;&gt;&lt;a href=&#34;#installation&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Installation
&lt;/h1&gt;&lt;p&gt;L&amp;rsquo;installation de uv est un jeu d&amp;rsquo;enfant. Vous avez plusieurs options, choisissez celle qui vous convient le mieux (n&amp;rsquo;hésitez pas à consulter la &lt;a class=&#34;link&#34; href=&#34;https://docs.astral.sh/uv/getting-started/installation/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;documentation officielle sur son installation&lt;/a&gt; si besoin) :&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-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Sur macOS et Linux - je vous recommande d&amp;#39;utiliser cela si possible&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl -LsSf https://astral.sh/uv/install.sh &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; sh
&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;c1&#34;&gt;# Sur Windows (avec PowerShell)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;powershell -c &lt;span class=&#34;s2&#34;&gt;&amp;#34;irm https://astral.sh/uv/install.ps1 | iex&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;c1&#34;&gt;# Avec pip (si vous avez déjà un environnement Python)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install uv
&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;Une fois installé, vous pouvez le mettre à jour très simplement :&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-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv self update
&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;Et voilà, uv est prêt à l&amp;rsquo;emploi !&lt;/p&gt;
&lt;h1 id=&#34;gérer-les-versions-de-python-avec-uv&#34;&gt;&lt;a href=&#34;#g%c3%a9rer-les-versions-de-python-avec-uv&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Gérer les versions de Python avec uv
&lt;/h1&gt;&lt;p&gt;Une des fonctionnalités sympathiques de uv est sa capacité à installer des versions spécifiques de Python. Plus besoin de passer par le site officiel Python, de jongler avec pyenv ou d&amp;rsquo;autres outils.&lt;/p&gt;
&lt;p&gt;Pour installer la dernière version stable de Python :&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-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv python install
&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;Besoin d&amp;rsquo;une version particulière ? Pas de problè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;/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;&lt;span class=&#34;c1&#34;&gt;# Installer Python 3.9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv python install 3.9
&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 pouvez ensuite utiliser cette version pour exécuter un script :&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-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv run --python 3.9 python mon_script.py
&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;blockquote&gt;
&lt;p&gt;Comme je vous l&amp;rsquo;expliquais un peu plus haut, les versions de Python installées par uv ne sont pas disponibles &amp;ldquo;globalement&amp;rdquo; sur votre système via la simple commande &lt;code&gt;python&lt;/code&gt;. Pour les utiliser, il faut passer par &lt;code&gt;uv run --python &amp;lt;version&amp;gt;&lt;/code&gt;, ou les activer dans un environnement virtuel créé avec cette version spécifique.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&#34;uvx-pour-exécuter-des-packages-à-la-volée&#34;&gt;&lt;a href=&#34;#uvx-pour-ex%c3%a9cuter-des-packages-%c3%a0-la-vol%c3%a9e&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;uvx pour exécuter des packages à la volée
&lt;/h1&gt;&lt;p&gt;Vous connaissez peut-être &lt;a class=&#34;link&#34; href=&#34;https://docs.npmjs.com/cli/v8/commands/npx&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;npx&lt;/a&gt; dans le monde JavaScript ? uvx (le shortcut de &lt;code&gt;uv tool run&lt;/code&gt;) est l&amp;rsquo;équivalent proposé par uv. Il permet d&amp;rsquo;exécuter une commande CLI Python (comme ruff, black, ipython, etc.) dans un environnement temporaire avec les dépendances spécifiées, sans polluer votre projet ou votre système.&lt;/p&gt;
&lt;p&gt;Par exemple, pour lancer une version spécifique de ruff :&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-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uvx --python 3.12 ruff@0.9.6 check main.py
&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;Ou pour lancer ipython avec requests disponible temporairement :&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-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uvx --with requests -p 3.13 ipython
&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;Extrêmement pratique pour des one-shots ou pour tester des outils !&lt;/p&gt;
&lt;h1 id=&#34;la-gestion-des-projets-avec-uv&#34;&gt;&lt;a href=&#34;#la-gestion-des-projets-avec-uv&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;La gestion des projets avec uv
&lt;/h1&gt;&lt;p&gt;Bon, toutes ces commandes, c&amp;rsquo;est très sympa, mais j&amp;rsquo;imagine que vous vous demandez comment intégrer uv dans un nouveau projet, ou dans un projet existant.&lt;/p&gt;
&lt;p&gt;Laissez-moi donc vous montrer toute la puissance de uv pour créer et gérer un projet Python.&lt;/p&gt;
&lt;h2 id=&#34;démarrer-un-nouveau-projet&#34;&gt;&lt;a href=&#34;#d%c3%a9marrer-un-nouveau-projet&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Démarrer un nouveau projet
&lt;/h2&gt;&lt;p&gt;Pour initialiser un nouveau projet avec uv :&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-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv init
&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 commande va créer quelques fichiers pour vous :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.python-version&lt;/code&gt; : Spécifie la version de Python à utiliser pour ce projet (par exemple, &lt;code&gt;3.11&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;main.py&lt;/code&gt; : Un fichier Python d&amp;rsquo;exemple.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pyproject.toml&lt;/code&gt; : Le fichier central pour la configuration de votre projet, y compris ses dépendances. C&amp;rsquo;est le standard moderne en Python.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Maintenant, voyons comment gérer nos dépendances.&lt;/p&gt;
&lt;p&gt;Avec uv, le &lt;code&gt;pyproject.toml&lt;/code&gt; devient votre source de vérité pour les dépendances.&lt;/p&gt;
&lt;p&gt;Pour ajouter une nouvelle dépendance à votre projet :&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-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv add requests
&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;Pour ajouter une dépendance de développement (uniquement pour le dev, comme ruff ou pytest) :&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;/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;uv add ruff --dev
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv add pytest --dev
&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;blockquote&gt;
&lt;p&gt;⚠️ Très important : La première fois que vous ajoutez une dépendance, uv va générer un fichier &lt;code&gt;uv.lock&lt;/code&gt;. Ce fichier contient les versions exactes de toutes vos dépendances (directes et indirectes) qui ont été résolues. Ce fichier &lt;code&gt;uv.lock&lt;/code&gt; est crucial et DOIT être commité dans votre repository GitHub. Il garantit que les versions de vos paquets soient les mêmes pour tout le monde, selon votre environnement de travail.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Une fois vos dépendances (notamment de dev) ajoutées, vous pouvez les utiliser avec &lt;code&gt;uv run&lt;/code&gt; :&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;/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;uv run ruff format .
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv run pytest
&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;Pour supprimer un paquet :&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;/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;&lt;span class=&#34;c1&#34;&gt;# Pour une dépendance normale&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv remove requests
&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;c1&#34;&gt;# Pour une dépendance de développement (notez le --group dev)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv remove ruff --group dev
&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;Dans le cas où vous utiliseriez uv en entreprise avec un index privé, vous pouvez aussi configurer cela !&lt;/p&gt;
&lt;p&gt;Par défaut, uv utilise PyPI. Si vous travaillez dans un environnement d&amp;rsquo;entreprise (avec un Artifactory ou un autre index privé), vous pouvez configurer uv pour l&amp;rsquo;utiliser via le fichier &lt;code&gt;pyproject.toml&lt;/code&gt;.&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;/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-toml&#34; data-lang=&#34;toml&#34;&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 class=&#34;nx&#34;&gt;tool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;uv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;index&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;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;votre-index&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;url&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://mon-artifactory.corp/api/pypi/mon-repo-virtual&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;publish-url&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://mon-artifactory.corp/api/pypi/mon-repo-local&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;default&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&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, vous pouvez par exemple exporter des variables d&amp;rsquo;environnement pour vous authentifier.&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;/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;&lt;span class=&#34;c1&#34;&gt;# Les variables d&amp;#39;environnement doivent respecter le format suivant : UV_INDEX_{name}_USERNAME&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;c1&#34;&gt;# où {name} est le nom de l&amp;#39;index que vous avez défini dans votre fichier pyproject.toml&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;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;UV_INDEX_VOTRE_INDEX_USERNAME&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;delia, antoine&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;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;UV_INDEX_VOTRE_INDEX_PASSWORD&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;cmVmdG**************************FJUjNw&amp;#34;&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;N&amp;rsquo;hésitez pas à consulter la &lt;a class=&#34;link&#34; href=&#34;https://docs.astral.sh/uv/configuration/indexes/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;documentation uv sur les index&lt;/a&gt; pour plus de détails.&lt;/p&gt;
&lt;h2 id=&#34;migrer-un-projet-existant-vers-uv&#34;&gt;&lt;a href=&#34;#migrer-un-projet-existant-vers-uv&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Migrer un projet existant vers uv
&lt;/h2&gt;&lt;p&gt;Vous avez un projet avec un bon vieux &lt;code&gt;requirements.txt&lt;/code&gt; ? La migration est assez simple :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Si vous n&amp;rsquo;avez pas de &lt;code&gt;pyproject.toml&lt;/code&gt;, créez-en un (n&amp;rsquo;hésitez pas à utiliser celui fourni plus haut).&lt;/li&gt;
&lt;li&gt;Lancez les commandes suivantes pour ajouter vos requirements dans votre pyproject.toml : &lt;code&gt;uv add -r requirements.txt&lt;/code&gt; et &lt;code&gt;uv add --dev -r requirements-dev.txt&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Une fois toutes les dépendances migrées, vous pouvez supprimer vos anciens fichiers &lt;code&gt;requirements.txt&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Si vous utilisiez d&amp;rsquo;autres outils comme Poetry, il existe des outils de migration (comme par exemple : &lt;code&gt;uvx migrate-to-uv&lt;/code&gt;).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Et voilà, votre projet est propulsé par uv !&lt;/p&gt;
&lt;h2 id=&#34;rejoindre-un-projet-qui-utilise-déjà-uv&#34;&gt;&lt;a href=&#34;#rejoindre-un-projet-qui-utilise-d%c3%a9j%c3%a0-uv&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Rejoindre un projet qui utilise déjà uv
&lt;/h2&gt;&lt;p&gt;Si vous clonez un projet qui est déjà géré par uv (il devrait donc y avoir un &lt;code&gt;pyproject.toml&lt;/code&gt; et un &lt;code&gt;uv.lock&lt;/code&gt;), la mise en place est d&amp;rsquo;une simplicité enfantine. Vous n&amp;rsquo;avez qu&amp;rsquo;à lancer :&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-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv sync
&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 commande magique va lire le fichier &lt;code&gt;uv.lock&lt;/code&gt; et installer &lt;em&gt;exactement&lt;/em&gt; les mêmes versions de tous les paquets qui y sont listés. N&amp;rsquo;est-ce pas beau tout ça ?&lt;/p&gt;
&lt;h1 id=&#34;build-et-publier-votre-projet&#34;&gt;&lt;a href=&#34;#build-et-publier-votre-projet&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Build et publier votre projet
&lt;/h1&gt;&lt;p&gt;uv ne s&amp;rsquo;arrête pas là et propose aussi des commandes pour le build et la publication.&lt;/p&gt;
&lt;p&gt;Pour construire votre package :&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-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv build
&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;Pour publier sur PyPI (ou un index privé) :&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;/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;uv publish
&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;# Pour un index privé, vous pourriez avoir besoin de spécifier l&amp;#39;URL (sauf si déjà spécifiée dans votre pyproject.toml)&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;c1&#34;&gt;# uv publish --repository-url https://mon-artifactory.corp/api/pypi/mon-repo-local&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;Et pour tester rapidement si votre package fraîchement buildé s&amp;rsquo;installe et s&amp;rsquo;importe correctement :&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;/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;&lt;span class=&#34;c1&#34;&gt;# Remplacez &amp;lt;MON_PACKAGE&amp;gt; par le nom de votre paquet&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv run --with &amp;lt;MON_PACKAGE&amp;gt;-&amp;lt;VERSION&amp;gt;.whl --no-project --python -c &lt;span class=&#34;s2&#34;&gt;&amp;#34;import &amp;lt;MON_PACKAGE&amp;gt;&amp;#34;&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;Et voilà ! Vous avez publié votre package en un clin d&amp;rsquo;oeil !&lt;/p&gt;
&lt;h1 id=&#34;nettoyer-votre-cache&#34;&gt;&lt;a href=&#34;#nettoyer-votre-cache&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Nettoyer votre cache
&lt;/h1&gt;&lt;p&gt;Avec le temps, uv (tout comme pip) accumule un cache de paquets téléchargés. Alors certes, cela permet rapidement d&amp;rsquo;installer vos dépendances sur plusieurs projets, mais à la longue, cela pourrait prendre pas mal de place sur votre ordinateur. Pour le nettoyer, il suffit de lancer la commande suivante :&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-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv cache clean
&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;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, uv n&amp;rsquo;est pas juste &amp;ldquo;encore un autre gestionnaire de paquets&amp;rdquo;. &lt;strong&gt;C&amp;rsquo;est une véritable bouffée d&amp;rsquo;air frais dans l&amp;rsquo;écosystème Python.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;La vitesse :&lt;/strong&gt; C&amp;rsquo;est le premier argument qui frappe lorsqu&amp;rsquo;on l&amp;rsquo;utilise. Les installations, les résolutions, tout est incroyablement plus rapide que pip. Sur de gros projets, le gain de temps est phénoménal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;L&amp;rsquo;unification :&lt;/strong&gt; uv regroupe des fonctionnalités qui nécessitaient auparavant plusieurs outils (pip, venv, pip-tools, voire pyenv pour des besoins basiques). Avoir une seule interface cohérente simplifie grandement le workflow.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;La conformité :&lt;/strong&gt; Les développeurs d&amp;rsquo;uv basent tous leurs choix sur les guidelines Python (ces fameux PEP). Vous pouvez donc être sûr que votre &lt;code&gt;pyproject.toml&lt;/code&gt; respecte les standards modernes de packaging Python.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;La fiabilité :&lt;/strong&gt; Le système de lockfile (&lt;code&gt;uv.lock&lt;/code&gt;) assure des builds reproductibles, un point essentiel pour le travail en équipe et l&amp;rsquo;intégration continue.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Depuis que j&amp;rsquo;utilise uv, mes interactions avec la gestion des dépendances Python sont devenues plus rapides, plus simples et plus agréables. &lt;strong&gt;C&amp;rsquo;est le genre d&amp;rsquo;outil qui, une fois adopté, vous fait vous demander comment vous faisiez avant.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Alors, si vous cherchez à moderniser votre utilisation de Python et à gagner en productivité (et en sérénité !), je ne peux que vous encourager à donner sa chance à uv. L&amp;rsquo;essayer, c&amp;rsquo;est très souvent l&amp;rsquo;adopter !&lt;/p&gt;
&lt;h1 id=&#34;références&#34;&gt;&lt;a href=&#34;#r%c3%a9f%c3%a9rences&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Références
&lt;/h1&gt;&lt;ul&gt;
&lt;li&gt;Documentation officielle uv : &lt;a class=&#34;link&#34; href=&#34;https://docs.astral.sh/uv&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://docs.astral.sh/uv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Repo GitHub uv : &lt;a class=&#34;link&#34; href=&#34;https://github.com/astral-sh/uv&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/astral-sh/uv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.bitecode.dev/p/a-year-of-uv-pros-cons-and-should&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;A year of uv: pros, cons, and should you switch? (bitecode.dev)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.bitecode.dev/p/uv-tricks&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;uv tricks (bitecode.dev)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;bonus--uv-cheatsheet&#34;&gt;&lt;a href=&#34;#bonus--uv-cheatsheet&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Bonus : uv cheatsheet
&lt;/h1&gt;&lt;p&gt;Je vous mets ici une liste de commandes uv ultra pratiques. Une sorte de cheatsheet si vous préférez. N&amp;rsquo;hésitez pas à revenir la consulter au besoin !&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;/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;&lt;span class=&#34;c1&#34;&gt;# Update uv&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv self update
&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;c1&#34;&gt;# Run a script with a specific Python version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv run --python 3.12.3 main.py
&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;c1&#34;&gt;# Quickly run a tool with a specific version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uvx --python 3.12 ruff@0.9.6 check
&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;c1&#34;&gt;# Quickly run ipython with requests installed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uvx --with requests -p 3.13 ipython
&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;c1&#34;&gt;# Update your project&amp;#39;s version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv version --bump &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;major/minor/patch&lt;span class=&#34;o&#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;c1&#34;&gt;# Clean the cache&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv cache clean
&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;</description>
        </item>
        <item>
        <title>AWS Lambda : La phase d&#39;INIT devient payante - faut-il s&#39;alarmer ?</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/aws-lambdas-init-phase-to-be-billed-soon-should-we-be-alarmed/</link>
        <pubDate>Tue, 13 May 2025 07:30:00 +0200</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/aws-lambdas-init-phase-to-be-billed-soon-should-we-be-alarmed/</guid>
        <description>&lt;img src="https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/aws-lambdas-init-phase-to-be-billed-soon-should-we-be-alarmed/lambda-init-billing.jpeg" alt="Featured image of post AWS Lambda : La phase d&#39;INIT devient payante - faut-il s&#39;alarmer ?" /&gt;&lt;h1 id=&#34;introduction&#34;&gt;&lt;a href=&#34;#introduction&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Introduction
&lt;/h1&gt;&lt;p&gt;Ah, les Lambdas. Probablement le service AWS que j&amp;rsquo;affectionne le plus ! En moins de temps qu&amp;rsquo;il ne faut pour le dire, elles permettent de créer un petit script ou carrément un backend API hosté dans le Cloud, et tout cela à moindre coût avec le &amp;ldquo;pay as you go&amp;rdquo;. Mais cela serait-il trop beau pour être vrai ?&lt;/p&gt;
&lt;p&gt;Il y a quelques jours, &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/blogs/compute/aws-lambda-standardizes-billing-for-init-phase&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS a annoncé une modification dans la manière dont la phase d&amp;rsquo;initialisation des Lambdas est facturée&lt;/a&gt;. &lt;strong&gt;À partir du 1er août 2025&lt;/strong&gt;, cette phase sera systématiquement incluse dans le calcul de la durée facturée, et ce, pour &lt;em&gt;toutes&lt;/em&gt; les Lambdas.&lt;/p&gt;
&lt;p&gt;Si vous n&amp;rsquo;étiez pas au courant, sachez que jusqu&amp;rsquo;à présent, si vous utilisiez des fonctions Lambdas avec un code packagé en ZIP avec des runtimes managés par AWS (comme Python, Node.js, etc.), la durée de cette phase &lt;code&gt;INIT&lt;/code&gt; n&amp;rsquo;était pas facturée. C&amp;rsquo;était un petit &amp;ldquo;cadeau&amp;rdquo; de la part d&amp;rsquo;AWS (plutôt sympa de leur part). Mais toutes les bonnes choses ont une fin, et il faudra maintenant payer ce temps d&amp;rsquo;initialisation de nos Lambdas.&lt;/p&gt;
&lt;p&gt;Alors, cela va-t-il rendre l&amp;rsquo;usage des Lambdas trop cher ? Et comment faire en sorte de réduire au maximum cette partie d&amp;rsquo;initialisation ? Je vous propose aujourd&amp;rsquo;hui de répondre à toutes ces questions !&lt;/p&gt;
&lt;h1 id=&#34;comprendre-le-cycle-de-vie-dune-lambda&#34;&gt;&lt;a href=&#34;#comprendre-le-cycle-de-vie-dune-lambda&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Comprendre le cycle de vie d&amp;rsquo;une Lambda
&lt;/h1&gt;&lt;p&gt;Avant de plonger dans la facturation, c&amp;rsquo;est l&amp;rsquo;occasion de se rappeler du &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtime-environment.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;cycle de vie d&amp;rsquo;une Lambda&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Pour simplifier la lecture, je ne rentrerai pas dans les détails des &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/lambda-extensions.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Lambda Extensions&lt;/a&gt; et de &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Lambda SnapStart&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Cela se compose de trois phases principales :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;INIT :&lt;/strong&gt; C&amp;rsquo;est l&amp;rsquo;étape du &amp;ldquo;démarrage à froid&amp;rdquo; ou cold start. Quand une nouvelle instance de votre fonction doit être créée pour répondre à une requête, Lambda prépare le terrain. Cette phase dure au maximum 10 secondes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;INVOKE :&lt;/strong&gt; C&amp;rsquo;est là que votre code (le handler de votre fonction) est exécuté pour traiter la requête.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SHUTDOWN :&lt;/strong&gt; Quand l&amp;rsquo;environnement d&amp;rsquo;exécution n&amp;rsquo;est plus utilisé pendant un certain temps, la Lambda se &amp;ldquo;shutdown&amp;rdquo; pour libérer les ressources. Si une nouvelle requête arrive, la Lambda devra de nouveau passer par la phase d&amp;rsquo;INIT.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/aws-lambdas-init-phase-to-be-billed-soon-should-we-be-alarmed/lambda_lifecycle.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Lambda Lifecycle&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Pendant la phase &lt;code&gt;INIT&lt;/code&gt;, &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtime-environment.html#runtimes-lifecycle-ib&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;votre Lambda fait plusieurs choses&lt;/a&gt; :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Récupère votre code (depuis S3 pour un ZIP, ou ECR pour une image Docker).&lt;/li&gt;
&lt;li&gt;Configure l&amp;rsquo;environnement avec la mémoire allouée, le runtime choisi, etc.&lt;/li&gt;
&lt;li&gt;Démarre le runtime (&lt;code&gt;Runtime INIT&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Exécute le code statique de votre fonction (tout ce qui est en dehors du handler, par exemple l&amp;rsquo;initialisation de variables globales ou de &lt;code&gt;boto3&lt;/code&gt;) (&lt;code&gt;Function INIT&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Le point clé à retenir de tout cela, c&amp;rsquo;est que la phase &lt;code&gt;INIT&lt;/code&gt; ne se produit que lors d&amp;rsquo;un démarrage &lt;em&gt;à froid&lt;/em&gt; (ce fameux cold start). Si une requête arrive alors qu&amp;rsquo;un environnement d&amp;rsquo;exécution est déjà &amp;ldquo;chaud&amp;rdquo; (prêt et réutilisé), cette phase est sautée, et on passe directement à l&amp;rsquo;&lt;code&gt;INVOKE&lt;/code&gt;. C&amp;rsquo;est ce qu&amp;rsquo;on appelle un &amp;ldquo;démarrage à chaud&amp;rdquo; (warm start), qui est bien plus rapide.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;AWS ne communique pas sur son calcul pour passer une Lambda &amp;ldquo;warm&amp;rdquo; à &amp;ldquo;cold&amp;rdquo;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&#34;le-changement-de-facturation-en-détail&#34;&gt;&lt;a href=&#34;#le-changement-de-facturation-en-d%c3%a9tail&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Le changement de facturation en détail
&lt;/h1&gt;&lt;p&gt;Actuellement, &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/lambda/pricing/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;la facturation des Lambdas&lt;/a&gt; repose sur deux éléments :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Le nombre de requêtes.&lt;/li&gt;
&lt;li&gt;La durée d&amp;rsquo;exécution de votre code, arrondie à la milliseconde supérieure (le coût de cette durée dépend de la mémoire allouée à la fonction).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Jusqu&amp;rsquo;au 1er août 2025, pour ces fonctions en ZIP avec runtime managé, la durée de la phase &lt;code&gt;INIT&lt;/code&gt; n&amp;rsquo;était pas comptée dans la &amp;ldquo;Durée Facturée&amp;rdquo; (&lt;code&gt;Billed Duration&lt;/code&gt;). On pouvait le voir dans les logs CloudWatch :&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-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Avant le 1er août 2025
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Notez que la Billed Duration est l&amp;#39;arrondie au supérieur
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# de la Duration sans tenir compte de la Init Duration
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;REPORT RequestId: xxxxx   Duration: 250.06 ms   Billed Duration: 251 ms   Init Duration: 100.77 ms
&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;# Après le 1er août 2025
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# La Billed Duration est maintenant l&amp;#39;arrondie au supérieur
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# de la Duration + la Init Duration
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;REPORT RequestId: xxxxx   Duration: 250.06 ms   Billed Duration: 351 ms   Init Duration: 100.77 ms
&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 pouvez le voir, AWS prendra maintenant en compte votre Init Duration en plus de la Duration pour réaliser son calcul de la Billed Duration.&lt;/p&gt;
&lt;h1 id=&#34;quel-impact-sur-la-facture-&#34;&gt;&lt;a href=&#34;#quel-impact-sur-la-facture-&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Quel impact sur la facture ?
&lt;/h1&gt;&lt;p&gt;Alors tout ça, c&amp;rsquo;est bien beau, mais allons-nous tous finir ruiner par ce changement ?&lt;/p&gt;
&lt;p&gt;Prenons un exemple pour y voir plus clair. Imaginons une Lambda en Python configurée avec 1024 Mo de mémoire, déployée dans la région &lt;code&gt;eu-west-1&lt;/code&gt; (Irlande).&lt;/p&gt;
&lt;p&gt;Supposons les points suivants :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;La Lambda reçoit 10 millions d&amp;rsquo;invocations par mois.&lt;/li&gt;
&lt;li&gt;Le taux de cold start est de 1% (&lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtime-environment.html#cold-start-latency&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;moyenne fournie par AWS&lt;/a&gt;), soit 100&#39;000 démarrages à froid par mois.&lt;/li&gt;
&lt;li&gt;La durée moyenne de l&amp;rsquo;invocation (&lt;code&gt;Duration&lt;/code&gt;) est de 3 secondes.&lt;/li&gt;
&lt;li&gt;La durée moyenne de l&amp;rsquo;initialisation (&lt;code&gt;Init Duration&lt;/code&gt;) est de 1 seconde.&lt;/li&gt;
&lt;li&gt;Coût par requête : $0.20 par million de requêtes.&lt;/li&gt;
&lt;li&gt;Coût de la durée (x86) : $0.0000166667 par GB-seconde.&lt;/li&gt;
&lt;/ul&gt;
&lt;details&gt;
  &lt;summary&gt;Détails des calculs&lt;/summary&gt;
&lt;p&gt;&lt;strong&gt;Calcul du coût AVANT le 1er août 2025 :&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Coût des requêtes :&lt;/strong&gt; 10 millions req * ($0.20 / 1 million req) = &lt;strong&gt;$2.00&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Coût de la durée :&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Invocations &amp;ldquo;à chaud&amp;rdquo; (9.9 millions) : Durée facturée = 3 secondes.&lt;/li&gt;
&lt;li&gt;Invocations &amp;ldquo;à froid&amp;rdquo; (100 000) : Durée facturée = 3 secondes (INIT non facturée).&lt;/li&gt;
&lt;li&gt;Durée facturée totale (secondes) : (9&#39;900&#39;000 * 3 s) + (100&#39;000 * 3 s) = 29&#39;700&#39;000 secondes + 300&#39;000 secondes = 30&#39;000&#39;000 secondes.&lt;/li&gt;
&lt;li&gt;Go-secondes totaux : 30&#39;000&#39;000 secondes * (1024 Mo / 1024 Mo) = 30&#39;000&#39;000 Go-s.&lt;/li&gt;
&lt;li&gt;Coût Durée : 30&#39;000&#39;000 Go-s * $0.0000166667/Go-s = &lt;strong&gt;$500.00&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Coût total mensuel (Avant) :&lt;/strong&gt; $2.00 + $500.00 = &lt;strong&gt;$502.00&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Calcul du coût APRÈS le 1er août 2025 :&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Coût des requêtes :&lt;/strong&gt; &lt;strong&gt;$2.00&lt;/strong&gt; (inchangé)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Coût de la durée :&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Invocations &amp;ldquo;à chaud&amp;rdquo; (9.9 millions) : Durée facturée = 3 secondes.&lt;/li&gt;
&lt;li&gt;Invocations &amp;ldquo;à froid&amp;rdquo; (100 000) : Durée facturée = 3 secondes (&lt;code&gt;Duration&lt;/code&gt;) + 1 seconde (&lt;code&gt;Init Duration&lt;/code&gt;) = 4 secondes.&lt;/li&gt;
&lt;li&gt;Durée facturée totale (secondes) : (9&#39;900&#39;000 * 3 s) + (100&#39;000 * 4 s) = 29&#39;700&#39;000 secondes + 400&#39;000 secondes = 30&#39;100&#39;000 secondes.&lt;/li&gt;
&lt;li&gt;Go-secondes totaux : 30&#39;100&#39;000 secondes * (1024 Mo / 1024 Mo) = 30&#39;100&#39;000 Go-s.&lt;/li&gt;
&lt;li&gt;Coût Durée : 30&#39;100&#39;000 Go-s * $0.0000166667/Go-s = &lt;strong&gt;$501.67&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Coût total mensuel (Après) :&lt;/strong&gt; $2.00 + $501.67 = &lt;strong&gt;$503.67&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/details&gt;
&lt;p&gt;Dans ce scénario précis, l&amp;rsquo;augmentation est seulement de &lt;strong&gt;$1.67 par mois&lt;/strong&gt;. C&amp;rsquo;est effectivement minime, et cela confirme la communication d&amp;rsquo;AWS. Mais faites quand même attention, car l&amp;rsquo;impact &lt;em&gt;réel&lt;/em&gt; dépendra fortement de :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;La mémoire allouée à vos Lambdas (plus de mémoire = coût par ms plus élevé).&lt;/li&gt;
&lt;li&gt;La durée réelle de votre phase &lt;code&gt;INIT&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Votre taux de cold start (peut être plus élevé si votre trafic est irrégulier).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il est donc judicieux de vérifier avec vos propres chiffres !&lt;/p&gt;
&lt;p&gt;Je vous mets ci-dessous un petit script qui vous permettra de rapidement tester cela de votre côté.&lt;/p&gt;
&lt;details&gt;
  &lt;summary&gt;Script Python&lt;/summary&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;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;45
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;46
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;47
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;48
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;49
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;50
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;51
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;52
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;53
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;54
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;55
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;56
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;57
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;58
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;59
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;60
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;61
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;62
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;63
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;64
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;65
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;66
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;67
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;68
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;69
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;70
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;71
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;72
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;73
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;74
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;75
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;76
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;77
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;78
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;79
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;80
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;81
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;82
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;83
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;84
&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-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;calculate_lambda_costs&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;n&#34;&gt;total_invocations_per_month&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&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;n&#34;&gt;cold_start_rate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&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;n&#34;&gt;average_invocation_duration_sec&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&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;n&#34;&gt;average_init_duration_sec&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&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;n&#34;&gt;allocated_memory_gb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&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;n&#34;&gt;cost_per_million_requests&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.20&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;n&#34;&gt;cost_per_gb_second&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.0000166667&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;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;n&#34;&gt;num_cold_starts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;total_invocations_per_month&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cold_start_rate&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;n&#34;&gt;num_warm_starts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;total_invocations_per_month&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_cold_starts&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;n&#34;&gt;request_cost&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;n&#34;&gt;total_invocations_per_month&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1_000_000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_per_million_requests&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;c1&#34;&gt;# Duration cost BEFORE&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;n&#34;&gt;billed_duration_warm_starts_sec_before&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_warm_starts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;average_invocation_duration_sec&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;n&#34;&gt;billed_duration_cold_starts_sec_before&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_cold_starts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;average_invocation_duration_sec&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;n&#34;&gt;total_billed_duration_sec_before&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;billed_duration_warm_starts_sec_before&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;billed_duration_cold_starts_sec_before&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;n&#34;&gt;total_gb_seconds_before&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;total_billed_duration_sec_before&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;allocated_memory_gb&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.024&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;n&#34;&gt;duration_cost_before&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;total_gb_seconds_before&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_per_gb_second&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;n&#34;&gt;total_monthly_cost_before&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;request_cost&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;duration_cost_before&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;c1&#34;&gt;# Duration cost AFTER&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;n&#34;&gt;billed_duration_warm_starts_sec_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_warm_starts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;average_invocation_duration_sec&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;n&#34;&gt;billed_duration_cold_starts_sec_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_cold_starts&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;n&#34;&gt;average_invocation_duration_sec&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;average_init_duration_sec&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&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;total_billed_duration_sec_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;billed_duration_warm_starts_sec_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;billed_duration_cold_starts_sec_after&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;n&#34;&gt;total_gb_seconds_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;total_billed_duration_sec_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;allocated_memory_gb&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.024&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;n&#34;&gt;duration_cost_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;total_gb_seconds_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_per_gb_second&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;n&#34;&gt;total_monthly_cost_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;request_cost&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;duration_cost_after&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;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;total_monthly_cost_before&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;total_monthly_cost_after&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&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;display_results&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cost_before&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_after&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;n&#34;&gt;cost_difference&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_before&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;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;Monthly cost increase: $&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cost_difference&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.2f&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;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_difference&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&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;n&#34;&gt;percentage_increase&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;n&#34;&gt;cost_difference&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_before&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;100&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_before&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;inf&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;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Percentage increase: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;percentage_increase&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.2f&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&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;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;vm&#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;__main__&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;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;AWS Lambda Cost Calculator (before/after Init Duration pricing change)&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;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Please enter the values for your scenario or press Enter to use default values.&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&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;n&#34;&gt;default_invocations&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;10_000_000&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;n&#34;&gt;default_cold_start_rate&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.01&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# 1%&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;n&#34;&gt;default_invocation_duration&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.0&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# seconds&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;n&#34;&gt;default_init_duration&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# seconds&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;n&#34;&gt;default_memory_gb&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.024&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# 1024 MB (1.024 GB)&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;k&#34;&gt;try&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;n&#34;&gt;invocations_str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Total invocations per month (default: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;default_invocations&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;,&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;n&#34;&gt;total_invocations_input&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;invocations_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;invocations_str&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;default_invocations&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;n&#34;&gt;cold_start_rate_str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Cold start rate (e.g., 0.01 for 1%, default: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;default_cold_start_rate&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;n&#34;&gt;cold_start_rate_input&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cold_start_rate_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cold_start_rate_str&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;default_cold_start_rate&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;n&#34;&gt;invocation_duration_str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Average invocation duration in seconds (default: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;default_invocation_duration&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;n&#34;&gt;invocation_duration_input&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;invocation_duration_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;invocation_duration_str&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;default_invocation_duration&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;n&#34;&gt;init_duration_str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Average initialization duration in seconds (default: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;default_init_duration&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;n&#34;&gt;init_duration_input&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;init_duration_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;init_duration_str&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;default_init_duration&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;n&#34;&gt;memory_gb_str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Memory allocated to Lambda in GB (e.g., 0.512 for 512MB, default: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;default_memory_gb&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;n&#34;&gt;memory_gb_input&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memory_gb_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;memory_gb_str&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;default_memory_gb&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;n&#34;&gt;cost_before&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;calculate_lambda_costs&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;n&#34;&gt;total_invocations_per_month&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total_invocations_input&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;n&#34;&gt;cold_start_rate&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cold_start_rate_input&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;n&#34;&gt;average_invocation_duration_sec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;invocation_duration_input&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;n&#34;&gt;average_init_duration_sec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;init_duration_input&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;n&#34;&gt;allocated_memory_gb&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memory_gb_input&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;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;n&#34;&gt;display_results&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cost_before&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_after&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&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;ValueError&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;nb&#34;&gt;print&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;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;Error: Please enter valid numbers.&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;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;Exception&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;e&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;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;An unexpected error occurred: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;e&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;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/details&gt;
&lt;h1 id=&#34;comment-surveiller-votre-phase-init-et-estimer-limpact-&#34;&gt;&lt;a href=&#34;#comment-surveiller-votre-phase-init-et-estimer-limpact-&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Comment surveiller votre phase INIT et estimer l&amp;rsquo;impact ?
&lt;/h1&gt;&lt;p&gt;Un script, c&amp;rsquo;est bien, mais si vous avez un paquet de Lambdas à checker, vous risquez de vous épuiser à la tâche.&lt;/p&gt;
&lt;p&gt;Heureusement, AWS nous donne quelques outils pour vérifier ça efficacement. En effet, comme vu plus haut, chaque Lambda va faire un &lt;code&gt;REPORT&lt;/code&gt; de son &lt;code&gt;Init Duration&lt;/code&gt;. Il nous est donc facile d&amp;rsquo;aggréger tout cela dans &lt;strong&gt;CloudWatch Logs Insights&lt;/strong&gt;. Et cerise sur le gâteau, AWS nous offre même la requête qui va bien.&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;/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-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;filter @type = &amp;#34;REPORT&amp;#34; and @billedDuration &amp;lt; (@duration + @initDuration) 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| stats sum((@memorySize/1000000/1024) * (@billedDuration/1000)) as BilledGBs, 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sum((@memorySize/1000000/1024) * ((ceil(@duration + @initDuration) - @billedDuration)/1000)) as UnbilledInitGBs, 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(UnbilledInitGBs/ (UnbilledInitGBs+BilledGBs)) as Ratio
&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;blockquote&gt;
&lt;p&gt;Gardez en mémoire que CloudWatch Logs Insights vous est facturé $0.005 par GB de data scanné (&lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/cloudwatch/pricing/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Plus qu&amp;rsquo;à lancer cette requête sur vos Lambdas (en utilisant le prefix &lt;code&gt;/aws/lambda&lt;/code&gt;), et vous obtiendrez le résultat suivant :&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;BilledGBs&lt;/th&gt;
          &lt;th&gt;UnbilledInitGBs&lt;/th&gt;
          &lt;th&gt;Ratio&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;512.8007&lt;/td&gt;
          &lt;td&gt;86.6699&lt;/td&gt;
          &lt;td&gt;0.1446&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Cette requête vous donne ainsi trois informations clés :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;BilledGBs&lt;/code&gt; : Le total de Go-secondes actuellement facturé.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UnbilledInitGBs&lt;/code&gt; : Le total de Go-secondes consommés pendant la phase &lt;code&gt;INIT&lt;/code&gt; qui n&amp;rsquo;étaient &lt;em&gt;pas&lt;/em&gt; facturés auparavant.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ratio&lt;/code&gt; : Le pourcentage que représentent ces Go-secondes &lt;code&gt;INIT&lt;/code&gt; non facturés par rapport au total des Go-secondes consommés.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dans notre exemple, la part du coût de l&amp;rsquo;&lt;code&gt;INIT&lt;/code&gt; représente &lt;strong&gt;14%&lt;/strong&gt; de notre future facture ! Selon votre facture actuelle, cela pourrait être non négligeable.&lt;/p&gt;
&lt;h1 id=&#34;comprendre-et-optimiser-sa-lambda&#34;&gt;&lt;a href=&#34;#comprendre-et-optimiser-sa-lambda&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Comprendre et optimiser sa Lambda
&lt;/h1&gt;&lt;p&gt;Bon, vous savez que vous allez devoir sortir la carte bleue. Mais n&amp;rsquo;y a-t-il pas un levier d&amp;rsquo;action pour diminuer cette augmentation dans votre facture ?&lt;/p&gt;
&lt;p&gt;Je vous donne ici quelques conseils pour utiliser cette phase INIT au mieux et ainsi réduire vos futurs coûts.&lt;/p&gt;
&lt;h2 id=&#34;utiliser-stratégiquement-la-phase-init&#34;&gt;&lt;a href=&#34;#utiliser-strat%c3%a9giquement-la-phase-init&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Utiliser stratégiquement la phase INIT
&lt;/h2&gt;&lt;p&gt;Votre premier réflexe serait peut-être de vous dire qu&amp;rsquo;il faudrait enlever tout ce code &lt;code&gt;INIT&lt;/code&gt; (celui hors du handler) pour le mettre dans votre handler. Comme ça, plus de facturation de l&amp;rsquo;&lt;code&gt;INIT&lt;/code&gt; ! Mais non seulement vous ne feriez que déplacer le problème (car l&amp;rsquo;exécution de ce code vous sera tout de même facturé), cela sera encore pire, car maintenant, mêmes vos executions de Lambda &amp;ldquo;warm start&amp;rdquo; devront traiter ce code !&lt;/p&gt;
&lt;p&gt;Car oui, rappelons que le code dans la phase &lt;code&gt;INIT&lt;/code&gt; est exécuté &lt;em&gt;uniquement&lt;/em&gt; pendant les &amp;ldquo;cold start&amp;rdquo;. C&amp;rsquo;est donc l&amp;rsquo;endroit idéal pour faire des opérations d&amp;rsquo;initialisation coûteuses qui pourront être réutilisées par les invocations suivantes (&amp;ldquo;warm start&amp;rdquo;). Cela est même &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html#function-code&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;recommandé par AWS&lt;/a&gt;. Ainsi, cette phase d&amp;rsquo;&lt;code&gt;INIT&lt;/code&gt; est parfaite pour :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Importer des librairies ou dépendances lourdes.&lt;/li&gt;
&lt;li&gt;Établir des connexions à d&amp;rsquo;autres services AWS (S3, DynamoDB, etc.) via les SDKs (&lt;code&gt;boto3&lt;/code&gt; pour Python).&lt;/li&gt;
&lt;li&gt;Créer des pools de connexions à des bases de données.&lt;/li&gt;
&lt;li&gt;Récupérer des paramètres ou des secrets depuis Systems Manager Parameter Store ou Secrets Manager.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Maximisez cette phase d&amp;rsquo;inititalisation pour réduire ainsi le temps d&amp;rsquo;exécutions des Lambdas qui elles tourneront en &amp;ldquo;warm start&amp;rdquo;.&lt;/p&gt;
&lt;h2 id=&#34;optimiser-la-taille-du-package&#34;&gt;&lt;a href=&#34;#optimiser-la-taille-du-package&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Optimiser la taille du package
&lt;/h2&gt;&lt;p&gt;C&amp;rsquo;est souvent le levier le plus simple, car parfois, on importe un peu tout et n&amp;rsquo;importe quoi dans notre Lambda. Alors, soyez sûr de n&amp;rsquo;inclure que des dépendances strictement nécessaires. Veillez également à exclure tout ce qui est lié à votre environnement de développement (je ne vous dis pas le nombre de fois que j&amp;rsquo;ai trouvé un dossier &lt;code&gt;node_modules&lt;/code&gt; ou &lt;code&gt;tests&lt;/code&gt; dans des Lambdas&amp;hellip;). Enfin, n&amp;rsquo;hésitez pas à consulter les articles d&amp;rsquo;AWS, car &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/blogs/developer/reduce-lambda-cold-start-times-migrate-to-aws-sdk-for-javascript-v3/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;certains taclent directement le sujet des cold start&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;lambda-snapstart&#34;&gt;&lt;a href=&#34;#lambda-snapstart&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Lambda SnapStart
&lt;/h2&gt;&lt;p&gt;Disponible pour les runtimes &lt;strong&gt;Java, .NET et Python&lt;/strong&gt;, &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;SnapStart&lt;/a&gt; est une fonctionnalité très intéressante pour combattre les &amp;ldquo;cold start&amp;rdquo;. Quand vous l&amp;rsquo;activez, Lambda prend un &amp;ldquo;snapshot&amp;rdquo; de l&amp;rsquo;environnement d&amp;rsquo;exécution initialisé &lt;em&gt;après&lt;/em&gt; la première phase &lt;code&gt;INIT&lt;/code&gt;. Pour les &amp;ldquo;cold start&amp;rdquo; suivants, la Lambda va restaurer ce snapshot au lieu de refaire toute la phase d&amp;rsquo;&lt;code&gt;INIT&lt;/code&gt;, ce qui vous fera gagner pas mal de temps.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;imagine qu&amp;rsquo;à la lecture de cette fonctionnalité, vous vous dites &amp;ldquo;mais enfin c&amp;rsquo;est super, je vais activer cette feature sur toutes mes Lambdas !&amp;rdquo;. Sauf qu&amp;rsquo;il y a quelques subtilités à connaître.&lt;/p&gt;
&lt;p&gt;Premièrement, SnapStart n&amp;rsquo;est pour l&amp;rsquo;instant &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html#snapstart-runtimes&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;compatible qu&amp;rsquo;avec des versions bien précises de certains langages&lt;/a&gt; (Python 3.12 minimum, NodeJS pas supporté, &amp;hellip;). Idem pour les régions, &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html#snapstart-supported-regions&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;seulement 9 d&amp;rsquo;entre elles supportent cette feature&lt;/a&gt; pour Python et .NET. Enfin, &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/lambda/pricing/#SnapStart_Pricing&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;cette feature n&amp;rsquo;est pas gratuite&lt;/a&gt;. Vérifiez bien le coût que cela pourrait engendrer si vous souhaitez l&amp;rsquo;activer sur vos Lambdas.
ialisation).&lt;/p&gt;
&lt;h2 id=&#34;provisioned-concurrency&#34;&gt;&lt;a href=&#34;#provisioned-concurrency&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Provisioned Concurrency
&lt;/h2&gt;&lt;p&gt;Si votre application a un trafic prévisible ou si la latence des cold start n&amp;rsquo;est pas envisageable, vous pouvez utiliser ce qu&amp;rsquo;on appelle la &amp;ldquo;&lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/provisioned-concurrency.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Provisioned Concurrency&lt;/a&gt;&amp;rdquo;. Vous demandez à votre Lambda de garder un certain nombre d&amp;rsquo;environnements d&amp;rsquo;exécution pré-initialisés (chauds) en permanence.&lt;/p&gt;
&lt;p&gt;Avantage : les requêtes arrivant sur ces instances provisionnées ne subissent &lt;em&gt;jamais&lt;/em&gt; de cold start. La phase &lt;code&gt;INIT&lt;/code&gt; est faite en amont, avant même la première requête.&lt;/p&gt;
&lt;p&gt;Inconvénient : vous payez pour la durée pendant laquelle ces environnements sont provisionnés, &lt;em&gt;qu&amp;rsquo;ils reçoivent des requêtes ou non&lt;/em&gt;. La phase &lt;code&gt;INIT&lt;/code&gt; est d&amp;rsquo;ailleurs facturée lors de la pré-initialisation.&lt;/p&gt;
&lt;p&gt;Là aussi, à vous de voir si cela vaut le coup d&amp;rsquo;activer cela sur certaines de vos Lambdas clées !&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;Le changement de facturation de la phase &lt;code&gt;INIT&lt;/code&gt; de Lambda qui arrive le &lt;strong&gt;1er août 2025&lt;/strong&gt; est avant tout une standardisation. Pour la majorité des Lambdas, cela signifie que la durée de cette phase sera désormais ajoutée à la durée facturée lors des cold start.&lt;/p&gt;
&lt;p&gt;Même si l&amp;rsquo;impact financier sera probablement faible pour vous, c&amp;rsquo;est une excellente occasion de :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Comprendre&lt;/strong&gt; le cycle de vie de vos Lambdas et ce qui se passe pendant l&amp;rsquo;initialisation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mesurer&lt;/strong&gt; la durée de la phase &lt;code&gt;INIT&lt;/code&gt; de vos fonctions critiques grâce aux outils CloudWatch.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optimiser&lt;/strong&gt; cette phase si nécessaire, en réduisant la taille de vos packages, en utilisant SnapStart, ou en envisageant la Provisioned Concurrency pour des cas spécifiques.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Alors, n&amp;rsquo;attendez pas le mois d&amp;rsquo;août ! Familiarisez-vous avec CloudWatch Logs Insights dès maintenant. Cela vous permettra d&amp;rsquo;identifier les Lambdas à optimiser en priorité et d&amp;rsquo;éviter toute mauvaise surprise sur votre facture AWS.&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>
        <item>
        <title>Postman pre-request script, plus besoin de regénérer votre access token</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2022/postman-pre-request-script-never-worry-about-refreshing-your-access-token/</link>
        <pubDate>Mon, 16 May 2022 22:49:13 +0200</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2022/postman-pre-request-script-never-worry-about-refreshing-your-access-token/</guid>
        <description>&lt;img src="https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2022/postman-pre-request-script-never-worry-about-refreshing-your-access-token/astronaut.jpeg" alt="Featured image of post Postman pre-request script, plus besoin de regénérer votre access token" /&gt;&lt;p&gt;L&amp;rsquo;une des tâches les plus courantes lorsque vous travaillez avec des APIs est de les &amp;ldquo;pinger&amp;rdquo; pour vérifier si elles fonctionnent comme prévu (aussi connu sous le nom de : tests).&lt;/p&gt;
&lt;p&gt;Un des outils les plus simples et utiles sur le marché est &lt;a class=&#34;link&#34; href=&#34;https://www.postman.com/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Postman&lt;/a&gt;, un client API qui vous permet de faire des requêtes à n&amp;rsquo;importe quelle URL, en utilisant toutes les méthodes que vous pouvez imaginer. Vous pouvez même spécifier des headers HTTP, ce qui est pratique si vous devez passer un token d&amp;rsquo;accès (access token) dans la requête pour authentifier votre appel API.&lt;/p&gt;
&lt;p&gt;Et c&amp;rsquo;est là que j&amp;rsquo;ai commencé à rencontrer un problème. Pas un véritable problème, mais quelque chose d&amp;rsquo;encore plus frustrant pour un ingénieur : &lt;strong&gt;la répétition&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;En fait, pour transmettre cet access token à la requête, vous devez d&amp;rsquo;abord le générer (généralement via un autre appel API). Le hic, c&amp;rsquo;est que cet access token est éphémère, et expire après une heure.&lt;/p&gt;
&lt;p&gt;Alors, qu&amp;rsquo;est-ce que cela implique ? Eh bien, chaque heure, avant de faire une nouvelle requête à votre API, vous devez d&amp;rsquo;abord faire une requête pour obtenir un nouveau token, copier le résultat, et le coller dans l&amp;rsquo;en-tête de la requête initiale. En tout, &lt;strong&gt;cela vous fera perdre 10 secondes&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Ouf ! Vous imaginez un peu ? 10 secondes ?! Tout ce que l&amp;rsquo;on pourrait accomplir si l&amp;rsquo;on arrivait à récupérer ce temps précieux !&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://imgs.xkcd.com/comics/is_it_worth_the_time.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Is It Worth the Time? - by xkcd&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Mais avec Postman, je savais que ce problème pouvait être résolu d&amp;rsquo;une manière ou d&amp;rsquo;une autre. Et en effet, après une simple recherche sur le web, je suis tombé sur la solution parfaite : &lt;a class=&#34;link&#34; href=&#34;https://learning.postman.com/docs/writing-scripts/pre-request-scripts/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Pre-request script&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;L&amp;rsquo;idée est assez simple : &lt;strong&gt;exécuter un script avant chaque requête&lt;/strong&gt;. Voilà.&lt;/p&gt;
&lt;p&gt;Comment cela peut-il nous aider, demandez-vous ? Eh bien, nous pouvons maintenant écrire un petit morceau de code qui va récupérer un nouvel access token et le stocker dans les variables de la collection dans laquelle nous nous trouvons. Ensuite, nos requêtes feront toujours référence à cette variable pour s&amp;rsquo;assurer qu&amp;rsquo;elles disposent d&amp;rsquo;un token à jour.&lt;/p&gt;
&lt;p&gt;Laissez-moi vous montrer un exemple que j&amp;rsquo;ai utilisé dans l&amp;rsquo;un de mes projets où j&amp;rsquo;avais besoin de récupérer un access token d&amp;rsquo;AWS Cognito avant chaque requête.&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-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;pm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;sendRequest&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;url&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://YOUR_COGNITO_DOMAIN_NAME_HERE.auth.eu-west-1.amazoncognito.com/oauth2/token&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;method&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;POST&amp;#39;&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;header&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;s1&#34;&gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;application/x-www-form-urlencoded&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;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;body&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;mode&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;urlencoded&amp;#39;&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;urlencoded&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;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;key&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;grant_type&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;value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;client_credentials&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;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;nx&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;client_id&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;value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;YOUR_CLIENT_ID_HERE&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;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;nx&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;client_secret&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;value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;YOUR_CLIENT_SECRET_HERE&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;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;nx&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;scope&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;value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;YOUR_SCOPE_HERE&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;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 class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;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;pm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;collectionVariables&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;access_token&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;access_token&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;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;Comme vous pouvez le voir, c&amp;rsquo;est assez simple, et cela peut probablement être appliqué à n&amp;rsquo;importe quel projet nécessitant une authentification OAuth.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;espère que cela vous a été utile et surtout n&amp;rsquo;oubliez pas : &lt;strong&gt;si vous pouvez économiser 10 secondes, faites-le !&lt;/strong&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>À Propos</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/about/</link>
        <pubDate>Sun, 06 Mar 2022 00:00:00 +0000</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/about/</guid>
        <description>&lt;p&gt;Je m&amp;rsquo;appelle Antoine Delia et je suis Cloud &amp;amp; DevOps Engineer.&lt;/p&gt;
&lt;p&gt;Sur ce blog, j&amp;rsquo;ai envie de parler de nombreux sujets liés au Cloud et à la culture DevOps. Ce sont des sujets qui me passionnent, et j&amp;rsquo;aime pouvoir transmettre mes connaissances avec une touche de légèreté, voire d&amp;rsquo;humour.&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;espère que cela vous plaira !&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Compétences :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cloud (AWS)&lt;/li&gt;
&lt;li&gt;Infrastructure as Code (Terraform / Serverless Framework / CloudFormation)&lt;/li&gt;
&lt;li&gt;Scripting (Python, Bash)&lt;/li&gt;
&lt;li&gt;CI/CD (GitHub Actions, Jenkins)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Projets et réalisations :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Cloud Optimist (le blog sur lequel vous vous trouvez) : blog Hugo déployé via GitHub Actions sur AWS, infra managée par Terraform&lt;/li&gt;
&lt;li&gt;Introduction au Serverless : séminaire virtuel (&lt;a class=&#34;link&#34; href=&#34;https://www.youtube.com/watch?v=nCGTWbUsfN4&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://www.youtube.com/watch?v=nCGTWbUsfN4&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;3 certifications AWS (Architect Associate / Developer Associate / Cloud Practitioner)&lt;/li&gt;
&lt;li&gt;1800+ points sur &lt;a class=&#34;link&#34; href=&#34;https://stackoverflow.com/users/4141606/antoine-delia?tab=profile&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;StackOverflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Marathon de Toulouse 2025 couru en 03:58:44&lt;/li&gt;
&lt;li&gt;TOEIC (965/990)&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Archives</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/archives/</link>
        <pubDate>Sun, 06 Mar 2022 00:00:00 +0000</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/archives/</guid>
        <description></description>
        </item>
        <item>
        <title>La Méthode du Canard en Plastique - pourquoi ça marche ?</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2019/the-rubber-duck-debugging/</link>
        <pubDate>Wed, 26 Jun 2019 22:49:13 +0200</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2019/the-rubber-duck-debugging/</guid>
        <description>&lt;img src="https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2019/the-rubber-duck-debugging/duck.jpg" alt="Featured image of post La Méthode du Canard en Plastique - pourquoi ça marche ?" /&gt;&lt;p&gt;&lt;strong&gt;La programmation est un art complexe.&lt;/strong&gt; Vous êtes un véritable architecte et votre mission est de concevoir, construire, décorer et entretenir une application, un peu comme vous le feriez pour une maison.&lt;/p&gt;
&lt;p&gt;Cependant, une difficulté émerge : &lt;strong&gt;vous devez communiquer des informations à une machine à travers des langages de programmation pour que tout fonctionne.&lt;/strong&gt; Alors que vous ne parlez pas à vos meubles pour les placer dans votre maison, n&amp;rsquo;est-ce pas ? &lt;em&gt;N&amp;rsquo;est-ce pas ?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Cette petite différence est cruciale, car il arrive parfois que vous rencontriez un problème sans savoir pourquoi il est là. Vous avez développé cette chose tellement parfaitement qu&amp;rsquo;elle ne devrait pas échouer. Et pourtant, voilà un bug, et vous ne savez pas pourquoi.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;La première chose à faire est bien évidemment d&amp;rsquo;accuser l&amp;rsquo;ordinateur.&lt;/strong&gt; Après tout, vous savez ce que vous faites, il n&amp;rsquo;y a aucune raison pour que vous ayez écrit quelque chose de travers. C&amp;rsquo;est probablement cet imbécile d&amp;rsquo;ordinateur qui vous fait encore passer pour un idiot. Mais la vérité est difficile à avaler.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;La machine fait exactement ce que vous lui dites de faire.&lt;/p&gt;
&lt;p&gt;&amp;ndash; &lt;cite&gt;Bill Gates, probablement&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Que vous le vouliez ou non, votre ordinateur est bête. Il récupère sans réfléchir l&amp;rsquo;information que vous lui fournissez et l&amp;rsquo;exécute. &lt;strong&gt;Et s&amp;rsquo;il échoue, c&amp;rsquo;est sans aucun doute de votre faute.&lt;/strong&gt; Je sais que ça fait mal, croyez-moi. Mais ne vous inquiétez pas trop, cela est arrivé à chacun de nous, et au final, tout le monde s&amp;rsquo;en est sorti.&lt;/p&gt;
&lt;p&gt;Maintenant, tout dépend de vous. Vous savez que vous avez fait quelque chose de travers, mais vous ne parvenez pas à savoir quoi. Que faire ? Faut-il chercher des réponses sur StackOverflow ? Démissionner de votre poste car vous n&amp;rsquo;êtes clairement pas à la hauteur ? La réponse est simple.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;La première étape quand vous êtes bloqué, est de faire appel à la sagesse du canard.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Je sais ce que vous pensez en ce moment : &lt;em&gt;Qu&amp;rsquo;est-ce que tu es en train de fumer et où puis-je trouver ça ?&lt;/em&gt; Mais croyez-moi, cette histoire de canard n&amp;rsquo;est pas une hallucination, c&amp;rsquo;est même LA meilleure façon de vous aider.&lt;/p&gt;
&lt;p&gt;Ne vous inquiétez pas cependant, vous n&amp;rsquo;aurez pas besoin de conduire à la ferme la plus proche et voler un canard pour appliquer ce conseil. Dans notre cas, un canard en plastique est tout ce dont nous avons besoin.&lt;/p&gt;
&lt;p&gt;Une fois que vous en avez un et que vous le placez sur votre bureau, la seule chose qu&amp;rsquo;il vous reste à faire est de lui parler. Allez-y, ne soyez pas timide. Et expliquez-lui ce qui se passe avec votre code.&lt;/p&gt;
&lt;p&gt;Je préfère vous en parler tout de suite pour que vous ne soyez pas choqué quand vous serez confronté à la vérité, mais le canard ne vous répondra pas. C&amp;rsquo;est déchirant, je sais. Cependant, &lt;strong&gt;il est l&amp;rsquo;auditeur parfait et sa patience est bien au-dessus de celle de n&amp;rsquo;importe quel autre être humain&lt;/strong&gt;, contrairement à vos collègues. De plus, le canard ne jugera jamais vos erreurs. Il est gentil et compréhensif.&lt;/p&gt;
&lt;p&gt;Et plus vous lui expliquerez vos problèmes, plus vous réaliserez ce qui n&amp;rsquo;allait pas dans votre code. En effet, le fait d&amp;rsquo;expliquer correctement au canard ce que vous tentez de faire mettra en évidence une petite incohérence entre ce que vous avez fait et ce que vous essayez d&amp;rsquo;accomplir. Petit à petit, vous serez bientôt capable de repérer la ligne exacte de code qui causait tous vos problèmes et de la corriger comme un pro.&lt;/p&gt;
&lt;p&gt;Et c&amp;rsquo;est pour ça que le canard est si utile. Non seulement vous laissez vos collègues travailler en paix, mais cet exercice vous oblige à prendre du recul par rapport à votre code afin de pouvoir l&amp;rsquo;expliquer à quelqu&amp;rsquo;un qui n&amp;rsquo;a aucune idée de ce qui se passe.&lt;/p&gt;
&lt;p&gt;Cet effort de mettre des mots sur le comportement attendu et ce que vous avez pu accomplir jusqu&amp;rsquo;à présent mettra en lumière toutes les erreurs potentielles que vous auriez pu commettre pendant le développement, des choses qu&amp;rsquo;on ne voit pas quand on passe huit heures à regarder son code sans s&amp;rsquo;arrêter.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;En décrivant ce que le code est censé faire et en observant ce qu&amp;rsquo;il fait réellement, toute incohérence entre ces deux devient apparente.&lt;/p&gt;
&lt;p&gt;&amp;ndash; &lt;cite&gt; &lt;a class=&#34;link&#34; href=&#34;https://www.sjbaker.org/humor/cardboard_dog.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Stephen J. Baker&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Alors, la prochaine fois que vous serez bloqué, ne dérangez pas vos collègues, économisez votre connexion internet et demandez simplement au canard !&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Si vous souhaitez en savoir plus sur cette méthode, je vous conseille vivement de jeter un œil au site qui a inspiré ce billet : &lt;cite&gt; &lt;a class=&#34;link&#34; href=&#34;https://rubberduckdebugging.com/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://rubberduckdebugging.com/&lt;/a&gt;&lt;/cite&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        </item>
        <item>
        <title>FizzBuzz, la façon la plus simple et efficace de tester un développeur</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2019/fizzbuzz/</link>
        <pubDate>Mon, 27 May 2019 13:35:55 +0200</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2019/fizzbuzz/</guid>
        <description>&lt;img src="https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2019/fizzbuzz/fizzbuzz.jpeg" alt="Featured image of post FizzBuzz, la façon la plus simple et efficace de tester un développeur" /&gt;&lt;p&gt;Lorsque je suis sorti de mon école d&amp;rsquo;ingénieur, j&amp;rsquo;ai passé beaucoup d&amp;rsquo;entretiens dans l&amp;rsquo;espoir d&amp;rsquo;obtenir un poste de développeur. Mes expériences s&amp;rsquo;étant limitées à quelques stages, je redoutais cette partie de l&amp;rsquo;entretien où je devais me lever et résoudre un exercice de code sur un tableau blanc, ou même simplement répondre à quelques questions techniques. Je me trompais.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Aucun entretien ne m&amp;rsquo;a testé sur mes compétences en développement.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;J&amp;rsquo;aurais pu mentir tout au long de l&amp;rsquo;entretien et tout de même obtenir le poste.&lt;/p&gt;
&lt;p&gt;Pour être honnête, je ne fais pas partie de ceux qui louent les questions techniques comme s&amp;rsquo;il s&amp;rsquo;agissait d&amp;rsquo;une formule magique pour détecter les bons développeurs. Je préfère penser qu&amp;rsquo;une personne avec un bon tempérament, passionnée et humainement agréable est beaucoup plus intéressante qu&amp;rsquo;un &amp;ldquo;je-sais-tout&amp;rdquo; qui ramène toujours sa science à la table sans vouloir entendre l&amp;rsquo;avis des autres. &lt;strong&gt;On peut combler un manque technique, mais on ne peut pas améliorer un mauvais caractère.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Cela étant dit, je crois qu&amp;rsquo;il est obligatoire de vérifier à minima la manière de penser de quelqu&amp;rsquo;un lorsqu&amp;rsquo;il est confronté à un problème. Parce qu&amp;rsquo;au final, c&amp;rsquo;est ce qu&amp;rsquo;il fera la plupart du temps : résoudre des problèmes. En ce sens, il est crucial de voir comment quelqu&amp;rsquo;un va réagir face à un problème. Va-t-il fuir ? Va-t-il immédiatement demander de l&amp;rsquo;aide ?&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;est là qu&amp;rsquo;intervient le test &lt;strong&gt;FizzBuzz&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Cet article a été inspiré par la vidéo de &lt;a class=&#34;link&#34; href=&#34;https://www.youtube.com/watch?v=QPZ0pIK_wsc&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Tom Scott&lt;/a&gt; que je vous recommande vivement de regarder si ce sujet vous intéresse.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;L&amp;rsquo;idée de FizzBuzz est simple. Vous devez énumérer les nombres à haute voix en commençant par 1 jusqu&amp;rsquo;à 100. Mais, si le nombre est un multiple de 3, vous devez dire &amp;ldquo;Fizz&amp;rdquo; à la place. De même, si le nombre est un multiple de 5, vous devez dire &amp;ldquo;Buzz&amp;rdquo;. Maintenant, vous vous demandez peut-être : &amp;ldquo;Que faire si c&amp;rsquo;est un multiple de 3 et de 5 ?&amp;rdquo;. Eh bien, vous devrez simplement dire &amp;ldquo;FizzBuzz&amp;rdquo;. &lt;em&gt;Générique de fin&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;En lisant ce test simple, vous pourriez vous demander pourquoi il devrait être utilisé, car à première vue, même un stagiaire pourrait le résoudre assez facilement. Eh bien, c&amp;rsquo;est ce que je pensais aussi, jusqu&amp;rsquo;à ce que je tombe sur &lt;a class=&#34;link&#34; href=&#34;https://blog.codinghorror.com/why-cant-programmers-program/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;l&amp;rsquo;article de Jeff Atwood à ce sujet&lt;/a&gt;, où il explique être surpris de voir que ce problème donnait beaucoup de mal à des candidats, seniors compris.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alors, essayons de le résoudre ensemble !&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Dans la plupart des entretiens techniques, vous avez généralement le choix du langage de programmation avec lequel vous souhaitez résoudre un problème (voir même d&amp;rsquo;écrire en &lt;a class=&#34;link&#34; href=&#34;https://fr.wikipedia.org/wiki/Pseudo-code&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;pseudo-code&lt;/a&gt;). Pour ce billet, j&amp;rsquo;utiliserai Python.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Avant toute chose, créons une boucle simple qui affiche tous les nombres de 1 à 100.&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;/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-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Premier piège ici, range exclut le dernier nombre que vous lui passez.&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;c1&#34;&gt;# Ici, nous commençons bien à 1, et finissons à 100.&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;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;101&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;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&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;On commence bien ! Maintenant, revenons à l&amp;rsquo;énoncé original : si le nombre est un multiple de 3, on affiche &amp;ldquo;Fizz&amp;rdquo;, si c&amp;rsquo;est un multiple de 5, on affiche &amp;ldquo;Buzz&amp;rdquo;. Ajoutons ces 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;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-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;101&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;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&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;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Fizz&amp;#39;&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;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&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;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Buzz&amp;#39;&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;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&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;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&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;Prenons un moment pour voir ce qu&amp;rsquo;on a fait ici. &lt;strong&gt;Pour vérifier si un nombre est un multiple de 3, nous utilisons le modulo avec le symbole &lt;code&gt;%&lt;/code&gt;.&lt;/strong&gt; Nous faisons la même chose pour les multiples de 5. Enfin, si le nombre n&amp;rsquo;est ni un multiple de 3 ni de 5, on l&amp;rsquo;affiche simplement.&lt;/p&gt;
&lt;p&gt;Ainsi, on obtient exactement ce que l&amp;rsquo;on veut !&amp;hellip; Sauf quand un nombre est un multiple de 3 ET de 5. Dans ce cas, &lt;strong&gt;les mots Fizz et Buzz ne sont pas affichés sur la même ligne !&lt;/strong&gt; Nous devons donc prendre en compte ce cas en ajoutant une nouvelle condition, et empêcher les deux premiers &lt;code&gt;if&lt;/code&gt; de se déclencher.&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-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;101&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;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&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;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Fizz&amp;#39;&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;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&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;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Buzz&amp;#39;&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;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&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;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;FizzBuzz&amp;#39;&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;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&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;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&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;Ça fonctionne enfin ! Mais à quel prix ? &lt;strong&gt;Ce code est un vrai désordre.&lt;/strong&gt; Et ce n&amp;rsquo;est en aucun cas un code facile à maintenir. Prenons cet exemple : que se passerait-il si nous voulions maintenant afficher le mot Fizz pour les multiples de 2 au lieu de 3 ? &lt;strong&gt;Nous devrons changer cette valeur à 4 endroits différents dans le code&lt;/strong&gt; pour que cela fonctionne.&lt;/p&gt;
&lt;p&gt;Cela peut sembler trivial avec un code aussi minimaliste, mais imaginez ce qui se passerait si cela arrivait dans un projet bien plus grand. &lt;strong&gt;Ce code est sujet à erreurs, complique sa maintenabilité et rend presque impossible l&amp;rsquo;ajout de nouvelles fonctionnalités facilement.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Essayons une autre approche pour rendre ce code plus élégant ! Déclarons d&amp;rsquo;abord une variable qui sera la valeur que nous voulons afficher à la fin. On la laisse vide pour l&amp;rsquo;instant. Chaque fois que nous avons une condition qui correspond, nous ajoutons simplement le mot correspondant à la variable. À la fin, vérifier si la variable est vide nous indiquera si nous devons l&amp;rsquo;afficher ou plutôt afficher le nombre.&lt;/p&gt;
&lt;p&gt;Voici ce que cela donne.&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-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;101&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;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;&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;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&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;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Fizz&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;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&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;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Buzz&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;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&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;C&amp;rsquo;est déjà beaucoup plus clair ! Non seulement nous avons réduit le nombre de lignes de moitié, mais nos vérifications &lt;code&gt;if&lt;/code&gt; sont désormais limpides et ne laissent aucune place à l&amp;rsquo;interprétation. De plus, nous pouvons facilement changer la valeur de n&amp;rsquo;importe quel nombre si nécessaire sans avoir à chercher toutes ses occurrences. Enfin, si nous devons ajouter une autre condition (pour les multiples de 7 par exemple), il nous suffira d&amp;rsquo;ajouter deux nouvelles lignes sans toucher au reste du code !&lt;/p&gt;
&lt;p&gt;Nous voyons enfin en quoi ce simple test FizzBuzz est si intéressant. Il nous a permis de tester la capacité d&amp;rsquo;une personne à utiliser des principes algorithmiques simples, mais aussi de vérifier sa manière de penser lorsqu&amp;rsquo;elle est confrontée à un problème, et si elle est capable de produire un code qui pourra être facilement maintenu dans le futur.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;En résumé, FizzBuzz est un bon moyen de différencier un développeur d&amp;rsquo;un bon développeur.&lt;/strong&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Liens</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/liens/</link>
        <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/liens/</guid>
        <description></description>
        </item>
        <item>
        <title>Recherche</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/search/</link>
        <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/fr/search/</guid>
        <description></description>
        </item>
        
    </channel>
</rss>
