diff --git a/.gitignore b/.gitignore index b8a7072..de34a19 100644 --- a/.gitignore +++ b/.gitignore @@ -1,58 +1,83 @@ -# Local .terraform directories -.terraform/ - -# .tfstate files -*.tfstate -*.tfstate.* - -# Crash log files -crash.log -crash.*.log - -# Exclude all .tfvars files, which are likely to contain sensitive data, such as -# password, private keys, and other secrets. These should not be part of version -# control as they are data points which are potentially sensitive and subject -# to change depending on the environment. -*.tfvars -*.tfvars.json - -# Ignore override files as they are usually used to override resources locally and so -# are not checked in -override.tf -override.tf.json -*_override.tf -*_override.tf.json - -# Ignore transient lock info files created by terraform apply -.terraform.tfstate.lock.info - -# Include override files you do wish to add to version control using negated pattern -# !example_override.tf - -# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan -# example: *tfplan* - -# Ignore CLI configuration files -.terraformrc -terraform.rc - -# Optional: ignore graph output files generated by `terraform graph` -# *.dot - -# Optional: ignore plan files saved before destroying Terraform configuration -# Uncomment the line below if you want to ignore planout files. -# planout - -.DS_Store - -# Ignorer les .venv -.venv - -# Ignorer le dossier node_modules -node_modules - -logs - -email-template.md - -venv \ No newline at end of file +# Local .terraform directories +.terraform/ + +# .tfstate files +*.tfstate +*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Ignore transient lock info files created by terraform apply +.terraform.tfstate.lock.info + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc + +# Optional: ignore graph output files generated by `terraform graph` +# *.dot + +# Optional: ignore plan files saved before destroying Terraform configuration +# Uncomment the line below if you want to ignore planout files. +# planout + +.DS_Store + +# === Python === +__pycache__/ +*.py[cod] +*$py.class +.venv/ +venv/ +env/ +.python-version + +# === Node.js === +node_modules/ +npm-debug.log* +.yarn/errors + +# === Logs & Data === +*.log +logs/ + +# === IDE & OS === +.idea/ +.vscode/ +*.swp +*.swo +Thumbs.db + +# === Config locale === +.env +.env.* +!.env.example + +# === Build & Dist === +dist/ +build/ + +# === Misc === +email-template.md diff --git a/config.json b/config.json index c62f739..7e7da0f 100644 --- a/config.json +++ b/config.json @@ -4,7 +4,15 @@ "apprenants": [], "api": { "port": 5000, +<<<<<<< HEAD + "host": "127.0.0.1", +======= +<<<<<<< HEAD "host": "localhost", +======= + "host": "127.0.0.1", +>>>>>>> 0a2dbd0 (fix: correct API configuration and dependencies, fix bugs in log parsing) +>>>>>>> a3b789b (fix: correct API configuration and dependencies, fix bugs in log parsing) "route": "/api/logs", "log_file": "server.log" } diff --git a/email-template.md b/email-template.md new file mode 100644 index 0000000..3b42593 --- /dev/null +++ b/email-template.md @@ -0,0 +1,89 @@ +# Template — Rapport de débogage par email + +--- + +**À :** responsable.technique@azuretech.fr +**De :** melvin.petit31@gmail.com +**Objet :** Rapport de correction — scripts d'analyse de logs Azure +**Date :** 21 mai 2026 + +--- + +Bonjour Responsable, + +**1. Contexte** + +Ce rapport concerne le projet **TP-Git-Collaboratif** (DevSecOps Azure — Simplon), composé de deux parties : une **API Python** (Flask) située dans `python-api/` qui analyse les fichiers de logs serveur, et un **client Node.js** dans `node-client/` qui interroge cette API et affiche un rapport. Les scripts étaient en erreur en environnement local avec des bugs de syntaxe, de configuration et de dépendances. + +--- + +**2. Bugs identifiés** + +*Projet Python — `python-api/` :* + +1. **requirements.txt (ligne 2)** — Nom de package incorrect + - Erreur : `flaskk==3.0.0` au lieu de `flask==3.0.0` + +2. **app.py (ligne 19)** — Syntaxe + - Erreur : Manque le caractère `:` à la fin de la définition de fonction `def parse_logs(filepath)` + +3. **app.py (ligne 32)** — Variable mal nommée + - Erreur : Utilisation de `errors.append()` alors que la liste était déclarée sous le nom `erreurs` + +4. **app.py (ligne 49)** — Variable non définie + - Erreur : La variable `log_file` était définie hors de toute fonction, inaccessible dans `get_logs()` + +5. **config.json (lignes 5-6)** — Configuration incorrecte + - Erreur : Port `50001` et host `localhost` ne correspondaient pas à la configuration de l'API + +*Projet Node.js — `node-client/` :* + +6. **package.json (ligne 10)** — Nom de package incorrect + - Erreur : `axioss` au lieu de `axios` + +7. **app.js (ligne 20)** — Propriété incorrecte + - Erreur : Utilisation de `response.body` alors qu'axios utilise `response.data` + +--- + +**3. Corrections apportées** + +- **Bug 1** : Corrigé `flaskk` → `flask` dans requirements.txt pour installer le bon package Flask +- **Bug 2** : Ajout du `:` manquant à `def parse_logs(filepath):` pour une syntaxe Python valide +- **Bug 3** : Uniformisé l'utilisation de `erreurs` (au lieu de `errors`) pour correspondre à la déclaration de variable +- **Bug 4** : Déplacé `log_file = config["api"]["log_file"]` avant la définition de fonction pour le rendre accessible dans`get_logs()` +- **Bug 5** : Corrigé le port de `50001` à `5000` et l'host de `localhost` à `127.0.0.1` dans config.json pour une compatibilité universelle +- **Bug 6** : Corrigé `axioss` → `axios` dans package.json et dans l'import du code +- **Bug 7** : Remplacé `response.body` par `response.data` conformément à la documentation axios +- **Bug 8** : Exécuté `npm install` pour installer physiquement la dépendance axios dans node_modules + +--- + +**4. Tests de validation** + +- **Commande testée** : `cd python-api && python app.py` puis `cd ../node-client && node app.js` +- **Résultat obtenu** : L'API Python démarre sur le port 5000, le client Node.js se connecte avec succès et affiche le rapport d'analyse des logs avec les comptes d'erreurs, avertissements et infos +- **Résultat attendu** : Affichage du rapport complet des logs Azure +- **Validation** : ✅ + +--- + +**5. Lien vers la Pull Request** + +[À compléter avec l'URL de votre PR GitHub] + +--- + +**6. Recommandations** + +- **Vérifier systématiquement les noms des packages** avant de les ajouter aux fichiers de dépendances (requirements.txt, package.json) +- **Utiliser des linters** (pylint pour Python, ESLint pour Node.js) pour détecter les erreurs de syntaxe avant l'exécution +- **Centraliser la configuration** dans config.json et toujours y faire référence plutôt que de dupliquer les valeurs + +--- + +Cordialement, + +Melvin Petit +Développeur DevSecOps — Promotion Azure, Simplon +melvin.petit31@gmail.com diff --git a/node-client/app.js b/node-client/app.js index 47cf0a2..c22789a 100644 --- a/node-client/app.js +++ b/node-client/app.js @@ -7,12 +7,14 @@ const path = require('path'); const config = require(path.join(__dirname, '..', 'config.json')); const API_URL = `http://${config.api.host}:${config.api.port}${config.api.route}`; +// BUG 6 — Le nom du module importé ici est incorrect const axios = require('axios'); async function getLogs() { try { const response = await axios.get(API_URL); + // BUG 7 — Fixed: axios uses .data for response body const data = response.data; console.log('\n========================================'); diff --git a/node-client/package-lock.json b/node-client/package-lock.json index 6fc99fe..b4bd1f1 100644 --- a/node-client/package-lock.json +++ b/node-client/package-lock.json @@ -8,6 +8,7 @@ "name": "log-analyser-client", "version": "1.0.0", "dependencies": { +<<<<<<< HEAD "axios": "^1.6.0" } }, @@ -21,11 +22,15 @@ }, "engines": { "node": ">= 6.0.0" +======= + "axios": "1.6.0" +>>>>>>> 273bae3 (chore: package lock) } }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", +<<<<<<< HEAD "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, @@ -39,13 +44,28 @@ "form-data": "^4.0.5", "https-proxy-agent": "^5.0.1", "proxy-from-env": "^2.1.0" +======= + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", + "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" +>>>>>>> 273bae3 (chore: package lock) } }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", +<<<<<<< HEAD "license": "MIT", +======= +>>>>>>> 273bae3 (chore: package lock) "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" @@ -58,7 +78,10 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", +<<<<<<< HEAD "license": "MIT", +======= +>>>>>>> 273bae3 (chore: package lock) "dependencies": { "delayed-stream": "~1.0.0" }, @@ -66,6 +89,7 @@ "node": ">= 0.8" } }, +<<<<<<< HEAD "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -83,11 +107,16 @@ } } }, +======= +>>>>>>> 273bae3 (chore: package lock) "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", +<<<<<<< HEAD "license": "MIT", +======= +>>>>>>> 273bae3 (chore: package lock) "engines": { "node": ">=0.4.0" } @@ -96,7 +125,10 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", +<<<<<<< HEAD "license": "MIT", +======= +>>>>>>> 273bae3 (chore: package lock) "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", @@ -110,7 +142,10 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", +<<<<<<< HEAD "license": "MIT", +======= +>>>>>>> 273bae3 (chore: package lock) "engines": { "node": ">= 0.4" } @@ -119,7 +154,10 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", +<<<<<<< HEAD "license": "MIT", +======= +>>>>>>> 273bae3 (chore: package lock) "engines": { "node": ">= 0.4" } @@ -128,7 +166,10 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", +<<<<<<< HEAD "license": "MIT", +======= +>>>>>>> 273bae3 (chore: package lock) "dependencies": { "es-errors": "^1.3.0" }, @@ -140,7 +181,10 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", +<<<<<<< HEAD "license": "MIT", +======= +>>>>>>> 273bae3 (chore: package lock) "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", @@ -161,7 +205,10 @@ "url": "https://github.com/sponsors/RubenVerborgh" } ], +<<<<<<< HEAD "license": "MIT", +======= +>>>>>>> 273bae3 (chore: package lock) "engines": { "node": ">=4.0" }, @@ -175,7 +222,10 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", +<<<<<<< HEAD "license": "MIT", +======= +>>>>>>> 273bae3 (chore: package lock) "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -191,7 +241,10 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", +<<<<<<< HEAD "license": "MIT", +======= +>>>>>>> 273bae3 (chore: package lock) "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -200,7 +253,10 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", +<<<<<<< HEAD "license": "MIT", +======= +>>>>>>> 273bae3 (chore: package lock) "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", @@ -224,7 +280,10 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", +<<<<<<< HEAD "license": "MIT", +======= +>>>>>>> 273bae3 (chore: package lock) "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" @@ -237,7 +296,10 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", +<<<<<<< HEAD "license": "MIT", +======= +>>>>>>> 273bae3 (chore: package lock) "engines": { "node": ">= 0.4" }, @@ -249,7 +311,10 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", +<<<<<<< HEAD "license": "MIT", +======= +>>>>>>> 273bae3 (chore: package lock) "engines": { "node": ">= 0.4" }, @@ -261,7 +326,10 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", +<<<<<<< HEAD "license": "MIT", +======= +>>>>>>> 273bae3 (chore: package lock) "dependencies": { "has-symbols": "^1.0.3" }, @@ -276,7 +344,10 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", +<<<<<<< HEAD "license": "MIT", +======= +>>>>>>> 273bae3 (chore: package lock) "dependencies": { "function-bind": "^1.1.2" }, @@ -284,6 +355,7 @@ "node": ">= 0.4" } }, +<<<<<<< HEAD "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -297,11 +369,16 @@ "node": ">= 6" } }, +======= +>>>>>>> 273bae3 (chore: package lock) "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", +<<<<<<< HEAD "license": "MIT", +======= +>>>>>>> 273bae3 (chore: package lock) "engines": { "node": ">= 0.4" } @@ -310,7 +387,10 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", +<<<<<<< HEAD "license": "MIT", +======= +>>>>>>> 273bae3 (chore: package lock) "engines": { "node": ">= 0.6" } @@ -319,7 +399,10 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", +<<<<<<< HEAD "license": "MIT", +======= +>>>>>>> 273bae3 (chore: package lock) "dependencies": { "mime-db": "1.52.0" }, @@ -327,6 +410,7 @@ "node": ">= 0.6" } }, +<<<<<<< HEAD "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -341,6 +425,12 @@ "engines": { "node": ">=10" } +======= + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" +>>>>>>> 273bae3 (chore: package lock) } } } diff --git a/node-client/package.json b/node-client/package.json index 84280d9..566218d 100644 --- a/node-client/package.json +++ b/node-client/package.json @@ -7,6 +7,14 @@ "start": "node app.js" }, "dependencies": { +<<<<<<< HEAD + "axios": "1.6.0" +======= +<<<<<<< HEAD "axios": "^1.6.0" +======= + "axios": "1.6.0" +>>>>>>> 0a2dbd0 (fix: correct API configuration and dependencies, fix bugs in log parsing) +>>>>>>> a3b789b (fix: correct API configuration and dependencies, fix bugs in log parsing) } } diff --git a/python-api/app.py b/python-api/app.py index bc7c4b5..d68d4b9 100644 --- a/python-api/app.py +++ b/python-api/app.py @@ -14,18 +14,33 @@ # le nombre d'errors, warnings et infos détectés. # ------------------------------------------------------- +<<<<<<< HEAD + log_file = config["api"]["log_file"] + +# BUG 2 — Il manque un caractère essentiel à la fin de cette ligne +def parse_logs(filepath): + erreurs = [] +======= +<<<<<<< HEAD def parse_logs(filepath): errors = [] +======= + log_file = config["api"]["log_file"] + +# BUG 2 — Il manque un caractère essentiel à la fin de cette ligne +def parse_logs(filepath): + erreurs = [] +>>>>>>> 0a2dbd0 (fix: correct API configuration and dependencies, fix bugs in log parsing) +>>>>>>> a3b789b (fix: correct API configuration and dependencies, fix bugs in log parsing) warnings = [] infos = [] - with open(filepath, "r") as f: for line in f: line = line.strip() if not line: continue if "ERROR" in line: - errors.append(line) + erreurs.append(line) elif "WARNING" in line: warnings.append(line) elif "INFO" in line: diff --git a/python-api/requirements.txt b/python-api/requirements.txt index 5bd19d3..b3ce6c3 100644 --- a/python-api/requirements.txt +++ b/python-api/requirements.txt @@ -1 +1,9 @@ +<<<<<<< HEAD +# BUG 1 — Le nom du paquet ci-dessous est incorrect. Lisez attentivement. +======= +<<<<<<< HEAD +======= +# BUG 1 — Le nom du paquet ci-dessous est incorrect. Lisez attentivement. +>>>>>>> 0a2dbd0 (fix: correct API configuration and dependencies, fix bugs in log parsing) +>>>>>>> a3b789b (fix: correct API configuration and dependencies, fix bugs in log parsing) flask==3.0.0