[{"data":1,"prerenderedAt":787},["ShallowReactive",2],{"/fr-fr/blog/learn-advanced-rust-programming-with-a-little-help-from-ai-code-suggestions":3,"navigation-fr-fr":42,"banner-fr-fr":447,"footer-fr-fr":457,"blog-post-authors-fr-fr-Michael Friedrich":667,"blog-related-posts-fr-fr-learn-advanced-rust-programming-with-a-little-help-from-ai-code-suggestions":681,"blog-promotions-fr-fr":726,"next-steps-fr-fr":778},{"id":4,"title":5,"authorSlugs":6,"body":8,"categorySlug":9,"config":10,"content":14,"description":8,"extension":29,"isFeatured":12,"meta":30,"navigation":31,"path":32,"publishedDate":20,"seo":33,"stem":37,"tagSlugs":38,"__hash__":41},"blogPosts/fr-fr/blog/learn-advanced-rust-programming-with-a-little-help-from-ai-code-suggestions.yml","Learn Advanced Rust Programming With A Little Help From Ai Code Suggestions",[7],"michael-friedrich",null,"ai-ml",{"slug":11,"featured":12,"template":13},"learn-advanced-rust-programming-with-a-little-help-from-ai-code-suggestions",false,"BlogPost",{"title":15,"description":16,"authors":17,"heroImage":19,"date":20,"body":21,"category":9,"tags":22,"updatedDate":28},"Programmation en Rust à l’aide de l'IA : tutoriel","Poursuivez votre apprentissage de la programmation en Rust à l'aide de ce tutoriel et des suggestions de code alimentées par l'IA de GitLab Duo.",[18],"Michael Friedrich","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662439/Blog/Hero%20Images/codewithheart.png","2023-10-12","Il y a 20 ans, pour apprendre un nouveau langage de programmation, il fallait installer la bibliothèque MSDN de Visual Studio 6 avec 6 CD-ROM. Trouver les bons algorithmes prenait du temps et nécessitait des livres et des recherches manuelles. Aujourd'hui, grâce à la collaboration à distance et à l'intelligence artificielle (IA), vous pouvez facilement créer un [espace de développement à distance](https://about.gitlab.com/blog/quick-start-guide-for-gitlab-workspaces/), partager votre écran et coder en groupe. De plus, [GitLab Duo offre des suggestions de code](/gitlab-duo-agent-platform/) alimentées par l'IA, adaptées à votre style de programmation et à votre expérience, même avec peu d'informations et de contexte.\n\nCe tutoriel basé sur notre [article d'introduction à Rust](/blog/learning-rust-with-a-little-help-from-ai-code-suggestions-getting-started/) vous guidera dans le développement d'une application simple de lecteur de flux.\n\n## Préparations\nConfigurez [VS Code](/blog/learning-rust-with-a-little-help-from-ai-code-suggestions-getting-started/#vs-code) et [votre environnement de développement Rust](/blog/learning-rust-with-a-little-help-from-ai-code-suggestions-getting-started/#development-environment-for-rust).\n\n### Suggestions de code\nVérifiez les suggestions de code avant de les accepter. GitLab Duo génère des suggestions de code en temps réel que vous pouvez accepter en appuyant sur la touche `tab`. Notez qu'il est plus fiable d'écrire du nouveau code que de refactoriser un code existant. Notez aussi que l'IA peut proposer des suggestions différentes pour le même code. Tenez compte des [limitations connues](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#known-limitations) qui peuvent affecter votre apprentissage.\n\n**Astuce :** les suggestions de code prennent en charge les instructions multilignes. Affinez les spécifications si besoin pour obtenir de meilleures suggestions.\n\n```rust\n    // Create a function that iterates over the source array\n    // and fetches the data using HTTP from the RSS feed items.\n    // Store the results in a new hash map.\n    // Print the hash map to the terminal.\n```\n\nLe volet de l'extension VS Code s'affiche lorsqu'une suggestion est proposée. Utilisez `tab` pour accepter les lignes suggérées, ou `cmd cursor right` pour accepter un mot. Le menu à trois points vous permet d'afficher la barre d'outils à tout moment.\n\n![Volet de l'extension VS Code des suggestions de code de GitLab Duo avec des instructions](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_code_suggestions_options_overlay_keep_toolbar.png)\n\n## Ressources Rust\nRust est l'un des [langages pris en charge par les suggestions de code](https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html#supported-languages). Le tutoriel [« Rust by Example »](https://doc.rust-lang.org/rust-by-example/) et le [livre officiel « Le langage de programmation Rust »](https://doc.rust-lang.org/book/) sont une bonne aide pour les débutants. Nous les utiliserons également dans cet article.\n\n### Création d'une application de lecture de flux\nIl existe plusieurs façons d'apprendre Rust en créant une application. Vous pouvez utiliser des bibliothèques Rust, appelées `Crates`. Nous les explorerons pus tard dans ce tutoriel. Vous pouvez aussi créer une application pour traiter des fichiers image en ligne de commande, résoudre un labyrinthe ou des Sudokus, ou même développer des jeux. Le livre [Hands-on Rust](https://hands-on-rust.com/) apprend Rust par la création d'un jeu d'exploration de donjon. Ma collègue, Fatima Sarah Khalid, a conçu [Dragon Realm en C++ en s'aidant de l'IA](/blog/building-a-text-adventure-using-cplusplus-and-code-suggestions/).\n\nNous allons construire une application pour collecter des informations depuis des versions de sécurité, des articles de blog et des forums comme Hacker News, via des flux RSS. Nous filtrerons certains mots-clés ou des versions spécifiques dans ces flux. Voici ce que notre application devra faire :\n\n1. Récupérer des données depuis des sites web HTTP, API REST, mais surtout depuis des flux RSS.\n2. Analyser les données.\n3. Présenter les données à l'utilisateur ou les sauvegarder.\n4. Optimiser la lecture des flux.\n\nLes données fournies par l'application dans notre exemple sont présentées dans cet article, après les étapes d'apprentissage :\n\n![Terminal VS Code, exécution de Cargo avec des sorties d'éléments formatées](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_terminal_cargo_run_formatted_output_final.png)\n\nL'application doit être modulaire, servant de base pour ajouter d'autres données, filtres et hooks pour des actions ultérieures.\n\n### Initialisation du projet\nRappel : `cargo init` dans la racine du projet crée la structure du fichier, y compris le point d'entrée `main()`. Nous allons créer et utiliser des modules Rust à l'étape suivante.\n\nD'abord, créez un répertoire nommé `learn-rust-ai-app-reader`, ouvrez-le et exécutez `cargo init`, ce qui initialise également (`git init`) un dépôt Git local. Configurez ensuite le dépôt distant avec l'URL par exemple `https://gitlab.com/gitlab-da/use-cases/ai/learn-with-ai/learn-rust-ai-app-reader`, ajustez le chemin de votre espace de nommage, et effectuez un push pour [créer automatiquement un nouveau projet privé sur GitLab](https://docs.gitlab.com/ee/user/project/#create-a-new-project-with-git-push).\n\n```shell\nmkdir learn-rust-ai-app-reader\ncd learn-rust-ai-app-reader\n\ncargo init\n\ngit remote add origin https://gitlab.com/gitlab-da/use-cases/ai/learn-with-ai/learn-rust-ai-app-reader.git\ngit push --set-upstream origin main\n```\n\nOuvrez VS Code à partir du répertoire créé. La CLI `code` ouvre une fenêtre VS Code sur macOS.\n\n```shell\ncode .\n```\n\n### Définition des URL des flux RSS\nAjoutez une table de hachage pour stocker les URL des flux RSS dans le fichier `src/main.rs` dans la fonction `main()`. Utilisez les suggestions de code de GitLab Duo pour créer un objet [`HashMap`](https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html) avec un commentaire multilignes et initialisez-le avec les valeurs par défaut pour Hacker News et TechCrunch. Vérifiez l'exactitude des URL incluses dans les suggestions.\n\n```rust\nfn main() {\n    // Define RSS feed URLs in the variable rss_feeds\n    // Use a HashMap\n    // Add Hacker News and TechCrunch\n    // Ensure to use String as type\n\n}\n```\n\nLe commentaire intégré au code doit inclure :\n\n1. Le nom de la variable `rss_feeds`.\n2. Le type `HashMap`.\n3. Les paires clé/valeur initiales.\n4. La string comme type utilisable avec les appels `to_string()`).\n\nVoici une suggestion possible :\n\n```rust\nuse std::collections::HashMap;\n\nfn main() {##$_0A$##    // Define RSS feed URLs in the variable rss_feeds##$_0A$##    // Use a HashMap##$_0A$##    // Add Hacker News and TechCrunch##$_0A$##    // Ensure to use String as type##$_0A$##    let rss_feeds = HashMap::from([##$_0A$##        (\"Hacker News\".to_string(), \"https://news.ycombinator.com/rss\".to_string()),##$_0A$##        (\"TechCrunch\".to_string(), \"https://techcrunch.com/feed/\".to_string()),##$_0A$##    ]);##$_0A$####$_0A$##}\n```\n\n![VS Code avec les suggestions de code pour les URL des flux RSS pour Hacker News et TechCrunch](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_main_array_rss_feed_urls_suggested.png)\n\nOuvrez un terminal dans VS Code (cmd+maj+p, recherchez `terminal`), exécutez `cargo build` pour appliquer les modifications. Ajoutez la ligne d'importation `use std::collections::HashMap;` suite au message d'erreur.\n\nEnsuite, utilisez les URL des flux RSS. Dans notre [article](/blog/learning-rust-with-a-little-help-from-ai-code-suggestions-getting-started/) précédent, nous avons expliqué la division du code en fonctions. Ce tutoriel se concentre sur l'organisation modulaire du code avec des modules Rust.\n\n## Modules\nLes [modules](https://doc.rust-lang.org/rust-by-example/mod.html) organisent le code et peuvent restreindre l'accès aux fonctions à partir de la portée main(). Pour notre application, nous récupérerons le flux RSS et analyserons la réponse XML. La structure appelante `main()` n'accèdera qu'à la fonction `get_feeds()`. Les autres fonctionnalités sont disponibles dans le module.\n\nCréez un fichier `feed_reader.rs` dans le répertoire `src/`. Demandez aux suggestions de code de créer un module public nommé `feed_reader` avec une fonction publique `get_feeds()` prenant une string HashMap en entrée. Assurez-vous que le nom du fichier et du module correspondent et suivent la [structure de module Rust](https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html).\n\n![Suggestions de code : créez un module public, avec des types de fonctions et d'intrants](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_rust_public_module_function_input.png)\n\nEn fournissant aux suggestions de code le nom de la variable et son type, le module `std::collections::HashMap` sera automatiquement importé. Astuce : ajustez les commentaires et les types de variables pour améliorer les suggestions. Passer des paramètres de fonction sous forme de références d'objet est une bonne pratique en Rust.\n\n```rust\n// Create public module feed_reader\n// Define get_feeds() function which takes rss_feeds as String HashMap reference as input\npub mod feed_reader {\n    use std::collections::HashMap;\n\n    pub fn get_feeds(rss_feeds: &HashMap\u003CString, String>) {\n        // Do something with the RSS feeds\n    }\n}\n```\n\n![Suggestions de code : module public avec la fonction `get_feeds()` et la variable d'intrant suggérée](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_rust_public_module_function_input.png)\n\nPour guider les suggestions de code, suivez ces étapes :\n\n1. `// Iterate over the RSS feed URLs`\n2. `// Fetch URL content`\n3. `// Parse XML body`\n4. `// Print the result`\n\n![Suggestions de code : module public avec la fonction `get_feeds()`, étape 1 : itération](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_rust_module_function_01_iterate.png)\n\n![Suggestions de code : module public avec la fonction `get_feeds()`, étape 2 : récupération du contenu de l'URL](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_rust_module_function_02_fetch_content.png)\n\n![Suggestions de code : module public avec la fonction `get_feeds()`, étape 3 : analyse du corps XML](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_rust_module_function_03_parse_body.png)\n\n![Suggestions de code : module public avec la fonction `get_feeds()`, étape 4 : impression des résultats](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_rust_module_function_04_print_result.png)\n\nSuggestion de code possible :\n\n```rust\n// Create public module feed_reader\n// Define get_feeds() function which takes rss_feeds as String HashMap reference as input\npub mod feed_reader {\n    use std::collections::HashMap;\n\n    pub fn get_feeds(rss_feeds: &HashMap\u003CString, String>) {\n        // Iterate over the RSS feed URLs\n        for (name, url) in rss_feeds {\n            println!(\"{}: {}\", name, url);\n\n            // Fetch URL content\n            let body = reqwest::blocking::get(url).unwrap().text().unwrap();\n\n            // Parse XML body\n            let parsed_body = roxmltree::Document::parse(&body).unwrap();\n\n            // Print the result\n            println!(\"{:#?}\", parsed_body);\n        }\n    }\n}\n```\n\nRemarquez le nouveau mot-clé : [`unwrap()`](https://doc.rust-lang.org/rust-by-example/error/option_unwrap.html). Rust n'accepte pas les valeurs `null` et utilise le [type `Option`](https://doc.rust-lang.org/rust-by-example/std/option.html) pour représenter les valeurs. Si vous avez la certitude d'utiliser un type encapsulé comme `Text` ou `String`, vous pouvez appeler la méthode `unwrap()` pour obtenir la valeur, mais elle provoquera un arrêt brutal du programme si la valeur est `None`.\n\n**Remarque** : les suggestions de code se réfèrent à la fonction `reqwest::blocking::get` pour suivre l'instruction `// Fetch URL content` du commentaire. Le nom de la [crate `reqwest`](https://docs.rs/reqwest/latest/reqwest/) n'est pas une faute de frappe. Cette crate simplifie les requêtes HTTP, en mode asynchrone ou bloquant.\n\nL'analyse XML peut varier selon les flux RSS, alors testez la fonction `get_feeds()` et ajustez le code si nécessaire.\n\n### Appel de la fonction du module dans main()\n\nLa fonction main() ne connaît pas encore la fonction `get_feeds()`. Nous devons donc importer son module. Contrairement à d'autres langages de programmation, qui utilisent les mots-clés `include` ou `import`, Rust utilise des répertoires de fichiers\n\npour organiser les modules. Dans notre exemple, les deux fichiers source existent au même niveau de répertoire. `feed_reader.rs` est interprété comme une crate, contenant un module appelé `feed_reader`, qui définit la fonction `get_feeds()`.\n\n```text\nsrc/\n  main.rs\n  feed_reader.rs\n```\n\nPour accéder à `get_feeds()` à partir du fichier `feed_reader.rs`, commencez par [indiquer le chemin du module](https://doc.rust-lang.org/book/ch07-04-bringing-paths-into-scope-with-the-use-keyword.html) dans la portée `main.rs`, puis appeler le chemin complet de la fonction.\n\n```rust\nmod feed_reader;\n\nfn main() {\n\n    feed_reader::feed_reader::get_feeds(&rss_feeds);\n\n```\n\nUtilisez le mot-clé `use` pour importer le chemin complet de la fonction avec un nom court.\n\n```rust\nmod feed_reader;\nuse feed_reader::feed_reader::get_feeds;\n\nfn main() {\n\n    get_feeds(&rss_feeds);\n\n```\n\n**Astuce :** consultez [l'article « Clear explanation of the Rust module system »](https://www.sheshbabu.com/posts/rust-module-system/) pour plus de détails.\n\n```diff\n\nfn main() {\n    // ...\n\n    // Print feed_reader get_feeds() output\n    println!(\"{}\", feed_reader::get_feeds(&rss_feeds));\n```\n\n```rust\nuse std::collections::HashMap;\n\nmod feed_reader;\n// Alternative: Import full function path\n//use feed_reader::feed_reader::get_feeds;\n\nfn main() {\n    // Define RSS feed URLs in the variable rss_feeds\n    // Use a HashMap\n    // Add Hacker News and TechCrunch\n    // Ensure to use String as type\n    let rss_feeds = HashMap::from([\n        (\"Hacker News\".to_string(), \"https://news.ycombinator.com/rss\".to_string()),\n        (\"TechCrunch\".to_string(), \"https://techcrunch.com/feed/\".to_string()),\n    ]);\n\n    // Call get_feeds() from feed_reader module\n    feed_reader::feed_reader::get_feeds(&rss_feeds);\n    // Alternative: Imported full path, use short path here.\n    //get_feeds(&rss_feeds);\n}\n```\n\nExécutez `cargo build` à nouveau dans le terminal pour compiler le code.\n\n```shell\ncargo build\n```\n\nDemander des suggestions de code pour des bibliothèques courantes (comme les requêtes HTTP ou l'analyse XML) peut provoquer des erreurs de compilation telles que :\n\n1. Erreur : `could not find blocking in reqwest`. Solution : activez la fonctionnalité `blocking` pour la crate dans `Config.toml`: `reqwest = { version = \"0.11.20\", features = [\"blocking\"] }`.\n2. Erreur : `failed to resolve: use of undeclared crate or module reqwest`. Solution : ajoutez la crate `reqwest`.\n3. Erreur : `failed to resolve: use of undeclared crate or module roxmltree`. Solution : ajoutez la crate `roxmltree`.\n\n```shell\nvim Config.toml\n\nreqwest = { version = \"0.11.20\", features = [\"blocking\"] }\n```\n\n```shell\ncargo add reqwest\ncargo add roxmltree\n```\n\n**Astuce :** copiez le message d'erreur avec l'en-tête `Rust \u003Cerror message>` dans un navigateur pour vérifier si la crate manquante est disponible. Cette recherche vous dirigera sur crates.io. Ajoutez ensuite les dépendances manquantes.\n\nAprès la compilation, exécutez le code avec `cargo run` et vérifiez la sortie du flux RSS de Hacker News.\n\n![Terminal VS Code, exécution de Cargo pour récupérer le flux XML de Hacker News](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_terminal_fetch_rss_feed_output_hacker_news.png)\n\nProchaine étape : analyse XML dans un format lisible par un humain Nous allons maintenant explorer les solutions existantes et le rôle des crates Rust.\n\n## Crates\nLes flux RSS suivent des protocoles et spécifications communs. Pour analyser les éléments XML et comprendre la structure de l'objet sous-jacent, vérifiez si un développeur a déjà résolu ce problème et utilisez son code.\n\nEn Rust, le code réutilisable est organisé en [`Crates`](https://doc.rust-lang.org/rust-by-example/crates.html) et disponible sur crates.io. Ajoutez ces dépendances dans le fichier `Config.toml` dans la section `[dependencies]` ou avec `cargo add \u003Cname>`.\n\nPour notre application, utilisez la [crate feed-rs](https://crates.io/crates/feed-rs) en exécutant la commande suivante dans le terminal :\n\n```shell\ncargo add feed-rs\n```\n\n![Terminal VS Code Terminal : ajout d'une crate, vérification dans le fichier Config.toml](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_rust_crate_add_feed-rs_explained.png)\n\n### feed-rs pour analyser un flux XML\nAccédez à `src/feed_reader.rs` pour modifier l'analyse XML. GitLab Duo sait appeler la fonction `parser::parse` de la crate `feed-rs`. Les suggestion de code comprennent le cas particulier : `feed-rs` [attend des octets bruts en entrée, et non des chaînes](https://docs.rs/feed-rs/latest/feed_rs/parser/fn.parse_with_uri.html) pour déterminer l'encodage. Fournissez des instructions dans le commentaire pour obtenir le résultat prévu.\n\n```rust\n            // Parse XML body with feed_rs parser, input in bytes\n            let parsed_body = feed_rs::parser::parse(body.as_bytes()).unwrap();\n```\n\n![Suggestions de code : module public avec la fonction `get_feeds()`, étape 5 : modification de l'analyseur XML en feed-rs](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_rust_module_function_05_use_feed_rs_to_parse.png)\n\nLes avantages de `feed-rs` se révèlent en exécutant votre programme avec la commande `cargo run` : les clés et valeurs sont converties en types d'objets Rust réutilisables.\n\n![Terminal VS Code, exécution de Cargo pour récupérer le flux XML de Hacker News](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_terminal_fetch_rss_feed_output_hacker_news_feed_rs.png)\n\n## Configuration du runtime : arguments de programme\nJusqu'à présent, nous avons utilisé des valeurs de flux RSS codées en dur. La prochaine étape est de configurer ces flux RSS au moment de l'exécution.\n\nRust propose des [arguments de programme](https://doc.rust-lang.org/rust-by-example/std_misc/arg.html) via la bibliothèque « Std misc » standard. Il est plus rapide d'apprendre [l'analyse des arguments](https://doc.rust-lang.org/rust-by-example/std_misc/arg/matching.html) directement que d'utiliser des crates (par exemple, la crate [clap](https://docs.rs/clap/latest/clap/)) ou de passer par un fichier de configuration ou un autre format ([TOML](https://toml.io/en/), YAML). Pour cet article, j'ai bien essayé d'autres pistes, mais sans succès. Relevez le défi et essayez de configurer les flux RSS d'une autre manière.\n\nUne méthode simple consiste à passer les paramètres sous la forme `\"name,url\"` avec les valeurs séparées par une virgule `,` pour extraire le nom et l'URL. Demandez aux suggestions de code d'effectuer cette action et d'inclure les nouvelles valeurs dans la table de hachage `rss_feeds`. La variable peut ne pas être modifiable et doit être remplacée par `let mut rss_feeds`.\n\nAccédez à `src/main.rs` et ajoutez le code suivant à la fonction `main()` après la variable `rss_feeds`. Écrivez un commentaire qui définit les arguments de programme et vérifiez le code suggéré.\n\n```rust\n    // Program args, format \"name,url\"\n    // Split value by , into name, url and add to rss_feeds\n```\n\n![Suggestions de code pour les arguments de programme et découpage des paires nom,URL pour la variable rss_feeds](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_rust_program_args_boring_solution.png)\n\nDans notre exemple, le code est le suivant :\n\n```rust\nfn main() {\n    // Define RSS feed URLs in the variable rss_feeds\n    // Use a HashMap\n    // Add Hacker News and TechCrunch\n    // Ensure to use String as type\n    let mut rss_feeds = HashMap::from([\n        (\"Hacker News\".to_string(), \"https://news.ycombinator.com/rss\".to_string()),\n        (\"TechCrunch\".to_string(), \"https://techcrunch.com/feed/\".to_string()),\n    ]);\n\n    // Program args, format \"name,url\"\n    // Split value by , into name, url and add to rss_feeds\n    for arg in std::env::args().skip(1) {\n        let mut split = arg.split(\",\");\n        let name = split.next().unwrap();\n        let url = split.next().unwrap();\n        rss_feeds.insert(name.to_string(), url.to_string());\n    }\n\n    // Call get_feeds() from feed_reader module\n    feed_reader::feed_reader::get_feeds(&rss_feeds);\n    // Alternative: Imported full path, use short path here.\n    //get_feeds(&rss_feeds);\n}\n```\n\nPassez les arguments directement avec `cargo run`, avant les arguments contenant `--`. Ajoutez des guillemets doubles à tous les arguments et une virgule après le nom. Utilisez l'URL du flux RSS comme argument. Séparez les arguments par des espaces.\n\n```shell\ncargo build\n\ncargo run -- \"GitLab Blog,https://about.gitlab.com/atom.xml\" \"CNCF,https://www.cncf.io/feed/\"\n```\n\n![Terminal VS Code, exemple de sortie de flux RSS pour le blog GitLab](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_terminal_gitlab_blog_rss_feed_example.png)\n\n### Gestion des erreurs des intrants saisis\nSi l'entrée ne correspond pas aux attentes du programme, [générez une erreur](https://doc.rust-lang.org/rust-by-example/error.html) pour aider à corriger les arguments, par exemple en cas d'URL invalide. Ajoutez un commentaire dans le code pour que les suggestions de code incluent une vérification de l'URL.\n\n```rust\n    // Ensure that URL contains a valid format, otherwise throw an error\n```\n\nVérifiez si `url` commence par `http://` ou `https://`. Sinon, utilisez la [macro panic!](https://doc.rust-lang.org/rust-by-example/std/panic.html) pour générer une erreur. Dans notre exemple, le code est le suivant :\n\n```rust\n    // Program args, format \"name,url\"\n    // Split value by , into name, url and add to rss_feeds\n    for arg in std::env::args().skip(1) {\n        let mut split = arg.split(\",\");\n        let name = split.next().unwrap();\n        let url = split.next().unwrap();\n\n        // Ensure that URL contains a valid format, otherwise throw an error\n        if !url.starts_with(\"http://\") && !url.starts_with(\"https://\") {\n            panic!(\"Invalid URL format: {}\", url);\n        }\n\n        rss_feeds.insert(name.to_string(), url.to_string());\n    }\n```\n\nTestez la gestion des erreurs en supprimant `:` dans l'une des chaînes d'URL. Ajoutez la variable d'environnement `RUST_BACKTRACE=full` pour un affichage plus détaillé des résultats lorsque l'appel `panic()`.\n\n```shell\nRUST_BACKTRACE=full cargo run -- \"GitLab Blog,https://about.gitlab.com/atom.xml\" \"CNCF,https//www.cncf.io/feed/\"\n```\n\n![Terminal VS Code avec un format d'URL incorrect, traçage des erreurs suite à un arrêt brutal du programme](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_terminal_url_format_error_panic_backtrace.png)\n\n## Persistance et stockage des données\nUne solution classique consiste à stocker les données du flux analysé dans un nouveau fichier. Demandez aux suggestions de code de générer un nom de fichier incluant le nom du flux RSS et la date au format ISO.\n\n```rust\n    // Parse XML body with feed_rs parser, input in bytes\n    let parsed_body = feed_rs::parser::parse(body.as_bytes()).unwrap();\n\n    // Print the result\n    println!(\"{:#?}\", parsed_body);\n\n    // Dump the parsed body to a file, as name-current-iso-date.xml\n    let now = chrono::offset::Local::now();\n    let filename = format!(\"{}-{}.xml\", name, now.format(\"%Y-%m-%d\"));\n    let mut file = std::fs::File::create(filename).unwrap();\n    file.write_all(body.as_bytes()).unwrap();\n```\n\nUtilisez la [crate chrono](https://crates.io/crates/chrono). Ajoutez-la à l'aide de `cargo add chrono`, puis exécutez `cargo build` et `cargo run`.\n\nLes fichiers seront enregistrés dans le répertoire où `cargo run` est exécuté. Si vous exécutez le binaire directement dans le répertoire `target/debug/`, les fichiers y seront sauvegardés.\n\n![VS Code avec fichier de contenu du flux RSS CNCF, enregistré sur le disque](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_cncf_rss_feed_saved_on_disk.png)\n\n## Optimisation\nLes URL dans `rss_feeds` sont traitées de manière séquentielle, ce qui peut être lent avec plus de 100 URL. Pourquoi ne pas les traiter en parallèle ?\n\n### Exécution asynchrone\nRust permet l'exécution asynchrone avec des [threads](https://doc.rust-lang.org/book/ch16-01-threads.html).\n\nLa méthode la plus simple est de créer un thread pour chaque URL de flux RSS. Nous explorerons les stratégies d'optimisation ultérieurement. Avant de passer à l'exécution parallèle, mesurez le temps d'exécution séquentiel en faisant précéder `time` par `cargo run`.\n\n```text\ntime cargo run -- \"GitLab Blog,https://about.gitlab.com/atom.xml\" \"CNCF,https://www.cncf.io/feed/\"\n\n0.21s user 0.08s system 10% cpu 2.898 total\n```\n\nCet exercice peut nécessiter du codage manuel. Conservez l'état séquentiel dans une validation Git et une nouvelle branche `sequential-exec` pour comparer l'impact de l'exécution parallèle.\n\n```shell\ngit commit -avm \"Sequential execution working\"\ngit checkout -b sequential-exec\ngit push -u origin sequential-exec\n\ngit checkout main\n```\n\n### Création de threads\nOuvrez `src/feed_reader.rs` et réusinez la fonction `get_feeds()`. Lancez une validation Git de l'état actuel, puis supprimez le contenu de la portée de la fonction. Ajoutez les commentaires suivants dans le code comme instructions pour les suggestions de code :\n\n1. `// Store threads in vector` : stockez les gestionnaires de thread dans un vecteur pour attendre que tous les threads se terminent à la fin de l'appel de la fonction.\n2. `// Loop over rss_feeds and spawn threads` : créez un code standard pour itérer sur les flux RSS et générer un thread pour chacun.\n\nAjoutez les instructions `use` suivantes pour les modules `thread` et `time`.\n\n```rust\n    use std::thread;\n    use std::time::Duration;\n```\n\nContinuez à écrire le code et fermez la boucle for. Ajoutez les gestionnaires de thread au vecteur `threads` et joignez-les à la fin de la fonction.\n\n```rust\n    pub fn get_feeds(rss_feeds: &HashMap\u003CString, String>) {\n\n        // Store threads in vector\n        let mut threads: Vec\u003Cthread::JoinHandle\u003C()>> = Vec::new();\n\n        // Loop over rss_feeds and spawn threads\n        for (name, url) in rss_feeds {\n            let thread_name = name.clone();\n            let thread_url = url.clone();\n            let thread = thread::spawn(move || {\n\n            });\n            threads.push(thread);\n        }\n\n        // Join threads\n        for thread in threads {\n            thread.join().unwrap();\n        }\n    }\n```\n\nAjoutez la crate `thread`, compilez et exécutez le code.\n\n```shell\ncargo add thread\n\ncargo build\n\ncargo run -- \"GitLab Blog,https://about.gitlab.com/atom.xml\" \"CNCF,https://www.cncf.io/feed/\"\n```\n\nAucune donnée n'est traitée ni affichée. Explorez les nouveaux mots-clés avant de réintégrer la fonctionnalité.\n\n### Portées, threads et fermetures des fonctions\nLe code suggéré utilise de nouveaux mots-clés et design patterns. Le gestionnaire de thread de type `thread::JoinHandle` permet d'attendre la fin des threads ([join()](https://doc.rust-lang.org/book/ch16-01-threads.html#waiting-for-all-threads-to-finish-using-join-handles)).\n\n`thread::spawn()` génère un thread pour passer un objet fonction. Une expression [de fermeture](https://doc.rust-lang.org/book/ch13-01-closures.html) est passée en tant que fonction anonyme. Les paramètres de fermeture sont passés avec la syntaxe `||`. La [fermeture `move`](https://doc.rust-lang.org/book/ch16-01-threads.html#using-move-closures-with-threads) déplace les variables de portée de la fonction dans celle du thread. Pas besoin de préciser manuellement les variables qui doivent être passées dans la nouvelle portée de la fonction/fermeture.\n\nCependant, `rss_feeds` est passé comme référence `&` par la structure d'appel de la fonction `get_feeds()` et n'est valide que dans la portée de la fonction. Utilisez le code suivant pour provoquer une erreur :\n\n```rust\npub fn get_feeds(rss_feeds: &HashMap\u003CString, String>) {\n\n    // Store threads in vector\n    let mut threads: Vec\u003Cthread::JoinHandle\u003C()>> = Vec::new();\n\n    // Loop over rss_feeds and spawn threads\n    for (key, value) in rss_feeds {\n        let thread = thread::spawn(move || {\n            println!(\"{}\", key);\n        });\n    }\n}\n```\n\n![Terminal VS Code, erreur liée à la portée de la variable et aux références avec une fermeture déplacée dans un thread](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_terminal_cargo_build_error_function_threads_variable_scopes.png)\n\nLa variable `key`, pourtant créée dans la portée de la fonction, fait référence à `rss_feeds` et ne peut pas être déplacée dans la portée du thread. Les valeurs accessibles depuis la table de hachage des paramètres de fonction `rss_feeds` nécessitent une copie locale avec `clone()`.\n\n![Terminal VS Code, création de thread avec clone](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_rust_thread_spawn_clone.png)\n\n```rust\npub fn get_feeds(rss_feeds: &HashMap\u003CString, String>) {\n\n    // Store threads in vector\n    let mut threads: Vec\u003Cthread::JoinHandle\u003C()>> = Vec::new();\n\n    // Loop over rss_feeds and spawn threads\n    for (name, url) in rss_feeds {\n        let thread_name = name.clone();\n        let thread_url = url.clone();\n        let thread = thread::spawn(move || {\n            // Use thread_name and thread_url as values, see next chapter for instructions.\n```\n\n## Analyse du flux XML dans les types d'objets\nL'étape suivante consiste à analyser le flux RSS dans la fermeture du thread. Ajoutez les commentaires suivants dans le code pour guider les suggestions de code :\n\n1. `// Parse XML body with feed_rs parser, input in bytes` : récupérer le contenu de l'URL du flux RSS et l'analyser avec les fonctions de la crate `feed_rs`.\n2. `// Check feed_type attribute feed_rs::model::FeedType::RSS2 or Atom and print its name` : extraire le type de flux pour comparer l'attribut `feed_type` avec [`feed_rs::model::FeedType`](https://docs.rs/feed-rs/latest/feed_rs/model/enum.FeedType.html). Les suggestions de code doivent aussi recevoir des instructions avec les valeurs enum exactes à comparer.\n\n![Demande adressée aux suggestions de code de comparer les types de flux spécifiques](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_feed_rs_type_condition.png)\n\n```rust\n            // Parse XML body with feed_rs parser, input in bytes\n            let body = reqwest::blocking::get(thread_url).unwrap().bytes().unwrap();\n            let feed = feed_rs::parser::parse(body.as_ref()).unwrap();\n\n            // Check feed_type attribute feed_rs::model::FeedType::RSS2 or Atom and print its name\n            if feed.feed_type == feed_rs::model::FeedType::RSS2 {\n                println!(\"{} is an RSS2 feed\", thread_name);\n            } else if feed.feed_type == feed_rs::model::FeedType::Atom {\n                println!(\"{} is an Atom feed\", thread_name);\n            }\n```\n\nExécutez le programme et vérifiez les données de sortie.\n\n```text\ntime cargo run -- \"GitLab Blog,https://about.gitlab.com/atom.xml\" \"CNCF,https://www.cncf.io/feed/\"\n\nCNCF is an RSS2 feed\nTechCrunch is an RSS2 feed\nGitLab Blog is an Atom feed\nHacker News is an RSS2 feed\n```\n\nPour cela, ouvrez les URL des flux dans le navigateur ou en inspectant les fichiers téléchargés.\n\nHacker News utilise RSS 2.0, avec `channel(title,link,description,item(title,link,pubDate,comments))`. TechCrunch et le blog de la CNCF ont une structure similaire.\n```xml\n\u003Crss version=\"2.0\">\u003Cchannel>\u003Ctitle>Hacker News\u003C/title>\u003Clink>https://news.ycombinator.com/\u003C/link>\u003Cdescription>Links for the intellectually curious, ranked by readers.\u003C/description>\u003Citem>\u003Ctitle>Writing a debugger from scratch: Breakpoints\u003C/title>\u003Clink>https://www.timdbg.com/posts/writing-a-debugger-from-scratch-part-5/\u003C/link>\u003CpubDate>Wed, 27 Sep 2023 06:31:25 +0000\u003C/pubDate>\u003Ccomments>https://news.ycombinator.com/item?id=37670938\u003C/comments>\u003Cdescription>\u003C![CDATA[\u003Ca href=\"https://news.ycombinator.com/item?id=37670938\">Comments\u003C/a>]]>\u003C/description>\u003C/item>\u003Citem>\n```\n\nLe blog de GitLab utilise le format de flux [Atom](https://datatracker.ietf.org/doc/html/rfc4287), similaire à RSS, mais nécessitant une logique d'analyse différente.\n```xml\n\u003C?xml version='1.0' encoding='utf-8' ?>\n\u003Cfeed xmlns='http://www.w3.org/2005/Atom'>\n\u003C!-- / Get release posts -->\n\u003C!-- / Get blog posts -->\n\u003Ctitle>GitLab\u003C/title>\n\u003Cid>https://about.gitlab.com/blog\u003C/id>\n\u003Clink href='https://about.gitlab.com/blog/' />\n\u003Cupdated>2023-09-26T00:00:00+00:00\u003C/updated>\n\u003Cauthor>\n\u003Cname>The GitLab Team\u003C/name>\n\u003C/author>\n\u003Centry>\n\u003Ctitle>Atlassian Server ending: Goodbye disjointed toolchain, hello DevSecOps platform\u003C/title>\n\u003Clink href='https://about.gitlab.com/blog/atlassian-server-ending-move-to-a-single-devsecops-platform/' rel='alternate' />\n\u003Cid>https://about.gitlab.com/blog/atlassian-server-ending-move-to-a-single-devsecops-platform/\u003C/id>\n\u003Cpublished>2023-09-26T00:00:00+00:00\u003C/published>\n\u003Cupdated>2023-09-26T00:00:00+00:00\u003C/updated>\n\u003Cauthor>\n\u003Cname>Dave Steer, Justin Farris\u003C/name>\n\u003C/author>\n```\n\n### Cartographie des types de données de flux génériques\nPour utiliser la fonction [`roxmltree::Document::parse`](https://docs.rs/roxmltree/latest/roxmltree/struct.Document.html) vous devez comprendre l'arborescence des nœuds XML et ses noms de balise. Heureusement, [feed_rs::model::Feed](https://docs.rs/feed-rs/latest/feed_rs/model/struct.Feed.html) gère à la fois les flux RSS et Atom. Nous pouvons donc continuer avec la crate `feed_rs`.\n\n1. Atom : Feed->Feed, Entry->Entry\n2. RSS : Channel->Feed, Item->Entry\n\nNous devons extraire les attributs requis et associer leurs types de données. Consultez la [documentation feed_rs::model](https://docs.rs/feed-rs/latest/feed_rs/model/index.html) pour comprendre les structures, leurs champs et implémentations. Cela évitera les erreurs de conversion et les échecs de compilation, spécifiques à l'implémentation de `feed_rs`.\n\nLa structure [`Feed`](https://docs.rs/feed-rs/latest/feed_rs/model/struct.Feed.html) fournit un `title` de type `Option\u003CText>` (avec une valeur ou vide). La structure [`Entry`](https://docs.rs/feed-rs/latest/feed_rs/model/struct.Entry.html) fournit les éléments suivants :\n\n1. `title` : `Option\u003CText>` avec [`Text`](https://docs.rs/feed-rs/latest/feed_rs/model/struct.Text.html) et le champ `content` comme la `String`.\n2. `updated` : `Option\u003CDateTime\u003CUtc>>` avec [`DateTime`](https://docs.rs/chrono/latest/chrono/struct.DateTime.html) avec la [méthode `format()`](https://docs.rs/chrono/latest/chrono/struct.DateTime.html#method.format).\n3. `summary` : `Option\u003CText>` [`Text`](https://docs.rs/feed-rs/latest/feed_rs/model/struct.Text.html) et le champ `content` comme la `String`.\n4. `links` : `Vec\u003CLink>`, vecteur avec les éléments [`Link`](https://docs.rs/feed-rs/latest/feed_rs/model/struct.Link.html). L'attribut `href` fournit la chaîne d'URL brute.\n\nUtilisez ces connaissances pour extraire les données des intrants de flux. Appelez `unwrap()` sur tous les types `Option` et ajoutez des instructions explicites aux suggestions de code.\n\n```rust\n                // https://docs.rs/feed-rs/latest/feed_rs/model/struct.Feed.html\n                // https://docs.rs/feed-rs/latest/feed_rs/model/struct.Entry.html\n                // Loop over all entries, and print\n                // title.unwrap().content\n                // published.unwrap().format\n                // summary.unwrap().content\n                // links href as joined string\n                for entry in feed.entries {\n                    println!(\"Title: {}\", entry.title.unwrap().content);\n                    println!(\"Published: {}\", entry.published.unwrap().format(\"%Y-%m-%d %H:%M:%S\"));\n                    println!(\"Summary: {}\", entry.summary.unwrap().content);\n                    println!(\"Links: {:?}\", entry.links.iter().map(|link| link.href.clone()).collect::\u003CVec\u003CString>>().join(\", \"));\n                    println!();\n                }\n```\n\n![Suggestions de code pour afficher les types d'éléments de flux, avec des exigences spécifiques](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_print_feed_entries_fields_with_rust_type_specifics.png)\n\n### Gestion des erreurs avec l'Option unwrap()\nCompilez, exécutez le programme, puis continuez avec des instructions multilignes. Remarque : `unwrap()` appelle la macro `panic!` et bloque le programme si des valeurs sont vides, comme un champ `summary` non défini dans les données du flux.\n\n```shell\nGitLab Blog is an Atom feed\nTitle: How the Colmena project uses GitLab to support citizen journalists\nPublished: 2023-09-27 00:00:00\nthread '\u003Cunnamed>' panicked at 'called `Option::unwrap()` on a `None` value', src/feed_reader.rs:40:59\n```\n\nUtilisez [`std::Option::unwrap_or_else`](https://doc.rust-lang.org/std/option/enum.Option.html#method.unwrap_or_else) pour définir une chaîne vide comme valeur par défaut. La syntaxe nécessite une fermeture qui renvoie une instanciation de structure `Text` vide.\n\nJ'ai dû m'y reprendre à plusieurs fois pour trouver l'initialisation correcte permettant de résoudre le problème, car le passage d'une chaîne vide ne fonctionne pas avec les types personnalisés. Je vais vous montrer mes tentatives et recherches.\n\n```rust\n// Problem: The `summary` attribute is not always initialized. unwrap() will panic! then.\n// Requires use mime; and use feed_rs::model::Text;\n/*\n// 1st attempt: Use unwrap() to extraxt Text from Option\u003CText> type.\nprintln!(\"Summary: {}\", entry.summary.unwrap().content);\n// 2nd attempt. Learned about unwrap_or_else, passing an empty string.\nprintln!(\"Summary: {}\", entry.summary.unwrap_or_else(|| \"\").content);\n// 3rd attempt. summary is of the Text type, pass a new struct instantiation.\nprintln!(\"Summary: {}\", entry.summary.unwrap_or_else(|| Text{}).content);\n// 4th attempt. Struct instantiation requires 3 field values.\nprintln!(\"Summary: {}\", entry.summary.unwrap_or_else(|| Text{\"\", \"\", \"\"}).content);\n// 5th attempt. Struct instantation with public fields requires key: value syntax\nprintln!(\"Summary: {}\", entry.summary.unwrap_or_else(|| Text{content_type: \"\", src: \"\", content: \"\"}).content);\n// 6th attempt. Reviewed expected Text types in https://docs.rs/feed-rs/latest/feed_rs/model/struct.Text.html and created Mime and String objects\nprintln!(\"Summary: {}\", entry.summary.unwrap_or_else(|| Text{content_type: mime::TEXT_PLAIN, src: String::new(), content: String::new()}).content);\n// 7th attempt: String and Option\u003CString> cannot be casted automagically. Compiler suggested using `Option::Some()`.\nprintln!(\"Summary: {}\", entry.summary.unwrap_or_else(|| Text{content_type: mime::TEXT_PLAIN, src: Option::Some(), content: String::new()}).content);\n*/\n\n// xth attempt: Solution. Option::Some() requires a new String object.\nprintln!(\"Summary: {}\", entry.summary.unwrap_or_else(|| Text{content_type: mime::TEXT_PLAIN, src: Option::Some(String::new()), content: String::new()}).content);\n```\n\nCette approche n'était pas satisfaisante, car la ligne de code était difficile à lire et nécessitait une retouche manuelle sans suggestions de code. Puis, j'ai trouvé où se nichait le problème : si `Option` a la valeur `none`, `unwrap()` génère une erreur. J'ai demandé aux suggestions de code s’il existe une méthode plus simple, avec ce nouveau commentaire :\n\n```text\n                // xth attempt: Solution. Option::Some() requires a new String object.\n                println!(\"Summary: {}\", entry.summary.unwrap_or_else(|| Text{content_type: mime::TEXT_PLAIN, src: Option::Some(String::new()), content: String::new()}).content);\n\n                // Alternatively, use Option.is_none()\n```\n\n![Demande aux suggestions de code d'une alternative pour Options.is_none](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/code_suggestions_after_complex_unwrap_or_else_ask_for_alternative_option.png)\n\nCette méthode améliore la lisibilité, moins de cycles CPU sont gaspillés sur `unwrap()` et la courbe d'apprentissage est excellente, de la résolution d'un problème complexe à l'utilisation d'une solution standard. Gagnant-gagnant.\n\nAjoutez le stockage des données XML sur le disque pour finaliser l'application de lecteur de flux.\n\n```rust\n                // Dump the parsed body to a file, as name-current-iso-date.xml\n                let file_name = format!(\"{}-{}.xml\", thread_name, chrono::Local::now().format(\"%Y-%m-%d-%H-%M-%S\"));\n                let mut file = std::fs::File::create(file_name).unwrap();\n                file.write_all(body.as_ref()).unwrap();\n```\n\nCompilez et exécutez le programme pour vérifier les données de sortie.\n\n```shell\ncargo build\n\ntime cargo run -- \"GitLab Blog,https://about.gitlab.com/atom.xml\" \"CNCF,https://www.cncf.io/feed/\"\n```\n\n![Terminal VS Code, exécution de Cargo avec des données de sortie d'intrants au format requis](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/vs_code_terminal_cargo_run_formatted_output_final.png)\n\n## Benchmarks\n\n### Exécution séquentielle vs parallèle\nComparez les temps d'exécution du code en créant cinq échantillons pour chaque type d'exécution.\n\n1. Exécution séquentielle. [Exemple de code source de la MR](https://gitlab.com/gitlab-da/use-cases/ai/learn-with-ai/learn-rust-ai-app-reader/-/merge_requests/1)\n2. Exécution parallèle. [Exemple de code source de la MR](https://gitlab.com/gitlab-da/use-cases/ai/learn-with-ai/learn-rust-ai-app-reader/-/merge_requests/3)\n\n```shell\n# Sequential\ngit checkout sequential-exec\n\ntime cargo run -- \"GitLab Blog,https://about.gitlab.com/atom.xml\" \"CNCF,https://www.cncf.io/feed/\"\n\n0.21s user 0.08s system 10% cpu 2.898 total\n0.21s user 0.08s system 11% cpu 2.585 total\n0.21s user 0.09s system 10% cpu 2.946 total\n0.19s user 0.08s system 10% cpu 2.714 total\n0.20s user 0.10s system 10% cpu 2.808 total\n```\n\n```shell\n# Parallel\ngit checkout parallel-exec\n\ntime cargo run -- \"GitLab Blog,https://about.gitlab.com/atom.xml\" \"CNCF,https://www.cncf.io/feed/\"\n\n0.19s user 0.08s system 17% cpu 1.515 total\n0.18s user 0.08s system 16% cpu 1.561 total\n0.18s user 0.07s system 17% cpu 1.414 total\n0.19s user 0.08s system 18% cpu 1.447 total\n0.17s user 0.08s system 16% cpu 1.453 total\n```\nAvec quatre threads RSS en parallèle, le temps total est presque réduit de moitié, mais le CPU est plus sollicité. Optimisons le code et les fonctionnalités.\n\nActuellement, nous utilisons la version de débogage Cargo, mais pas encore les versions optimisées. L'exécution parallèle a ses limites : les points de terminaison HTTP peuvent atteindre leur débit maximum, et\nchaque thread nécessite un changement de contexte dans le noyau, consommant des ressources. Lorsqu'un thread reçoit des ressources de calcul, d'autres sont mis en veille. Un trop grand nombre de threads peut ralentir le système. Pour éviter cela, utilisez des design patterns comme les [files d'attente de travail](https://docs.rs/work-queue/latest/work_queue/). Un pool de threads récupère cette tâche pour une exécution asynchrone.\n\nRust garantir la synchronisation des données entre les threads à l'aide des [canaux](https://doc.rust-lang.org/rust-by-example/std_misc/channels.html). Pour garantir un accès simultané aux données, des [mutexes (exclusions mutuelles)](https://doc.rust-lang.org/std/sync/struct.Mutex.html) fournissent des verrous sûrs.\n\n### CI/CD avec mise en cache Rust\nAjoutez la configuration CI/CD suivante dans le fichier `.gitlab-ci.yml`. Le job `run-latest` appelle `cargo run` avec des exemples d'URL de flux RSS et mesure le temps d'exécution en continu.\n\n```text\nstages:\n  - build\n  - test\n  - run\n\ndefault:\n  image: rust:latest\n  cache:\n    key: ${CI_COMMIT_REF_SLUG}\n    paths:\n      - .cargo/bin\n      - .cargo/registry/index\n      - .cargo/registry/cache\n      - target/debug/deps\n      - target/debug/build\n    policy: pull-push\n\n# Cargo data needs to be in the project directory for being cached.\nvariables:\n  CARGO_HOME: ${CI_PROJECT_DIR}/.cargo\n\nbuild-latest:\n  stage: build\n  script:\n    - cargo build --verbose\n\ntest-latest:\n  stage: build\n  script:\n    - cargo test --verbose\n\nrun-latest:\n  stage: run\n  script:\n    - time cargo run -- \"GitLab Blog,https://about.gitlab.com/atom.xml\" \"CNCF,https://www.cncf.io/feed/\"\n```\n\n![Pipelines GitLab CI/CD pour Rust, données de sortie de l'exécution Cargo](https://about.gitlab.com/images/blogimages/learn-rust-with-ai-code-suggestions-advanced-programming/gitlab_cicd_pipeline_rust_cargo_run_output.png)\n\n## Étapes suivantes\nRédiger cet article a été un défi pour maîtriser les techniques avancées de Rust et optimiser les suggestions de code. Ces dernières sont très utiles pour générer rapidement du code, avec le contexte local et pour ajuster l'algorithme à mesure que vous écrivez le code. Dans cet article, j'ai partagé les défis et les solutions. L'exemple de code pour l'application de lecture est disponible dans [le projet learn-rust-ai-app-reader](https://gitlab.com/gitlab-da/use-cases/ai/learn-with-ai/learn-rust-ai-app-reader).\n\nL'analyse des flux RSS étant complexe, elle nécessite des structures de données, des requêtes HTTP externes et des optimisations parallèles. Alors, `pourquoi ne pas utiliser la crate std::rss` -- pour une exécution asynchrone avancée. Cela ne démontre pas toutes les fonctionnalités de Rust abordées dans cet article, mais vous pouvez essayer de réécrire le code avec la [crate `rss`](https://docs.rs/rss/latest/rss/) pour pratiquer l'exécution asynchrone.\n\n### Exercices d'apprentissage de l'exécution asynchrone\nCet article pose les bases pour explorer le stockage persistant et la présentation des données. Pour vous perfectionner votre application en Rust, voici quelques idées :\n\n1. Stockage des données : utilisez une base de données comme sqlite et suivez les mises à jour des flux RSS.\n2. Notifications : déclenchez des notifications dans Telegram, ou autres.\n3. Fonctionnalités : étendez les types de lecteurs aux [API REST](https://about.gitlab.com/fr-fr/blog/what-is-rest-api/ \"API REST\")\n4. Configuration : intégrez des fichiers de configuration pour les flux RSS, les API, etc.\n5. Efficacité : ajoutez des filtres et des balises d'abonnement.\n6. Déploiement : utilisez un serveur Web, collectez les indicateurs avec Prometheus et déployez sur Kubernetes.\n\nNous aborderons certains de ces sujets dans un prochain article. En attendant, essayez d'implémenter des flux RSS existants et explorez d'autres bibliothèques Rust (`crates`).\n\n### Votre retour d'expérience\nLorsque vous utilisez les suggestions de code de [GitLab Duo](/gitlab-duo-agent-platform/), n'hésitez pas à [partager vos retours dans le ticket prévu à cet effet](https://gitlab.com/gitlab-org/gitlab/-/issues/405152).\n",[23,24,25,26,27],"DevSecOps","careers","tutorial","workflow","AI/ML","2025-01-27","yml",{},true,"/fr-fr/blog/learn-advanced-rust-programming-with-a-little-help-from-ai-code-suggestions",{"title":15,"description":16,"ogTitle":15,"ogDescription":16,"noIndex":12,"ogImage":19,"ogUrl":34,"ogSiteName":35,"ogType":36,"canonicalUrls":34},"https://about.gitlab.com/blog/learn-advanced-rust-programming-with-a-little-help-from-ai-code-suggestions","https://about.gitlab.com","article","fr-fr/blog/learn-advanced-rust-programming-with-a-little-help-from-ai-code-suggestions",[39,24,25,26,40],"devsecops","aiml","ZMGmoNv0u0oHQ6V0fqWNE31BhMVxzikqh_BVBlscCUc",{"data":43},{"logo":44,"freeTrial":49,"sales":54,"login":59,"items":64,"search":374,"minimal":409,"duo":428,"pricingDeployment":437},{"config":45},{"href":46,"dataGaName":47,"dataGaLocation":48},"/fr-fr/","gitlab logo","header",{"text":50,"config":51},"Commencer un essai gratuit",{"href":52,"dataGaName":53,"dataGaLocation":48},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/fr-fr&glm_content=default-saas-trial/","free trial",{"text":55,"config":56},"Contacter l'équipe commerciale",{"href":57,"dataGaName":58,"dataGaLocation":48},"/fr-fr/sales/","sales",{"text":60,"config":61},"Connexion",{"href":62,"dataGaName":63,"dataGaLocation":48},"https://gitlab.com/users/sign_in/","sign in",[65,92,189,194,295,355],{"text":66,"config":67,"cards":69},"Plateforme",{"dataNavLevelOne":68},"platform",[70,76,84],{"title":66,"description":71,"link":72},"La plateforme d'orchestration intelligente pour le DevSecOps",{"text":73,"config":74},"Découvrir notre plateforme",{"href":75,"dataGaName":68,"dataGaLocation":48},"/fr-fr/platform/",{"title":77,"description":78,"link":79},"GitLab Duo Agent Platform","L'IA agentique pour l'ensemble du cycle de développement logiciel",{"text":80,"config":81},"Découvrir GitLab Duo",{"href":82,"dataGaName":83,"dataGaLocation":48},"/fr-fr/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":85,"description":86,"link":87},"Choisir GitLab","Découvrez les principales raisons pour lesquelles les entreprises choisissent GitLab",{"text":88,"config":89},"En savoir plus",{"href":90,"dataGaName":91,"dataGaLocation":48},"/fr-fr/why-gitlab/","why gitlab",{"text":93,"left":31,"config":94,"link":96,"lists":100,"footer":171},"Produit",{"dataNavLevelOne":95},"solutions",{"text":97,"config":98},"Voir toutes les solutions",{"href":99,"dataGaName":95,"dataGaLocation":48},"/fr-fr/solutions/",[101,126,149],{"title":102,"description":103,"link":104,"items":109},"Automatisation","CI/CD et automatisation pour accélérer le déploiement",{"config":105},{"icon":106,"href":107,"dataGaName":108,"dataGaLocation":48},"AutomatedCodeAlt","/fr-fr/solutions/delivery-automation/","automated software delivery",[110,114,117,122],{"text":111,"config":112},"CI/CD",{"href":113,"dataGaLocation":48,"dataGaName":111},"/fr-fr/solutions/continuous-integration/",{"text":77,"config":115},{"href":82,"dataGaLocation":48,"dataGaName":116},"gitlab duo agent platform - product menu",{"text":118,"config":119},"Gestion du code source",{"href":120,"dataGaLocation":48,"dataGaName":121},"/fr-fr/solutions/source-code-management/","Source Code Management",{"text":123,"config":124},"Livraison de logiciels automatisée",{"href":107,"dataGaLocation":48,"dataGaName":125},"Automated software delivery",{"title":127,"description":128,"link":129,"items":134},"Sécurité","Livrez du code plus rapidement sans compromettre la sécurité",{"config":130},{"href":131,"dataGaName":132,"dataGaLocation":48,"icon":133},"/fr-fr/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[135,139,144],{"text":136,"config":137},"Tests de sécurité des applications",{"href":131,"dataGaName":138,"dataGaLocation":48},"Application security testing",{"text":140,"config":141},"Sécurité de la chaîne d'approvisionnement logicielle",{"href":142,"dataGaLocation":48,"dataGaName":143},"/fr-fr/solutions/supply-chain/","Software supply chain security",{"text":145,"config":146},"Conformité logicielle",{"href":147,"dataGaName":148,"dataGaLocation":48},"/fr-fr/solutions/software-compliance/","Software Compliance",{"title":150,"link":151,"items":156},"Mesures",{"config":152},{"icon":153,"href":154,"dataGaName":155,"dataGaLocation":48},"DigitalTransformation","/fr-fr/solutions/visibility-measurement/","visibility and measurement",[157,161,166],{"text":158,"config":159},"Visibilité et mesures",{"href":154,"dataGaLocation":48,"dataGaName":160},"Visibility and Measurement",{"text":162,"config":163},"Gestion de la chaîne de valeur",{"href":164,"dataGaLocation":48,"dataGaName":165},"/fr-fr/solutions/value-stream-management/","Value Stream Management",{"text":167,"config":168},"Données d'analyse et informations clés",{"href":169,"dataGaLocation":48,"dataGaName":170},"/fr-fr/solutions/analytics-and-insights/","Analytics and insights",{"title":172,"items":173},"GitLab pour",[174,179,184],{"text":175,"config":176},"Entreprises",{"href":177,"dataGaLocation":48,"dataGaName":178},"/fr-fr/enterprise/","enterprise",{"text":180,"config":181},"PME",{"href":182,"dataGaLocation":48,"dataGaName":183},"/fr-fr/small-business/","small business",{"text":185,"config":186},"Secteur public",{"href":187,"dataGaLocation":48,"dataGaName":188},"/fr-fr/solutions/public-sector/","public sector",{"text":190,"config":191},"Tarifs",{"href":192,"dataGaName":193,"dataGaLocation":48,"dataNavLevelOne":193},"/fr-fr/pricing/","pricing",{"text":195,"config":196,"link":198,"lists":202,"feature":282},"Ressources",{"dataNavLevelOne":197},"resources",{"text":199,"config":200},"Afficher toutes les ressources",{"href":201,"dataGaName":197,"dataGaLocation":48},"/fr-fr/resources/",[203,236,254],{"title":204,"items":205},"Premiers pas",[206,211,216,221,226,231],{"text":207,"config":208},"Installation",{"href":209,"dataGaName":210,"dataGaLocation":48},"/fr-fr/install/","install",{"text":212,"config":213},"Guides de démarrage",{"href":214,"dataGaName":215,"dataGaLocation":48},"/fr-fr/get-started/","quick setup checklists",{"text":217,"config":218},"Apprentissage",{"href":219,"dataGaLocation":48,"dataGaName":220},"https://university.gitlab.com/","learn",{"text":222,"config":223},"Documentation sur le produit",{"href":224,"dataGaName":225,"dataGaLocation":48},"https://docs.gitlab.com/","product documentation",{"text":227,"config":228},"Vidéos sur les bonnes pratiques",{"href":229,"dataGaName":230,"dataGaLocation":48},"/fr-fr/getting-started-videos/","best practice videos",{"text":232,"config":233},"Intégrations",{"href":234,"dataGaName":235,"dataGaLocation":48},"/fr-fr/integrations/","integrations",{"title":237,"items":238},"Découvrir",[239,244,249],{"text":240,"config":241},"Témoignages clients",{"href":242,"dataGaName":243,"dataGaLocation":48},"/fr-fr/customers/","customer success stories",{"text":245,"config":246},"Blog",{"href":247,"dataGaName":248,"dataGaLocation":48},"/fr-fr/blog/","blog",{"text":250,"config":251},"Travail à distance",{"href":252,"dataGaName":253,"dataGaLocation":48},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":255,"items":256},"Connecter",[257,262,267,272,277],{"text":258,"config":259},"Services GitLab",{"href":260,"dataGaName":261,"dataGaLocation":48},"/fr-fr/services/","services",{"text":263,"config":264},"Communauté",{"href":265,"dataGaName":266,"dataGaLocation":48},"/community/","community",{"text":268,"config":269},"Forum",{"href":270,"dataGaName":271,"dataGaLocation":48},"https://forum.gitlab.com/","forum",{"text":273,"config":274},"Événements",{"href":275,"dataGaName":276,"dataGaLocation":48},"/events/","events",{"text":278,"config":279},"Partenaires",{"href":280,"dataGaName":281,"dataGaLocation":48},"/fr-fr/partners/","partners",{"backgroundColor":283,"textColor":284,"text":285,"image":286,"link":290},"#2f2a6b","#fff","L'avenir du développement logiciel. Tendances et perspectives.",{"altText":287,"config":288},"carte promo The Source",{"src":289},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":291,"config":292},"Lire les articles les plus récents",{"href":293,"dataGaName":294,"dataGaLocation":48},"/fr-fr/the-source/","the source",{"text":296,"config":297,"lists":299},"Société",{"dataNavLevelOne":298},"company",[300],{"items":301},[302,307,313,315,320,325,330,335,340,345,350],{"text":303,"config":304},"À propos",{"href":305,"dataGaName":306,"dataGaLocation":48},"/fr-fr/company/","about",{"text":308,"config":309,"footerGa":312},"Carrières",{"href":310,"dataGaName":311,"dataGaLocation":48},"/jobs/","jobs",{"dataGaName":311},{"text":273,"config":314},{"href":275,"dataGaName":276,"dataGaLocation":48},{"text":316,"config":317},"Leadership",{"href":318,"dataGaName":319,"dataGaLocation":48},"/company/team/e-group/","leadership",{"text":321,"config":322},"Équipe",{"href":323,"dataGaName":324,"dataGaLocation":48},"/company/team/","team",{"text":326,"config":327},"Manuel",{"href":328,"dataGaName":329,"dataGaLocation":48},"https://handbook.gitlab.com/","handbook",{"text":331,"config":332},"Relations avec les investisseurs",{"href":333,"dataGaName":334,"dataGaLocation":48},"https://ir.gitlab.com/","investor relations",{"text":336,"config":337},"Centre de confiance",{"href":338,"dataGaName":339,"dataGaLocation":48},"/fr-fr/security/","trust center",{"text":341,"config":342},"Centre pour la transparence de l'IA",{"href":343,"dataGaName":344,"dataGaLocation":48},"/fr-fr/ai-transparency-center/","ai transparency center",{"text":346,"config":347},"Newsletter",{"href":348,"dataGaName":349,"dataGaLocation":48},"/company/contact/#contact-forms","newsletter",{"text":351,"config":352},"Presse",{"href":353,"dataGaName":354,"dataGaLocation":48},"/press/","press",{"text":356,"config":357,"lists":358},"Nous contacter",{"dataNavLevelOne":298},[359],{"items":360},[361,364,369],{"text":55,"config":362},{"href":57,"dataGaName":363,"dataGaLocation":48},"talk to sales",{"text":365,"config":366},"Portail d’assistance",{"href":367,"dataGaName":368,"dataGaLocation":48},"https://support.gitlab.com","support portal",{"text":370,"config":371},"Portail clients GitLab",{"href":372,"dataGaName":373,"dataGaLocation":48},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":375,"login":376,"suggestions":383},"Fermer",{"text":377,"link":378},"Pour rechercher des dépôts et des projets, connectez-vous à",{"text":379,"config":380},"gitlab.com",{"href":62,"dataGaName":381,"dataGaLocation":382},"search login","search",{"text":384,"default":385},"Suggestions",[386,388,393,395,400,405],{"text":77,"config":387},{"href":82,"dataGaName":77,"dataGaLocation":382},{"text":389,"config":390},"Suggestions de code (IA)",{"href":391,"dataGaName":392,"dataGaLocation":382},"/fr-fr/solutions/code-suggestions/","Code Suggestions (AI)",{"text":111,"config":394},{"href":113,"dataGaName":111,"dataGaLocation":382},{"text":396,"config":397},"GitLab sur AWS",{"href":398,"dataGaName":399,"dataGaLocation":382},"/fr-fr/partners/technology-partners/aws/","GitLab on AWS",{"text":401,"config":402},"GitLab sur Google Cloud ",{"href":403,"dataGaName":404,"dataGaLocation":382},"/fr-fr/partners/technology-partners/google-cloud-platform/","GitLab on Google Cloud",{"text":406,"config":407},"Pourquoi utiliser GitLab ?",{"href":90,"dataGaName":408,"dataGaLocation":382},"Why GitLab?",{"freeTrial":410,"mobileIcon":415,"desktopIcon":420,"secondaryButton":423},{"text":411,"config":412},"Commencer votre essai gratuit",{"href":413,"dataGaName":53,"dataGaLocation":414},"https://gitlab.com/-/trials/new/","nav",{"altText":416,"config":417},"Icône GitLab",{"src":418,"dataGaName":419,"dataGaLocation":414},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":416,"config":421},{"src":422,"dataGaName":419,"dataGaLocation":414},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":424,"config":425},"Commencer",{"href":426,"dataGaName":427,"dataGaLocation":414},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/fr-fr/get-started/","get started",{"freeTrial":429,"mobileIcon":433,"desktopIcon":435},{"text":430,"config":431},"En savoir plus sur GitLab Duo",{"href":82,"dataGaName":432,"dataGaLocation":414},"gitlab duo",{"altText":416,"config":434},{"src":418,"dataGaName":419,"dataGaLocation":414},{"altText":416,"config":436},{"src":422,"dataGaName":419,"dataGaLocation":414},{"freeTrial":438,"mobileIcon":443,"desktopIcon":445},{"text":439,"config":440},"Retour aux tarifs",{"href":192,"dataGaName":441,"dataGaLocation":414,"icon":442},"back to pricing","GoBack",{"altText":416,"config":444},{"src":418,"dataGaName":419,"dataGaLocation":414},{"altText":416,"config":446},{"src":422,"dataGaName":419,"dataGaLocation":414},{"title":448,"button":449,"config":454},"Découvrez comment l'IA agentique transforme la livraison logicielle",{"text":450,"config":451},"Regarder GitLab Transcend maintenant",{"href":452,"dataGaName":453,"dataGaLocation":48},"/fr-fr/events/transcend/virtual/","transcend event",{"layout":455,"icon":456,"disabled":31},"release","AiStar",{"data":458},{"text":459,"source":460,"edit":466,"contribute":471,"config":476,"items":481,"minimal":658},"Git est une marque déposée de Software Freedom Conservancy et notre utilisation de « GitLab » est sous licence",{"text":461,"config":462},"Afficher le code source de la page",{"href":463,"dataGaName":464,"dataGaLocation":465},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":467,"config":468},"Modifier cette page",{"href":469,"dataGaName":470,"dataGaLocation":465},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":472,"config":473},"Veuillez contribuer",{"href":474,"dataGaName":475,"dataGaLocation":465},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":477,"facebook":478,"youtube":479,"linkedin":480},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[482,505,559,591,626],{"title":66,"links":483,"subMenu":488},[484],{"text":485,"config":486},"Plateforme DevSecOps",{"href":75,"dataGaName":487,"dataGaLocation":465},"devsecops platform",[489],{"title":190,"links":490},[491,495,500],{"text":492,"config":493},"Voir les forfaits",{"href":192,"dataGaName":494,"dataGaLocation":465},"view plans",{"text":496,"config":497},"Pourquoi choisir GitLab Premium ?",{"href":498,"dataGaName":499,"dataGaLocation":465},"/fr-fr/pricing/premium/","why premium",{"text":501,"config":502},"Pourquoi choisir GitLab Ultimate ?",{"href":503,"dataGaName":504,"dataGaLocation":465},"/fr-fr/pricing/ultimate/","why ultimate",{"title":506,"links":507},"Solutions",[508,513,516,518,523,528,532,535,538,543,545,547,549,554],{"text":509,"config":510},"Transformation digitale",{"href":511,"dataGaName":512,"dataGaLocation":465},"/fr-fr/topics/digital-transformation/","digital transformation",{"text":514,"config":515},"Sécurité et conformité",{"href":131,"dataGaName":138,"dataGaLocation":465},{"text":123,"config":517},{"href":107,"dataGaName":108,"dataGaLocation":465},{"text":519,"config":520},"Développement agile",{"href":521,"dataGaName":522,"dataGaLocation":465},"/fr-fr/solutions/agile-delivery/","agile delivery",{"text":524,"config":525},"Transformation cloud",{"href":526,"dataGaName":527,"dataGaLocation":465},"/fr-fr/topics/cloud-native/","cloud transformation",{"text":529,"config":530},"SCM",{"href":120,"dataGaName":531,"dataGaLocation":465},"source code management",{"text":111,"config":533},{"href":113,"dataGaName":534,"dataGaLocation":465},"continuous integration & delivery",{"text":162,"config":536},{"href":164,"dataGaName":537,"dataGaLocation":465},"value stream management",{"text":539,"config":540},"GitOps",{"href":541,"dataGaName":542,"dataGaLocation":465},"/fr-fr/solutions/gitops/","gitops",{"text":175,"config":544},{"href":177,"dataGaName":178,"dataGaLocation":465},{"text":180,"config":546},{"href":182,"dataGaName":183,"dataGaLocation":465},{"text":185,"config":548},{"href":187,"dataGaName":188,"dataGaLocation":465},{"text":550,"config":551},"Formation",{"href":552,"dataGaName":553,"dataGaLocation":465},"/fr-fr/solutions/education/","education",{"text":555,"config":556},"Services financiers",{"href":557,"dataGaName":558,"dataGaLocation":465},"/fr-fr/solutions/finance/","financial services",{"title":195,"links":560},[561,563,566,568,571,573,576,579,581,583,585,587,589],{"text":207,"config":562},{"href":209,"dataGaName":210,"dataGaLocation":465},{"text":564,"config":565},"Guides de démarrage rapide",{"href":214,"dataGaName":215,"dataGaLocation":465},{"text":217,"config":567},{"href":219,"dataGaName":220,"dataGaLocation":465},{"text":222,"config":569},{"href":224,"dataGaName":570,"dataGaLocation":465},"docs",{"text":245,"config":572},{"href":247,"dataGaName":248},{"text":574,"config":575},"Histoires de réussite client",{"href":242,"dataGaLocation":465},{"text":577,"config":578},"Histoires de succès client",{"href":242,"dataGaName":243,"dataGaLocation":465},{"text":250,"config":580},{"href":252,"dataGaName":253,"dataGaLocation":465},{"text":258,"config":582},{"href":260,"dataGaName":261,"dataGaLocation":465},{"text":263,"config":584},{"href":265,"dataGaName":266,"dataGaLocation":465},{"text":268,"config":586},{"href":270,"dataGaName":271,"dataGaLocation":465},{"text":273,"config":588},{"href":275,"dataGaName":276,"dataGaLocation":465},{"text":278,"config":590},{"href":280,"dataGaName":281,"dataGaLocation":465},{"title":296,"links":592},[593,595,598,600,602,604,606,610,615,617,619,621],{"text":303,"config":594},{"href":305,"dataGaName":298,"dataGaLocation":465},{"text":596,"config":597},"Emplois",{"href":310,"dataGaName":311,"dataGaLocation":465},{"text":316,"config":599},{"href":318,"dataGaName":319,"dataGaLocation":465},{"text":321,"config":601},{"href":323,"dataGaName":324,"dataGaLocation":465},{"text":326,"config":603},{"href":328,"dataGaName":329,"dataGaLocation":465},{"text":331,"config":605},{"href":333,"dataGaName":334,"dataGaLocation":465},{"text":607,"config":608},"Sustainability",{"href":609,"dataGaName":607,"dataGaLocation":465},"/sustainability/",{"text":611,"config":612},"Diversité, inclusion et appartenance (DIB)",{"href":613,"dataGaName":614,"dataGaLocation":465},"/fr-fr/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":336,"config":616},{"href":338,"dataGaName":339,"dataGaLocation":465},{"text":346,"config":618},{"href":348,"dataGaName":349,"dataGaLocation":465},{"text":351,"config":620},{"href":353,"dataGaName":354,"dataGaLocation":465},{"text":622,"config":623},"Déclaration de transparence sur l'esclavage moderne",{"href":624,"dataGaName":625,"dataGaLocation":465},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":356,"links":627},[628,631,636,638,643,648,653],{"text":629,"config":630},"Échanger avec un expert",{"href":57,"dataGaName":58,"dataGaLocation":465},{"text":632,"config":633},"Aide",{"href":634,"dataGaName":635,"dataGaLocation":465},"https://support.gitlab.com/hc/en-us/articles/11626483177756-GitLab-Support","get help",{"text":370,"config":637},{"href":372,"dataGaName":373,"dataGaLocation":465},{"text":639,"config":640},"Statut",{"href":641,"dataGaName":642,"dataGaLocation":465},"https://status.gitlab.com/","status",{"text":644,"config":645},"Conditions d'utilisation",{"href":646,"dataGaName":647},"/terms/","terms of use",{"text":649,"config":650},"Déclaration de confidentialité",{"href":651,"dataGaName":652,"dataGaLocation":465},"/fr-fr/privacy/","privacy statement",{"text":654,"config":655},"Préférences en matière de cookies",{"dataGaName":656,"dataGaLocation":465,"id":657,"isOneTrustButton":31},"cookie preferences","ot-sdk-btn",{"items":659},[660,662,665],{"text":644,"config":661},{"href":646,"dataGaName":647,"dataGaLocation":465},{"text":663,"config":664},"Politique de confidentialité",{"href":651,"dataGaName":652,"dataGaLocation":465},{"text":654,"config":666},{"dataGaName":656,"dataGaLocation":465,"id":657,"isOneTrustButton":31},[668],{"id":669,"title":18,"body":8,"config":670,"content":672,"description":8,"extension":29,"meta":676,"navigation":31,"path":677,"seo":678,"stem":679,"__hash__":680},"blogAuthors/en-us/blog/authors/michael-friedrich.yml",{"template":671},"BlogAuthor",{"name":18,"config":673},{"headshot":674,"ctfId":675},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659879/Blog/Author%20Headshots/dnsmichi-headshot.jpg","dnsmichi",{},"/en-us/blog/authors/michael-friedrich",{},"en-us/blog/authors/michael-friedrich","lJ-nfRIhdG49Arfrxdn1Vv4UppwD51BB13S3HwIswt4",[682,698,711],{"content":683,"config":696},{"title":684,"description":685,"authors":686,"body":689,"heroImage":690,"date":691,"category":9,"tags":692},"GitLab et Vertex AI sur Google Cloud : vers un développement logiciel agentique","Découvrez comment les clients Google Cloud adoptent GitLab et Vertex AI pour les modèles de base, les contrôles d'entreprise et la richesse de Model Garden.\n",[687,688],"Regnard Raquedan","Rajesh Agadi","GitLab Duo Agent Platform redéfinit la façon dont les organisations conçoivent, sécurisent et livrent leurs logiciels. Depuis sa disponibilité générale en janvier 2026, la plateforme intègre l'IA agentique à chaque phase du cycle de développement logiciel. GitLab Duo Agent Platform constitue une couche d'orchestration intelligente au sein de laquelle les équipes de développement et leurs agents spécialisés planifient, codent, révisent et corrigent ensemble les vulnérabilités de sécurité.\n\nGrâce à ce partenariat, [GitLab Duo Agent Platform](https://about.gitlab.com/fr-fr/gitlab-duo-agent-platform/) automatise l'orchestration du développement logiciel et la gestion du contexte du cycle de vie via son intégration à Vertex AI sur Google Cloud, qui alimente la couche de modèles pour les appels d'agents. Les équipes continuent de travailler sur les tickets, les merge requests, les pipelines et les workflows de sécurité, tandis que l'inférence suit la posture Google Cloud qu'elles ont déjà définie.\n\nLes avancées des modèles Vertex AI de Google Cloud élargissent les possibilités d'utilisation de GitLab Duo Agent Platform pour les clients Google Cloud. Ces derniers bénéficient d'un plan de contrôle [DevSecOps](https://about.gitlab.com/fr-fr/topics/devsecops/ \"Qu'est-ce que le DevSecOps ?\") alimenté par l'IA dans GitLab, soutenu par une infrastructure d'IA en constante évolution dans Vertex AI, ainsi que par les options de déploiement et d'intégration flexibles de GitLab Duo Agent Platform. Cette combinaison permet des workflows agentiques plus performants et mieux gouvernés à l'échelle de l'entreprise.\n\n![Illustration conceptuelle de GitLab Duo Agent Platform intégré à Vertex AI de Google Cloud pour alimenter le développement logiciel agentique et les workflows d'IA gouvernés](https://res.cloudinary.com/about-gitlab-com/image/upload/v1776165990/b7jlux9kydafncwy8spc.png)\n\n## Des agents qui interviennent tout au long du cycle de vie\n\nDe nombreux outils d'IA se concentrent sur une seule tâche : accélérer la [génération de code](https://about.gitlab.com/fr-fr/topics/devops/ai-code-generation-guide/ \"Génération de code\"). GitLab Duo Agent Platform va plus loin. La plateforme orchestre des agents d'IA sur l'ensemble du cycle de vie du développement logiciel (SDLC), de la planification à la livraison en passant par les contrôles de sécurité, et ce pour de nombreuses équipes travaillant sur de multiples projets et releases. À cette échelle, les assistants d'IA pour le code sont indispensables à l'innovation continue, mais ne suffisent pas à eux seuls.\n\nLes assistants de codage à usage unique ont rarement une vision complète de l'état d'un projet. Le backlog, les merge requests en attente, les jobs en échec et les résultats de sécurité sont disponibles dans GitLab, mais une fenêtre de chat distincte dans un assistant de codage n'hérite pas de cette vue d'ensemble du [SDLC](https://about.gitlab.com/fr-fr/blog/what-is-sdlc/ \"Qu'est-ce que le SDLC ?\"). Ce manque se traduit par des transferts manuels, des explications répétées à une IA dépourvue de contexte, et des équipes de gouvernance qui tentent de cartographier les flux de données entre des outils qui n'ont jamais été conçus comme un système unifié.\n\nGitLab Duo Agent Platform contribue à combler ce fossé en exécutant des agents et des flows sur les mêmes objets que ceux utilisés quotidiennement par les équipes d'ingénierie. Vertex AI fournit ensuite les modèles et services que ces agents sollicitent lorsque Google Cloud est votre environnement d'inférence de référence, la passerelle d'IA (AI-Gateway) de GitLab gérant les accès afin que les administrateurs disposent d'une cartographie claire des connexions. Par exemple, l'agent Planner analyse les backlogs, décompose les epics en tâches structurées et applique des frameworks de priorisation pour aider les équipes à décider de ce qu'elles doivent développer ensuite. L'agent Security Analyst trie les vulnérabilités, détaille les risques en langage clair et recommande des mesures correctives par ordre de priorité. Des flows intégrés connectent ces agents au sein de processus de bout en bout, sans que les équipes de développement aient à gérer chaque transfert manuellement.\n\nAgentic Chat dans GitLab Duo Agent Platform offre une expérience unifiée pour les équipes de développement. Elles formulent des requêtes en langage naturel pour obtenir des réponses contextuelles basées sur un raisonnement multi-étapes qui s'appuie sur l'état complet d'un projet : ses tickets, ses merge requests, ses pipelines, ses résultats de sécurité et son code source. GitLab servant de système d'enregistrement pour le SDLC avec un modèle de données unifié, les agents GitLab Duo opèrent dans un contexte de cycle de vie qui échappe aux assistants d'IA autonomes et spécifiques à un outil.\n\n### Amplifiés par Vertex AI\n\nGitLab Duo Agent Platform est conçue pour offrir une flexibilité en matière de modèles, car elle attribue différentes capacités à différents modèles en fonction de ceux qui offrent les meilleures performances pour une tâche donnée. Ce choix architectural porte ses fruits sur Google Cloud, où Vertex AI joue le rôle d'environnement géré pour les modèles de base et les services associés, et offre un vaste écosystème de modèles et une infrastructure gérée qui contribuent à repousser encore plus loin les capacités de la plateforme.\n\nLes dernières générations de modèles d'IA disponibles via Vertex AI apportent des améliorations significatives en matière de raisonnement, d'utilisation des outils et de compréhension des contextes longs par rapport aux versions précédentes. Des propriétés sur lesquelles s'appuient les agents de GitLab sur de nombreux projets et équipes qui disposent de codes sources volumineux et complexes. Des fenêtres de contexte plus longues et une intégration plus riche des outils dans les modèles sous-jacents élargissent ce que les agents peuvent accomplir en une seule action, ce qui est particulièrement important pour des charges de travail telles que l'analyse approfondie du backlog ou le contrôle de sécurité d'un monorepo.\n\n[Vertex AI Model Garden](https://cloud.google.com/model-garden), avec son accès à un large éventail de modèles de base, offre aux clients la flexibilité nécessaire pour effectuer ces choix en fonction des performances, des coûts et des exigences réglementaires, sans la contrainte d'un fournisseur unique.\n\nPar ailleurs, les clients de GitLab peuvent utiliser la fonctionnalité Bring Your Own Model (BYOM) pour GitLab Duo Agent Platform, afin que les fournisseurs et les passerelles approuvés s'intègrent là où votre modèle de sécurité l'exige. L'article [consacré à GitLab Duo Agent Platform Self-Hosted et BYOM](https://about.gitlab.com/fr-fr/blog/agentic-ai-enterprise-control-self-hosted-duo-agent-platform-and-byom/) décrit le fonctionnement de cette configuration. Grâce à cette option de déploiement, les clients accèdent à un plus large éventail d'options de modèles qu'ils peuvent adapter à leur processus de développement logiciel : le bon modèle pour le bon workflow, avec les bonnes mesures de protection.\n\nPour GitLab, la décision de s'appuyer sur Vertex AI a été motivée par le besoin d'une fiabilité de niveau entreprise et d'une gamme de modèles inégalée. Vertex AI et Model Garden prennent entièrement en charge les aspects les plus complexes de l'hébergement des [grands modèles de langage (LLM)](https://about.gitlab.com/fr-fr/blog/large-language-model/ \"Qu'est-ce qu'un LLM ?\"), ce qui signifie que la livraison rapide de versions, la robustesse de la sécurité et la rigueur de la gouvernance sont intégrées de façon transparente dans l'intégration. Au-delà de l'offre de modèles Gemini, Vertex AI offre un accès mondial à faible latence à un vaste catalogue de modèles tiers et [open source](https://about.gitlab.com/fr-fr/blog/what-is-open-source/ \"Qu'est-ce que l'open source ?\").\n\nCombiné à l'approche de pointe de Google Cloud en matière de confidentialité des données et de protection des modèles, Vertex AI s'est imposé comme le choix évident pour alimenter l'[expérience développeur](https://about.gitlab.com/fr-fr/topics/devops/what-is-developer-experience/ \"Expérience développeur\") nouvelle génération de GitLab.\n\nEn intégrant Vertex AI Model Garden à son backend, GitLab renforce considérablement sa plateforme [DevSecOps](https://about.gitlab.com/fr-fr/topics/devsecops/ \"Qu'est-ce que le DevSecOps ?\") sans en répercuter la complexité sur les utilisateurs. Les équipes de développement n'ont pas à évaluer ni à gérer les LLM sous-jacents ; elles bénéficient au contraire d'un workflow simplifié et assisté par l'IA pour construire leurs applications.\n\nGitLab gère entièrement l'orchestration cloud et permet aux équipes de développement de se concentrer pleinement sur l'écriture d'un code de qualité, tandis que Vertex AI alimente les fonctionnalités qui les accompagnent.\n\n## Ce que cela signifie pour les clients Google Cloud\n\nGitLab Duo Agent Platform fournit déjà des agents d'IA qui opèrent sur l'ensemble du cycle de vie logiciel au sein d'un système d'enregistrement unique et gouverné. Sur Google Cloud, la plateforme favorise une innovation rapide à mesure que Vertex AI continue de faire évoluer les couches de modèles et d'infrastructure.\n\nPour les clients Google Cloud, cette intégration se traduit par une livraison logicielle rationalisée avec une gouvernance d'entreprise stricte. Pour les équipes d'ingénierie de plateforme, cela signifie normaliser les modèles Vertex qui alimentent les suggestions, les analyses et les corrections dans GitLab, plutôt que de répertorier des dizaines d'outils côté client. Les programmes de sécurité en bénéficient lorsque les agents proposent et valident des correctifs au même endroit où les équipes trient déjà les résultats, ce qui réduit les changements de contexte et les tâches qui s'échapperaient autrement vers des canaux non gérés.\n\nDu point de vue de l'économie et des politiques cloud, orienter l'inférence des agents vers Vertex depuis GitLab maintient l'utilisation à proximité des accords et contrôles déjà en place sur Google Cloud, ce qui contribue à éviter les dépenses redondantes et les chemins parallèles qui contournent les processus d'approvisionnement.\n\nVertex AI étant un fournisseur d'infrastructure sous-jacente de GitLab Duo Agent Platform, les organisations peuvent considérablement accroître la productivité de leurs équipes de développement sans les contraintes et les risques liés à la gestion de chaînes d'outils d'IA fragmentées. Les équipes restent alignées au sein d'un système d'enregistrement unique et sécurisé, ce qui leur permet de construire des applications plus rapidement et de livrer en toute confiance.\n\nLa collaboration entre GitLab et Google Cloud se construit depuis 2018. Aujourd'hui, elle représente l'une des collaborations les plus complètes pour les organisations qui souhaitent passer d'expérimentations en matière d'IA à un développement logiciel agentique entièrement gouverné sur Google Cloud. À mesure que les deux plateformes continuent d'évoluer, GitLab en élargissant son orchestration d'agents et son contexte développeur, et Vertex AI en repoussant les limites des capacités des modèles et de l'infrastructure des agents, la valeur ajoutée pour les clients communs ne cessera de croître.\n\n> [Commencez un essai gratuit de GitLab Duo Agent Platform](https://about.gitlab.com/fr-fr/free-trial/?utm_medium=blog&utm_source=blog&utm_campaign=eg_emea_x_trial_x_fr_blog_fr) pour découvrir la puissance de GitLab et Vertex AI sur Google Cloud.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663121/Blog/Hero%20Images/LogoLockupPlusLight.png","2026-04-15",[27,281,693,694,695],"google","news","product",{"featured":31,"template":13,"slug":697},"gitlab-and-vertex-ai-on-google-cloud",{"content":699,"config":709},{"title":700,"description":701,"authors":702,"heroImage":704,"date":705,"body":706,"category":9,"tags":707},"Accélérez votre développement avec GitLab Duo Agent Platform et Claude","Découvrez comment tirer parti des modèles d'IA externes comme Claude d'Anthropic pour automatiser la génération de code et la création de pipelines directement dans GitLab.",[703],"Cesar Saavedra","https://res.cloudinary.com/about-gitlab-com/image/upload/v1772058602/epl3sinfezlzxnppxak6.png","2026-04-09","Les équipes de développement logiciel modernes sont confrontées à un défi majeur : comment maintenir la cadence de développement tout en garantissant la qualité du code, la sécurité et la cohérence dans le cadre de projets complexes ?\n\nBien que les assistants IA pour le code aient accéléré la productivité individuelle des équipes, ils fonctionnent souvent en marge du workflow de développement global. Ce manque d'intégration oblige les développeurs à basculer constamment entre différents outils, à traduire manuellement les suggestions de l'IA en code exploitable et à consacrer un temps précieux à des tâches répétitives qui pourraient être automatisées.\n\n[GitLab Duo Agent Platform](https://about.gitlab.com/fr-fr/gitlab-duo-agent-platform/) résout ce problème en offrant une intégration transparente avec des modèles d'IA externes comme Claude d'Anthropic, Codex d'OpenAI et bien d'autres encore.\n\nEn créant des agents externes au sein de GitLab Duo Agent Platform, les organisations peuvent personnaliser les capacités de l'IA selon leurs besoins, workflows et normes spécifiques, directement dans l'environnement GitLab qu'elles connaissent. Les agents comprennent le contexte de votre projet, respectent vos normes de code et peuvent accomplir de manière autonome des tâches complexes en plusieurs étapes, de l'idée initiale au code prêt pour la production.\n\nRegardez cette démonstration vidéo et suivez les étapes ci-dessous pour vous lancer :\n\n\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/BPmoVCeyWJA?si=50ktjKxPUNpicXve\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\n\n## Cas d'utilisation concrets\n\nVoici trois cas d'utilisation qui illustrent comment les agents externes transforment le cycle de vie du développement :\n\n### 1. De l'idée au code\n\nEn partant d'un projet vide et d'une description détaillée du ticket, l'agent externe (dans ce cas, Claude) prend en charge l'intégralité du développement de l'application. Le titre du ticket correspond à l'application souhaitée et la description énumère ses spécifications.\n\nL'agent lit le contexte (informations du projet, ressources associées, etc.), analyse les exigences détaillées dans le ticket, génère une application web Java full stack avec les composants d'interface utilisateur appropriés, implémente la logique métier avec les taux d'intérêt indiqués et crée une merge request comprenant l'ensemble du code prêt à être révisé.\n\nL'application générée inclut des classes Java backend, des fichiers HTML/CSS/JavaScript frontend et la configuration du build en fonction des spécifications du ticket d'origine. Les équipes peuvent ensuite tester l'application localement, vérifier les fonctionnalités et continuer à itérer avec l'agent par le biais d'une conversation en langage naturel.\n\n![Ticket détaillant les exigences de l'application](https://res.cloudinary.com/about-gitlab-com/image/upload/v1772058387/irzlmm0gukanjt7ryq9b.png \"Ticket détaillant les exigences de l'application\")\n\n\n\n![Prompt pour que l'agent externe crée une merge request avec implémentation de l'application](https://res.cloudinary.com/about-gitlab-com/image/upload/v1772058392/ajr6nquefob7lefdcxng.png \"Prompt pour que l'agent externe crée une merge request avec implémentation  de l'application\")\n\n\n\n\n![Implémentation terminée par l'agent externe](https://res.cloudinary.com/about-gitlab-com/image/upload/v1772058387/gbwwawybg9u4jzibuurw.png \"Implémentation terminée par l'agent externe\")\n\n\n\n![Nouvelle application créée par l'agent externe](https://res.cloudinary.com/about-gitlab-com/image/upload/v1772058387/rijlwchqo1zytp842bld.png \"Nouvelle application créée par l'agent externe\")\n\n\n\n![Build et exécution locale de l'application](https://res.cloudinary.com/about-gitlab-com/image/upload/v1772058386/aycpfxa0mdbfbxf2ydu3.png \"Build et exécution locale de l'application\")\n\n\n\n![Test local de l'application](https://res.cloudinary.com/about-gitlab-com/image/upload/v1772058388/rxlvwmzlx8vor92qhotl.png \"Test local de l'application\")\n\n### 2. Revue de code\n\nL'assurance qualité ne se limite pas à la génération de code. Dans le deuxième cas d'utilisation, le même agent externe effectue une revue de code complète de l'application qu'il a créée. En mentionnant l'agent dans un commentaire de la merge request, les équipes reçoivent une analyse détaillée comprenant les points forts du code, les problèmes critiques, les préoccupations de priorité moyenne, les améliorations mineures, les évaluations de sécurité, les notes de test, les métriques du code et les recommandations accompagnées d'un statut d'approbation. Ce processus de revue automatisée garantit la cohérence et détecte les problèmes potentiels avant qu'ils n'atteignent la production. Il permet aussi de libérer les développeurs expérimentés pour qu'ils se concentrent sur les décisions architecturales plutôt que sur les inspections routinières du code.\n\n\n![Demande de revue de code à l'agent externe](https://res.cloudinary.com/about-gitlab-com/image/upload/v1772058387/ri7x5qkx9bfnidfn8gx1.png \"Demande de revue de code à l'agent externe\")\n\n\n\n![Résultats de la revue de code par l'agent externe](https://res.cloudinary.com/about-gitlab-com/image/upload/v1772058392/trdamdekrnvkbnfz0twg.png \"Résultats de la revue de code par l'agent externe\")\n\n\n\n### 3. Création d'un pipeline pour construire une image de conteneur\n\nLe dernier cas d'utilisation se concentre sur une lacune courante : l'automatisation du déploiement. Lorsque la merge request ne dispose pas de [pipeline CI/CD](https://about.gitlab.com/fr-fr/topics/ci-cd/cicd-pipeline/ \"Qu'est-ce qu'un pipeline CI/CD ?\"), les équipes peuvent simplement demander à l'agent externe d'en créer un. L'agent génère une configuration de pipeline complète qui construit l'application, crée un Dockerfile au moyen d'images de base adaptées à la version Java du projet, construit une image [Docker](https://about.gitlab.com/fr-fr/blog/what-is-docker-comprehensive-guide/ \"Qu'est-ce que Docker ?\") et la déploie dans le registre de conteneurs intégré de GitLab. Le pipeline s'exécute automatiquement et suit les étapes de build, de création d'image Docker et de déploiement dans le registre sans configuration ni intervention manuelle.\n\n\n![Prompt pour que l'agent externe crée un pipeline et une image de conteneur](https://res.cloudinary.com/about-gitlab-com/image/upload/v1772058392/bwqipksewm1hejuycwqh.png \"Prompt pour que l'agent externe crée un pipeline et une image de conteneur\")\n\n\n\n![Nouveau pipeline et fichiers Dockerfile créés par l'agent externe](https://res.cloudinary.com/about-gitlab-com/image/upload/v1772058395/agyr8hhc1vax7aarsxoj.png \"Nouveau pipeline et fichiers Dockerfile créés par l'agent externe\")\n\n\n\n![Exécution réussie du pipeline venant d'être créé](https://res.cloudinary.com/about-gitlab-com/image/upload/v1772058395/cdm4mye5edkpemedpxts.png \"Exécution réussie du pipeline venant d'être créé\")\n\n\n\n![Image de conteneur créée suite à l'exécution du pipeline](https://res.cloudinary.com/about-gitlab-com/image/upload/v1772058395/bifx71xz9k7vedbo9xl3.png \"Image de conteneur créée suite à l'exécution du pipeline\")\n\n## Résumé\n\nAvec ses agents externes, GitLab Duo Agent Platform représente un changement fondamental dans la manière dont les organisations abordent le développement logiciel. En remédiant à l'isolation des outils d'IA et à la fragmentation des workflows, les agents externes offrent une automatisation intelligente directement dans les plateformes que les équipes utilisent déjà. Plutôt que de traiter l'IA comme un assistant de codage séparé, GitLab Duo Agent Platform intègre de manière transparente des modèles externes comme Claude dans votre workflow GitLab, pour que les agents puissent comprendre le contexte complet du projet, respecter les normes de l'organisation et gérer en toute autonomie des tâches complexes à chaque étape du [SDLC](https://about.gitlab.com/fr-fr/blog/what-is-sdlc/ \"Qu'est-ce que le SDLC ?\").\n\nLa proposition de valeur est claire : les équipes de développement accélèrent les délais de livraison, maintiennent une qualité de code cohérente, réduisent le travail répétitif et libèrent les ingénieurs expérimentés afin qu'ils se concentrent sur l'innovation plutôt que sur les tâches routinières. De la génération de code prêt pour la production basée sur des descriptions de tickets à la réalisation de revues de code approfondies et à l'automatisation des pipelines de déploiement, les agents externes deviennent des collaborateurs de confiance qui comprennent les besoins et normes spécifiques de votre organisation.\n\nDécouvrez comment votre équipe peut livrer plus rapidement et maintenir une qualité de code supérieure sans changer de contexte tout au long du cycle de vie du développement logiciel. Essayez [GitLab Duo Agent Platform](https://about.gitlab.com/fr-fr/gitlab-duo-agent-platform/?utm_medium=blog&utm_source=blog&utm_campaign=eg_emea_x_trial_x_fr_blog_fr) dès aujourd'hui. Ensuite, consultez notre article [« Démarrer avec GitLab Duo Agent Platform : le guide complet »](https://about.gitlab.com/fr-fr/blog/gitlab-duo-agent-platform-complete-getting-started-guide/).\n\n",[695,27,708],"features",{"featured":12,"template":13,"slug":710},"gitlab-duo-agent-platform-with-claude-accelerates-development",{"content":712,"config":724},{"date":713,"title":714,"description":715,"authors":716,"heroImage":719,"body":720,"category":9,"tags":721},"2026-04-01","Accélérer l'innovation dans la chaîne de développement logiciel avec GitLab Duo Agent Platform et AWS Bedrock","Enjeux actuels, vision de GitLab et cas d'usage concrets : découvrez comment une orchestration intelligente des agents d'IA peut transformer votre organisation.",[717,718],"Olivier Dupré","Charlotte Delbosc","https://res.cloudinary.com/about-gitlab-com/image/upload/f_auto,q_auto,c_lfill/v1751464636/htrk5th3q0tq1rcfntkp.png","Accélérer le développement logiciel grâce à l'intelligence artificielle, c'est la promesse que beaucoup d'entreprises cherchent à tenir. Mais entre la multiplication des outils, la multiplication des modèles et la pression croissante en matière de [sécurité et de conformité](https://about.gitlab.com/fr-fr/blog/meet-regulatory-standards-with-gitlab/ \"Sécurité et conformité\"), la réalité est souvent plus complexe qu'un simple gain de productivité sur l'écriture de code.\n\nComment passer d'une IA expérimentale et fragmentée à une IA véritablement industrialisée, gouvernée et intégrée à l'ensemble du cycle de développement logiciel ? C'est la question centrale à laquelle GitLab répond avec GitLab Duo Agent Platform, en offrant à ses clients toute la flexibilité dont ils ont besoin en termes d’hébergement des modèles, pour répondre à leurs contraintes opérationnelles.\n\nDécouvrez dans cet article comment l'orchestration intelligente des agents d'IA peut transformer l’ensemble du cycle de développement logiciel, à travers deux cas d’usage concrets avec AWS Bedrock comme backend LLM.\n\n> 🎯 Essayez [GitLab Duo Agent Platform](https://about.gitlab.com/fr-fr/gitlab-duo-agent-platform/?utm_medium=blog&utm_source=blog&utm_campaign=eg_emea_x_trial_x_fr_blog_fr) dès aujourd'hui !\n\n## L'IA en entreprise : de l'expérimentation à la gouvernance à grande échelle\n\nEn 2025, **près de 88 % des organisations utilisaient déjà l'IA dans au moins une fonction métier**, selon une enquête de McKinsey. Un chiffre qui illustre un basculement majeur : l'IA n'est plus un sujet d'expérimentation isolée. Elle est devenue un enjeu de production, de gouvernance et de gestion des risques à l'échelle de l'entreprise.\n\n![Enquête de McKinsey 2025](https://res.cloudinary.com/about-gitlab-com/image/upload/v1774026444/orfmpn658y49717y3n8f.png)\n\nSur les deux dernières années, l'utilisation de l'IA générative s’est intensifiée, entraînant dans son sillage une multiplication d'outils, de modèles et de preuves de concept. Une complexité croissante qui soulève une question de fond : qui utilise quel modèle, avec quelles données, et sous quel niveau de sécurité et de conformité ? Face à ce manque de visibilité, les entreprises réclament désormais davantage de traçabilité, de contrôle et de gouvernance sur leur utilisation de l’IA. \n\n## Le paradoxe de l'IA dans le développement logiciel\n\nDans la chaîne de développement logiciel, un paradoxe s'est installé : l'IA a certes accéléré la phase de codage, mais toutes les autres étapes du cycle de développement logiciel restent des goulots d'étranglement. Spécifications, revues de code, tests, sécurité, déploiements, surveillance… autant d'étapes qui n'ont pas encore pleinement profité des avantages de l’intelligence artificielle.\n\nC’est dans ce contexte que s'inscrit la stratégie de GitLab : passer d’une approche fragmentée de l’IA à une plateforme unifiée où le code, la sécurité et la conformité ainsi que l’IA coexistent au même endroit. \n\n## GitLab : de l’approche DevSecOps  à l’orchestration intelligente\n\nGitLab a transformé sa plateforme, d’une simple plateforme [CI/CD](https://about.gitlab.com/fr-fr/topics/ci-cd/ \"Qu'est-ce que le CI/CD ?\") pour gérer étape par étape le cycle de vie logiciel à une **plateforme d'orchestration intelligente** qui unifie à la fois le DevSecOps et l'IA.\n\nL'objectif n'est plus seulement d'automatiser chaque étape individuellement, mais de **permettre aux équipes d'orchestrer leurs agents d’IA** pour livrer des logiciels plus vite, de manière plus sécurisée, et avec une gouvernance renforcée depuis une plateforme unique.\n\n### Une intégration adaptée à vos besoins\n\nL'approche de GitLab s’adapte à vos contraintes existantes : \n\n* **Intégration à vos workflows existants** : projets, pipelines, outils.\n* **Exploitation de votre contexte métier** : les agents GitLab s'appuient sur votre code et votre contexte pour être immédiatement opérationnels sur vos applications.\n* **Respect de vos règles de sécurité et de conformité** : politiques d'accès, localisation des données.\n* **Maîtrise totale de votre infrastructure** : avec des modèles auto-gérés ou hébergés sur AWS, vous avez la possibilité d'utiliser les modèles de votre choix, tout en conservant vos données et votre contrôle. Et si vos contraintes l'exigent, vous pouvez également basculer sur AWS European Sovereign Cloud, voire fonctionner en environnement totalement isolé d'Internet.\n\nPour illustrer concrètement ces capacités, intéressons-nous aux deux cas d'usage suivants.\n\n## GitLab Duo Agent Platform et AWS Bedrock en pratique\n\nLes deux cas d'usage présentés ci-dessous s'appuient sur une instance GitLab déployée sur AWS, avec AWS Bedrock comme backend LLM. Les modèles ont été préalablement configurés dans GitLab pour alimenter les différentes fonctionnalités de GitLab Duo Agent Platform : suggestion de code, GitLab Duo Agentic Chat, explication de code, etc. \n\n### Cas d'usage 1 : utilisation de l’agent Security Analyst\n\nLes scans SAST et SCA sont essentiels, mais ils génèrent souvent un volume important de vulnérabilités, difficiles à classer, prioriser et traiter efficacement. C'est là qu'intervient l'agent Security Analyst de GitLab. Cet agent d’IA spécialisé joue le rôle d'un analyste sécurité augmenté : \n\n* Il se connecte aux résultats des scans de sécurité.\n* Il analyse les vulnérabilités et estime leurs niveaux de risque.\n* Il priorise les éléments critiques et propose des plans de remédiation.\n\nLes bénéfices sont mesurables : moins de bruit pour les développeurs, un gain de temps pour les équipes AppSec, et une réduction observable du volume de vulnérabilités en production.\n\nLa sécurité n'est pas le seul domaine où les agents d’IA font la différence. Le cas d'usage suivant montre comment cette même logique d'orchestration peut transformer le quotidien des équipes de développement avec l’aide de plusieurs agents spécialisés. \n\n### Cas d'usage 2 : de la user story à la merge request avec des agents d’IA\n\nTransformer une user story en code fonctionnel, accompagné de tests et d’une documentation, est un processus long et variable d'un développeur à l'autre. \n\nPour faciliter le travail des équipes, GitLab propose un **flow “Développeur” qui orchestre simultanément plusieurs agents d’IA** à partir d’un simple ticket :\n\n1. Un agent propose le **plan de développement** et **génère le code**.\n2. Un agent **effectue les tests**.\n3. Un agent **rédige et met à jour la documentation**.\n\nCe flow de bout en bout permet de gagner un temps précieux entre l’idée et le développement, tout en standardisant les pratiques et en garantissant la conformité avec les contraintes de l'entreprise.\n\n## L'IA comme levier industriel\n\nL'enjeu n'est pas d'avoir plus d'IA, mais de faire en sorte que **les équipes et les agents d’IA collaborent ensemble à l'échelle de l'entreprise**. Avec GitLab et son approche d’orchestration intelligente, les équipes DevSecOps alignent leurs workflows, leurs règles de sécurité et leurs modèles pour faire de l’IA un véritable avantage compétitif. \n\n> 🎯 Prêt à accélérer votre développement logiciel ? Essayez [GitLab Duo Agent Platform](https://about.gitlab.com/fr-fr/gitlab-duo-agent-platform/?utm_medium=blog&utm_source=blog&utm_campaign=eg_emea_x_trial_x_fr_blog_fr) dès aujourd'hui !\n\n### Ressources complémentaires\n\n* [GitLab Duo Agent Platform : le guide complet](https://about.gitlab.com/fr-fr/blog/gitlab-duo-agent-platform-complete-getting-started-guide/)\n* [Démarrer avec GitLab Duo Agent Platform](https://about.gitlab.com/fr-fr/blog/introduction-to-gitlab-duo-agent-platform/)\n* [Démarrer avec GitLab Duo Agentic Chat](https://about.gitlab.com/fr-fr/blog/getting-started-with-gitlab-duo-agentic-chat/)\n* [GitLab Duo Agent Platform : comprendre les agents](https://about.gitlab.com/fr-fr/blog/understanding-agents-foundational-custom-external/)\n* [Comprendre les flows : workflows multi-agents](https://about.gitlab.com/fr-fr/blog/understanding-flows-multi-agent-workflows/)\n* [Découvrir le catalogue d'IA : créer et partager des agents et des flows](https://about.gitlab.com/fr-fr/blog/ai-catalog-discover-and-share-agents/)\n* [Surveiller, gérer et automatiser les workflows d'IA](https://about.gitlab.com/fr-fr/blog/monitor-manage-automate-ai-workflows/) \n* [Intégrer le Model Context Protocol](https://about.gitlab.com/fr-fr/blog/duo-agent-platform-with-mcp/)\n* [Personnaliser GitLab Duo Agent Platform : règles, prompts et workflows](https://about.gitlab.com/fr-fr/blog/customizing-gitlab-duo-chat-rules-prompts-workflows/)",[722,27,723],"AWS","DevSecOps platform",{"featured":31,"template":13,"slug":725},"gitlab-duo-agent-platform-and-aws-bedrock",{"promotions":727},[728,741,752,764],{"id":729,"categories":730,"header":731,"text":732,"button":733,"image":738},"ai-modernization",[9],"Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":734,"config":735},"Get your AI maturity score",{"href":736,"dataGaName":737,"dataGaLocation":248},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":739},{"src":740},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":742,"categories":743,"header":744,"text":732,"button":745,"image":749},"devops-modernization",[695,39],"Are you just managing tools or shipping innovation?",{"text":746,"config":747},"Get your DevOps maturity score",{"href":748,"dataGaName":737,"dataGaLocation":248},"/assessments/devops-modernization-assessment/",{"config":750},{"src":751},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":753,"categories":754,"header":756,"text":732,"button":757,"image":761},"security-modernization",[755],"security","Are you trading speed for security?",{"text":758,"config":759},"Get your security maturity score",{"href":760,"dataGaName":737,"dataGaLocation":248},"/assessments/security-modernization-assessment/",{"config":762},{"src":763},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":765,"paths":766,"header":769,"text":770,"button":771,"image":776},"github-azure-migration",[767,768],"migration-from-azure-devops-to-gitlab","integrating-azure-devops-scm-and-gitlab","Is your team ready for GitHub's Azure move?","GitHub is already rebuilding around Azure. Find out what it means for you.",{"text":772,"config":773},"See how GitLab compares to GitHub",{"href":774,"dataGaName":775,"dataGaLocation":248},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":777},{"src":751},{"header":779,"blurb":780,"button":781,"secondaryButton":785},"Commencez à développer plus rapidement dès aujourd'hui","Découvrez ce que votre équipe peut accomplir avec la plateforme d'orchestration intelligente pour le DevSecOps.\n",{"text":50,"config":782},{"href":783,"dataGaName":53,"dataGaLocation":784},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/fr-fr/","feature",{"text":55,"config":786},{"href":57,"dataGaName":58,"dataGaLocation":784},1776447743066]