diff --git a/Dockerfile.business b/Dockerfile.business index 8c5e1bd..5c7c902 100644 --- a/Dockerfile.business +++ b/Dockerfile.business @@ -32,9 +32,11 @@ RUN npx techradar install && \ # --- CONFIGURATION BUSINESS --- # Application de la logique Business (remplacement de la config et des données) +# Préserver la structure de dossiers par date pour que le framework puisse parser les dates RUN cp radar-business/config-business.json config.json && \ rm -rf radar/* && \ - cp -r radar-business/2025-01-15/* radar/ + mkdir -p radar/2025-01-15 && \ + cp -r radar-business/2025-01-15/* radar/2025-01-15/ # Exposition du port interne EXPOSE 3000 diff --git a/scripts/verify-blips.js b/scripts/verify-blips.js new file mode 100755 index 0000000..4fd516c --- /dev/null +++ b/scripts/verify-blips.js @@ -0,0 +1,225 @@ +#!/usr/bin/env node + +/** + * Script pour vérifier le format des blips et corriger les problèmes + */ + +const fs = require('fs'); +const path = require('path'); + +const REQUIRED_FIELDS = ['title', 'ring', 'quadrant', 'tags']; +const VALID_RINGS = ['adopt', 'trial', 'assess', 'hold']; +const VALID_QUADRANTS = [ + 'technologies-differentiantes', + 'technologies-commodite', + 'technologies-risque', + 'technologies-emergentes' +]; + +function parseBlip(filePath) { + const content = fs.readFileSync(filePath, 'utf-8'); + const frontMatterMatch = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/); + + if (!frontMatterMatch) { + return { error: 'No front matter found', file: filePath }; + } + + const frontMatter = frontMatterMatch[1]; + const body = frontMatterMatch[2]; + + const metadata = {}; + for (const line of frontMatter.split('\n')) { + const match = line.match(/^(\w+):\s*(.+)$/); + if (match) { + const key = match[1]; + let value = match[2].trim(); + + // Parser les valeurs + if (value === 'true') value = true; + else if (value === 'false') value = false; + else if (!isNaN(value) && value !== '') value = Number(value); + else if (value.startsWith('[')) { + value = value.slice(1, -1).split(',').map(v => v.trim().replace(/['"]/g, '')); + } else if (value.startsWith('"') && value.endsWith('"')) { + value = value.slice(1, -1); + } + + metadata[key] = value; + } + } + + return { metadata, body, file: filePath }; +} + +function validateBlip(blip) { + const errors = []; + const warnings = []; + + if (blip.error) { + return { errors: [blip.error], warnings: [] }; + } + + // Vérifier les champs requis + for (const field of REQUIRED_FIELDS) { + if (!blip.metadata[field]) { + errors.push(`Missing required field: ${field}`); + } + } + + // Vérifier le format des valeurs + if (blip.metadata.ring && !VALID_RINGS.includes(blip.metadata.ring)) { + errors.push(`Invalid ring: ${blip.metadata.ring}. Valid values: ${VALID_RINGS.join(', ')}`); + } + + if (blip.metadata.quadrant && !VALID_QUADRANTS.includes(blip.metadata.quadrant)) { + errors.push(`Invalid quadrant: ${blip.metadata.quadrant}. Valid values: ${VALID_QUADRANTS.join(', ')}`); + } + + if (blip.metadata.tags) { + if (!Array.isArray(blip.metadata.tags)) { + errors.push(`Tags must be an array, got: ${typeof blip.metadata.tags}`); + } else if (blip.metadata.tags.length === 0) { + warnings.push('Tags array is empty'); + } + } + + if (!blip.metadata.title || blip.metadata.title.trim() === '') { + errors.push('Title is empty or missing'); + } + + return { errors, warnings }; +} + +function verifyAllBlips(radarDir) { + const files = fs.readdirSync(radarDir) + .filter(f => f.endsWith('.md')) + .map(f => path.join(radarDir, f)); + + const results = { + total: files.length, + valid: 0, + invalid: 0, + errors: [], + warnings: [] + }; + + console.log(`\nVérification de ${files.length} fichiers blips...\n`); + + for (const file of files) { + const blip = parseBlip(file); + const validation = validateBlip(blip); + const filename = path.basename(file); + + if (validation.errors.length > 0) { + results.invalid++; + results.errors.push({ + file: filename, + errors: validation.errors + }); + console.log(`❌ ${filename}`); + validation.errors.forEach(err => console.log(` - ${err}`)); + } else { + results.valid++; + if (validation.warnings.length > 0) { + results.warnings.push({ + file: filename, + warnings: validation.warnings + }); + console.log(`⚠️ ${filename} (warnings)`); + validation.warnings.forEach(warn => console.log(` - ${warn}`)); + } else { + console.log(`✅ ${filename}`); + } + } + } + + console.log(`\n📊 Résumé:`); + console.log(` ✅ Valides: ${results.valid}`); + console.log(` ❌ Invalides: ${results.invalid}`); + console.log(` ⚠️ Avertissements: ${results.warnings.length}`); + + if (results.errors.length > 0) { + console.log(`\n❌ Fichiers avec erreurs:`); + results.errors.forEach(({ file, errors }) => { + console.log(`\n ${file}:`); + errors.forEach(err => console.log(` - ${err}`)); + }); + } + + if (results.warnings.length > 0) { + console.log(`\n⚠️ Fichiers avec avertissements:`); + results.warnings.forEach(({ file, warnings }) => { + console.log(`\n ${file}:`); + warnings.forEach(warn => console.log(` - ${warn}`)); + }); + } + + return results; +} + +// Vérifier le format des dates des releases +function verifyReleaseDates() { + console.log('\n📅 Vérification des dates de release...\n'); + + const radarDir = path.join(__dirname, '../radar-business'); + const dirs = fs.readdirSync(radarDir, { withFileTypes: true }) + .filter(dirent => dirent.isDirectory()) + .map(dirent => dirent.name); + + const datePattern = /^\d{4}-\d{2}-\d{2}$/; + const errors = []; + + for (const dir of dirs) { + if (datePattern.test(dir)) { + const date = new Date(dir); + if (isNaN(date.getTime())) { + errors.push(`Invalid date format: ${dir} (cannot parse as date)`); + console.log(`❌ ${dir} - Date invalide`); + } else { + console.log(`✅ ${dir} - Date valide (${date.toLocaleDateString('fr-FR')})`); + } + } else { + errors.push(`Invalid date format: ${dir} (must be YYYY-MM-DD)`); + console.log(`❌ ${dir} - Format invalide (doit être YYYY-MM-DD)`); + } + } + + if (errors.length > 0) { + console.log(`\n❌ Erreurs de format de date:`); + errors.forEach(err => console.log(` - ${err}`)); + } + + return errors.length === 0; +} + +// Main +function main() { + const radarDir = path.join(__dirname, '../radar-business/2025-01-15'); + + if (!fs.existsSync(radarDir)) { + console.error(`Répertoire non trouvé: ${radarDir}`); + process.exit(1); + } + + // Vérifier les dates + const datesValid = verifyReleaseDates(); + + // Vérifier les blips + const results = verifyAllBlips(radarDir); + + // Résultat final + if (results.invalid > 0 || !datesValid) { + console.log('\n❌ Des erreurs ont été détectées. Veuillez les corriger.'); + process.exit(1); + } else { + console.log('\n✅ Tous les fichiers sont valides !'); + process.exit(0); + } +} + +if (require.main === module) { + main(); +} + +module.exports = { parseBlip, validateBlip, verifyAllBlips, verifyReleaseDates }; +