push-guardian 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dockerignore +15 -0
- package/.pushguardian-plugins.json +10 -0
- package/Dockerfile +41 -0
- package/Dockerfile.dev +20 -0
- package/README.md +386 -0
- package/TECHNO.md +139 -0
- package/babel.config.js +1 -0
- package/developper_utils.md +119 -0
- package/docker-compose.yml +41 -0
- package/docs/PLUGINS.md +223 -0
- package/docs/technical/architecture.md +298 -0
- package/docs/technical/performance-guide.md +390 -0
- package/docs/technical/plugin-persistence.md +169 -0
- package/docs/technical/plugins-guide.md +409 -0
- package/jest.config.js +22 -0
- package/package.json +53 -0
- package/plugins/example-plugin/index.js +55 -0
- package/plugins/example-plugin/plugin.json +8 -0
- package/scripts/coverage-report.js +75 -0
- package/src/cli/command/config.js +33 -0
- package/src/cli/command/install.js +137 -0
- package/src/cli/command/mirror.js +90 -0
- package/src/cli/command/performance.js +160 -0
- package/src/cli/command/plugin.js +171 -0
- package/src/cli/command/security.js +152 -0
- package/src/cli/command/shell.js +238 -0
- package/src/cli/command/validate.js +54 -0
- package/src/cli/index.js +23 -0
- package/src/cli/install/codeQualityTools.js +156 -0
- package/src/cli/install/hooks.js +89 -0
- package/src/cli/install/mirroring.js +299 -0
- package/src/core/codeQualityTools/configAnalyzer.js +216 -0
- package/src/core/codeQualityTools/configGenerator.js +381 -0
- package/src/core/codeQualityTools/configManager.js +65 -0
- package/src/core/codeQualityTools/fileDetector.js +62 -0
- package/src/core/codeQualityTools/languageTools.js +104 -0
- package/src/core/codeQualityTools/toolInstaller.js +53 -0
- package/src/core/configManager.js +43 -0
- package/src/core/errorCMD.js +9 -0
- package/src/core/interactiveMenu/interactiveMenu.js +73 -0
- package/src/core/mirroring/branchSynchronizer.js +59 -0
- package/src/core/mirroring/generate.js +114 -0
- package/src/core/mirroring/repoManager.js +112 -0
- package/src/core/mirroring/syncManager.js +176 -0
- package/src/core/module/env-loader.js +109 -0
- package/src/core/performance/metricsCollector.js +217 -0
- package/src/core/performance/performanceAnalyzer.js +182 -0
- package/src/core/plugins/basePlugin.js +89 -0
- package/src/core/plugins/pluginManager.js +123 -0
- package/src/core/plugins/pluginRegistry.js +215 -0
- package/src/core/validator.js +53 -0
- package/src/hooks/constrains/constrains.js +174 -0
- package/src/hooks/constrains/constraintEngine.js +140 -0
- package/src/utils/chalk-wrapper.js +26 -0
- package/src/utils/exec-wrapper.js +6 -0
- package/tests/fixtures/mock-eslint-config-array.js +8 -0
- package/tests/fixtures/mock-eslint-config-single.js +6 -0
- package/tests/fixtures/mockLoadedPlugin.js +11 -0
- package/tests/setup.js +28 -0
- package/tests/unit/basePlugin.test.js +355 -0
- package/tests/unit/branchSynchronizer.test.js +308 -0
- package/tests/unit/cli-commands.test.js +144 -0
- package/tests/unit/codeQualityConfigManager.test.js +233 -0
- package/tests/unit/codeQualityTools.test.js +36 -0
- package/tests/unit/command-install.test.js +247 -0
- package/tests/unit/command-mirror.test.js +179 -0
- package/tests/unit/command-performance.test.js +169 -0
- package/tests/unit/command-plugin.test.js +288 -0
- package/tests/unit/command-security.test.js +277 -0
- package/tests/unit/command-shell.test.js +325 -0
- package/tests/unit/configAnalyzer.test.js +593 -0
- package/tests/unit/configGenerator.test.js +808 -0
- package/tests/unit/configManager.test.js +195 -0
- package/tests/unit/constrains.test.js +463 -0
- package/tests/unit/constraint.test.js +554 -0
- package/tests/unit/env-loader.test.js +279 -0
- package/tests/unit/fileDetector.test.js +171 -0
- package/tests/unit/install-codeQualityTools.test.js +343 -0
- package/tests/unit/install-hooks.test.js +280 -0
- package/tests/unit/install-mirroring.test.js +731 -0
- package/tests/unit/install-modules.test.js +81 -0
- package/tests/unit/interactiveMenu.test.js +426 -0
- package/tests/unit/languageTools.test.js +244 -0
- package/tests/unit/metricsCollector.test.js +354 -0
- package/tests/unit/mirroring-generate.test.js +96 -0
- package/tests/unit/modules-exist.test.js +96 -0
- package/tests/unit/performanceAnalyzer.test.js +473 -0
- package/tests/unit/pluginManager.test.js +427 -0
- package/tests/unit/pluginRegistry.test.js +592 -0
- package/tests/unit/repoManager.test.js +469 -0
- package/tests/unit/reviewAppManager.test.js +5 -0
- package/tests/unit/security-command.test.js +43 -0
- package/tests/unit/syncManager.test.js +494 -0
- package/tests/unit/toolInstaller.test.js +240 -0
- package/tests/unit/utils.test.js +144 -0
- package/tests/unit/validator.test.js +215 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
const { installHooks } = require('../install/hooks');
|
|
2
|
+
const interactiveMenu = require('../../core/interactiveMenu/interactiveMenu');
|
|
3
|
+
const { installCodeQualityTools } = require('../install/codeQualityTools');
|
|
4
|
+
const { installMirroringTools } = require('../install/mirroring');
|
|
5
|
+
const { loadConfig } = require('../../core/configManager');
|
|
6
|
+
const { getChalk } = require('../../utils/chalk-wrapper');
|
|
7
|
+
|
|
8
|
+
module.exports = {
|
|
9
|
+
name: 'install',
|
|
10
|
+
description: 'Installer les hooks Git',
|
|
11
|
+
options: [
|
|
12
|
+
{
|
|
13
|
+
flags: '-f, --force',
|
|
14
|
+
description: "forcer l'installation même si déjà installé"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
flags: '-a, --all',
|
|
18
|
+
description: 'installer tous les modules disponibles'
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
flags: '--hooks',
|
|
22
|
+
description: 'installer les hooks Git'
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
flags: '--code-quality',
|
|
26
|
+
description: 'installer les outils de qualité de code'
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
flags: '--skip-hooks',
|
|
30
|
+
description: 'ne pas installer les hooks Git'
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
flags: '--skip-code-quality',
|
|
34
|
+
description: 'ne pas installer les outils de qualité de code'
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
flags: '--mirroring',
|
|
38
|
+
description: 'installer le système de mirroring'
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
flags: '--skip-mirroring',
|
|
42
|
+
description: 'ne pas installer le système de mirroring'
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
flags: '--file <path>',
|
|
46
|
+
description: 'installer les modules qui se trouvent dans le fichier de configuration'
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
action: async (options) => {
|
|
50
|
+
const chalk = getChalk();
|
|
51
|
+
try {
|
|
52
|
+
if (
|
|
53
|
+
(options.hooks && options.skipHooks) ||
|
|
54
|
+
(options.codeQuality && options.skipCodeQuality) ||
|
|
55
|
+
(options.mirroring && options.skipMirroring)
|
|
56
|
+
) {
|
|
57
|
+
console.log(
|
|
58
|
+
chalk.red(
|
|
59
|
+
'❌ Options conflictuelles. Veuillez vérifier vos options.\n\t\tVous ne pouvez pas utiliser --hooks et --skip-hooks, --code-quality et --skip-code-quality, ou --mirroring et --skip-mirroring simultanément.'
|
|
60
|
+
)
|
|
61
|
+
);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const config = options.file ? loadConfig(options.file) : null;
|
|
66
|
+
let selected = ['Hooks Git', 'Code Quality Tools', 'Mirroring'];
|
|
67
|
+
let preselectedHooks = false;
|
|
68
|
+
let preselectedCQT = [];
|
|
69
|
+
let preselectedMirroring = false;
|
|
70
|
+
|
|
71
|
+
if (options.file && config && config.install) {
|
|
72
|
+
if (config.install.hooks === true) {
|
|
73
|
+
preselectedHooks = true;
|
|
74
|
+
}
|
|
75
|
+
if (config.install.CQT && Array.isArray(config.install.CQT)) {
|
|
76
|
+
preselectedCQT = config.install.CQT;
|
|
77
|
+
}
|
|
78
|
+
if (config.install.mirroring === true) {
|
|
79
|
+
preselectedMirroring = true;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (options.skipHooks) selected = selected.filter((item) => item !== 'Hooks Git');
|
|
84
|
+
if (options.skipCodeQuality) selected = selected.filter((item) => item !== 'Code Quality Tools');
|
|
85
|
+
if (options.skipMirroring) selected = selected.filter((item) => item !== 'Mirroring');
|
|
86
|
+
else if (
|
|
87
|
+
options.hooks ||
|
|
88
|
+
options.codeQuality ||
|
|
89
|
+
options.mirroring ||
|
|
90
|
+
options.skipHooks ||
|
|
91
|
+
options.skipCodeQuality ||
|
|
92
|
+
options.skipMirroring
|
|
93
|
+
) {
|
|
94
|
+
selected = [];
|
|
95
|
+
if (options.hooks && !options.skipHooks) selected.push('Hooks Git');
|
|
96
|
+
if (options.codeQuality && !options.skipCodeQuality) selected.push('Code Quality Tools');
|
|
97
|
+
if (options.mirroring && !options.skipMirroring) selected.push('Mirroring');
|
|
98
|
+
|
|
99
|
+
/* istanbul ignore next */
|
|
100
|
+
if (
|
|
101
|
+
!options.hooks &&
|
|
102
|
+
!options.codeQuality &&
|
|
103
|
+
!options.mirroring &&
|
|
104
|
+
(options.skipHooks || options.skipCodeQuality || options.skipMirroring)
|
|
105
|
+
) {
|
|
106
|
+
if (!options.skipHooks) selected.push('Hooks Git');
|
|
107
|
+
if (!options.skipCodeQuality) selected.push('Code Quality Tools');
|
|
108
|
+
if (!options.skipMirroring) selected.push('Mirroring');
|
|
109
|
+
}
|
|
110
|
+
} else {
|
|
111
|
+
if (options.all) {
|
|
112
|
+
selected = ['Hooks Git', 'Code Quality Tools', 'Mirroring'];
|
|
113
|
+
} else if (preselectedHooks || preselectedCQT.length > 0 || preselectedMirroring) {
|
|
114
|
+
selected = [];
|
|
115
|
+
if (preselectedHooks) selected.push('Hooks Git');
|
|
116
|
+
if (preselectedCQT.length > 0) selected.push('Code Quality Tools');
|
|
117
|
+
if (preselectedMirroring) selected.push('Mirroring');
|
|
118
|
+
} else {
|
|
119
|
+
selected = await interactiveMenu('Choisissez les modules à installer', selected);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const installers = {
|
|
124
|
+
'Hooks Git': () => installHooks(['commit-msg', 'post-checkout', 'pre-push'], options.force),
|
|
125
|
+
'Code Quality Tools': () => installCodeQualityTools(options.all, preselectedCQT),
|
|
126
|
+
Mirroring: () => installMirroringTools()
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
selected.forEach((item) => {
|
|
130
|
+
const installSelected = installers[item];
|
|
131
|
+
if (installSelected) installSelected();
|
|
132
|
+
});
|
|
133
|
+
} catch (error) {
|
|
134
|
+
console.error(chalk.red('❌ Une erreur est survenue :'), error.message);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
const { loadConfig } = require('../../core/configManager');
|
|
2
|
+
const { SyncManager } = require('../../core/mirroring/syncManager');
|
|
3
|
+
const { generateWorkflow } = require('../../core/mirroring/generate');
|
|
4
|
+
const errorCMD = require('../../core/errorCMD');
|
|
5
|
+
const { getEnv, loadEnv } = require('../../core/module/env-loader');
|
|
6
|
+
const { getChalk } = require('../../utils/chalk-wrapper');
|
|
7
|
+
|
|
8
|
+
module.exports = {
|
|
9
|
+
name: 'mirror',
|
|
10
|
+
description: 'Référentiels miroirs sur plusieurs plateformes (GitHub, GitLab, BitBucket, Azure DevOps)',
|
|
11
|
+
options: [
|
|
12
|
+
{ flags: '-s --source <platform>', description: 'Plateforme source (github, gitlab, bitbucket, azure)' },
|
|
13
|
+
{ flags: '-t --target <platform>', description: 'Plateforme cible (github, gitlab, bitbucket, azure)' },
|
|
14
|
+
{
|
|
15
|
+
flags: '-r --repo <name>',
|
|
16
|
+
description: 'Nom du référentiel source (et cible si --target-repo non spécifié)'
|
|
17
|
+
},
|
|
18
|
+
{ flags: '--source-repo <name>', description: 'Nom du référentiel source' },
|
|
19
|
+
{ flags: '--target-repo <name>', description: 'Nom du référentiel cible' },
|
|
20
|
+
{ flags: '--source-owner <owner>', description: 'Propriétaire du référentiel source (requis pour GitHub)' },
|
|
21
|
+
{ flags: '--target-owner <owner>', description: 'Propriétaire du référentiel cible (requis pour GitHub)' },
|
|
22
|
+
{ flags: '-S --sync-branches', description: 'Activer la synchronisation des branches' },
|
|
23
|
+
{ flags: '-p --public-repo', description: 'Visibilité du mirroir en public' },
|
|
24
|
+
{ flags: '-g --generate', description: 'Génére un workflow' }
|
|
25
|
+
],
|
|
26
|
+
action: async (options) => {
|
|
27
|
+
const chalk = getChalk();
|
|
28
|
+
const normalizePlatform = (platform) => (platform ? String(platform).trim().toLowerCase() : platform);
|
|
29
|
+
try {
|
|
30
|
+
loadEnv();
|
|
31
|
+
const config = loadConfig();
|
|
32
|
+
|
|
33
|
+
if (options.generate) {
|
|
34
|
+
generateWorkflow();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!config.mirroring) {
|
|
39
|
+
console.log(chalk.red('❌ Configuration de mise en miroir manquante dans push-guardian.config.json'));
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const sourcePlatform = normalizePlatform(options.source || getEnv('SOURCE_PLATFORM'));
|
|
44
|
+
const targetPlatform = normalizePlatform(options.target || getEnv('TARGET_PLATFORM'));
|
|
45
|
+
const sourceRepo = options.sourceRepo || getEnv('SOURCE_REPO');
|
|
46
|
+
const targetRepo = options.targetRepo || options.repo || getEnv('TARGET_REPO');
|
|
47
|
+
const sourceOwner = options.sourceOwner || getEnv('SOURCE_OWNER');
|
|
48
|
+
const targetOwner = options.targetOwner || getEnv('TARGET_OWNER');
|
|
49
|
+
|
|
50
|
+
console.log(
|
|
51
|
+
`SP: ${sourcePlatform}\tTP: ${targetPlatform}\tSR: ${sourceRepo}\tTR: ${targetRepo}\tSO: ${sourceOwner}\tTO: ${targetOwner}`
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
if (!sourcePlatform || !targetPlatform || !sourceRepo || !targetRepo || !sourceOwner || !targetOwner) {
|
|
55
|
+
console.log(
|
|
56
|
+
chalk.red(
|
|
57
|
+
"❌ Plateformes, repos et propriétaires source/cible requis. Spécifiez-les via options ou configurez des valeurs par défaut lors de l'installation."
|
|
58
|
+
)
|
|
59
|
+
);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const platformsConfig = {
|
|
64
|
+
...(config.mirroring.platforms || {})
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
[sourcePlatform, targetPlatform].filter(Boolean).forEach((platform) => {
|
|
68
|
+
platformsConfig[platform] = {
|
|
69
|
+
...(platformsConfig[platform] || {}),
|
|
70
|
+
enabled: true
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const syncManager = new SyncManager(platformsConfig);
|
|
75
|
+
await syncManager.mirror(
|
|
76
|
+
sourcePlatform,
|
|
77
|
+
targetPlatform,
|
|
78
|
+
sourceRepo,
|
|
79
|
+
targetRepo,
|
|
80
|
+
sourceOwner,
|
|
81
|
+
targetOwner,
|
|
82
|
+
options.syncBranches,
|
|
83
|
+
options.publicRepo
|
|
84
|
+
);
|
|
85
|
+
console.log(chalk.green('✅ Mise en miroir terminée avec succès'));
|
|
86
|
+
} catch (error) {
|
|
87
|
+
errorCMD(error);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
const performanceAnalyzer = require('../../core/performance/performanceAnalyzer');
|
|
2
|
+
const metricsCollector = require('../../core/performance/metricsCollector');
|
|
3
|
+
const { getChalk } = require('../../utils/chalk-wrapper');
|
|
4
|
+
const chalk = getChalk();
|
|
5
|
+
|
|
6
|
+
module.exports = {
|
|
7
|
+
name: 'performance',
|
|
8
|
+
description: 'Analyser les performances de push-guardian',
|
|
9
|
+
options: [
|
|
10
|
+
{
|
|
11
|
+
flags: '-a, --analyze',
|
|
12
|
+
description: 'Analyser les performances actuelles'
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
flags: '-c, --compare <path>',
|
|
16
|
+
description: 'Comparer avec un rapport précédent'
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
flags: '-r, --report',
|
|
20
|
+
description: 'Afficher le dernier rapport'
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
flags: '--reset',
|
|
24
|
+
description: 'Réinitialiser les métriques'
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
flags: '-d, --detailed',
|
|
28
|
+
description: 'Afficher les détails complets'
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
flags: '-j, --json',
|
|
32
|
+
description: 'Sortie au format JSON'
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
action: async (options) => {
|
|
36
|
+
try {
|
|
37
|
+
// Vérifier les options conflictuelles
|
|
38
|
+
const actions = [options.analyze, options.compare, options.report, options.reset].filter(Boolean);
|
|
39
|
+
if (actions.length > 1) {
|
|
40
|
+
console.log(
|
|
41
|
+
chalk.red(
|
|
42
|
+
'❌ Options conflictuelles. Veuillez choisir une seule action: --analyze, --compare, --report ou --reset'
|
|
43
|
+
)
|
|
44
|
+
);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Si aucune option n'est fournie, afficher l'aide
|
|
49
|
+
if (!options.analyze && !options.compare && !options.report && !options.reset) {
|
|
50
|
+
console.log(chalk.yellow('Actions disponibles:'));
|
|
51
|
+
console.log(chalk.cyan(' -a, --analyze') + ' - Analyser les performances actuelles');
|
|
52
|
+
console.log(chalk.cyan(' -c, --compare <path>') + ' - Comparer avec un rapport précédent');
|
|
53
|
+
console.log(chalk.cyan(' -r, --report') + ' - Afficher le dernier rapport');
|
|
54
|
+
console.log(chalk.cyan(' --reset') + ' - Réinitialiser les métriques');
|
|
55
|
+
console.log(chalk.gray('\nOptions supplémentaires: -d, --detailed, -j, --json'));
|
|
56
|
+
console.log(chalk.gray('Exemple: npx push-guardian performance --analyze --detailed'));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Exécuter l'action demandée
|
|
61
|
+
if (options.analyze) {
|
|
62
|
+
console.log(chalk.blue('📊 Analyse des performances en cours...'));
|
|
63
|
+
await performanceAnalyzer.analyze(options);
|
|
64
|
+
if (options.detailed) {
|
|
65
|
+
displayDetailedMetrics();
|
|
66
|
+
}
|
|
67
|
+
} else if (options.compare) {
|
|
68
|
+
console.log(chalk.blue('📊 Comparaison des rapports...'));
|
|
69
|
+
await performanceAnalyzer.compare(options.compare, options);
|
|
70
|
+
} else if (options.report) {
|
|
71
|
+
console.log(chalk.blue('📊 Rapport de performance actuel:'));
|
|
72
|
+
displayCurrentMetrics(options);
|
|
73
|
+
} else if (options.reset) {
|
|
74
|
+
metricsCollector.reset();
|
|
75
|
+
console.log(chalk.green('✅ Métriques réinitialisées'));
|
|
76
|
+
}
|
|
77
|
+
} catch (error) {
|
|
78
|
+
console.log(chalk.red('❌ Erreur:'), error.message);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Affiche les métriques actuelles
|
|
86
|
+
*/
|
|
87
|
+
function displayCurrentMetrics(options) {
|
|
88
|
+
const metrics = metricsCollector.getMetrics();
|
|
89
|
+
|
|
90
|
+
if (options.json) {
|
|
91
|
+
console.log(JSON.stringify(metrics, null, 2));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
console.log(chalk.bold('\n📈 Métriques de performance:\n'));
|
|
96
|
+
|
|
97
|
+
// Métriques système
|
|
98
|
+
if (metrics.system) {
|
|
99
|
+
console.log(chalk.cyan('Système:'));
|
|
100
|
+
console.log(` RAM min: ${chalk.yellow(metrics.system.memory.min.toFixed(2))} MB`);
|
|
101
|
+
console.log(` RAM max: ${chalk.yellow(metrics.system.memory.max.toFixed(2))} MB`);
|
|
102
|
+
console.log(` RAM moyenne: ${chalk.yellow(metrics.system.memory.avg.toFixed(2))} MB`);
|
|
103
|
+
console.log(` Threads actifs: ${chalk.yellow(metrics.system.threads.active)}`);
|
|
104
|
+
console.log(` Ressources actives: ${chalk.yellow(metrics.system.threads.resources)}`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (metrics.validation) {
|
|
108
|
+
console.log(chalk.cyan('\nValidation:'));
|
|
109
|
+
console.log(` Durée: ${chalk.yellow(metrics.validation.duration || 0)}ms`);
|
|
110
|
+
console.log(` Fichiers analysés: ${chalk.yellow(metrics.validation.filesAnalyzed || 0)}`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (metrics.plugins) {
|
|
114
|
+
console.log(chalk.cyan('\nPlugins:'));
|
|
115
|
+
console.log(` Chargés: ${chalk.yellow(metrics.plugins.loaded || 0)}`);
|
|
116
|
+
console.log(` Temps de chargement: ${chalk.yellow(metrics.plugins.loadTime || 0)}ms`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (metrics.git) {
|
|
120
|
+
console.log(chalk.cyan('\nGit:'));
|
|
121
|
+
console.log(` Opérations: ${chalk.yellow(metrics.git.operations || 0)}`);
|
|
122
|
+
console.log(` Durée totale: ${chalk.yellow(metrics.git.duration || 0)}ms`);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Afficher les statistiques calculées
|
|
126
|
+
if (metrics.stats) {
|
|
127
|
+
console.log(chalk.cyan('\nStatistiques:'));
|
|
128
|
+
|
|
129
|
+
if (metrics.stats.validation && metrics.stats.validation.count > 0) {
|
|
130
|
+
console.log(
|
|
131
|
+
` Validations: ${chalk.yellow(metrics.stats.validation.count)} (${chalk.yellow(metrics.stats.validation.successRate.toFixed(1))}% succès)`
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (metrics.stats.hooks && metrics.stats.hooks.count > 0) {
|
|
136
|
+
console.log(
|
|
137
|
+
` Hooks: ${chalk.yellow(metrics.stats.hooks.count)} (${chalk.yellow(metrics.stats.hooks.avgDuration.toFixed(2))}ms moy.)`
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (metrics.stats.linting && metrics.stats.linting.count > 0) {
|
|
142
|
+
console.log(
|
|
143
|
+
` Linting: ${chalk.yellow(metrics.stats.linting.count)} (${chalk.yellow(metrics.stats.linting.avgDuration.toFixed(2))}ms moy.)`
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
console.log();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Affiche les métriques détaillées
|
|
153
|
+
*/
|
|
154
|
+
function displayDetailedMetrics() {
|
|
155
|
+
const metrics = metricsCollector.getMetrics();
|
|
156
|
+
|
|
157
|
+
console.log(chalk.bold('\n🔍 Détails des métriques:\n'));
|
|
158
|
+
console.log(JSON.stringify(metrics, null, 2));
|
|
159
|
+
console.log();
|
|
160
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
const pluginRegistry = require('../../core/plugins/pluginRegistry');
|
|
2
|
+
const pluginManager = require('../../core/plugins/pluginManager');
|
|
3
|
+
const { getChalk } = require('../../utils/chalk-wrapper');
|
|
4
|
+
const chalk = getChalk();
|
|
5
|
+
|
|
6
|
+
module.exports = {
|
|
7
|
+
name: 'plugin',
|
|
8
|
+
description: 'Gestion des plugins push-guardian (list, commands, run, enable, disable, help)',
|
|
9
|
+
arguments: [
|
|
10
|
+
{
|
|
11
|
+
name: '<action>',
|
|
12
|
+
description: 'Action a executer (list, commands, run, enable, disable)'
|
|
13
|
+
},
|
|
14
|
+
{ name: '[args...]', description: "Arguments de l'action" }
|
|
15
|
+
],
|
|
16
|
+
action: async (action, args, options) => {
|
|
17
|
+
await pluginCommand([action, ...args], options);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Commande de gestion des plugins
|
|
23
|
+
* @param {Array} args - Arguments de la commande
|
|
24
|
+
* @param {Object} options - Options de la commande
|
|
25
|
+
*/
|
|
26
|
+
async function pluginCommand(args, options) {
|
|
27
|
+
const action = args[0];
|
|
28
|
+
|
|
29
|
+
if (!action) {
|
|
30
|
+
displayHelp();
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
switch (action) {
|
|
35
|
+
case 'enable':
|
|
36
|
+
await handleEnable(args[1]);
|
|
37
|
+
break;
|
|
38
|
+
|
|
39
|
+
case 'disable':
|
|
40
|
+
await handleDisable(args[1]);
|
|
41
|
+
break;
|
|
42
|
+
|
|
43
|
+
case 'list':
|
|
44
|
+
handleList();
|
|
45
|
+
break;
|
|
46
|
+
|
|
47
|
+
case 'commands':
|
|
48
|
+
handleCommands();
|
|
49
|
+
break;
|
|
50
|
+
|
|
51
|
+
case 'run':
|
|
52
|
+
await handleRun(args.slice(1), options);
|
|
53
|
+
break;
|
|
54
|
+
|
|
55
|
+
default:
|
|
56
|
+
console.log(chalk.red(`Action inconnue: ${action}`));
|
|
57
|
+
displayHelp();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Active un plugin
|
|
63
|
+
*/
|
|
64
|
+
async function handleEnable(pluginName) {
|
|
65
|
+
if (!pluginName) {
|
|
66
|
+
console.log(chalk.red('Nom du plugin requis'));
|
|
67
|
+
console.log(chalk.yellow('Usage: push-guardian plugin enable <nom>'));
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
pluginRegistry.enablePlugin(pluginName);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Désactive un plugin
|
|
76
|
+
*/
|
|
77
|
+
async function handleDisable(pluginName) {
|
|
78
|
+
if (!pluginName) {
|
|
79
|
+
console.log(chalk.red('Nom du plugin requis'));
|
|
80
|
+
console.log(chalk.yellow('Usage: push-guardian plugin disable <nom>'));
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
pluginRegistry.disablePlugin(pluginName);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Liste les plugins installés
|
|
89
|
+
*/
|
|
90
|
+
function handleList() {
|
|
91
|
+
pluginManager.listPlugins();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Liste les commandes disponibles
|
|
96
|
+
*/
|
|
97
|
+
function handleCommands() {
|
|
98
|
+
pluginManager.displayCommands();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Exécute une commande d'un plugin
|
|
103
|
+
*/
|
|
104
|
+
async function handleRun(runArgs, options) {
|
|
105
|
+
if (!runArgs || runArgs.length === 0) {
|
|
106
|
+
console.log(chalk.red('Nom de commande requis'));
|
|
107
|
+
console.log(chalk.yellow('Usage: push-guardian plugin run <commande> [args...]'));
|
|
108
|
+
console.log(chalk.yellow(' ou: push-guardian plugin run <plugin> <commande> [args...]'));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
let pluginName;
|
|
113
|
+
let commandName;
|
|
114
|
+
let args = [];
|
|
115
|
+
|
|
116
|
+
const [firstArg, secondArg] = runArgs;
|
|
117
|
+
const pluginInfo = pluginRegistry.getPluginInfo(firstArg);
|
|
118
|
+
const isExplicitPluginSyntax = Boolean(secondArg) && Boolean(pluginInfo);
|
|
119
|
+
|
|
120
|
+
if (isExplicitPluginSyntax) {
|
|
121
|
+
pluginName = firstArg;
|
|
122
|
+
commandName = secondArg;
|
|
123
|
+
args = runArgs.slice(2);
|
|
124
|
+
} else {
|
|
125
|
+
commandName = firstArg;
|
|
126
|
+
args = runArgs.slice(1);
|
|
127
|
+
|
|
128
|
+
const matches = pluginManager.listCommands().filter((cmd) => cmd.command === commandName);
|
|
129
|
+
|
|
130
|
+
if (matches.length === 0) {
|
|
131
|
+
console.log(chalk.red(`Commande plugin introuvable: ${commandName}`));
|
|
132
|
+
console.log(chalk.yellow('Utilisez: push-guardian plugin commands'));
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (matches.length > 1) {
|
|
137
|
+
const plugins = [...new Set(matches.map((m) => m.plugin))].join(', ');
|
|
138
|
+
console.log(chalk.red(`Commande ambiguë: ${commandName}`));
|
|
139
|
+
console.log(chalk.yellow(`Plugins correspondants: ${plugins}`));
|
|
140
|
+
console.log(chalk.yellow(`Utilisez: push-guardian plugin run <plugin> ${commandName} [args...]`));
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
pluginName = matches[0].plugin;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
const result = await pluginManager.executeCommand(pluginName, commandName, args, options);
|
|
149
|
+
if (result !== undefined) {
|
|
150
|
+
console.log(result);
|
|
151
|
+
}
|
|
152
|
+
} catch (error) {
|
|
153
|
+
console.log(chalk.red('Erreur:'), error.message);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Affiche l'aide
|
|
159
|
+
*/
|
|
160
|
+
function displayHelp() {
|
|
161
|
+
console.log(chalk.bold('\nGestion des plugins push-guardian\n'));
|
|
162
|
+
console.log(chalk.cyan('Usage:') + ' push-guardian plugin <action> [options]\n');
|
|
163
|
+
console.log(chalk.bold('Actions disponibles:\n'));
|
|
164
|
+
console.log(' ' + chalk.green('enable <nom>') + ' - Active un plugin');
|
|
165
|
+
console.log(' ' + chalk.green('disable <nom>') + ' - Desactive un plugin');
|
|
166
|
+
console.log(' ' + chalk.green('list') + ' - Liste les plugins installes');
|
|
167
|
+
console.log(' ' + chalk.green('commands') + ' - Liste les commandes disponibles');
|
|
168
|
+
console.log(' ' + chalk.green('run <cmd> [args...]') + ' - Execute une commande unique');
|
|
169
|
+
console.log(' ' + chalk.green('run <plugin> <cmd>') + ' - Execute une commande de plugin');
|
|
170
|
+
console.log();
|
|
171
|
+
}
|