@ovh-ux/manager-static-analysis-kit 0.8.0 → 0.10.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.
Files changed (86) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +59 -69
  3. package/bin/cli-path-config.js +31 -0
  4. package/bin/code-duplication-cli.js +96 -0
  5. package/bin/code-duplication-tests-cli.js +68 -0
  6. package/bin/lint-cli.js +1 -1
  7. package/bin/perf-budgets-cli.js +58 -297
  8. package/bin/perf-budgets-tests-cli.js +1 -3
  9. package/bin/static-dynamic-quality-checks.js +138 -0
  10. package/bin/tests-coverage-cli-tests.js +67 -0
  11. package/bin/tests-coverage-cli.js +137 -0
  12. package/bin/types-coverage-cli.js +195 -0
  13. package/bin/types-coverage-tests-cli.js +68 -0
  14. package/bin/utils/apps-utils.js +64 -0
  15. package/bin/utils/args-parse-utils.js +229 -0
  16. package/bin/utils/file-utils.js +52 -0
  17. package/bin/utils/log-utils.js +29 -0
  18. package/bin/utils/runner-utils.js +85 -0
  19. package/bin/utils/turbo-utils.js +150 -0
  20. package/dist/adapters/code-duplication/helpers/code-duplication-analysis-helper.d.ts +9 -0
  21. package/dist/adapters/code-duplication/helpers/code-duplication-analysis-helper.d.ts.map +1 -0
  22. package/dist/adapters/code-duplication/helpers/code-duplication-analysis-helper.js +294 -0
  23. package/dist/adapters/code-duplication/types/CodeDuplication.d.ts +63 -0
  24. package/dist/adapters/code-duplication/types/CodeDuplication.d.ts.map +1 -0
  25. package/dist/adapters/code-duplication/types/CodeDuplication.js +1 -0
  26. package/dist/adapters/eslint/rules/eslint-prettier.js +1 -1
  27. package/dist/adapters/html-a11y-validation/helpers/html-a11y-tests-setup.d.ts +62 -0
  28. package/dist/adapters/html-a11y-validation/helpers/html-a11y-tests-setup.d.ts.map +1 -0
  29. package/dist/adapters/html-a11y-validation/helpers/html-a11y-tests-setup.js +73 -0
  30. package/dist/adapters/html-w3c-validation/helpers/html-w3c-tests-setup.d.ts +19 -0
  31. package/dist/adapters/html-w3c-validation/helpers/html-w3c-tests-setup.d.ts.map +1 -0
  32. package/dist/adapters/html-w3c-validation/helpers/html-w3c-tests-setup.js +32 -0
  33. package/dist/adapters/html-w3c-validation/helpers/html-w3c-validator.d.ts +4 -0
  34. package/dist/adapters/html-w3c-validation/helpers/html-w3c-validator.d.ts.map +1 -0
  35. package/dist/adapters/html-w3c-validation/helpers/html-w3c-validator.js +89 -0
  36. package/dist/adapters/html-w3c-validation/types/HtmlW3CValidator.d.ts +6 -0
  37. package/dist/adapters/html-w3c-validation/types/HtmlW3CValidator.d.ts.map +1 -0
  38. package/dist/adapters/html-w3c-validation/types/HtmlW3CValidator.js +1 -0
  39. package/dist/adapters/html-w3c-validation/types/globals/vnu-jar.d.ts +5 -0
  40. package/dist/adapters/perf-budgets/helpers/perfs-bundle-analysis-helper.d.ts +1 -1
  41. package/dist/adapters/perf-budgets/helpers/perfs-bundle-analysis-helper.d.ts.map +1 -1
  42. package/dist/adapters/perf-budgets/helpers/perfs-bundle-analysis-helper.js +2 -3
  43. package/dist/adapters/tests-coverage/helpers/tests-coverage-analysis-helper.d.ts +4 -0
  44. package/dist/adapters/tests-coverage/helpers/tests-coverage-analysis-helper.d.ts.map +1 -0
  45. package/dist/adapters/tests-coverage/helpers/tests-coverage-analysis-helper.js +215 -0
  46. package/dist/adapters/tests-coverage/types/TestsCoverage.d.ts +36 -0
  47. package/dist/adapters/tests-coverage/types/TestsCoverage.d.ts.map +1 -0
  48. package/dist/adapters/tests-coverage/types/TestsCoverage.js +6 -0
  49. package/dist/adapters/types-coverage/helpers/types-coverage-analysis-helper.d.ts +4 -0
  50. package/dist/adapters/types-coverage/helpers/types-coverage-analysis-helper.d.ts.map +1 -0
  51. package/dist/adapters/types-coverage/helpers/types-coverage-analysis-helper.js +231 -0
  52. package/dist/adapters/types-coverage/types/TypesCoverage.d.ts +38 -0
  53. package/dist/adapters/types-coverage/types/TypesCoverage.d.ts.map +1 -0
  54. package/dist/adapters/types-coverage/types/TypesCoverage.js +1 -0
  55. package/dist/configs/architecture-analysis-config.d.ts +5 -0
  56. package/dist/configs/architecture-analysis-config.d.ts.map +1 -0
  57. package/dist/configs/{madge-config.js → architecture-analysis-config.js} +1 -1
  58. package/dist/configs/code-duplication-config.d.ts +22 -0
  59. package/dist/configs/code-duplication-config.d.ts.map +1 -0
  60. package/dist/configs/code-duplication-config.js +22 -0
  61. package/dist/configs/{prettier-config.d.ts → code-formatter-config.d.ts} +1 -1
  62. package/dist/configs/code-formatter-config.d.ts.map +1 -0
  63. package/dist/configs/file-globs-config.d.ts +0 -3
  64. package/dist/configs/file-globs-config.d.ts.map +1 -1
  65. package/dist/configs/file-globs-config.js +0 -3
  66. package/dist/configs/naming-conventions-config.d.ts.map +1 -1
  67. package/dist/configs/naming-conventions-config.js +2 -0
  68. package/dist/configs/shared-exclusion-patterns.d.ts +1 -0
  69. package/dist/configs/shared-exclusion-patterns.d.ts.map +1 -1
  70. package/dist/configs/shared-exclusion-patterns.js +23 -1
  71. package/dist/configs/tests-coverage-config.d.ts +12 -0
  72. package/dist/configs/tests-coverage-config.d.ts.map +1 -0
  73. package/dist/configs/tests-coverage-config.js +11 -0
  74. package/dist/configs/types-coverage-config.d.ts +33 -0
  75. package/dist/configs/types-coverage-config.d.ts.map +1 -0
  76. package/dist/configs/types-coverage-config.js +24 -0
  77. package/dist/tsconfig.tsbuildinfo +1 -1
  78. package/package.json +32 -7
  79. package/bin/cli-utils.js +0 -56
  80. package/dist/configs/jscpd-config.d.ts +0 -7
  81. package/dist/configs/jscpd-config.d.ts.map +0 -1
  82. package/dist/configs/jscpd-config.js +0 -7
  83. package/dist/configs/madge-config.d.ts +0 -5
  84. package/dist/configs/madge-config.d.ts.map +0 -1
  85. package/dist/configs/prettier-config.d.ts.map +0 -1
  86. /package/dist/configs/{prettier-config.js → code-formatter-config.js} +0 -0
package/CHANGELOG.md CHANGED
@@ -3,6 +3,43 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [0.10.0](https://github.com/ovh/manager/compare/@ovh-ux/manager-static-analysis-kit@0.9.0...@ovh-ux/manager-static-analysis-kit@0.10.0) (2025-10-02)
7
+
8
+
9
+ ### Features
10
+
11
+ * add loose types calculation to types reports ([2398431](https://github.com/ovh/manager/commit/2398431ae3bf9e5300683894fa5fe6a12371108f)), closes [#MANAGER-19923](https://github.com/ovh/manager/issues/MANAGER-19923)
12
+ * clarify loose types metrics ([ef00a39](https://github.com/ovh/manager/commit/ef00a39fce3cd661ba89673cf9263637a5ec31b8)), closes [#MANAGER-19923](https://github.com/ovh/manager/issues/MANAGER-19923)
13
+ * enhance code duplication reporting ([bfbe364](https://github.com/ovh/manager/commit/bfbe3644d31bde25229dad7cfd2ff0446440fd49)), closes [#MANAGER-19923](https://github.com/ovh/manager/issues/MANAGER-19923)
14
+ * enhance loose types report format ([1688577](https://github.com/ovh/manager/commit/168857738ba67e1406e5fb138c2d2f0c3789305b)), closes [#MANAGER-19923](https://github.com/ovh/manager/issues/MANAGER-19923)
15
+ * improve static and dynamic reporting ([09de1f8](https://github.com/ovh/manager/commit/09de1f86d2e57a7ba61612ae3df45d121da39908)), closes [#MANAGER-19923](https://github.com/ovh/manager/issues/MANAGER-19923)
16
+
17
+
18
+
19
+
20
+
21
+ # [0.9.0](https://github.com/ovh/manager/compare/@ovh-ux/manager-static-analysis-kit@0.8.0...@ovh-ux/manager-static-analysis-kit@0.9.0) (2025-09-18)
22
+
23
+
24
+ ### Bug Fixes
25
+
26
+ * md lint issues ([0d2fe8e](https://github.com/ovh/manager/commit/0d2fe8e49f3594f5abc9d8e6b306b0b71a065c6c)), closes [#MANAGER-17958](https://github.com/ovh/manager/issues/MANAGER-17958)
27
+
28
+
29
+ ### Features
30
+
31
+ * a11y and w3c unit tests expectations ([5a2d75d](https://github.com/ovh/manager/commit/5a2d75dba8a8877253871aa0a7c12dc2c79d1423)), closes [#MANAGER-17958](https://github.com/ovh/manager/issues/MANAGER-17958)
32
+ * code duplication analysis ([d431254](https://github.com/ovh/manager/commit/d4312543737541257185be6e54358dfb49285d51)), closes [#MANAGER-17958](https://github.com/ovh/manager/issues/MANAGER-17958)
33
+ * extend tests cases ([69ad98b](https://github.com/ovh/manager/commit/69ad98b3d02c615996f5c4ad9067a93a10b58ec4)), closes [#MANAGER-17958](https://github.com/ovh/manager/issues/MANAGER-17958)
34
+ * global unit tests coverage reports ([e11191a](https://github.com/ovh/manager/commit/e11191a24609d56e76fd3eacaeac79d4c3b1ab4a)), closes [#MANAGER-17958](https://github.com/ovh/manager/issues/MANAGER-17958)
35
+ * single html entry for all static and dynamic checks ([0556811](https://github.com/ovh/manager/commit/0556811b4f15ad3288f34b3ba8e468a1c9fee061)), closes [#MANAGER-18576](https://github.com/ovh/manager/issues/MANAGER-18576)
36
+ * typeScript types coverage analysis ([65f7d2f](https://github.com/ovh/manager/commit/65f7d2f22e4c68aa897d135e11642cd26073846b)), closes [#MANAGER-17958](https://github.com/ovh/manager/issues/MANAGER-17958)
37
+ * update documentation ([316add2](https://github.com/ovh/manager/commit/316add2055f4a27a3446d5361ee26e0baadbf2b8)), closes [#MANAGER-17958](https://github.com/ovh/manager/issues/MANAGER-17958)
38
+
39
+
40
+
41
+
42
+
6
43
  # [0.8.0](https://github.com/ovh/manager/compare/@ovh-ux/manager-static-analysis-kit@0.7.1...@ovh-ux/manager-static-analysis-kit@0.8.0) (2025-09-11)
7
44
 
8
45
 
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # 🧪static-analysis-kit
1
+ # 🧪 static-analysis-kit
2
2
 
3
3
  A modular, extensible, and future-ready toolkit for defining, adapting, and sharing static analysis rules across projects in the `manager` monorepo.
4
4
 
@@ -6,103 +6,93 @@ A modular, extensible, and future-ready toolkit for defining, adapting, and shar
6
6
 
7
7
  ## 🚀 What Is It?
8
8
 
9
- `static-analysis-kit` provides a unified platform for code quality, complexity, duplication, and architectural analysis. It separates semantic rule definitions from tool-specific integrations using a clean adapter-based architecture.
9
+ `static-analysis-kit` provides a unified platform for **static & dynamic quality checks**: linting, duplication, type coverage, tests coverage, and performance budgets.
10
10
 
11
- It currently supports:
12
- - ESLint (flat config)
13
- - Madge (dependency graph & circular analysis)
14
- - JSCPD (code duplication detection)
15
- - Code Health Meter (complexity, Halstead, maintainability, SLOC, architecture)
11
+ It separates semantic rule definitions from tool-specific integrations using a clean adapter-based architecture.
16
12
 
17
13
  ---
18
14
 
19
- ## 🎯 Why We Built This
15
+ ## 📦 Tools Exposed by the Kit
20
16
 
21
- - Reuse rules across projects and tools
22
- - Avoid duplication of `.eslintrc`, `.prettierrc`, `.madgerc`, etc.
23
- - Standardize how we measure code health and enforce architectural boundaries
24
- - Enable safe and gradual migration to new tooling
17
+ The kit currently provides:
25
18
 
26
- ---
19
+ - **ESLint** (flat config, adapters for React, TS, a11y, imports, naming, Storybook, Tailwind, TanStack, Vitest)
20
+ - **Code Duplication Reports** (`manager-code-duplication`)
21
+ - **Performance Budgets** (`manager-perf-budgets`)
22
+ - **Tests Coverage Reports** (`manager-tests-coverage`)
23
+ - **Types Coverage Reports** (`manager-types-coverage`)
24
+ - **W3C & A11Y Unit Tests Matchers** (`expect(container).toBeAccessible()`, `await expect(html).toBeValidHtml()`)
27
25
 
28
- ## 🧱 Structure Overview
26
+ Coming soon:
27
+ - **Madge** (dependency graph & circular analysis)
28
+ - **Code Health Meter** (complexity, Halstead, maintainability, SLOC)
29
29
 
30
- ```
31
- static-analysis-kit/
32
- ├── src/
33
- │ ├── code-analysis.ts # Central entry point (exports adapters)
34
- │ ├── configs/ # Tool-agnostic semantic rule definitions
35
- │ │ ├── complexity.ts
36
- │ │ ├── madge-options.ts
37
- │ │ └── jscpd-options.ts
38
- │ └── adapters/
39
- │ ├── eslint/ # ESLint flat config + rules
40
- │ │ ├── config/
41
- │ │ │ └── eslint.config.ts
42
- │ │ └── rules/
43
- │ ├── madge/ # Madge analysis adapter
44
- │ ├── jscpd/ # JSCPD (duplication) adapter
45
- │ ├── prettier/ # Optional: shared formatting config
46
- │ └── code-health-meter/ # Halstead, MI, Cyclomatic, SLOC
47
- ```
30
+ > Each tool has its own README inside the kit with full usage & configuration details.
31
+ > See:
32
+ > - [Code Duplication](src/adapters/code-duplication/README.md)
33
+ > - [Performance Budgets](src/adapters/perf-budgets/README.md)
34
+ > - [Tests Coverage](src/adapters/tests-coverage/README.md)
35
+ > - [Types Coverage](src/adapters/types-coverage/README.md)
36
+ > - [HTML W3C Validation](src/adapters/html-w3c-validation/README.md)
37
+ > - [HTML Accessibility Matcher](src/adapters/html-a11y-validation/README.md)
48
38
 
49
39
  ---
50
40
 
51
- ## 🛠️ Usage in an App
52
-
53
- ```ts
54
- // apps/zimbra/eslint.config.ts
55
- import { eslintConfig } from '@ovh-ux/manager-static-analysis-kit';
56
-
57
- export default [...eslintConfig];
58
- ```
41
+ ## 🧑‍💻 Combined Quality Checks
59
42
 
60
- This will apply all enabled ESLint rule groups from the toolkit, using flat config format (ESLint v8+).
43
+ The kit also provides a **single entrypoint** for running all static & dynamic quality checks in parallel:
61
44
 
62
- ```ts
63
- // apps/zimbra/prettier.config.ts
64
- import { prettierConfig } from '@ovh-ux/manager-static-analysis-kit';
45
+ ```bash
46
+ # Run all quality checks
47
+ yarn manager-static-dynamic-quality-checks
65
48
 
66
- export default [...prettierConfig];
49
+ # Run only tests-related checks
50
+ yarn manager-static-dynamic-quality-checks --tests
67
51
  ```
68
52
 
69
- ---
53
+ ### Run by Type
70
54
 
71
- ## 🧠 Design Principles
55
+ You can also target subsets of checks:
72
56
 
73
- - **Composable**: Adapters are modular, rules are grouped by category
74
- - **Decoupled**: Semantic configs live separately from tool logic
75
- - **Pluggable**: Easy to add new tools (e.g. Biome, Oxlint)
76
- - **Testable**: Configs are plain TS, easy to mock and verify
57
+ ```bash
58
+ yarn manager-code-duplication
59
+ yarn manager-perf-budgets
60
+ yarn manager-tests-coverage
61
+ yarn manager-types-coverage
62
+ ```
77
63
 
78
64
  ---
79
65
 
80
- ## 🔮 Future Flexibility
81
-
82
- This architecture is designed to easily accommodate:
83
-
84
- - `biome/` adapter (Rust-based formatter/linter)
85
- - `oxlint/` adapter (high-performance Rust linter)
86
- - `depcruise/`, `pmd/`, `stylelint/` or internal tools
66
+ ## 🧱 Structure Overview
87
67
 
88
- Each would follow the same adapter pattern and pull from shared `configs/` where applicable.
68
+ ```
69
+ static-analysis-kit/
70
+ ├── src/
71
+ │ ├── code-analysis.ts # Central entry point (exports adapters)
72
+ │ ├── configs/ # Tool-agnostic semantic rule definitions
73
+ │ └── adapters/ # Tool integrations
74
+ │ ├── eslint/
75
+ │ ├── code-duplication/ # Duplication reports
76
+ │ ├── perf-budgets/ # Performance analyzer
77
+ │ ├── tests-coverage/ # Test coverage reports
78
+ │ ├── types-coverage/ # TS coverage reports
79
+ │ ├── madge/ # Coming soon
80
+ │ └── code-health-meter/ # Coming soon
81
+ ```
89
82
 
90
83
  ---
91
84
 
92
- ## 🧑‍💻 Contributing
93
-
94
- If you’re adding a new rule or adapter:
85
+ ## 🧠 Design Principles
95
86
 
96
- 1. Put semantic/shared config in `configs/` if reusable.
97
- 2. Create a new adapter directory in `adapters/` (e.g., `eslint`, `madge`).
98
- 3. Add a domain-specific config, transformer, or wrapper.
99
- 4. Wire into `code-analysis.ts` as needed.
100
- 5. Document your addition.
87
+ - **Composable**: Adapters are modular, rules are grouped by category.
88
+ - **Decoupled**: Semantic configs live separately from tool logic.
89
+ - **Pluggable**: Easy to add new tools (e.g., Biome, Oxlint).
90
+ - **CI/CD Ready**: All tools produce JSON + HTML reports for pipelines.
101
91
 
102
92
  ---
103
93
 
104
94
  ## 📬 Feedback Welcome
105
95
 
106
- The goal is to create a robust, composable, and organization-wide standard for static analysis.
96
+ The goal is to create a **robust, composable, and organization-wide standard** for static analysis and dynamic quality checks.
107
97
 
108
- Feel free to suggest improvements or new integrations!
98
+ Suggestions & contributions are welcome.
@@ -0,0 +1,31 @@
1
+ import path from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
3
+
4
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
5
+
6
+ export const rootDir = path.resolve(__dirname, '../../..');
7
+ export const outputRootDir = path.resolve(__dirname, '../../../../static-dynamic-quality-reports');
8
+
9
+ export const appsDir = path.join(rootDir, 'manager/apps');
10
+
11
+ export const bundleAnalyzerBinPath = path.resolve(__dirname, '../node_modules/.bin/analyze');
12
+ export const perfBudgetsReportDirName = 'perf-budgets-reports';
13
+ export const perfBudgetCombinedJsonReportName = 'perf-budgets-combined-report.json';
14
+ export const perfBudgetCombinedHtmlReportName = 'perf-budgets-combined-report.html';
15
+
16
+ export const jscpdBinPath = path.resolve(__dirname, '../node_modules/.bin/jscpd');
17
+ export const codeDupReportsRootDirName = 'code-duplication-reports';
18
+ export const codeDupCombinedJsonReportName = 'code-duplication-combined-report.json';
19
+ export const codeDupCombinedHtmlReportName = 'code-duplication-combined-report.html';
20
+
21
+ export const testsCoverageReportsRootDirName = 'tests-coverage-reports';
22
+ export const testsCoverageCombinedJsonReportName = 'tests-coverage-combined-report.json';
23
+ export const testsCoverageCombinedHtmlReportName = 'tests-coverage-combined-report.html';
24
+
25
+ export const tsTypesCoverageBin = path.resolve(
26
+ __dirname,
27
+ '../node_modules/.bin/typescript-coverage-report',
28
+ );
29
+ export const typesCoverageReportsRootDirName = 'types-coverage-reports';
30
+ export const typesCoverageCombinedJsonReportName = 'types-coverage-combined-report.json';
31
+ export const typesCoverageCombinedHtmlReportName = 'types-coverage-combined-report.html';
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import process from 'node:process';
5
+
6
+ import {
7
+ collectCodeDuplication,
8
+ generateCodeDuplicationHtml,
9
+ } from '../dist/adapters/code-duplication/helpers/code-duplication-analysis-helper.js';
10
+ import {
11
+ appsDir,
12
+ codeDupCombinedHtmlReportName,
13
+ codeDupCombinedJsonReportName,
14
+ codeDupReportsRootDirName,
15
+ jscpdBinPath,
16
+ outputRootDir,
17
+ } from './cli-path-config.js';
18
+ import { buildCodeDuplicationArgs, parseCliTargets } from './utils/args-parse-utils.js';
19
+ import { logError, logInfo, logWarn } from './utils/log-utils.js';
20
+ import { ensureBinExists, runAppsAnalysis, runCommand } from './utils/runner-utils.js';
21
+
22
+ /**
23
+ * Run `jscpd` code duplication analysis for a single app.
24
+ *
25
+ * @param {string} appDir - Absolute path to the app’s root directory.
26
+ * @param {string} appShortName - Shortened app name (from package.json or folder).
27
+ * @returns {boolean} True if analysis completed successfully, false otherwise.
28
+ */
29
+ function runAppCodeDuplication(appDir, appShortName) {
30
+ try {
31
+ const absoluteOutputDir = path.join(outputRootDir, codeDupReportsRootDirName, appShortName);
32
+ fs.mkdirSync(absoluteOutputDir, { recursive: true });
33
+
34
+ // Relative output path from the app dir (keeps paths clean inside HTML reports)
35
+ const relativeOutputDir = path.relative(appDir, absoluteOutputDir);
36
+
37
+ logInfo(`Running jscpd for ${appShortName} → ${absoluteOutputDir}`);
38
+
39
+ const args = [...buildCodeDuplicationArgs(relativeOutputDir), appDir];
40
+ const ok = runCommand(jscpdBinPath, args, appDir);
41
+
42
+ // Validate expected reports
43
+ const jsonReport = path.join(absoluteOutputDir, 'jscpd-report.json');
44
+ const htmlReport = path.join(absoluteOutputDir, 'html', 'index.html');
45
+
46
+ if (!fs.existsSync(jsonReport)) {
47
+ logWarn(`⚠️ Missing jscpd-report.json at ${jsonReport}`);
48
+ }
49
+ if (!fs.existsSync(htmlReport)) {
50
+ logWarn(`⚠️ Missing html/index.html at ${htmlReport}`);
51
+ }
52
+
53
+ return ok;
54
+ } catch (err) {
55
+ logError(`Fatal error: ${err.stack || err.message}`);
56
+ return false;
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Main CLI entrypoint for code duplication analysis.
62
+ *
63
+ * - Ensures the `jscpd` binary is available
64
+ * - Resolves target app folders from CLI args
65
+ * - Runs per-app analysis via {@link runAppCodeDuplication}
66
+ * - Generates combined JSON + HTML reports across all apps
67
+ *
68
+ * Exits process with code `1` if no apps were analyzed successfully
69
+ * or if a fatal error occurred.
70
+ */
71
+ function main() {
72
+ try {
73
+ ensureBinExists(jscpdBinPath, 'jscpd');
74
+
75
+ const { appFolders } = parseCliTargets(appsDir);
76
+
77
+ runAppsAnalysis({
78
+ appsDir,
79
+ appFolders,
80
+ requireReact: true,
81
+ binaryLabel: 'Code duplication',
82
+ appRunner: runAppCodeDuplication,
83
+ reportsRootDirName: codeDupReportsRootDirName,
84
+ combinedJson: codeDupCombinedJsonReportName,
85
+ combinedHtml: codeDupCombinedHtmlReportName,
86
+ collectFn: collectCodeDuplication,
87
+ generateHtmlFn: generateCodeDuplicationHtml,
88
+ outputRootDir,
89
+ });
90
+ } catch (err) {
91
+ logError(`Fatal error: ${err.stack || err.message}`);
92
+ process.exit(1);
93
+ }
94
+ }
95
+
96
+ main();
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env node
2
+ import { spawnSync } from 'node:child_process';
3
+
4
+ import { logError, logInfo } from './utils/log-utils.js';
5
+
6
+ // Define the set of validation test cases for code-duplication CLI
7
+ const cases = [
8
+ // Debug only — very slow, runs across all apps
9
+ // { name: 'Auto-discovery (all apps)', cmd: 'yarn manager-code-duplication', expect: 0 },
10
+
11
+ { name: 'Single app (zimbra)', cmd: 'yarn manager-code-duplication --app zimbra', expect: 0 },
12
+ {
13
+ name: 'Multiple apps (container,zimbra,web-ongoing-operations,key-management-service)',
14
+ cmd: 'yarn manager-code-duplication --apps container,zimbra,web-ongoing-operations,key-management-service',
15
+ expect: 0,
16
+ },
17
+ {
18
+ name: 'Single package (container)',
19
+ cmd: 'yarn manager-code-duplication --package @ovh-ux/manager-container-app',
20
+ expect: 0,
21
+ },
22
+ {
23
+ name: 'Multiple packages (zimbra,pci-workflow)',
24
+ cmd: 'yarn manager-code-duplication --packages @ovh-ux/manager-zimbra-app,@ovh-ux/manager-pci-workflow-app',
25
+ expect: 0,
26
+ },
27
+ {
28
+ name: 'Mixed valid+invalid apps',
29
+ cmd: 'yarn manager-code-duplication --apps zimbra,unknown-app,container',
30
+ expect: 0,
31
+ },
32
+ {
33
+ name: 'Mixed valid+invalid packages',
34
+ cmd: 'yarn manager-code-duplication --packages @ovh-ux/manager-zimbra-app,@ovh-ux/manager-ghost-app',
35
+ expect: 0,
36
+ },
37
+ {
38
+ name: 'All invalid apps',
39
+ cmd: 'yarn manager-code-duplication --apps doesnotexist1,doesnotexist2',
40
+ expect: 1,
41
+ },
42
+ {
43
+ name: 'All invalid packages',
44
+ cmd: 'yarn manager-code-duplication --packages @ovh-ux/manager-ghost-app,@ovh-ux/manager-missing-app',
45
+ expect: 1,
46
+ },
47
+ ];
48
+
49
+ let failed = 0;
50
+
51
+ for (const test of cases) {
52
+ logInfo(`\n🔎 Running: ${test.name}`);
53
+ const [bin, ...args] = test.cmd.split(' ');
54
+ const result = spawnSync(bin, args, { stdio: 'inherit', shell: true });
55
+
56
+ if (result.status !== test.expect) {
57
+ logError(`❌ ${test.name} failed (expected exit ${test.expect}, got ${result.status})`);
58
+ failed++;
59
+ } else {
60
+ logInfo(`✅ ${test.name} passed`);
61
+ }
62
+ }
63
+
64
+ if (failed > 0) {
65
+ logError(`\n❌ ${failed} test(s) failed.`);
66
+ } else {
67
+ logInfo('\n🎉 All code-duplication-tests CLI validation tests passed!');
68
+ }
package/bin/lint-cli.js CHANGED
@@ -5,7 +5,7 @@ import { dirname, join, resolve } from 'node:path';
5
5
  import process, { cwd } from 'node:process';
6
6
  import { fileURLToPath, pathToFileURL } from 'node:url';
7
7
 
8
- import { logError, logInfo } from './cli-utils.js';
8
+ import { logError, logInfo } from './utils/log-utils.js';
9
9
 
10
10
  const __dirname = dirname(fileURLToPath(import.meta.url));
11
11
  const userCwd = cwd();