- 1. Vue d’ensemble
- 2. Arborescence
- 3. Flux d’analyse
- 4. Modèle
- 5. Analyseurs
- 6. Règles intégrées
- 7. Directives, contextes, profils
- 8. Notation et calibrage
- 9. Correction automatique
- 10. Référence (baseline)
- 11. Rapports
- 12. Internationalisation
- 13. Interface Flutter
- 14. Tests
- 15. Commits et publication
- 16. Build et packaging
check-script est une bibliothèque Dart (lib/) exposée par un CLI
(bin/check_script.dart) et une interface Flutter (gui/). Elle orchestre
des analyseurs de scripts shell et Python 3 (outils externes et règles
intégrées),
normalise leurs résultats en problèmes (Finding) classés par catégorie et
sévérité, les dédoublonne, applique directives, contextes et configuration,
calcule les notes et produit les rapports. Elle sait aussi corriger les
défauts sûrs et comparer une analyse à une référence.
-
Exploiter les outils existants (ShellCheck, shfmt, bashate, checkbashisms, gitleaks, trufflehog,
bash -n) plutôt que les réécrire ; les règles intégrées couvrent ce qu’ils ne traitent pas et assurent une analyse minimale sans eux. -
Dégradation gracieuse : un outil absent est signalé, jamais bloquant ; sans shfmt, les règles structurelles retombent sur un lexer heuristique.
-
Bibliothèque d’abord :
lib/n’écrit jamais sur la console ; le CLI et l’interface ne sont que des façades. -
Testabilité : l’exécution des commandes passe par
CommandRunner(remplacé par un faux dans les tests) ; les parseurs sont des fonctions pures testées sur des sorties réelles enregistrées ; un corpus fige le comportement sur des scripts réels. -
Pas de fuite de secrets : jamais recopiés dans les rapports, trufflehog lancé sans vérification réseau.
bin/check_script.dart CLI : options, correction, sorties, seuils, codes retour
lib/check_script.dart Exports de la bibliothèque
lib/src/
model/finding.dart Category, Severity, Finding (hint, url, fingerprint), ToolRun
model/report.dart ScriptReport, Comparison (+ toJson)
script_info.dart ScriptInfo : shebang, Dialect, métriques, CRLF
config.dart CheckConfig, Profile, ToolConfig, ScoringConfig, Thresholds (YAML)
i18n.dart Lang, Tr (texte bilingue), Messages (libellés)
engine.dart Engine : orchestration, progression, annulation, dédoublonnage,
enrichissement (liens), contextes, configuration, tri
scoring.dart scoreCategory, globalScore, sizeFactor, gradeFor
suppressions.dart Directives # check-script disable…
baseline.dart Empreintes (FNV-1a), Baseline, comparaison
fixer.dart --fix : corrections ShellCheck, intégrées, shfmt ; contrôle syntaxe
diff.dart Diff unifié (Myers)
discovery.dart collectScripts, isScriptFile, isExcluded (fichiers, dossiers,
fichiers hôtes)
watch.dart watchTargets : lots de fichiers modifiés (--watch, vue Dossier)
embedded.dart Scripts intégrés (GitHub Actions, GitLab CI, Dockerfile,
Makefile, Ansible) : script virtuel ligne à ligne, SEC023
version.dart appVersion (synchronisée avec pubspec.yaml)
rules/catalog.dart Catalogue des règles intégrées (titre, conseil, contexte),
ExecContext, escalades de sévérité par contexte
rules/examples.dart Exemples « à éviter / à écrire » par règle (shell et Python)
rules/custom_rules.dart CustomRule (rules.custom), CustomRulesAnalyzer
rules/references.dart Références CWE / OWASP / ANSSI des règles (ruleReferences),
intitulés, liens, findingReferences, matchesReference (--ref)
lsp/server.dart Serveur LSP (check-script lsp) : trames JSON-RPC,
diagnostics (complets / pendant la frappe), survol,
corrections rapides, formatage, checkScript/score
highlight.dart Coloration : jetons par ligne (shell, Python, YAML,
Dockerfile, Makefile), états multilignes (heredoc…)
explain.dart ScoreExplanation, explainScore (coût et gain par règle, plan
vers le niveau supérieur), sortByQuickWin
result_cache.dart ResultCache (rapports JSON par clé), fastHash (FNV-1a 64 bits)
git.dart changedSince (--changed-since), normalizedPath
history.dart FolderHistory, HistoryEntry (historique des dossiers : GUI,
--history-dir, --dashboard)
feedback.dart FalsePositive, FalsePositiveLog, anonymizeCode
json_num.dart jsonInt : lecture tolérante des nombres du JSON des outils
(nombre ou chaîne selon la version)
reporters/dashboard.dart renderDashboard, DashboardRepo, sparkline (tableau de bord)
config_discovery.dart findProjectConfig (.checkscript.yaml jusqu'à la racine git)
ignore.dart IgnoreRules (motifs au format .gitignore : --exclude, exclude:,
.checkscriptignore), utilisé par collectScripts et watchTargets
init.dart check-script init : suggestProfile, renderInitConfig
rule_doc.dart check-script explain : findRules, similarRuleIds, renderRuleDoc
report_diff.dart check-script diff : diffReports, ReportsDiff, renderDiffText / Markdown / Json
baseline_update.dart --baseline-update : updateBaseline (resserrage de la référence)
rules/same_rules.dart sameRuleIds : la même règle dans plusieurs outils (Ruff S ↔
Bandit B, Ruff PL ↔ Pylint, ShellCheck ↔ intégrées)
rules/registry.dart RuleEntry, knownRules : règles intégrées et codes externes
classés, titres bilingues (onglet Règles de l'interface)
analyzers/
analyzer.dart Analyzer, AnalysisContext, CommandRunner, CancelToken
shellcheck.dart ShellCheck (JSON) et table de classement SCxxxx
external_tools.dart Contrôle syntaxique (bash -n, compilation Python), shfmt,
bashate, checkbashisms et leurs parseurs
python_tools.dart Ruff, Bandit, Semgrep, mypy, Pyright, Pylint, Radon, Vermin :
invocation, parseurs, classement, équivalents
python_rules.dart Règles intégrées Python ; PythonFacts (module ast via python3,
repli ligne à ligne)
python_deps.dart Imports (pydeps : PYROB005, PYPOR002), dépendances déclarées
(requirements, pyproject, PEP 723…), pip-audit
commands.dart Inventaire des commandes externes (CommandUse), paquets
dnf / apt, présence (command -v), ROB017
ci_tools.dart hadolint (Dockerfile), actionlint et zizmor (workflows) :
fichier hôte sur l'entrée standard, appliesTo, parseurs
secrets.dart gitleaks, trufflehog
ast.dart AstFacts : faits extraits de `shfmt --to-json`
shell_lexer.dart Lexer heuristique (repli sans shfmt)
builtin_rules.dart Détection des règles intégrées (lignes, structure, fichier)
reporters/
reporters.dart Terminal, Markdown, AsciiDoc, JSON ; OutputFormat, render()
html.dart HTML autonome (filtres, source annotée)
sarif.dart SARIF 2.1.0
codeclimate.dart GitLab Code Quality
junit.dart JUnit XML, annotations GitHub Actions (--format github)
pdf.dart Rapport d'audit PDF (paquet pdf) : polices du système,
repli latin-1 ; renderBytes (reporters.dart) pour l'écrire
gui/ Interface Flutter (voir <<gui>>)
editors/vscode/ Extension VS Code (TypeScript, vscode-languageclient) :
npm run package → .vsix ; npm test → test de bout en bout
dans un vrai VS Code (CHECK_SCRIPT, VSCODE_EXECUTABLE)
editors/eclipse/ Plugin Eclipse (LSP4E, éditeur générique) : Maven Tycho,
mvn -f editors/eclipse/pom.xml verify → site de mise à jour
(copier d'abord LICENSE dans bundles/fr.chla28.checkscript/)
editors/geany/lsp.conf Configuration du greffon LSP Client de Geany
action.yml Action GitHub composite (compile check-script, annotations,
résumé, SARIF) ; testée par .github/workflows/self-check.yml
tool/calibrate.dart Calibrage sur le corpus
tool/false_positives.dart Synthèse des faux positifs signalés (par règle)
test/ Tests ; fixtures/ (dont sorties réelles des outils), corpus/
completions/ Complétions bash et zsh
doc/ Guides, page de manuel (check-script.1.fr.adoc), exemples CI
packaging/rpm/ Specs RPM (CLI, interface)
scripts/ build-dist.sh, build-rpm.sh, build-editors.sh, install.sh, uninstall.sh,
pre-commit-hook.sh
.pre-commit-hooks.yaml Hooks pour le framework pre-commitfichier ──► ScriptInfo.fromContent (shebang ou extension .py → Dialect, CRLF, lignes)
│
▼
Engine.analyze ── pour chaque Analyzer du langage du script (analyzersFor),
│ activé, dans l'ordre de priorité :
│ shell : syntax → shellcheck → gitleaks → trufflehog → checkbashisms
│ → builtin (arbre shfmt si disponible) → shfmt → bashate
│ python : syntax → bandit → ruff → semgrep → mypy → pyright → pylint
│ → vermin → radon → gitleaks → trufflehog → builtin (ast)
│ outils lancés en parallèle (Future.wait), résultats rangés dans
│ l'ordre de priorité ; Engine(parallel: false) pour l'ordre strict
│ onProgress(AnalysisProgress) ; CancelToken vérifié à chaque outil
│ analyzeFiles(paths, jobs) : plusieurs scripts à la fois (défaut
│ Engine.defaultJobs = processeurs / 4, entre 1 et 4), ordre conservé
▼
deduplicate ── garde le premier de chaque groupe de doublons
Suppressions ── directives # check-script disable… (comptées dans `suppressed`)
enrich ── liens de documentation, conseils génériques des outils externes
escalate ── sévérités relevées selon les contextes (root, cron, systemd)
applyConfig ── rules.disabled, rules.overrides
fingerprintAll── empreintes stables (baseline, SARIF, Code Quality)
sortFindings ── catégorie, sévérité, ligne
scoreCategory × 5, globalScore
▼
ScriptReport ──► Baseline.compare (si référence) ──► render(format)Finding-
tool,ruleId,category,severity,line(0 = fichier),column,message,snippet,equivalents(codes d’autres outils désignant le même défaut),hint(conseil),url(documentation),fingerprint,endLine(fin de l’instruction multi-ligne signalée, pour le dédoublonnage : recouvrement de lignes, étendue ≤maxDuplicateSpan),edits(correction concrète :TextEdit1-based, fin exclusive ; issue dufixShellCheck ou deattachFixespour les corrections intégrées).Finding.fromJsonrelittoJson.fixPreviewen tire les lignes avant / après ;exampleFor(rules/examples.dart) donne l’exemple générique d’une règle. ToolRun-
ok,missing,skipped,failed,disabled; version ; nombre de problèmes ;detail(ast/lexerpour les règles intégrées). ScriptReport-
script, outils, problèmes, 5
CategoryScore, note globale, niveau, date,suppressed,profile,contexts,comparison.
abstract class Analyzer {
String get name; // clé de configuration
ToolLanguage get language; // shell (défaut), python ou any
Future<AnalyzerResult> analyze(AnalysisContext ctx);
Future<String?> version(CommandRunner runner, CheckConfig config); // null = absent, '?' = illisible
}CommandRunner.run(exe, args, {stdin, cancel}) renvoie null si
l’exécutable est introuvable. ProcessCommandRunner force LC_ALL=C, écrit
stdin (utilisé par shfmt --to-json, bash -n, le formatage de --fix)
et tue le processus quand le CancelToken est déclenché. Les analyseurs
passent par ctx.run(…), qui transmet le jeton.
| Outil | Invocation | Parseur / classement |
|---|---|---|
syntax |
|
|
shellcheck |
|
|
gitleaks |
|
|
trufflehog |
|
|
checkbashisms |
|
|
builtin |
|
|
shfmt |
|
|
bashate |
|
|
syntax (Python) |
|
|
ruff |
|
|
bandit |
|
|
semgrep |
|
|
mypy |
|
|
pyright |
|
|
pylint |
|
|
radon |
|
|
vermin |
|
|
builtin (Python) |
|
|
shellcheckMap classe explicitement les codes significatifs ; sinon
classifyShellcheck applique : SC3xxx → Portabilité (Medium/Low), SC1xxx
error → Robustesse/High, style → Maintenabilité/Low, sinon Robustesse
selon le niveau. Les bashismes qui cassent sous dash (SC2112/2113
function, SC3010 [[, SC3011 <<<, SC3020 &>, SC3030/3054 tableaux,
SC3005/3006 ((, SC3018, SC3001) sont High — décision issue du calibrage.
Deux problèmes sont doublons si l’un des equivalents de l’un correspond au
ruleId de l’autre (exact ou préfixe *) et qu’ils portent sur la même
ligne — ou que l’un est « fichier » (ligne 0) ou une erreur SYNTAX. Même
outil : même ligne et (même règle ou équivalent). Le premier rencontré est
conservé ; l’ordre de defaultAnalyzers() fixe la priorité.
Ruff Snnn = Bandit Bnnn (mêmes numéros) ; Ruff PLxnnnn = Pylint
xnnnn ; table _ruffToPylint pour les autres (E722 = W0702, B006 =
W0102…) ; Semgrep équivaut aux codes Bandit et Ruff de sécurité de la même
ligne ; mypy aux diagnostics Pyright (report*) ; les erreurs de version
(match en 3.9) de Ruff et Pyright sont classées Portabilité et équivalent
à VERMIN. Les messages Bandit B105–B107 et Semgrep « secret » sont
caviardés, et leurs lignes masquées (_revealsSecret).
rules/catalog.dart décrit chaque règle : identifiant, catégorie, sévérité,
titre et conseil de correction bilingues (Tr), contextes d’activation.
La détection est séparée (builtin_rules.dart) ; add(id, line, …) y crée
le Finding à partir du catalogue et ignore les règles dont le contexte
n’est pas déclaré.
AstFacts (analyzers/ast.dart) parcourt le JSON de shfmt --to-json :
-
functions: nom, lignes de début et de fin ; -
blocks: structures de contrôle et profondeur (else/elif au même niveau) ; -
commands: nom littéral, arguments littéraux (nullsi expansion),hasExpansion,checked(condition de if/while, opérande gauche de&&/||— opérateurs 10 et 11 —, commande niée),inLoop,inSubstitution.
Avec l’arbre, les règles de commande (SEC003, SEC012, ROB005, ROB007,
ROB011, POR004, POR005, POR007, PERF003, PERF004) et structurelles (MNT002,
MNT003) sont exactes ; les LineRule marquées astCovered sont alors
ignorées. Sans shfmt, lexScript (commentaires, chaînes masquées dans
bare, heredocs) et les expressions régulières prennent le relais.
-
Ajouter une
RuleInfodansruleCatalog(titre et conseil fr/en, contextes éventuels). -
Ajouter sa détection : une
LineRuledanslineRules(avecequivalents, etastCovered+ un cas dans_astStructuresi elle porte sur une commande), ou une règle fichier dansrunBuiltinRules. -
Si elle doit être relevée dans un contexte, compléter
contextEscalations. -
Tests : un cas déclencheur et un cas sain (
builtin_rules_test.dartounew_rules_test.dart), puisUPDATE_GOLDEN=1 dart test test/corpus_test.dartsi le corpus change — en vérifiant chaque écart. -
Mettre à jour le tableau des règles de
doc/user.fr.adoc.
-
Suppressions.parselit# check-script disable=(ligne, ou ligne de code suivante pour un commentaire seul),disable-next-line=,disable-file=; jokers*etall. -
ExecContext(root,cron,systemd) : règles conditionnelles (RuleInfo.contexts) etcontextEscalations(sévérité seulement relevée). -
Profile:CheckConfig.forProfilefournit la base ;CheckConfig.parseapplique le YAML par-dessus (le profil de la ligne de commande prime sur la cléprofile:).
facteur(n) = √(référence / max(référence, lignes de code)) référence = 100
pénalité = Σ_règles poids(sévérité) × (1 + log2 occurrences) × (facteur si Medium/Low)
note = clamp(10 − pénalité, 0, 10), arrondie au dixième
globale = min(moyenne pondérée, pire catégorie + 1,5) maxGapToWorst
niveau = A ≥ 9, B ≥ 7,5, C ≥ 6, D ≥ 4, ELe corpus test/corpus/ réunit des copies figées de scripts de la suite
AuditTools et des scripts typiques (installeur curl | bash, sauvegarde
cron ancienne, script init POSIX avec bashismes, bibliothèque propre), et
12 scripts Python py_* écrits pour le calibrage (outil propre, client
d’API négligent, installeur dangereux, style Python 2, fonctionnalités
3.10+…). Semgrep est écarté du contrôle des niveaux (règles téléchargées).
labels.yaml donne pour chacun, établi a priori en lisant le script, la
plage de niveaux attendue (avec et sans contexte), les règles obligatoires
et interdites.
dart run tool/calibrate.dart --details # notes réelles vs plages attenduesDeux ajustements en sont issus : bashismes cassant dash classés High, et plafond de la note globale ramené de « pire + 2,5 » à « pire + 1,5 ». Tout changement de poids doit laisser le corpus conforme.
Le calibrage Python (0.7.0) a aligné les sévérités sur l’échelle shell sans
toucher au modèle : secrets en dur Critical si la valeur est réaliste (comme
SEC002), exécution de code ou de données High (comme SEC003), PYSEC001
Medium (comme SEC022), shebang python High ; il a ajouté PYROB003 (cron
sans verrou, comme ROB014) et PYROB004 (code de retour de main() perdu),
et compte les docstrings comme de la documentation. Trois plages a priori
jugées trop sévères au regard de l’échelle shell ont été révisées, avec leur
justification dans labels.yaml.
fixScript enchaîne : remplacements ShellCheck (parseShellcheckFixes,
applyEdits : positions 1-based, fin exclusive, tabulation = 1 colonne,
éditions en conflit ignorées), corrections intégrées (applyBuiltinFixes,
jamais dans un heredoc, une chaîne multi-lignes ou un commentaire ;
replaceBackticks ignore les apostrophes et les backticks échappés), puis
shfmt -ln -i sur l’entrée standard. Si <shell> -n accepte l’original mais
refuse le résultat, FixResult.aborted est renseigné et rien n’est écrit.
Pour un script Python (_fixPython) : ruff check --fix puis ruff format
sur l’entrée standard (--stdin-filename=script.py), les corrections étant
comptées d’après la sortie JSON ; contrôle par la compilation Python
(syntaxRegression utilise SyntaxAnalyzer.commandFor).
unifiedDiff (Myers) produit le diff de --dry-run et de l’interface.
fingerprintAll calcule fnv1a64(outil|règle|ligne normalisée|rang) : le
numéro de ligne n’entre pas dans l’empreinte. Baseline.parse relit un
rapport JSON ; compare apparie par empreinte (multiensemble) et renvoie
Comparison (nouveaux, corrigés, inchangés, notes précédentes). Les rapports
ne détaillent alors que les nouveaux problèmes (detailFindings).
render(reports, format, RenderOptions) ; OutputFormat : terminal,
markdown, asciidoc, json, sarif, html, codeclimate (déduit de
l’extension par OutputFormat.fromPath).
-
SARIF : une règle par couple outil/règle (
help,helpUri,security-severitypour la sécurité), résultats avecpartialFingerprints,startLine ≥ 1. -
Code Quality :
check_name,severity(blocker/critical/major/minor),fingerprint,location.lines.begin. -
HTML : page unique sans ressource externe, thème clair/sombre, filtres, source annotée (ancres
#s<i>-L<n>).
Format JSON (extrait) :
{
"tool": "check-script", "version": "0.24.1",
"reports": [{
"file": "deploy.sh", "dialect": "bash",
"lines": {"total": 16, "code": 15, "comments": 0},
"profile": "standard", "contexts": ["root"],
"global": {"score": 1.5, "grade": "E"},
"categories": [{"category": "security", "score": 0.0, "total": 10,
"critical": 3, "high": 3, "medium": 3, "low": 1}],
"suppressed": 0,
"comparison": {"new": 1, "fixed": 2, "unchanged": 30, "previousGlobal": 2.5,
"previousScores": {"security": 0.0}},
"tools": [{"tool": "shellcheck", "status": "ok", "version": "0.11.0", "findings": 14}],
"findings": [{"tool": "builtin", "rule": "SEC001", "category": "security",
"severity": "critical", "line": 5, "column": 0, "message": "…",
"snippet": "…", "hint": "…", "fingerprint": "9f2c…",
"edits": [{"line": 5, "column": 12, "endLine": 5,
"endColumn": 12, "replacement": " || exit"}]}]
}]
}Lang.fromEnvironment (LC_ALL > LC_MESSAGES > LANG) ; libellés dans
Messages (bibliothèque) et S (interface) ; règles : Tr(fr, en) dans le
catalogue ; messages des outils externes non traduits ; décimales à virgule
en français.
gui/ dépend de la bibliothèque par path: ../.
gui/lib/main.dart Application, navigation, glisser-déposer, progression
gui/lib/app_state.dart AppState (ChangeNotifier) et GuiSettings (shared_preferences)
gui/lib/strings.dart Libellés propres à l'interface (fr/en)
gui/lib/screens/analysis_screen.dart Source + onglets Synthèse / Problèmes, correction, export
gui/lib/screens/folder_screen.dart Tableau triable, tendance (sortReports)
gui/lib/screens/settings_screen.dart Langue, thème, profil, contextes, outils, YAML
gui/lib/editor.dart detectEditor, editorCommandLine, openInEditor
gui/lib/code_style.dart Police du code (JetBrains Mono embarquée, gui/fonts/, OFL),
CodeFont (InheritedWidget), couleurs des jetons,
polices mono installées (fc-list)
gui/lib/screens/rules_screen.dart Règles : cases à cocher (GuiSettings.disabledRules, fusionné
à rules.disabled par buildConfig ; celles de baseConfig
sont verrouillées), recherche, filtres, règles rencontrées
(AppState.seenRules, mémorisées)
gui/lib/widgets/ radar_chart (RadarPainter), score_panel, source_view,
findings_list, fix_panel (code de correction), split_view
(séparateur déplaçable), common (couleurs, badges, DeltaChip)AppState construit la configuration (buildConfig : YAML éventuel,
profil, contextes, outils désactivés), lance Engine avec onProgress et un
CancelToken, gère la référence, proposeFix / applyFix (copie .orig)
et l’export. Attention : Flutter possède un widget Baseline ; importer
package:flutter/material.dart avec hide Baseline là où la classe de la
bibliothèque est utilisée.
Tests : flutter test (état, tri, radar, écrans). Captures hors écran avec
les vraies polices système :
cd gui && SCREENSHOT_DIR=/tmp/shots flutter test test/screenshot_test.dartLes captures françaises sont écrites dans SCREENSHOT_DIR, les anglaises dans SCREENSHOT_DIR/en.
L’interface est déclarée dans le lanceur MainGUI (kToolSpecs, id
check_script, commande check-script-gui, bundle check_script_gui).
dart test # bibliothèque et CLI
UPDATE_GOLDEN=1 dart test test/corpus_test.dart # régénérer les instantanés (après vérification)
dart analyze --fatal-infos
(cd gui && flutter analyze && flutter test)| Fichier | Contenu |
|---|---|
|
Chaque règle (déclencheur / cas sain), dialectes, contextes, profils, entropie, catalogue |
|
Faits extraits de l’arbre shfmt réel ; règles sur l’arbre ; |
|
Parseurs sur les sorties réelles des outils |
|
Directives |
|
Empreintes, comparaison |
|
Remplacements ShellCheck, corrections intégrées, abandon, diff |
|
SARIF, HTML, conseils, secrets externes, progression, annulation |
|
Moteur, notation, configuration |
|
Rapports, options et codes de sortie |
|
Instantanés, règles obligatoires / interdites, plages de niveaux |
|
Directives obsolètes (MNT011), explication de la note et gain rapide, SARIF |
|
Même règle entre outils, exclusions transmises, |
|
Parseurs des outils Python (sorties réelles de |
|
Corrections par problème, exemples, rapport HTML |
|
Exemples de CI ( |
|
Non-régression du barème : instantané des notes du corpus pour les trois profils ( |
|
|
|
Motifs |
|
Vrais outils (ignorés s’ils sont absents), dont Ruff, Bandit, mypy, Radon, Vermin sur |
Toute correction de règle s’accompagne d’un test qui échoue avant la correction ; tout faux positif trouvé sur un script réel rejoint le corpus.
Les messages de commit suivent les Conventional Commits : types, portées et description en anglais (l’historique jusqu’à 0.18.5 est en français), sans point final, première ligne de 100 caractères au plus.
feat(gui): ajoute l'onglet Règles
fix(flatpak): lance les outils par leur chemin absolu
docs(user): précise --changed-since
feat(engine)!: change le format JSON ← « ! » ou « BREAKING CHANGE: » : incompatibleTypes : feat, fix, perf, refactor, docs, test, build, ci,
style, chore, revert. Portées usuelles : engine, cli, gui,
python, rules, reporters, flatpak, appimage, rpm, ci, doc.
-
Contrôle local :
scripts/install-git-hooks.shactive.githooks/(core.hooksPath) ; le hookcommit-msgrefuse un message non conforme (git commit --no-verifypour passer outre). -
Contrôle CI :
.github/workflows/commits.ymlvérifie les nouveaux commits de chaque push et pull request (tool/commit_lint.dart --range). -
Publication :
dart run tool/release.dart --dry-runaffiche la version suivante et la section du CHANGELOG ; sans--dry-run, synchronise les fichiers de version, écrit le CHANGELOG, commitechore(release): X.Y.Zet taguevX.Y.Z(--pushpour pousser, ce qui déclenche la publication GitHub). Version :feat→ mineure, autre changement → correctif, incompatible → majeure (mineure tant que la version est 0.x). Les notes rédigées sous « ## Unreleased » sont gardées en tête de la section.
scripts/build-dist.sh [VERSION] [--rpm] [--editors] [--install] [--skip-tests] [--no-gui]
(appelé aussi par l’orchestrateur AuditTools/scripts/build-dist.sh) :
analyse et tests (Dart et Flutter), binaire CLI, bundle Flutter (version
injectée par --build-name), page de manuel (asciidoctor), complétions,
documentation et exemples CI, .desktop et icône, SBOM et rapport CVE si
sbom-generator est présent, archive, RPM (scripts/build-rpm.sh, depuis
git archive HEAD : seul le contenu commité est empaqueté).
scripts/build-editors.sh [VERSION] [--skip-tests] [--no-vscode] [--no-eclipse] :
extension VS Code (npm ci, tests de bout en bout sous xvfb-run ou DISPLAY,
vsce package) et site de mise à jour Eclipse (Tycho) →
dist/check-script-VERSION.vsix et dist/check-script-eclipse-VERSION.zip.
scripts/build-appimage.sh [--skip-build] : bundle Flutter et CLI
compilée dans un AppDir (AppRun : interface par défaut, CLI avec --cli
ou via un lien nommé check-script), .desktop, icône et métadonnées
AppStream communs (packaging/linux/), puis appimagetool (PATH,
APPIMAGETOOL, ou téléchargé dans build/appimage/) → dist/CheckScript-VERSION-ARCH.AppImage.
scripts/build-flatpak.sh [--install] [--skip-build] : mêmes binaires,
manifeste packaging/flatpak/fr.chla28.check_script_gui.yml (runtime
GNOME 50, qui fournit GTK 3), flatpak-builder (ou org.flatpak.Builder),
runtime et SDK installés depuis Flathub pour l’utilisateur →
dist/CheckScript-VERSION-ARCH.flatpak. Dans le Flatpak,
ProcessCommandRunner lance les outils sur l’hôte (hostInvocation :
flatpak-spawn --host --env=LC_ALL=C …, présence vérifiée par command -v
sur l’hôte) ; les lanceurs placent TMPDIR dans le cache de l’application,
dont le chemin est identique dans le bac à sable et sur l’hôte.
Dans le Flatpak, le PATH de l’utilisateur sur l’hôte est lu une fois par
un shell de connexion (bash -lc, pour ~/.local/bin, ~/bin…) et chaque
outil est lancé par son chemin absolu résolu sur l’hôte : le portail
cherche l’exécutable avec son propre PATH minimal, pas celui de --env.
Publication (.github/workflows/release.yml) : à chaque tag v*, tests
(sans outils externes, pour des résultats indépendants des versions d’outils
des distributions), puis archive, AppImage et Flatpak (Ubuntu 24.04), RPM
(conteneur Fedora 44), et release GitHub avec les fichiers et l’extrait du
CHANGELOG. Flutter est figé (FLUTTER_VERSION).
Les deux scripts partagent scripts/package-common.sh et affichent la glibc
minimale requise par les binaires (2.34 actuellement : Rocky 9, runtimes
Flatpak) ; pour une AppImage largement compatible, construire sur la
distribution la plus ancienne visée.
Les specs neutralisent le strip et le debuginfo (ils corrompent les binaires
AOT Dart) ; le spec de l’interface désactive le scan automatique des
dépendances (moteur Flutter embarqué). Licence : LGPL-3.0-or-later
(LICENSE), reprise par les specs et les métadonnées AppStream.
La version figure dans pubspec.yaml, gui/pubspec.yaml,
lib/src/version.dart et CHANGELOG.md ; build-dist.sh signale un
écart entre les deux premiers fichiers Dart.