homelab_automation/documentation/ANSIBLE_EDITOR_DESIGN.md
Bruno Charest 05087aa380
Some checks failed
Tests / Backend Tests (Python) (3.10) (push) Has been cancelled
Tests / Backend Tests (Python) (3.11) (push) Has been cancelled
Tests / Backend Tests (Python) (3.12) (push) Has been cancelled
Tests / Frontend Tests (JS) (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / All Tests Passed (push) Has been cancelled
Replace manual upsert logic with SQLite native upsert in Docker CRUD repositories, enhance Ansible backup playbook with better error handling and file permissions, add favicon endpoint, and improve playbook editor UI with syntax highlighting, lint integration, quality badges, and enhanced code editing features
2025-12-17 15:36:49 -05:00

444 lines
16 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 🎯 Ansible Playbook Editor - Design & Architecture
## Résumé Exécutif
Refonte complète de l'éditeur de playbooks Ansible pour offrir une **expérience IDE-like** avec:
- Éditeur CodeMirror 6 avec coloration syntaxique Ansible/YAML avancée
- Intégration ansible-lint non-bloquante avec feedback temps réel
- Score de qualité et historique par playbook
- UX professionnelle inspirée de VS Code/GitHub Actions
---
## 1. Vision UX Globale
### Philosophie Design
- **Clarté avant tout**: Interface sobre, focalisée sur le code
- **Feedback intelligent**: Guidage proactif sans interruption du flux
- **Progressive disclosure**: Complexité révélée au bon moment
- **Performance**: Réactivité < 100ms pour les interactions
### Principes UX
| Principe | Application |
|----------|-------------|
| **Non-bloquant** | Lint en arrière-plan, édition jamais interrompue |
| **Contextuel** | Erreurs affichées à leur emplacement exact |
| **Actionnable** | Chaque diagnostic propose une correction |
| **Discret** | Pas de popup intrusif, indicateurs subtils |
---
## 2. Design de l'Éditeur
### 2.1 Architecture de l'Éditeur
```
┌─────────────────────────────────────────────────────────────────┐
│ 📄 playbook-name.yml [Quality: 92/100 ✓] │
├─────────────────────────────────────────────────────────────────┤
│ ┌──────┬────────────────────────────────────────────────────┐ │
│ │ LINT │ ERRORS (2) WARNINGS (3) INFO (1) │ │
│ ├──────┴────────────────────────────────────────────────────┤ │
│ │ │ │
│ │ [Gutter] [Code Editor Area] │ │
│ │ ⚠ 1 --- │ │
│ │ 2 - name: Deploy application │ │
│ │ 3 hosts: all │ │
│ │ ⛔ 4 become: yes │ │
│ │ ╭──────────────────────────────────────────╮ │ │
│ │ │ ⛔ risky-file-permissions: Missing mode │ │ │
│ │ │ for file operation │ │ │
│ │ │ 📖 Learn more | ✨ Auto-fix │ │ │
│ │ ╰──────────────────────────────────────────╯ │ │
│ │ 5 vars: │ │
│ │ 6 category: deploy │ │
│ │ │ │
│ └────────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ [✓ YAML Valid] [⚠ 5 issues] [Ln 4, Col 5] [Annuler] [Save] │
└─────────────────────────────────────────────────────────────────┘
```
### 2.2 Coloration Syntaxique Ansible
#### Tokens à highlighter
| Type | Exemples | Couleur (thème sombre) |
|------|----------|------------------------|
| **Clés Ansible** | `hosts`, `tasks`, `vars`, `handlers`, `become` | `#c792ea` (violet) |
| **Modules** | `ansible.builtin.copy`, `community.docker.docker_container` | `#82aaff` (bleu) |
| **Variables Jinja** | `{{ var }}`, `{% if %}` | `#c3e88d` (vert) |
| **Valeurs booléennes** | `true`, `false`, `yes`, `no` | `#f78c6c` (orange) |
| **Commentaires** | `# comment` | `#546e7a` (gris) |
| **Strings** | `"text"`, `'text'` | `#c3e88d` (vert clair) |
| **Nombres** | `123`, `0.5` | `#f78c6c` (orange) |
| **Ancres YAML** | `&anchor`, `*reference` | `#89ddff` (cyan) |
### 2.3 Fonctionnalités Éditeur
1. **Auto-indentation YAML** (2 espaces)
2. **Bracket matching** pour `{{ }}`, `{% %}`, `[]`, `{}`
3. **Fold/Unfold** des blocs YAML
4. **Minimap** optionnelle
5. **Search & Replace** avec regex
6. **Multi-curseur**
---
## 3. Intégration ansible-lint
### 3.1 Bouton Lint Intelligent
#### États visuels
```
┌─────────────────────────────────────────────────────────────┐
│ État │ Icône │ Couleur │ Animation │
├─────────────┼───────────┼────────────┼────────────────────┤
│ Idle │ 🔍 │ Gris │ Aucune │
│ Running │ ⟳ │ Bleu │ Rotation │
│ Success │ ✓ │ Vert │ Pulse subtil │
│ Warnings │ ⚠ (3) │ Jaune │ Aucune │
│ Errors │ ⛔ (2) │ Rouge │ Aucune │
└─────────────────────────────────────────────────────────────┘
```
### 3.2 Affichage des Résultats
#### Gutter Markers
- Icône colorée dans la marge gauche à la ligne concernée
- Survol = tooltip avec résumé
- Clic = panneau détaillé
#### Inline Diagnostics
```yaml
- name: Copy config
ansible.builtin.copy:
src: config.yml
dest: /etc/app/config.yml
# ⛔ risky-file-permissions: File permissions unset or incorrect
# 💡 Ajouter: mode: '0644'
```
#### Panneau Problèmes (optionnel)
Liste scrollable de tous les problèmes, filtrable par sévérité.
### 3.3 Workflow Utilisateur
```
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Ouvrir │────▶│ Éditer │────▶│ Lint │
│ playbook │ │ contenu │ │ (auto/btn) │
└──────────────┘ └──────────────┘ └──────┬───────┘
┌────────────────────────────────────────┤
▼ ▼
┌──────────────┐ ┌──────────────┐
│ Afficher │ │ Sauvegarder │
│ résultats │ │ (possible) │
└──────────────┘ └──────┬───────┘
┌──────────────┐
│ Exécuter │
│ (bloqué si │
│ erreurs*) │
└──────────────┘
* Configurable
```
### 3.4 Comportement Non-Bloquant
| Action | Lint bloque ? | Sauvegarde bloque ? | Exécution bloque ? |
|--------|---------------|---------------------|-------------------|
| Lint en cours | | | |
| Warnings | | | |
| Errors | | | Avertissement |
---
## 4. Architecture Technique
### 4.1 Backend - API ansible-lint
#### Endpoint
```
POST /api/playbooks/{filename}/lint
```
#### Request
```json
{
"content": "---\n- name: My playbook\n hosts: all\n...",
"rules": ["yaml", "risky-file-permissions"], // optionnel
"skip_rules": ["no-changed-when"] // optionnel
}
```
#### Response
```json
{
"success": true,
"execution_time_ms": 342,
"summary": {
"total": 5,
"errors": 2,
"warnings": 2,
"info": 1
},
"quality_score": 72,
"issues": [
{
"rule_id": "risky-file-permissions",
"severity": "error",
"message": "File permissions unset or incorrect",
"filename": "playbook.yml",
"line": 12,
"column": 5,
"context": " ansible.builtin.copy:",
"help_url": "https://ansible-lint.readthedocs.io/rules/risky-file-permissions/",
"fix_suggestion": "Add 'mode: \"0644\"' parameter"
}
]
}
```
#### Implémentation Backend
```python
# app/routes/lint.py
import asyncio
import json
import tempfile
from pathlib import Path
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
router = APIRouter()
class LintRequest(BaseModel):
content: str
rules: list[str] | None = None
skip_rules: list[str] | None = None
class LintIssue(BaseModel):
rule_id: str
severity: str # error, warning, info
message: str
line: int
column: int
context: str | None = None
help_url: str | None = None
fix_suggestion: str | None = None
class LintResponse(BaseModel):
success: bool
execution_time_ms: int
summary: dict
quality_score: int
issues: list[LintIssue]
@router.post("/{filename}/lint")
async def lint_playbook(filename: str, request: LintRequest):
"""Exécute ansible-lint sur le contenu d'un playbook."""
start_time = asyncio.get_event_loop().time()
# Créer fichier temporaire
with tempfile.NamedTemporaryFile(
mode='w', suffix='.yml', delete=False
) as f:
f.write(request.content)
temp_path = f.name
try:
# Construire commande ansible-lint
cmd = [
'ansible-lint',
'--format', 'json',
'--nocolor',
temp_path
]
if request.skip_rules:
for rule in request.skip_rules:
cmd.extend(['--skip-list', rule])
# Exécuter
process = await asyncio.create_subprocess_exec(
*cmd,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE
)
stdout, stderr = await process.communicate()
# Parser JSON
issues = parse_ansible_lint_output(stdout.decode(), temp_path, filename)
# Calculer score
score = calculate_quality_score(issues, len(request.content.split('\n')))
execution_time = int((asyncio.get_event_loop().time() - start_time) * 1000)
return LintResponse(
success=True,
execution_time_ms=execution_time,
summary={
"total": len(issues),
"errors": sum(1 for i in issues if i.severity == "error"),
"warnings": sum(1 for i in issues if i.severity == "warning"),
"info": sum(1 for i in issues if i.severity == "info")
},
quality_score=score,
issues=issues
)
finally:
Path(temp_path).unlink(missing_ok=True)
```
### 4.2 Frontend - Composants
#### Structure des composants
```
PlaybookEditor/
├── EditorContainer # Container principal
├── CodeMirrorEditor # Instance CodeMirror 6
├── LintButton # Bouton avec états
├── LintResultsPanel # Panneau latéral/bas
├── GutterMarkers # Marqueurs dans la marge
├── InlineDiagnostics # Diagnostics inline
├── QualityBadge # Score de qualité
└── StatusBar # Barre de statut
```
#### Gestion d'état
```javascript
const editorState = {
// Contenu
content: '',
originalContent: '',
isDirty: false,
// Lint
lintStatus: 'idle', // idle | running | success | warnings | errors
lintResults: null,
lastLintTime: null,
// Qualité
qualityScore: null,
// UI
showProblemsPanel: false,
activeIssueIndex: null,
// Config
lintOnSave: true,
blockExecutionOnErrors: true
};
```
#### Stratégie de Performance
1. **Debounce**: Lint auto après 1500ms d'inactivité
2. **Abort Controller**: Annuler lint précédent si nouvelle édition
3. **Virtual Scrolling**: Pour longs playbooks (>1000 lignes)
4. **Web Worker**: Parser YAML en background (optionnel)
---
## 5. Idées Bonus à Forte Valeur
### 5.1 📊 Quality Score Dashboard
Score 0-100 basé sur:
- Nombre d'erreurs (-20 pts/erreur)
- Nombre de warnings (-5 pts/warning)
- Bonnes pratiques suivies (+5 pts)
- Historique (trend: amélioration ou dégradation)
```
┌────────────────────────────────────────┐
│ Quality Score: 87/100 ↑ +5 │
│ ████████████████████░░░░ │
│ │
│ ✓ No deprecated modules │
│ ✓ FQCN used consistently │
│ ⚠ 2 missing task names │
│ ⚠ 1 risky permission │
└────────────────────────────────────────┘
```
### 5.2 🔧 Auto-Fix Suggestions
Pour certaines règles, proposer des corrections automatiques:
- `no-free-form`: Convertir en syntaxe structurée
- `risky-file-permissions`: Ajouter `mode: '0644'`
- `fqcn`: Convertir `copy``ansible.builtin.copy`
- `yaml[truthy]`: Convertir `yes``true`
### 5.3 📈 Lint History par Playbook
Stocker l'historique des scores pour chaque playbook:
```json
{
"playbook": "deploy-app.yml",
"history": [
{"date": "2025-01-15", "score": 65, "errors": 3, "warnings": 5},
{"date": "2025-01-16", "score": 78, "errors": 1, "warnings": 3},
{"date": "2025-01-17", "score": 92, "errors": 0, "warnings": 1}
]
}
```
### 5.4 💡 Assistant Bonnes Pratiques
Suggestions proactives basées sur le contexte:
- "Cette tâche modifie des fichiers. Ajoutez un handler notify."
- "Utilisez become_user au lieu de become pour plus de sécurité."
- "Préférez ansible.builtin.command à shell pour les commandes simples."
### 5.5 🔄 Pré-validation Commit
Hook optionnel pour valider avant git commit (documentation fournie).
---
## 6. Plan d'Implémentation
### Phase 1: Backend Lint API ✅
- [x] Endpoint `/api/playbooks/{filename}/lint`
- [x] Parsing JSON ansible-lint
- [x] Calcul quality score
- [x] Suggestions de correction par règle
- [x] URLs de documentation
### Phase 2: Éditeur CodeMirror 6 ✅
- [x] Intégration CDN CodeMirror 6 (avec fallback textarea)
- [x] Configuration YAML + thème personnalisé
- [x] Coloration Ansible avancée
### Phase 3: UI ansible-lint ✅
- [x] LintButton avec états (idle, running, success, warnings, errors)
- [x] Panneau problèmes avec navigation vers ligne
- [x] Badge de qualité coloré
- [x] Onglets Éditeur / Problèmes
### Phase 4: Bonus ✅
- [x] Quality Score (0-100) avec bonus/malus
- [x] Suggestions de fix par règle
- [x] Liens vers documentation ansible-lint
### Tests ✅
- [x] 24 tests unitaires (100% passing)
- [x] Tests parsing JSON/texte
- [x] Tests endpoint API
- [x] Tests calcul score qualité
---
## 7. Résumé Pitch Produit
> **Éditeur Ansible IDE-like pour votre Homelab**
>
> Passez de "ça marche peut-être" à "je suis sûr que c'est correct" avec notre éditeur de playbooks intelligent.
>
> ✨ **Coloration syntaxique Ansible** - Modules, variables Jinja, clés YAML
> 🔍 **ansible-lint intégré** - Feedback en temps réel, sans bloquer
> 📊 **Score de qualité** - Suivez l'évolution de vos playbooks
> ⚡ **Non-bloquant** - Éditez, sauvegardez, le lint tourne en arrière-plan
> 🎯 **Actionnable** - Chaque erreur avec explication et suggestion de fix