pr-checkmate 1.22.7 → 1.23.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/README.md +101 -333
- package/cspell.json +9 -1
- package/dist/cli.js +32 -2
- package/dist/config/constants.d.ts +25 -1
- package/dist/config/constants.js +157 -38
- package/dist/config/index.d.ts +15 -2
- package/dist/config/index.js +28 -7
- package/dist/config/loader.js +5 -1
- package/dist/core/checks/dependencies/banned-imports.d.ts +2 -0
- package/dist/core/checks/dependencies/banned-imports.js +71 -0
- package/dist/core/checks/{circular-deps.d.ts → dependencies/circular-deps.d.ts} +1 -1
- package/dist/core/checks/{circular-deps.js → dependencies/circular-deps.js} +9 -10
- package/dist/core/checks/{dependency-check.d.ts → dependencies/dependency-check.d.ts} +1 -1
- package/dist/core/checks/{dependency-check.js → dependencies/dependency-check.js} +3 -3
- package/dist/core/checks/{license-check.d.ts → dependencies/license-check.d.ts} +1 -1
- package/dist/core/checks/{license-check.js → dependencies/license-check.js} +3 -3
- package/dist/core/checks/{npm-audit.d.ts → dependencies/npm-audit.d.ts} +1 -1
- package/dist/core/checks/{npm-audit.js → dependencies/npm-audit.js} +3 -3
- package/dist/core/checks/{outdated-deps.d.ts → dependencies/outdated-deps.d.ts} +1 -1
- package/dist/core/checks/{outdated-deps.js → dependencies/outdated-deps.js} +3 -3
- package/dist/core/checks/dependencies/vuln-scan.d.ts +9 -0
- package/dist/core/checks/dependencies/vuln-scan.js +41 -0
- package/dist/core/checks/findings.d.ts +37 -1
- package/dist/core/checks/findings.js +80 -3
- package/dist/core/checks/git/custom-rules.d.ts +2 -0
- package/dist/core/checks/git/custom-rules.js +102 -0
- package/dist/core/checks/{diff-smell.d.ts → git/diff-smell.d.ts} +1 -1
- package/dist/core/checks/{diff-smell.js → git/diff-smell.js} +3 -3
- package/dist/core/checks/git/large-files.d.ts +2 -0
- package/dist/core/checks/git/large-files.js +83 -0
- package/dist/core/checks/git/leftover-debug.d.ts +2 -0
- package/dist/core/checks/git/leftover-debug.js +77 -0
- package/dist/core/checks/git/lockfile-drift.d.ts +2 -0
- package/dist/core/checks/git/lockfile-drift.js +114 -0
- package/dist/core/checks/git/merge-conflict.d.ts +2 -0
- package/dist/core/checks/git/merge-conflict.js +109 -0
- package/dist/core/checks/git/missing-tests.d.ts +2 -0
- package/dist/core/checks/git/missing-tests.js +92 -0
- package/dist/core/checks/git/todo-fixme.d.ts +7 -0
- package/dist/core/checks/git/todo-fixme.js +74 -0
- package/dist/core/checks/{cpp-format.d.ts → languages/cpp-format.d.ts} +1 -1
- package/dist/core/checks/{cpp-format.js → languages/cpp-format.js} +3 -3
- package/dist/core/checks/languages/csharp-format.d.ts +13 -0
- package/dist/core/checks/languages/csharp-format.js +52 -0
- package/dist/core/checks/languages/go-format.d.ts +8 -0
- package/dist/core/checks/languages/go-format.js +48 -0
- package/dist/core/checks/languages/go-lint.d.ts +8 -0
- package/dist/core/checks/languages/go-lint.js +48 -0
- package/dist/core/checks/{kotlin-lint.d.ts → languages/kotlin-lint.d.ts} +1 -1
- package/dist/core/checks/{kotlin-lint.js → languages/kotlin-lint.js} +13 -17
- package/dist/core/checks/{lint.d.ts → languages/lint.d.ts} +1 -1
- package/dist/core/checks/{lint.js → languages/lint.js} +25 -14
- package/dist/core/checks/languages/php-format.d.ts +9 -0
- package/dist/core/checks/languages/php-format.js +49 -0
- package/dist/core/checks/{prettier.d.ts → languages/prettier.d.ts} +1 -1
- package/dist/core/checks/{prettier.js → languages/prettier.js} +10 -10
- package/dist/core/checks/{python-format.d.ts → languages/python-format.d.ts} +1 -1
- package/dist/core/checks/{python-format.js → languages/python-format.js} +3 -3
- package/dist/core/checks/{python-lint.d.ts → languages/python-lint.d.ts} +1 -1
- package/dist/core/checks/{python-lint.js → languages/python-lint.js} +3 -3
- package/dist/core/checks/languages/python-typecheck.d.ts +9 -0
- package/dist/core/checks/languages/python-typecheck.js +66 -0
- package/dist/core/checks/languages/ruby-lint.d.ts +8 -0
- package/dist/core/checks/languages/ruby-lint.js +50 -0
- package/dist/core/checks/languages/rust-format.d.ts +9 -0
- package/dist/core/checks/languages/rust-format.js +45 -0
- package/dist/core/checks/languages/rust-lint.d.ts +8 -0
- package/dist/core/checks/languages/rust-lint.js +50 -0
- package/dist/core/checks/{swift-lint.d.ts → languages/swift-lint.d.ts} +1 -1
- package/dist/core/checks/{swift-lint.js → languages/swift-lint.js} +13 -17
- package/dist/core/checks/{typecheck.d.ts → languages/typecheck.d.ts} +1 -1
- package/dist/core/checks/{typecheck.js → languages/typecheck.js} +3 -3
- package/dist/core/checks/{commitlint.d.ts → pr/commitlint.d.ts} +1 -1
- package/dist/core/checks/{commitlint.js → pr/commitlint.js} +4 -4
- package/dist/core/checks/{pr-body.d.ts → pr/pr-body.d.ts} +1 -1
- package/dist/core/checks/{pr-body.js → pr/pr-body.js} +2 -2
- package/dist/core/checks/{pr-size-check.d.ts → pr/pr-size-check.d.ts} +1 -1
- package/dist/core/checks/{pr-size-check.js → pr/pr-size-check.js} +13 -11
- package/dist/core/checks/{pr-title-lint.d.ts → pr/pr-title-lint.d.ts} +1 -1
- package/dist/core/checks/{pr-title-lint.js → pr/pr-title-lint.js} +2 -2
- package/dist/core/checks/quality/case-collision.d.ts +8 -0
- package/dist/core/checks/quality/case-collision.js +40 -0
- package/dist/core/checks/quality/config-validation.d.ts +8 -0
- package/dist/core/checks/quality/config-validation.js +63 -0
- package/dist/core/checks/quality/coverage.d.ts +2 -0
- package/dist/core/checks/quality/coverage.js +63 -0
- package/dist/core/checks/{dead-code.d.ts → quality/dead-code.d.ts} +1 -1
- package/dist/core/checks/{dead-code.js → quality/dead-code.js} +4 -4
- package/dist/core/checks/{duplicate-check.d.ts → quality/duplicate-check.d.ts} +1 -1
- package/dist/core/checks/{duplicate-check.js → quality/duplicate-check.js} +11 -15
- package/dist/core/checks/quality/license-header.d.ts +7 -0
- package/dist/core/checks/quality/license-header.js +74 -0
- package/dist/core/checks/{markdown-lint.d.ts → quality/markdown-lint.d.ts} +1 -1
- package/dist/core/checks/{markdown-lint.js → quality/markdown-lint.js} +8 -21
- package/dist/core/checks/{spellcheck.d.ts → quality/spellcheck.d.ts} +1 -1
- package/dist/core/checks/{spellcheck.js → quality/spellcheck.js} +11 -19
- package/dist/core/checks/{diff-security.d.ts → security/diff-security.d.ts} +1 -1
- package/dist/core/checks/security/diff-security.js +262 -0
- package/dist/core/checks/security/dockerfile-security.d.ts +2 -0
- package/dist/core/checks/security/dockerfile-security.js +92 -0
- package/dist/core/checks/security/migration-safety.d.ts +2 -0
- package/dist/core/checks/security/migration-safety.js +110 -0
- package/dist/core/checks/{security.d.ts → security/security.d.ts} +1 -1
- package/dist/core/checks/{security.js → security/security.js} +4 -4
- package/dist/core/checks/{sensitive-file-guard.d.ts → security/sensitive-file-guard.d.ts} +1 -1
- package/dist/core/checks/{sensitive-file-guard.js → security/sensitive-file-guard.js} +4 -4
- package/dist/core/checks/security/workflow-security.d.ts +2 -0
- package/dist/core/checks/security/workflow-security.js +75 -0
- package/dist/core/context.js +54 -10
- package/dist/core/registry.js +73 -28
- package/dist/core/reporters.d.ts +4 -3
- package/dist/core/reporters.js +104 -4
- package/dist/core/run-checks.js +21 -3
- package/dist/core/targets.d.ts +17 -1
- package/dist/core/targets.js +74 -4
- package/dist/core/types.d.ts +13 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -1
- package/dist/init.js +86 -8
- package/dist/interfaces/index.d.ts +101 -1
- package/dist/scripts/copy-configs.js +6 -1
- package/dist/utils/detect-language.d.ts +1 -1
- package/dist/utils/detect-language.js +32 -3
- package/dist/utils/glob.d.ts +10 -0
- package/dist/utils/glob.js +25 -0
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +1 -1
- package/eslint-default-rules.json +62 -0
- package/eslint.config.mjs +6 -66
- package/package.json +3 -1
- package/pr-checkmate.schema.json +166 -0
- package/src/config/cspell.json +9 -1
- package/src/config/eslint-default-rules.json +62 -0
- package/src/config/pr-checkmate.schema.json +166 -0
- package/dist/core/checks/diff-security.js +0 -145
- package/dist/utils/delta.d.ts +0 -5
- package/dist/utils/delta.js +0 -53
- package/src/config/eslint.config.mjs +0 -180
- /package/dist/core/checks/{ruff-shared.d.ts → languages/ruff-shared.d.ts} +0 -0
- /package/dist/core/checks/{ruff-shared.js → languages/ruff-shared.js} +0 -0
package/dist/config/constants.js
CHANGED
|
@@ -3,57 +3,109 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.CONFIG_FILE = exports.documentation = exports.DEFAULT_ALLOW_PACKAGES = exports.DEFAULT_COMMANDS = exports.SOURCE_EXTENSIONS = exports.DUPLICATE_CODE_FORMATS = exports.CONFIG_FILE_PATTERNS = exports.DEAD_CODE_IGNORE_DEFAULTS = exports.DUPLICATE_IGNORE_DEFAULTS = exports.IGNORE_PATTERNS = void 0;
|
|
6
|
+
exports.KNOWN_CONFIG_KEYS = exports.CONFIG_FILE = exports.documentation = exports.DEFAULT_ALLOW_PACKAGES = exports.DEFAULT_COMMANDS = exports.SOURCE_EXTENSIONS = exports.DUPLICATE_CODE_FORMATS = exports.CONFIG_FILE_PATTERNS = exports.DEAD_CODE_IGNORE_DEFAULTS = exports.DUPLICATE_IGNORE_DEFAULTS = exports.IGNORE_PATTERNS = exports.IGNORED_DIRS = void 0;
|
|
7
7
|
const node_path_1 = __importDefault(require("node:path"));
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* Build output, dependency, tooling, and report directories that are never
|
|
10
|
+
* product code. Every check excludes them by directory-name segment match (see
|
|
11
|
+
* `targets.ts`): a match on any segment of a path drops the file. Untracked
|
|
12
|
+
* build dirs are already excluded because checks read git-tracked files only —
|
|
13
|
+
* this list additionally covers dirs that repos commonly *commit* (`.github`,
|
|
14
|
+
* `.vscode`, `.idea`, `.claude`) and any checked-in build artifacts.
|
|
15
|
+
*
|
|
16
|
+
* Covers the common ecosystems: Node/JS/web, Python, Java/Kotlin/Gradle/Android,
|
|
17
|
+
* Swift/iOS/Xcode, and C/C++/CMake. Add more here.
|
|
18
|
+
*/
|
|
19
|
+
exports.IGNORED_DIRS = [
|
|
20
|
+
// VCS, editors, and CI/tooling config
|
|
21
|
+
'.git',
|
|
22
|
+
'.github',
|
|
23
|
+
'.gitlab',
|
|
24
|
+
'.vscode',
|
|
25
|
+
'.vs',
|
|
26
|
+
'.idea',
|
|
27
|
+
'.claude',
|
|
28
|
+
'.cursor',
|
|
29
|
+
'.husky',
|
|
30
|
+
'.circleci',
|
|
31
|
+
// Node / JS / web — build output & caches
|
|
32
|
+
'node_modules',
|
|
33
|
+
'dist',
|
|
34
|
+
'build',
|
|
35
|
+
'build-release',
|
|
36
|
+
'out',
|
|
37
|
+
'coverage',
|
|
38
|
+
'.next',
|
|
39
|
+
'.nuxt',
|
|
40
|
+
'.svelte-kit',
|
|
41
|
+
'.turbo',
|
|
42
|
+
'.cache',
|
|
43
|
+
'.parcel-cache',
|
|
44
|
+
'.vercel',
|
|
45
|
+
'.wrangler',
|
|
46
|
+
'.serverless',
|
|
47
|
+
'.terraform',
|
|
48
|
+
// Python
|
|
49
|
+
'__pycache__',
|
|
50
|
+
'.pytest_cache',
|
|
51
|
+
'.mypy_cache',
|
|
52
|
+
'.ruff_cache',
|
|
53
|
+
'.tox',
|
|
54
|
+
'.venv',
|
|
55
|
+
'venv',
|
|
56
|
+
'.eggs',
|
|
57
|
+
'htmlcov',
|
|
58
|
+
// Java / Kotlin / Gradle / Android
|
|
59
|
+
'.gradle',
|
|
60
|
+
'.kotlin',
|
|
61
|
+
'target',
|
|
62
|
+
'gen',
|
|
63
|
+
'captures',
|
|
64
|
+
// Swift / iOS / Xcode
|
|
65
|
+
'.build',
|
|
66
|
+
'.swiftpm',
|
|
67
|
+
'DerivedData',
|
|
68
|
+
'Pods',
|
|
69
|
+
'Carthage',
|
|
70
|
+
// C / C++ / CMake
|
|
71
|
+
'CMakeFiles',
|
|
72
|
+
'cmake-build-debug',
|
|
73
|
+
'cmake-build-release',
|
|
74
|
+
'_deps',
|
|
75
|
+
// Test reports / results / logs / release artifacts
|
|
76
|
+
'reports',
|
|
77
|
+
'report',
|
|
78
|
+
'test-reports',
|
|
79
|
+
'test-report',
|
|
80
|
+
'test-output',
|
|
81
|
+
'test-results',
|
|
82
|
+
'results',
|
|
83
|
+
'result',
|
|
84
|
+
'logs',
|
|
85
|
+
'allure-report',
|
|
86
|
+
'allure-results',
|
|
87
|
+
'playwright-report',
|
|
88
|
+
'.wdio',
|
|
89
|
+
];
|
|
90
|
+
/**
|
|
91
|
+
* Glob form of the ignore list, for tools that take glob ignores directly
|
|
92
|
+
* (ESLint `--ignore-pattern`, cspell `--exclude`, the generated
|
|
93
|
+
* `.prettierignore`). Combines {@link IGNORED_DIRS} with a few tool-specific
|
|
94
|
+
* nested report globs that are not plain directory names.
|
|
10
95
|
*/
|
|
11
96
|
exports.IGNORE_PATTERNS = [
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
'**/.git/**',
|
|
15
|
-
'**/build/**',
|
|
16
|
-
'**/coverage/**',
|
|
17
|
-
'**/.next/**',
|
|
18
|
-
'**/.nuxt/**',
|
|
19
|
-
'**/out/**',
|
|
20
|
-
'**/__pycache__/**',
|
|
21
|
-
'**/.pytest_cache/**',
|
|
22
|
-
'**/.venv/**',
|
|
23
|
-
'**/venv/**',
|
|
24
|
-
'**/allure-report/**',
|
|
25
|
-
'**/allure-results/**',
|
|
26
|
-
'**/reports/**',
|
|
27
|
-
'**/report/**',
|
|
28
|
-
'**/test-reports/**',
|
|
29
|
-
'**/test-report/**',
|
|
30
|
-
'**/test-output/**',
|
|
31
|
-
'**/test-results/**',
|
|
32
|
-
'**/results/**',
|
|
33
|
-
'**/result/**',
|
|
34
|
-
'**/logs/**',
|
|
35
|
-
// Jest
|
|
97
|
+
...exports.IGNORED_DIRS.map(dir => `**/${dir}/**`),
|
|
98
|
+
// Tool-specific nested report dirs / files (not bare directory names)
|
|
36
99
|
'**/jest-html-reporters-*/**',
|
|
37
100
|
'**/jest-stare/**',
|
|
38
|
-
// Cypress
|
|
39
101
|
'**/cypress/reports/**',
|
|
40
102
|
'**/cypress/videos/**',
|
|
41
103
|
'**/cypress/screenshots/**',
|
|
42
|
-
// Playwright
|
|
43
|
-
'**/playwright-report/**',
|
|
44
|
-
// WebdriverIO
|
|
45
|
-
'**/.wdio/**',
|
|
46
|
-
'**/wdio-logs/**',
|
|
47
|
-
// Mocha / Jasmine
|
|
48
104
|
'**/mochawesome-report/**',
|
|
49
105
|
'**/mochawesome-reports/**',
|
|
50
|
-
// JUnit / Surefire / Maven
|
|
51
106
|
'**/target/surefire-reports/**',
|
|
52
107
|
'**/target/failsafe-reports/**',
|
|
53
|
-
|
|
54
|
-
'**/.pytest_cache/**',
|
|
55
|
-
'**/htmlcov/**',
|
|
56
|
-
// Misc reports
|
|
108
|
+
'**/wdio-logs/**',
|
|
57
109
|
'**/lint-report/**',
|
|
58
110
|
'**/audit-report/**',
|
|
59
111
|
];
|
|
@@ -162,3 +214,70 @@ exports.documentation = {
|
|
|
162
214
|
cspell: 'https://cspell.org/configuration/',
|
|
163
215
|
};
|
|
164
216
|
exports.CONFIG_FILE = node_path_1.default.resolve(process.cwd(), 'pr-checkmate.json');
|
|
217
|
+
/**
|
|
218
|
+
* Every top-level key PR CheckMate recognises in pr-checkmate.json — the union
|
|
219
|
+
* of the `PRCheckMateConfig` interface fields and the keys the `init` generator
|
|
220
|
+
* writes (which use `eslint`/`cspell`/`markdownlint` rather than the interface's
|
|
221
|
+
* `lint`/`spellcheck`). The Config Validation check warns on any key not in this
|
|
222
|
+
* set (typos), ignoring `//`-prefixed comment keys and `$schema`. Keep in sync
|
|
223
|
+
* when adding a new configurable check.
|
|
224
|
+
*/
|
|
225
|
+
exports.KNOWN_CONFIG_KEYS = new Set([
|
|
226
|
+
// core
|
|
227
|
+
'sourcePath',
|
|
228
|
+
'ignoreDirs',
|
|
229
|
+
'languages',
|
|
230
|
+
'severity',
|
|
231
|
+
'customRules',
|
|
232
|
+
'$schema',
|
|
233
|
+
'commands',
|
|
234
|
+
'documentation',
|
|
235
|
+
'configValidation',
|
|
236
|
+
// linters/formatters (interface + init aliases)
|
|
237
|
+
'lint',
|
|
238
|
+
'eslint',
|
|
239
|
+
'prettier',
|
|
240
|
+
'spellcheck',
|
|
241
|
+
'cspell',
|
|
242
|
+
'markdownlint',
|
|
243
|
+
'typecheck',
|
|
244
|
+
// security
|
|
245
|
+
'security',
|
|
246
|
+
'diffSecurity',
|
|
247
|
+
'workflowSecurity',
|
|
248
|
+
'dockerfileSecurity',
|
|
249
|
+
'sensitiveFileGuard',
|
|
250
|
+
'migrationSafety',
|
|
251
|
+
// dependencies
|
|
252
|
+
'dependency',
|
|
253
|
+
'outdatedDeps',
|
|
254
|
+
'licenseCheck',
|
|
255
|
+
'vulnScan',
|
|
256
|
+
'bannedImports',
|
|
257
|
+
// git-diff / PR
|
|
258
|
+
'mergeConflict',
|
|
259
|
+
'diffSmell',
|
|
260
|
+
'leftoverDebug',
|
|
261
|
+
'todoFixme',
|
|
262
|
+
'lockfileDrift',
|
|
263
|
+
'largeFiles',
|
|
264
|
+
'missingTests',
|
|
265
|
+
'coverage',
|
|
266
|
+
'caseCollision',
|
|
267
|
+
'licenseHeader',
|
|
268
|
+
'duplicate',
|
|
269
|
+
'deadCode',
|
|
270
|
+
'prBody',
|
|
271
|
+
'prSize',
|
|
272
|
+
'commitlint',
|
|
273
|
+
// languages
|
|
274
|
+
'cpp',
|
|
275
|
+
'python',
|
|
276
|
+
'swift',
|
|
277
|
+
'kotlin',
|
|
278
|
+
'go',
|
|
279
|
+
'rust',
|
|
280
|
+
'csharp',
|
|
281
|
+
'ruby',
|
|
282
|
+
'php',
|
|
283
|
+
]);
|
package/dist/config/index.d.ts
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
export * from './constants';
|
|
2
2
|
export { loadProjectConfig } from '../config/loader';
|
|
3
3
|
/**
|
|
4
|
-
* Get
|
|
5
|
-
*
|
|
4
|
+
* Get the configured source path(s) dynamically as a normalized list.
|
|
5
|
+
* Accepts a single string or an array in pr-checkmate.json; empty/invalid
|
|
6
|
+
* values fall back to `['.']` (the whole repo). Clients narrow scanning to a
|
|
7
|
+
* subdirectory by setting `sourcePath` in their pr-checkmate.json. Always reads
|
|
8
|
+
* fresh config.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getSourcePaths(): string[];
|
|
11
|
+
/**
|
|
12
|
+
* Get a single source path (first configured entry) for callers that only
|
|
13
|
+
* support one directory. Prefer `getSourcePaths()` for scan targets.
|
|
6
14
|
*/
|
|
7
15
|
export declare function getSourcePath(): string;
|
|
16
|
+
/**
|
|
17
|
+
* Get the effective list of directory names excluded from every check
|
|
18
|
+
* (client `ignoreDirs` in pr-checkmate.json, or the curated default).
|
|
19
|
+
*/
|
|
20
|
+
export declare function getIgnoredDirs(): string[];
|
|
8
21
|
/**
|
|
9
22
|
* Get path to package config files
|
|
10
23
|
*/
|
package/dist/config/index.js
CHANGED
|
@@ -18,16 +18,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
20
|
exports.loadProjectConfig = void 0;
|
|
21
|
+
exports.getSourcePaths = getSourcePaths;
|
|
21
22
|
exports.getSourcePath = getSourcePath;
|
|
23
|
+
exports.getIgnoredDirs = getIgnoredDirs;
|
|
22
24
|
exports.getPackageConfigPath = getPackageConfigPath;
|
|
23
25
|
exports.hasLocalConfig = hasLocalConfig;
|
|
24
26
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
25
27
|
const node_path_1 = __importDefault(require("node:path"));
|
|
28
|
+
const loader_1 = require("../config/loader");
|
|
26
29
|
const utils_1 = require("../utils");
|
|
27
30
|
const constants_1 = require("./constants");
|
|
28
31
|
__exportStar(require("./constants"), exports);
|
|
29
|
-
var
|
|
30
|
-
Object.defineProperty(exports, "loadProjectConfig", { enumerable: true, get: function () { return
|
|
32
|
+
var loader_2 = require("../config/loader");
|
|
33
|
+
Object.defineProperty(exports, "loadProjectConfig", { enumerable: true, get: function () { return loader_2.loadProjectConfig; } });
|
|
31
34
|
/**
|
|
32
35
|
* Load configuration dynamically (always reads fresh config)
|
|
33
36
|
*/
|
|
@@ -41,15 +44,33 @@ function loadConfig() {
|
|
|
41
44
|
catch (err) {
|
|
42
45
|
utils_1.logger.warn(`⚠️ Failed to read config from ${constants_1.CONFIG_FILE}, using defaults${err}`);
|
|
43
46
|
}
|
|
44
|
-
return { sourcePath: '
|
|
47
|
+
return { sourcePath: '.' };
|
|
45
48
|
}
|
|
46
49
|
/**
|
|
47
|
-
* Get
|
|
48
|
-
*
|
|
50
|
+
* Get the configured source path(s) dynamically as a normalized list.
|
|
51
|
+
* Accepts a single string or an array in pr-checkmate.json; empty/invalid
|
|
52
|
+
* values fall back to `['.']` (the whole repo). Clients narrow scanning to a
|
|
53
|
+
* subdirectory by setting `sourcePath` in their pr-checkmate.json. Always reads
|
|
54
|
+
* fresh config.
|
|
55
|
+
*/
|
|
56
|
+
function getSourcePaths() {
|
|
57
|
+
const { sourcePath } = loadConfig();
|
|
58
|
+
const paths = (Array.isArray(sourcePath) ? sourcePath : [sourcePath]).filter((p) => typeof p === 'string' && p.trim().length > 0);
|
|
59
|
+
return paths.length > 0 ? paths : ['.'];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get a single source path (first configured entry) for callers that only
|
|
63
|
+
* support one directory. Prefer `getSourcePaths()` for scan targets.
|
|
49
64
|
*/
|
|
50
65
|
function getSourcePath() {
|
|
51
|
-
|
|
52
|
-
|
|
66
|
+
return getSourcePaths()[0];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get the effective list of directory names excluded from every check
|
|
70
|
+
* (client `ignoreDirs` in pr-checkmate.json, or the curated default).
|
|
71
|
+
*/
|
|
72
|
+
function getIgnoredDirs() {
|
|
73
|
+
return (0, loader_1.loadProjectConfig)().ignoreDirs ?? [];
|
|
53
74
|
}
|
|
54
75
|
/**
|
|
55
76
|
* Get path to package config files
|
package/dist/config/loader.js
CHANGED
|
@@ -34,6 +34,9 @@ function mergeWithDefaults(userConfig) {
|
|
|
34
34
|
const defaults = getDefaultConfig();
|
|
35
35
|
return {
|
|
36
36
|
sourcePath: userConfig.sourcePath || defaults.sourcePath,
|
|
37
|
+
// Replace (not merge): the client sees the full default list in their
|
|
38
|
+
// generated config and edits it directly, so their list is authoritative.
|
|
39
|
+
ignoreDirs: userConfig.ignoreDirs ?? defaults.ignoreDirs,
|
|
37
40
|
lint: {
|
|
38
41
|
rules: { ...defaults.lint?.rules, ...userConfig.lint?.rules },
|
|
39
42
|
ignorePatterns: [
|
|
@@ -90,7 +93,8 @@ function mergeWithDefaults(userConfig) {
|
|
|
90
93
|
*/
|
|
91
94
|
function getDefaultConfig() {
|
|
92
95
|
return {
|
|
93
|
-
sourcePath: '
|
|
96
|
+
sourcePath: '.',
|
|
97
|
+
ignoreDirs: [...constants_1.IGNORED_DIRS],
|
|
94
98
|
lint: {
|
|
95
99
|
rules: {
|
|
96
100
|
'no-console': 'warn',
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.bannedImportsCheck = void 0;
|
|
4
|
+
const utils_1 = require("../../../utils");
|
|
5
|
+
const types_1 = require("../../types");
|
|
6
|
+
const findings_1 = require("../findings");
|
|
7
|
+
const PREFIX = 'Banned Imports';
|
|
8
|
+
const escapeRe = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
9
|
+
/**
|
|
10
|
+
* Compile `bannedImports` into matchers that catch a banned package via an ES
|
|
11
|
+
* import, a CommonJS require, or its addition to a manifest dependency list.
|
|
12
|
+
*/
|
|
13
|
+
function compileBans(ctx) {
|
|
14
|
+
const list = ctx.config.bannedImports ?? [];
|
|
15
|
+
return list
|
|
16
|
+
.filter(b => b?.name)
|
|
17
|
+
.map(b => {
|
|
18
|
+
const n = escapeRe(b.name);
|
|
19
|
+
const re = new RegExp(`from\\s+['"]${n}(?:/[^'"]*)?['"]|require\\(\\s*['"]${n}(?:/[^'"]*)?['"]|import\\s+['"]${n}['"]|["']${n}["']\\s*:`);
|
|
20
|
+
return {
|
|
21
|
+
message: b.message ?? `banned dependency: ${b.name}`,
|
|
22
|
+
re,
|
|
23
|
+
severity: b.severity === 'error' ? 'error' : 'warn',
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
exports.bannedImportsCheck = {
|
|
28
|
+
name: 'Banned Imports',
|
|
29
|
+
phase: 'informational',
|
|
30
|
+
applies(ctx) {
|
|
31
|
+
return (ctx.config.bannedImports?.length ?? 0) > 0 && Boolean(ctx.baseSha);
|
|
32
|
+
},
|
|
33
|
+
async run(ctx) {
|
|
34
|
+
var _a;
|
|
35
|
+
const bans = compileBans(ctx);
|
|
36
|
+
if (bans.length === 0)
|
|
37
|
+
return (0, types_1.pass)('no banned imports configured');
|
|
38
|
+
try {
|
|
39
|
+
const stdout = await (0, findings_1.diffAddedLines)(ctx, ['*']);
|
|
40
|
+
const errors = {};
|
|
41
|
+
const warnings = {};
|
|
42
|
+
for (const raw of stdout.split('\n')) {
|
|
43
|
+
if (!raw.startsWith('+') || raw.startsWith('+++'))
|
|
44
|
+
continue;
|
|
45
|
+
const content = raw.slice(1);
|
|
46
|
+
for (const ban of bans) {
|
|
47
|
+
if (ban.re.test(content)) {
|
|
48
|
+
const bucket = ban.severity === 'error' ? errors : warnings;
|
|
49
|
+
(bucket[_a = ban.message] ?? (bucket[_a] = [])).push(content.trim().substring(0, 100));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const totalErrors = (0, findings_1.bucketTotal)(errors);
|
|
54
|
+
const totalWarnings = (0, findings_1.bucketTotal)(warnings);
|
|
55
|
+
if (totalErrors === 0 && totalWarnings === 0)
|
|
56
|
+
return (0, types_1.pass)();
|
|
57
|
+
(0, findings_1.logFindings)(errors, { prefix: PREFIX, isError: true, sampleLimit: 3 });
|
|
58
|
+
(0, findings_1.logFindings)(warnings, { prefix: PREFIX, sampleLimit: 3 });
|
|
59
|
+
const parts = [];
|
|
60
|
+
if (totalErrors > 0)
|
|
61
|
+
parts.push(`${totalErrors} banned (error)`);
|
|
62
|
+
if (totalWarnings > 0)
|
|
63
|
+
parts.push(`${totalWarnings} banned (warn)`);
|
|
64
|
+
return totalErrors > 0 ? (0, types_1.fail)(parts.join(', ')) : (0, types_1.warn)(parts.join(', '));
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
utils_1.logger.warn(`[Banned Imports]: ⚠️ Could not analyze diff\n${err}`);
|
|
68
|
+
return (0, types_1.skip)('diff unavailable');
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Check } from '
|
|
1
|
+
import { Check } from '../../types';
|
|
2
2
|
export declare const circularDepsCheck: Check;
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.circularDepsCheck = void 0;
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const types_1 = require("
|
|
4
|
+
const config_1 = require("../../../config");
|
|
5
|
+
const utils_1 = require("../../../utils");
|
|
6
|
+
const execa_1 = require("../../../utils/execa");
|
|
7
|
+
const targets_1 = require("../../targets");
|
|
8
|
+
const types_1 = require("../../types");
|
|
12
9
|
exports.circularDepsCheck = {
|
|
13
10
|
name: 'Circular Deps',
|
|
14
11
|
phase: 'blocking',
|
|
@@ -16,8 +13,10 @@ exports.circularDepsCheck = {
|
|
|
16
13
|
return ctx.languages.includes('typescript') || ctx.languages.includes('javascript');
|
|
17
14
|
},
|
|
18
15
|
async run(ctx) {
|
|
19
|
-
const
|
|
20
|
-
|
|
16
|
+
const files = await (0, targets_1.listTrackedFiles)(ctx, ['*.ts', '*.tsx', '*.js', '*.jsx'], (0, config_1.getSourcePaths)());
|
|
17
|
+
if (files.length === 0)
|
|
18
|
+
return (0, types_1.pass)();
|
|
19
|
+
const result = await (0, execa_1.execa)('npx', ['dpdm', '--no-warning', '--no-tree', '--circular', ...files], {
|
|
21
20
|
cwd: ctx.cwd,
|
|
22
21
|
reject: false,
|
|
23
22
|
});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Check } from '
|
|
1
|
+
import { Check } from '../../types';
|
|
2
2
|
export declare const dependencyCheck: Check;
|
|
@@ -6,9 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.dependencyCheck = void 0;
|
|
7
7
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
-
const utils_1 = require("
|
|
10
|
-
const execa_1 = require("
|
|
11
|
-
const types_1 = require("
|
|
9
|
+
const utils_1 = require("../../../utils");
|
|
10
|
+
const execa_1 = require("../../../utils/execa");
|
|
11
|
+
const types_1 = require("../../types");
|
|
12
12
|
exports.dependencyCheck = {
|
|
13
13
|
name: 'Dependencies',
|
|
14
14
|
phase: 'blocking',
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Check } from '
|
|
1
|
+
import { Check } from '../../types';
|
|
2
2
|
export declare const licenseCheck: Check;
|
|
@@ -6,9 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.licenseCheck = void 0;
|
|
7
7
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
-
const utils_1 = require("
|
|
10
|
-
const execa_1 = require("
|
|
11
|
-
const types_1 = require("
|
|
9
|
+
const utils_1 = require("../../../utils");
|
|
10
|
+
const execa_1 = require("../../../utils/execa");
|
|
11
|
+
const types_1 = require("../../types");
|
|
12
12
|
const FORBIDDEN_LICENSES = ['GPL-2.0', 'GPL-3.0', 'AGPL-3.0', 'LGPL-2.0', 'LGPL-2.1', 'LGPL-3.0'];
|
|
13
13
|
/** Strip the trailing "@version" to get the bare package name (scoped-safe). */
|
|
14
14
|
function bareName(pkgKey) {
|
|
@@ -6,9 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.npmAuditCheck = void 0;
|
|
7
7
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
-
const utils_1 = require("
|
|
10
|
-
const execa_1 = require("
|
|
11
|
-
const types_1 = require("
|
|
9
|
+
const utils_1 = require("../../../utils");
|
|
10
|
+
const execa_1 = require("../../../utils/execa");
|
|
11
|
+
const types_1 = require("../../types");
|
|
12
12
|
const SEVERITY_ORDER = ['info', 'low', 'moderate', 'high', 'critical'];
|
|
13
13
|
function isSeverityAtLeast(severity, level) {
|
|
14
14
|
const sevIdx = SEVERITY_ORDER.indexOf(severity);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Check } from '
|
|
1
|
+
import { Check } from '../../types';
|
|
2
2
|
export declare const outdatedDepsCheck: Check;
|
|
@@ -6,9 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.outdatedDepsCheck = void 0;
|
|
7
7
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
-
const utils_1 = require("
|
|
10
|
-
const execa_1 = require("
|
|
11
|
-
const types_1 = require("
|
|
9
|
+
const utils_1 = require("../../../utils");
|
|
10
|
+
const execa_1 = require("../../../utils/execa");
|
|
11
|
+
const types_1 = require("../../types");
|
|
12
12
|
exports.outdatedDepsCheck = {
|
|
13
13
|
name: 'Outdated Deps',
|
|
14
14
|
phase: 'informational',
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Check } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Cross-language dependency vulnerability scan via osv-scanner, which reads
|
|
4
|
+
* lockfiles across ecosystems (npm, PyPI, Go, crates, Maven, …) against the OSV
|
|
5
|
+
* database. Runner-dependency and opt-in (`vulnScan.enabled: true`): osv-scanner
|
|
6
|
+
* must be on the runner, and the check skips gracefully when it is absent.
|
|
7
|
+
* Complements the JS-only `npm-audit` with coverage for every other ecosystem.
|
|
8
|
+
*/
|
|
9
|
+
export declare const vulnScanCheck: Check;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.vulnScanCheck = void 0;
|
|
4
|
+
const utils_1 = require("../../../utils");
|
|
5
|
+
const execa_1 = require("../../../utils/execa");
|
|
6
|
+
const types_1 = require("../../types");
|
|
7
|
+
/**
|
|
8
|
+
* Cross-language dependency vulnerability scan via osv-scanner, which reads
|
|
9
|
+
* lockfiles across ecosystems (npm, PyPI, Go, crates, Maven, …) against the OSV
|
|
10
|
+
* database. Runner-dependency and opt-in (`vulnScan.enabled: true`): osv-scanner
|
|
11
|
+
* must be on the runner, and the check skips gracefully when it is absent.
|
|
12
|
+
* Complements the JS-only `npm-audit` with coverage for every other ecosystem.
|
|
13
|
+
*/
|
|
14
|
+
exports.vulnScanCheck = {
|
|
15
|
+
name: 'Vuln Scan',
|
|
16
|
+
phase: 'informational',
|
|
17
|
+
applies(ctx) {
|
|
18
|
+
return ctx.config.vulnScan?.enabled === true;
|
|
19
|
+
},
|
|
20
|
+
async run(ctx) {
|
|
21
|
+
const result = await (0, execa_1.execa)('osv-scanner', ['-r', '.'], { cwd: ctx.cwd, reject: false });
|
|
22
|
+
// execa v9 with reject:false resolves (not throws) with `code: 'ENOENT'`
|
|
23
|
+
// when the binary is absent — detect the missing scanner on the result.
|
|
24
|
+
if (result.code === 'ENOENT')
|
|
25
|
+
return (0, types_1.skip)('osv-scanner not installed');
|
|
26
|
+
if (result.exitCode === 0) {
|
|
27
|
+
utils_1.logger.info('[Vuln Scan]: ✅ No known vulnerabilities');
|
|
28
|
+
return (0, types_1.pass)();
|
|
29
|
+
}
|
|
30
|
+
const lines = [result.stdout, result.stderr]
|
|
31
|
+
.filter(Boolean)
|
|
32
|
+
.join('\n')
|
|
33
|
+
.split('\n')
|
|
34
|
+
.filter(l => /\b(CVE-|GHSA-|vulnerab|advisor)/i.test(l));
|
|
35
|
+
utils_1.logger.warn('[Vuln Scan]: ⚠️ known vulnerabilities found:');
|
|
36
|
+
lines.slice(0, 10).forEach(l => utils_1.logger.warn(` ${l.trim()}`));
|
|
37
|
+
if (lines.length > 10)
|
|
38
|
+
utils_1.logger.warn(` ... and ${lines.length - 10} more`);
|
|
39
|
+
return (0, types_1.warn)(`${lines.length || 'unknown'} vulnerability finding(s) (osv-scanner)`);
|
|
40
|
+
},
|
|
41
|
+
};
|
|
@@ -1,4 +1,26 @@
|
|
|
1
1
|
import { CheckContext, CheckOutcome } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Client-configurable severity for a check's findings, read from that check's
|
|
4
|
+
* config block (e.g. `mergeConflict.severity`). `error` fails the run, `warn`
|
|
5
|
+
* only advises. Every check declares a natural default; the client overrides it
|
|
6
|
+
* per repo in pr-checkmate.json — promoting an advisory check to a gate, or
|
|
7
|
+
* downgrading a blocking one, with no code change.
|
|
8
|
+
*/
|
|
9
|
+
export type Severity = 'error' | 'warn';
|
|
10
|
+
export interface SeverityEmitter {
|
|
11
|
+
/** Log at the resolved level (`logger.error` for error, `logger.warn` for warn). */
|
|
12
|
+
log: (msg: string) => void;
|
|
13
|
+
/** Prefix icon matching the level. */
|
|
14
|
+
icon: string;
|
|
15
|
+
/** Build the outcome at the resolved level (`fail` for error, `warn` for warn). */
|
|
16
|
+
emit: (details: string) => CheckOutcome;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Resolve a check's effective severity (`configured` from config, else its
|
|
20
|
+
* `fallback`) into a matched logger, icon, and outcome constructor — so a check
|
|
21
|
+
* logs and returns consistently at whatever level the client chose.
|
|
22
|
+
*/
|
|
23
|
+
export declare function severityEmitter(configured: Severity | undefined, fallback: Severity): SeverityEmitter;
|
|
2
24
|
/** Findings grouped by label → matching sample strings. */
|
|
3
25
|
export type FindingBucket = Record<string, string[]>;
|
|
4
26
|
/**
|
|
@@ -6,6 +28,14 @@ export type FindingBucket = Record<string, string[]>;
|
|
|
6
28
|
* (zero context, added/copied/modified/renamed files) for added-line scanning.
|
|
7
29
|
*/
|
|
8
30
|
export declare function diffAddedLines(ctx: CheckContext, globs: string[]): Promise<string>;
|
|
31
|
+
/**
|
|
32
|
+
* Strip a trailing line comment (`//` or `#`) from a line, tracking quote state
|
|
33
|
+
* so a marker inside a string literal (or a `#` in `"#fff"`, a `//` in a quoted
|
|
34
|
+
* URL) is preserved. Heuristic, not a tokenizer: block comments and regex
|
|
35
|
+
* literals aren't handled. Used by code-targeting checks so `# print(x)` or
|
|
36
|
+
* `// eval(x)` in a comment isn't flagged as real code.
|
|
37
|
+
*/
|
|
38
|
+
export declare function stripInlineComment(line: string): string;
|
|
9
39
|
/** Total number of findings across all labels in a bucket. */
|
|
10
40
|
export declare function bucketTotal(bucket: FindingBucket): number;
|
|
11
41
|
interface LogOptions {
|
|
@@ -31,10 +61,16 @@ interface SeverityReportOptions {
|
|
|
31
61
|
showCount?: boolean;
|
|
32
62
|
/** Max samples printed per label; omit to print all. */
|
|
33
63
|
sampleLimit?: number;
|
|
64
|
+
/**
|
|
65
|
+
* Finding labels to suppress (client `<check>.ignore`). A label is dropped
|
|
66
|
+
* when it contains any ignore entry (case-insensitive), so a repo can mute a
|
|
67
|
+
* single built-in finding without disabling the whole check.
|
|
68
|
+
*/
|
|
69
|
+
ignore?: string[];
|
|
34
70
|
}
|
|
35
71
|
/**
|
|
36
72
|
* Report error/warning finding buckets: log both, then produce the outcome.
|
|
37
73
|
* Returns pass() when both buckets are empty, otherwise warn() with a summary.
|
|
38
74
|
*/
|
|
39
|
-
export declare function reportSeverityBuckets(
|
|
75
|
+
export declare function reportSeverityBuckets(errorsIn: FindingBucket, warningsIn: FindingBucket, opts: SeverityReportOptions): CheckOutcome;
|
|
40
76
|
export {};
|