pr-checkmate 1.22.0 → 1.22.2
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 +0 -2
- package/dist/cli.d.ts +2 -0
- package/dist/config/config.d.ts +2 -0
- package/dist/config/constants.d.ts +44 -0
- package/dist/config/index.d.ts +23 -0
- package/dist/config/loader.d.ts +14 -0
- package/dist/core/checks/circular-deps.d.ts +2 -0
- package/dist/core/checks/commitlint.d.ts +2 -0
- package/dist/core/checks/cpp-format.d.ts +7 -0
- package/dist/core/checks/dead-code.d.ts +2 -0
- package/dist/core/checks/dependency-check.d.ts +2 -0
- package/dist/core/checks/diff-security.d.ts +2 -0
- package/dist/core/checks/diff-smell.d.ts +2 -0
- package/dist/core/checks/duplicate-check.d.ts +2 -0
- package/dist/core/checks/findings.d.ts +40 -0
- package/dist/core/checks/kotlin-lint.d.ts +2 -0
- package/dist/core/checks/license-check.d.ts +2 -0
- package/dist/core/checks/lint.d.ts +2 -0
- package/dist/core/checks/markdown-lint.d.ts +2 -0
- package/dist/core/checks/npm-audit.d.ts +6 -0
- package/dist/core/checks/outdated-deps.d.ts +2 -0
- package/dist/core/checks/pr-body.d.ts +2 -0
- package/dist/core/checks/pr-size-check.d.ts +2 -0
- package/dist/core/checks/pr-title-lint.d.ts +2 -0
- package/dist/core/checks/prettier.d.ts +2 -0
- package/dist/core/checks/python-format.d.ts +7 -0
- package/dist/core/checks/python-lint.d.ts +9 -0
- package/dist/core/checks/security.d.ts +7 -0
- package/dist/core/checks/sensitive-file-guard.d.ts +2 -0
- package/dist/core/checks/spellcheck.d.ts +2 -0
- package/dist/core/checks/swift-lint.d.ts +2 -0
- package/dist/core/checks/typecheck.d.ts +2 -0
- package/dist/core/checks/typecheck.js +9 -0
- package/dist/core/context.d.ts +6 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/core/registry.d.ts +6 -0
- package/dist/core/reporters.d.ts +7 -0
- package/dist/core/run-checks.d.ts +9 -0
- package/dist/core/run-checks.js +31 -3
- package/dist/core/targets.d.ts +11 -0
- package/dist/core/types.d.ts +102 -0
- package/dist/core/types.js +7 -1
- package/dist/index.d.ts +9 -0
- package/dist/index.js +8 -1
- package/dist/init.d.ts +5 -0
- package/dist/init.js +5 -1
- package/dist/interfaces/index.d.ts +129 -0
- package/dist/scripts/copy-configs.d.ts +5 -0
- package/dist/scripts/publish-github.d.ts +1 -0
- package/dist/utils/delta.d.ts +5 -0
- package/dist/utils/detect-language.d.ts +10 -0
- package/dist/utils/index.d.ts +10 -0
- package/dist/utils/logger.d.ts +20 -0
- package/dist/utils/own-deps.d.ts +14 -0
- package/dist/utils/resolve-bin.d.ts +17 -0
- package/dist/utils/result-collector.d.ts +33 -0
- package/package.json +10 -2
package/README.md
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
# ♟️ PR CheckMate
|
|
2
2
|
|
|
3
3
|

|
|
4
|
-

|
|
5
4
|

|
|
6
|
-
|
|
7
5
|

|
|
8
6
|

|
|
9
7
|

|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common patterns to ignore in all checks
|
|
3
|
+
*/
|
|
4
|
+
export declare const IGNORE_PATTERNS: string[];
|
|
5
|
+
export declare const CONFIG_FILE_PATTERNS: string[];
|
|
6
|
+
/**
|
|
7
|
+
* File extensions to check
|
|
8
|
+
*/
|
|
9
|
+
export declare const SOURCE_EXTENSIONS: {
|
|
10
|
+
typescript: string[];
|
|
11
|
+
javascript: string[];
|
|
12
|
+
markdown: string[];
|
|
13
|
+
json: string[];
|
|
14
|
+
all: string[];
|
|
15
|
+
};
|
|
16
|
+
export declare const DEFAULT_COMMANDS: {
|
|
17
|
+
'npx pr-checkmate init': string;
|
|
18
|
+
'npx pr-checkmate all': string;
|
|
19
|
+
'npx pr-checkmate lint': string;
|
|
20
|
+
'npx pr-checkmate prettier': string;
|
|
21
|
+
'npx pr-checkmate deps': string;
|
|
22
|
+
'npx pr-checkmate npm-audit': string;
|
|
23
|
+
'npx pr-checkmate security': string;
|
|
24
|
+
'npx pr-checkmate spellcheck': string;
|
|
25
|
+
'npx pr-checkmate typecheck': string;
|
|
26
|
+
'npx pr-checkmate diff-smell': string;
|
|
27
|
+
'npx pr-checkmate pr-body': string;
|
|
28
|
+
'npx pr-checkmate duplicate': string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Packages allow-listed for the license check by default.
|
|
32
|
+
*
|
|
33
|
+
* These are pr-checkmate's own bundled cspell dictionaries. Some ship under
|
|
34
|
+
* copyleft licenses (GPL/LGPL), but they are pr-checkmate dependencies — not
|
|
35
|
+
* the consumer's — so clients should never have to allow-list them manually.
|
|
36
|
+
*/
|
|
37
|
+
export declare const DEFAULT_ALLOW_PACKAGES: string[];
|
|
38
|
+
export declare const documentation: {
|
|
39
|
+
eslint: string;
|
|
40
|
+
typescriptEslint: string;
|
|
41
|
+
prettier: string;
|
|
42
|
+
cspell: string;
|
|
43
|
+
};
|
|
44
|
+
export declare const CONFIG_FILE: string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export * from './constants';
|
|
2
|
+
export { loadProjectConfig } from '../config/loader';
|
|
3
|
+
/**
|
|
4
|
+
* Get SOURCE_PATH dynamically
|
|
5
|
+
* This ensures fresh config is always read
|
|
6
|
+
*/
|
|
7
|
+
export declare function getSourcePath(): string;
|
|
8
|
+
/**
|
|
9
|
+
* Get path to package config files
|
|
10
|
+
*/
|
|
11
|
+
export declare function getPackageConfigPath(fileName: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Check if project has local config
|
|
14
|
+
*/
|
|
15
|
+
export declare function hasLocalConfig(configNames: string[]): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* For backward compatibility, also export as constant
|
|
18
|
+
* But this will be evaluated at module load time
|
|
19
|
+
*/
|
|
20
|
+
export declare const config: {
|
|
21
|
+
sourcePath: string;
|
|
22
|
+
};
|
|
23
|
+
export declare const SOURCE_PATH: string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { PRCheckMateConfig } from '../interfaces';
|
|
2
|
+
/**
|
|
3
|
+
* Load project configuration from pr-checkmate.json
|
|
4
|
+
* Falls back to defaults if not found
|
|
5
|
+
*/
|
|
6
|
+
export declare function loadProjectConfig(): PRCheckMateConfig;
|
|
7
|
+
/**
|
|
8
|
+
* Get default configuration
|
|
9
|
+
*/
|
|
10
|
+
export declare function getDefaultConfig(): PRCheckMateConfig;
|
|
11
|
+
/**
|
|
12
|
+
* Export config for external use
|
|
13
|
+
*/
|
|
14
|
+
export declare const DEFAULT_CONFIG: PRCheckMateConfig;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Check } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Formats C/C++ code with clang-format, bundled as a self-contained WASM CLI
|
|
4
|
+
* (`@wasm-fmt/clang-format`) so it runs on a bare Node image with no system
|
|
5
|
+
* clang install. Read-only in check mode; rewrites files in place when `write`.
|
|
6
|
+
*/
|
|
7
|
+
export declare const cppFormatCheck: Check;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { CheckContext, CheckOutcome } from '../types';
|
|
2
|
+
/** Findings grouped by label → matching sample strings. */
|
|
3
|
+
export type FindingBucket = Record<string, string[]>;
|
|
4
|
+
/**
|
|
5
|
+
* Run `git diff` over the given file globs, returning the raw unified diff
|
|
6
|
+
* (zero context, added/copied/modified/renamed files) for added-line scanning.
|
|
7
|
+
*/
|
|
8
|
+
export declare function diffAddedLines(ctx: CheckContext, globs: string[]): Promise<string>;
|
|
9
|
+
/** Total number of findings across all labels in a bucket. */
|
|
10
|
+
export declare function bucketTotal(bucket: FindingBucket): number;
|
|
11
|
+
interface LogOptions {
|
|
12
|
+
/** Log prefix, e.g. 'Diff Security'. */
|
|
13
|
+
prefix: string;
|
|
14
|
+
/** Use logger.error + ❌ instead of logger.warn + ⚠️. */
|
|
15
|
+
isError?: boolean;
|
|
16
|
+
/** Append ": N occurrence(s)" after the label (default true). */
|
|
17
|
+
showCount?: boolean;
|
|
18
|
+
/** Max samples printed per label; omit to print all. */
|
|
19
|
+
sampleLimit?: number;
|
|
20
|
+
}
|
|
21
|
+
/** Log one bucket of findings using the shared check format. */
|
|
22
|
+
export declare function logFindings(bucket: FindingBucket, opts: LogOptions): void;
|
|
23
|
+
interface SeverityReportOptions {
|
|
24
|
+
/** Log prefix, e.g. 'Diff Security'. */
|
|
25
|
+
prefix: string;
|
|
26
|
+
/** Summary phrasing given the error count. */
|
|
27
|
+
errorSummary: (n: number) => string;
|
|
28
|
+
/** Summary phrasing given the warning count. */
|
|
29
|
+
warningSummary: (n: number) => string;
|
|
30
|
+
/** Append ": N occurrence(s)" after each label (default true). */
|
|
31
|
+
showCount?: boolean;
|
|
32
|
+
/** Max samples printed per label; omit to print all. */
|
|
33
|
+
sampleLimit?: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Report error/warning finding buckets: log both, then produce the outcome.
|
|
37
|
+
* Returns pass() when both buckets are empty, otherwise warn() with a summary.
|
|
38
|
+
*/
|
|
39
|
+
export declare function reportSeverityBuckets(errors: FindingBucket, warnings: FindingBucket, opts: SeverityReportOptions): CheckOutcome;
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Check } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Formats changed Python files with Ruff's formatter (WASM, no Python/pip needed).
|
|
4
|
+
* Read-only in check mode (`warn` when files differ from formatted output); rewrites
|
|
5
|
+
* files in place when `write` so CI can auto-commit — mirrors the Prettier/C++ checks.
|
|
6
|
+
*/
|
|
7
|
+
export declare const pythonFormatCheck: Check;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Check } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Lints changed Python files with Ruff, bundled as a self-contained WASM module
|
|
4
|
+
* (`@astral-sh/ruff-wasm-nodejs`) so it runs on a bare Node image with no Python
|
|
5
|
+
* or pip install. Informational by design — reports issues without failing the
|
|
6
|
+
* build, matching how formatting checks roll out; promote to blocking per repo
|
|
7
|
+
* once teams have adopted it. Uses Ruff's default rule set (pyflakes + pycodestyle).
|
|
8
|
+
*/
|
|
9
|
+
export declare const pythonLintCheck: Check;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Check } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Secret scanning via the bundled gitleaks package. Language-agnostic — runs on
|
|
4
|
+
* every repo (Node, Python, C++, mobile). Secrets found → fail (blocking).
|
|
5
|
+
* Tooling/infra errors → warn, so a scanner hiccup never blocks an unrelated PR.
|
|
6
|
+
*/
|
|
7
|
+
export declare const securityCheck: Check;
|
|
@@ -32,6 +32,15 @@ exports.typecheckCheck = {
|
|
|
32
32
|
return node_fs_1.default.existsSync(node_path_1.default.join(ctx.cwd, 'tsconfig.json'));
|
|
33
33
|
},
|
|
34
34
|
async run(ctx) {
|
|
35
|
+
// tsc needs the project's installed type declarations — everything listed in
|
|
36
|
+
// tsconfig's `types`, plus every imported @types package — to resolve. When the
|
|
37
|
+
// project's dependencies aren't installed (e.g. a CI step that runs pr-checkmate
|
|
38
|
+
// via npx without a prior `npm ci`), tsc emits a wall of cryptic TS2688
|
|
39
|
+
// "cannot find type definition file" errors that look like code problems but are
|
|
40
|
+
// really a setup gap. Skip with an actionable message instead of failing the PR.
|
|
41
|
+
if (!node_fs_1.default.existsSync(node_path_1.default.join(ctx.cwd, 'node_modules'))) {
|
|
42
|
+
return (0, types_1.skip)('project dependencies not installed (no node_modules) — run `npm ci` before typecheck');
|
|
43
|
+
}
|
|
35
44
|
const tscBin = resolveTsc(ctx.cwd);
|
|
36
45
|
const result = await (0, execa_1.execa)(process.execPath, [tscBin, '--noEmit'], {
|
|
37
46
|
cwd: ctx.cwd,
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CheckContext, RunOptions } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Assemble the shared CheckContext once per run. Language detection is skipped
|
|
4
|
+
* when the caller supplies `languages` (e.g. PRValidator passes its ProjectType).
|
|
5
|
+
*/
|
|
6
|
+
export declare function buildContext(opts?: RunOptions): Promise<CheckContext>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CheckReport, CheckResult } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Emit the report through the selected channel.
|
|
4
|
+
* none: nothing · stdout: console table · github: table + upsert PR comment.
|
|
5
|
+
*/
|
|
6
|
+
export declare function report(kind: 'none' | 'stdout' | 'github', result: CheckReport): Promise<void>;
|
|
7
|
+
export type { CheckResult };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { CheckReport, RunOptions } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Run all applicable checks and return a structured report.
|
|
4
|
+
*
|
|
5
|
+
* Never throws for check violations and never calls `process.exit` — callers
|
|
6
|
+
* (CLI, PRValidator) decide what a failure means. Phases run in order; checks
|
|
7
|
+
* within a phase run in parallel.
|
|
8
|
+
*/
|
|
9
|
+
export declare function runChecks(opts?: RunOptions): Promise<CheckReport>;
|
package/dist/core/run-checks.js
CHANGED
|
@@ -7,7 +7,35 @@ const context_1 = require("./context");
|
|
|
7
7
|
const registry_1 = require("./registry");
|
|
8
8
|
const reporters_1 = require("./reporters");
|
|
9
9
|
const types_1 = require("./types");
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Resolve which checks to run: the built-in registry, custom `opts.checks`, or a mix.
|
|
12
|
+
* - no custom checks → the built-in registry
|
|
13
|
+
* - `extendRegistry !== false` → registry + custom (a custom check overrides a
|
|
14
|
+
* built-in one sharing its name)
|
|
15
|
+
* - `extendRegistry === false` → only the provided custom checks
|
|
16
|
+
*/
|
|
17
|
+
function resolveChecks(opts) {
|
|
18
|
+
const custom = opts.checks ?? [];
|
|
19
|
+
if (opts.extendRegistry === false)
|
|
20
|
+
return custom;
|
|
21
|
+
if (custom.length === 0)
|
|
22
|
+
return registry_1.REGISTRY;
|
|
23
|
+
const byName = new Map();
|
|
24
|
+
for (const c of registry_1.REGISTRY)
|
|
25
|
+
byName.set(c.name, c);
|
|
26
|
+
for (const c of custom)
|
|
27
|
+
byName.set(c.name, c); // custom wins on name clash
|
|
28
|
+
return [...byName.values()];
|
|
29
|
+
}
|
|
30
|
+
/** Emit the report via a preset channel or a custom reporter function. */
|
|
31
|
+
async function emitReport(reporter, result) {
|
|
32
|
+
if (typeof reporter === 'function') {
|
|
33
|
+
await reporter(result);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
await (0, reporters_1.report)(reporter ?? 'stdout', result);
|
|
37
|
+
}
|
|
38
|
+
/** Apply only/skip filters to the resolved check set. */
|
|
11
39
|
function selectChecks(checks, opts) {
|
|
12
40
|
const only = opts.only && opts.only.length > 0 ? new Set(opts.only) : null;
|
|
13
41
|
const skip = new Set(opts.skip ?? []);
|
|
@@ -49,7 +77,7 @@ async function runOne(check, ctx, collector) {
|
|
|
49
77
|
*/
|
|
50
78
|
async function runChecks(opts = {}) {
|
|
51
79
|
const ctx = await (0, context_1.buildContext)(opts);
|
|
52
|
-
const selected = selectChecks(
|
|
80
|
+
const selected = selectChecks(resolveChecks(opts), opts);
|
|
53
81
|
const collector = new result_collector_1.ResultCollector();
|
|
54
82
|
for (const phase of types_1.PHASES) {
|
|
55
83
|
const inPhase = selected.filter(c => c.phase === phase);
|
|
@@ -61,6 +89,6 @@ async function runChecks(opts = {}) {
|
|
|
61
89
|
summary,
|
|
62
90
|
ok: summary.failed === 0,
|
|
63
91
|
};
|
|
64
|
-
await (
|
|
92
|
+
await emitReport(opts.reporter, result);
|
|
65
93
|
return result;
|
|
66
94
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CheckContext } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Lists the files a language check should operate on, matched by pathspec `globs`
|
|
4
|
+
* (e.g. `['*.py']`). Uses the PR diff range when available (delta mode), else
|
|
5
|
+
* scans all tracked files. Returns an empty array when nothing matches, and
|
|
6
|
+
* `null` when git itself is unusable (caller should `skip`).
|
|
7
|
+
*
|
|
8
|
+
* Only ACMR files are returned (Added/Copied/Modified/Renamed) — deletions are
|
|
9
|
+
* excluded, so every returned path exists on disk and is safe to read.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveTargetFiles(ctx: CheckContext, globs: string[]): Promise<string[] | null>;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { PRCheckMateConfig } from '../interfaces';
|
|
2
|
+
import type { Language } from '../utils/detect-language';
|
|
3
|
+
import type { CheckResult, CheckStatus } from '../utils/result-collector';
|
|
4
|
+
export type { CheckResult, CheckStatus, Language };
|
|
5
|
+
/**
|
|
6
|
+
* Execution phases, run strictly in order. Within a phase checks run in parallel.
|
|
7
|
+
* `format` runs last because formatters (prettier) may write files.
|
|
8
|
+
*/
|
|
9
|
+
export type Phase = 'blocking' | 'informational' | 'format';
|
|
10
|
+
export declare const PHASES: readonly Phase[];
|
|
11
|
+
/**
|
|
12
|
+
* Everything a check needs to run. Assembled once by `buildContext` and shared
|
|
13
|
+
* across all checks — no check reads `process.cwd()` or `process.env` directly.
|
|
14
|
+
*/
|
|
15
|
+
export interface CheckContext {
|
|
16
|
+
/** Repository root the checks operate on. */
|
|
17
|
+
cwd: string;
|
|
18
|
+
/** Languages detected (or supplied) for this repo — drives `applies` gating. */
|
|
19
|
+
languages: Language[];
|
|
20
|
+
/** Merged pr-checkmate.json + defaults. */
|
|
21
|
+
config: PRCheckMateConfig;
|
|
22
|
+
/** When false, checks that would modify files (prettier, --fix) run read-only or skip the write. */
|
|
23
|
+
write: boolean;
|
|
24
|
+
/** Diff range for delta-aware checks; undefined → full-repo scan. */
|
|
25
|
+
baseSha?: string;
|
|
26
|
+
headSha?: string;
|
|
27
|
+
}
|
|
28
|
+
/** Outcome of a single check — the name is attached by the orchestrator. */
|
|
29
|
+
export interface CheckOutcome {
|
|
30
|
+
status: CheckStatus;
|
|
31
|
+
details?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A single quality gate. `applies` decides relevance (language/marker gating);
|
|
35
|
+
* `run` performs the check and returns an outcome. `run` must NOT throw for
|
|
36
|
+
* violations — return `fail`/`warn` instead. Thrown errors are caught by the
|
|
37
|
+
* orchestrator and recorded as `fail`.
|
|
38
|
+
*/
|
|
39
|
+
export interface Check {
|
|
40
|
+
name: string;
|
|
41
|
+
phase: Phase;
|
|
42
|
+
applies(ctx: CheckContext): boolean | Promise<boolean>;
|
|
43
|
+
run(ctx: CheckContext): Promise<CheckOutcome>;
|
|
44
|
+
}
|
|
45
|
+
export type ReporterKind = 'none' | 'stdout' | 'github';
|
|
46
|
+
/** Custom reporter: receives the final report to emit however the consumer wants. */
|
|
47
|
+
export type ReporterFn = (report: CheckReport) => void | Promise<void>;
|
|
48
|
+
export interface RunOptions {
|
|
49
|
+
cwd?: string;
|
|
50
|
+
/** Override language detection (e.g. PRValidator passes its already-detected type). */
|
|
51
|
+
languages?: Language[];
|
|
52
|
+
/** Whitelist of check names — when set, only these run. */
|
|
53
|
+
only?: string[];
|
|
54
|
+
/** Blacklist of check names — always excluded. */
|
|
55
|
+
skip?: string[];
|
|
56
|
+
/**
|
|
57
|
+
* Extra checks to run. Combined with the built-in registry per `extendRegistry`.
|
|
58
|
+
* Lets consumers (e.g. PRValidator) plug their own `Check`s into the same pipeline.
|
|
59
|
+
*/
|
|
60
|
+
checks?: Check[];
|
|
61
|
+
/**
|
|
62
|
+
* How `checks` combines with the built-in registry:
|
|
63
|
+
* - `true` (default when `checks` is set): append; a custom check overrides a
|
|
64
|
+
* built-in one with the same name.
|
|
65
|
+
* - `false`: run ONLY the provided `checks`, ignoring the built-in registry.
|
|
66
|
+
*/
|
|
67
|
+
extendRegistry?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Where the report goes:
|
|
70
|
+
* - `'none'`: nothing (just return the report)
|
|
71
|
+
* - `'stdout'`: print the summary table
|
|
72
|
+
* - `'github'`: print + upsert a PR comment
|
|
73
|
+
* - a function: receives the `CheckReport` (e.g. forward to Slack).
|
|
74
|
+
*/
|
|
75
|
+
reporter?: ReporterKind | ReporterFn;
|
|
76
|
+
/** Allow file-modifying checks to write. Default false. */
|
|
77
|
+
write?: boolean;
|
|
78
|
+
config?: PRCheckMateConfig;
|
|
79
|
+
baseSha?: string;
|
|
80
|
+
headSha?: string;
|
|
81
|
+
}
|
|
82
|
+
export interface CheckReport {
|
|
83
|
+
results: CheckResult[];
|
|
84
|
+
summary: {
|
|
85
|
+
passed: number;
|
|
86
|
+
warned: number;
|
|
87
|
+
failed: number;
|
|
88
|
+
skipped: number;
|
|
89
|
+
};
|
|
90
|
+
/** True when no check failed (warnings/skips do not affect it). */
|
|
91
|
+
ok: boolean;
|
|
92
|
+
}
|
|
93
|
+
/** Outcome constructors — keep check bodies terse. */
|
|
94
|
+
export declare const pass: (details?: string) => CheckOutcome;
|
|
95
|
+
export declare const warn: (details: string) => CheckOutcome;
|
|
96
|
+
export declare const fail: (details: string) => CheckOutcome;
|
|
97
|
+
export declare const skip: (details: string) => CheckOutcome;
|
|
98
|
+
/**
|
|
99
|
+
* Identity helper for authoring a `Check` with full type inference and checking.
|
|
100
|
+
* Purely ergonomic — `defineCheck({ ... })` is equivalent to `{ ... } satisfies Check`.
|
|
101
|
+
*/
|
|
102
|
+
export declare const defineCheck: (check: Check) => Check;
|
package/dist/core/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.skip = exports.fail = exports.warn = exports.pass = exports.PHASES = void 0;
|
|
3
|
+
exports.defineCheck = exports.skip = exports.fail = exports.warn = exports.pass = exports.PHASES = void 0;
|
|
4
4
|
exports.PHASES = ['blocking', 'informational', 'format'];
|
|
5
5
|
/** Outcome constructors — keep check bodies terse. */
|
|
6
6
|
const pass = (details) => ({
|
|
@@ -14,3 +14,9 @@ const fail = (details) => ({ status: 'fail', details });
|
|
|
14
14
|
exports.fail = fail;
|
|
15
15
|
const skip = (details) => ({ status: 'skip', details });
|
|
16
16
|
exports.skip = skip;
|
|
17
|
+
/**
|
|
18
|
+
* Identity helper for authoring a `Check` with full type inference and checking.
|
|
19
|
+
* Purely ergonomic — `defineCheck({ ... })` is equivalent to `{ ... } satisfies Check`.
|
|
20
|
+
*/
|
|
21
|
+
const defineCheck = (check) => check;
|
|
22
|
+
exports.defineCheck = defineCheck;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PR CheckMate — automated PR quality checks.
|
|
3
|
+
*
|
|
4
|
+
* @module pr-checkmate
|
|
5
|
+
*/
|
|
6
|
+
export { runChecks, buildContext, REGISTRY } from './core';
|
|
7
|
+
export { pass, warn, fail, skip, defineCheck } from './core';
|
|
8
|
+
export type { Check, CheckContext, CheckOutcome, CheckReport, CheckResult, CheckStatus, Language, Phase, ReporterFn, ReporterKind, RunOptions, } from './core';
|
|
9
|
+
export { getSourcePath, getPackageConfigPath, hasLocalConfig } from './config';
|
package/dist/index.js
CHANGED
|
@@ -5,13 +5,20 @@
|
|
|
5
5
|
* @module pr-checkmate
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.hasLocalConfig = exports.getPackageConfigPath = exports.getSourcePath = exports.REGISTRY = exports.buildContext = exports.runChecks = void 0;
|
|
8
|
+
exports.hasLocalConfig = exports.getPackageConfigPath = exports.getSourcePath = exports.defineCheck = exports.skip = exports.fail = exports.warn = exports.pass = exports.REGISTRY = exports.buildContext = exports.runChecks = void 0;
|
|
9
9
|
// Primary programmatic API: run checks and receive a structured report.
|
|
10
10
|
// Never throws for violations, never calls process.exit — the caller decides.
|
|
11
11
|
var core_1 = require("./core");
|
|
12
12
|
Object.defineProperty(exports, "runChecks", { enumerable: true, get: function () { return core_1.runChecks; } });
|
|
13
13
|
Object.defineProperty(exports, "buildContext", { enumerable: true, get: function () { return core_1.buildContext; } });
|
|
14
14
|
Object.defineProperty(exports, "REGISTRY", { enumerable: true, get: function () { return core_1.REGISTRY; } });
|
|
15
|
+
// Authoring helpers for consumers writing their own checks (plugins).
|
|
16
|
+
var core_2 = require("./core");
|
|
17
|
+
Object.defineProperty(exports, "pass", { enumerable: true, get: function () { return core_2.pass; } });
|
|
18
|
+
Object.defineProperty(exports, "warn", { enumerable: true, get: function () { return core_2.warn; } });
|
|
19
|
+
Object.defineProperty(exports, "fail", { enumerable: true, get: function () { return core_2.fail; } });
|
|
20
|
+
Object.defineProperty(exports, "skip", { enumerable: true, get: function () { return core_2.skip; } });
|
|
21
|
+
Object.defineProperty(exports, "defineCheck", { enumerable: true, get: function () { return core_2.defineCheck; } });
|
|
15
22
|
// Config helpers for consumers embedding pr-checkmate.
|
|
16
23
|
var config_1 = require("./config");
|
|
17
24
|
Object.defineProperty(exports, "getSourcePath", { enumerable: true, get: function () { return config_1.getSourcePath; } });
|
package/dist/init.d.ts
ADDED
package/dist/init.js
CHANGED
|
@@ -19,7 +19,11 @@ const DEFAULT_CONFIG = {
|
|
|
19
19
|
commands: config_1.DEFAULT_COMMANDS,
|
|
20
20
|
// ESLint customization
|
|
21
21
|
eslint: {
|
|
22
|
-
rules: {
|
|
22
|
+
rules: {
|
|
23
|
+
// Off by default: its `--fix` injects empty `/** */` JSDoc stubs into
|
|
24
|
+
// client source files. Set to 'warn'/'error' to opt into doc enforcement.
|
|
25
|
+
'jsdoc/require-jsdoc': 'off',
|
|
26
|
+
},
|
|
23
27
|
ignorePatterns: [],
|
|
24
28
|
},
|
|
25
29
|
// Prettier customization
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { Language } from '../utils/detect-language';
|
|
2
|
+
export interface ConfigFile {
|
|
3
|
+
source: string;
|
|
4
|
+
dest: string;
|
|
5
|
+
}
|
|
6
|
+
export interface PrettierConfig {
|
|
7
|
+
semi: boolean;
|
|
8
|
+
singleQuote: boolean;
|
|
9
|
+
trailingComma: string;
|
|
10
|
+
bracketSpacing: boolean;
|
|
11
|
+
arrowParens: string;
|
|
12
|
+
printWidth: number;
|
|
13
|
+
}
|
|
14
|
+
export interface CspellConfig {
|
|
15
|
+
version: string;
|
|
16
|
+
language: string;
|
|
17
|
+
import?: string[];
|
|
18
|
+
words: string[];
|
|
19
|
+
ignorePaths: string[];
|
|
20
|
+
enableFiletypes: string[];
|
|
21
|
+
ignoreRegExpList: string[];
|
|
22
|
+
}
|
|
23
|
+
export interface PRCheckMateConfig {
|
|
24
|
+
sourcePath: string;
|
|
25
|
+
languages?: Language[];
|
|
26
|
+
lint?: {
|
|
27
|
+
rules?: Record<string, any>;
|
|
28
|
+
ignorePatterns?: string[];
|
|
29
|
+
};
|
|
30
|
+
prettier?: {
|
|
31
|
+
config?: Record<string, any>;
|
|
32
|
+
};
|
|
33
|
+
spellcheck?: {
|
|
34
|
+
words?: string[];
|
|
35
|
+
ignoreWords?: string[];
|
|
36
|
+
ignorePaths?: string[];
|
|
37
|
+
};
|
|
38
|
+
security?: {
|
|
39
|
+
gitleaks?: {
|
|
40
|
+
enabled: boolean;
|
|
41
|
+
};
|
|
42
|
+
'npm-audit'?: {
|
|
43
|
+
enabled: boolean;
|
|
44
|
+
auditLevel: string;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
typecheck?: {
|
|
48
|
+
enabled?: boolean;
|
|
49
|
+
};
|
|
50
|
+
cpp?: {
|
|
51
|
+
enabled?: boolean;
|
|
52
|
+
clangFormat?: {
|
|
53
|
+
style?: string;
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
python?: {
|
|
57
|
+
enabled?: boolean;
|
|
58
|
+
ruff?: {
|
|
59
|
+
lint?: boolean;
|
|
60
|
+
format?: boolean;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
diffSmell?: {
|
|
64
|
+
enabled?: boolean;
|
|
65
|
+
};
|
|
66
|
+
prBody?: {
|
|
67
|
+
enabled?: boolean;
|
|
68
|
+
minLength?: number;
|
|
69
|
+
requireTicket?: boolean;
|
|
70
|
+
};
|
|
71
|
+
duplicate?: {
|
|
72
|
+
enabled?: boolean;
|
|
73
|
+
minLines?: number;
|
|
74
|
+
minTokens?: number;
|
|
75
|
+
};
|
|
76
|
+
commitlint?: {
|
|
77
|
+
enabled?: boolean;
|
|
78
|
+
types?: string[];
|
|
79
|
+
/**
|
|
80
|
+
* Regex sources (matched case-insensitively) for commit messages to skip,
|
|
81
|
+
* e.g. release PRs or squash-merge titles that don't follow conventional
|
|
82
|
+
* commits. Applied in addition to commitlint's built-in merge/revert ignores.
|
|
83
|
+
*/
|
|
84
|
+
ignores?: string[];
|
|
85
|
+
};
|
|
86
|
+
diffSecurity?: {
|
|
87
|
+
enabled?: boolean;
|
|
88
|
+
};
|
|
89
|
+
sensitiveFileGuard?: {
|
|
90
|
+
enabled?: boolean;
|
|
91
|
+
};
|
|
92
|
+
swift?: {
|
|
93
|
+
enabled?: boolean;
|
|
94
|
+
};
|
|
95
|
+
kotlin?: {
|
|
96
|
+
enabled?: boolean;
|
|
97
|
+
};
|
|
98
|
+
deadCode?: {
|
|
99
|
+
enabled?: boolean;
|
|
100
|
+
};
|
|
101
|
+
licenseCheck?: {
|
|
102
|
+
allowPackages?: string[];
|
|
103
|
+
allowLicenses?: string[];
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
export interface CheckmateConfig {
|
|
107
|
+
skipLint?: boolean;
|
|
108
|
+
skipDeps?: boolean;
|
|
109
|
+
skipFormat?: boolean;
|
|
110
|
+
skipSpell?: boolean;
|
|
111
|
+
skipSecurity?: boolean;
|
|
112
|
+
skipNpmAudit?: boolean;
|
|
113
|
+
skipCircularDeps?: boolean;
|
|
114
|
+
skipLicense?: boolean;
|
|
115
|
+
skipPrSize?: boolean;
|
|
116
|
+
skipPrTitle?: boolean;
|
|
117
|
+
skipOutdated?: boolean;
|
|
118
|
+
skipMarkdown?: boolean;
|
|
119
|
+
skipTypecheck?: boolean;
|
|
120
|
+
skipDiffSmell?: boolean;
|
|
121
|
+
skipPrBody?: boolean;
|
|
122
|
+
skipDuplicate?: boolean;
|
|
123
|
+
skipDiffSecurity?: boolean;
|
|
124
|
+
skipSensitiveFiles?: boolean;
|
|
125
|
+
skipDeadCode?: boolean;
|
|
126
|
+
autoCommit?: boolean;
|
|
127
|
+
}
|
|
128
|
+
export type { CheckStatus, CheckResult } from '../utils/result-collector';
|
|
129
|
+
export type { Language } from '../utils/detect-language';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type Language = 'typescript' | 'javascript' | 'python' | 'cpp' | 'swift' | 'kotlin';
|
|
2
|
+
/**
|
|
3
|
+
* Detects which languages a repository uses, combining marker files (definitive)
|
|
4
|
+
* with tracked source-file counts (breadth). A language is reported when it has a
|
|
5
|
+
* marker file OR at least one tracked source file.
|
|
6
|
+
*
|
|
7
|
+
* @returns languages ordered by tracked file count (most-used first). `.h` headers
|
|
8
|
+
* are intentionally excluded from the C++ count since they are ambiguous with C.
|
|
9
|
+
*/
|
|
10
|
+
export declare function detectLanguages(root?: string): Promise<Language[]>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './logger';
|
|
2
|
+
export * from './delta';
|
|
3
|
+
export * from './result-collector';
|
|
4
|
+
export * from './resolve-bin';
|
|
5
|
+
export * from './own-deps';
|
|
6
|
+
export * from './detect-language';
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
*/
|
|
10
|
+
export declare function cleanupTempFile(filePath: string): void;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
type LogLevel = 'log' | 'info' | 'warn' | 'error' | 'debug';
|
|
2
|
+
declare class Logger {
|
|
3
|
+
private logs;
|
|
4
|
+
private levelOrder;
|
|
5
|
+
private currentLevel;
|
|
6
|
+
private getTimestamp;
|
|
7
|
+
private shouldLog;
|
|
8
|
+
private colorize;
|
|
9
|
+
private logMessage;
|
|
10
|
+
log(msg: string): void;
|
|
11
|
+
info(msg: string): void;
|
|
12
|
+
warn(msg: string): void;
|
|
13
|
+
error(msg: string, err?: unknown): void;
|
|
14
|
+
debug(msg: string): void;
|
|
15
|
+
getLogs(): string[];
|
|
16
|
+
setLevel(level: LogLevel): void;
|
|
17
|
+
clear(): void;
|
|
18
|
+
}
|
|
19
|
+
export declare const logger: Logger;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute the full set of package names in pr-checkmate's own dependency
|
|
3
|
+
* closure (direct + transitive runtime dependencies), plus pr-checkmate itself.
|
|
4
|
+
*
|
|
5
|
+
* pr-checkmate installs into the consumer's node_modules, so its own runtime
|
|
6
|
+
* deps (eslint plugins, cspell dictionaries, …) become part of the consumer's
|
|
7
|
+
* production dependency tree. Some carry copyleft licenses that would otherwise
|
|
8
|
+
* trip pr-checkmate's own license check against an innocent client. These are
|
|
9
|
+
* pr-checkmate's dependencies, not the client's, so they must be exempt.
|
|
10
|
+
*
|
|
11
|
+
* Result is cached for the process. Returns a set containing only pr-checkmate
|
|
12
|
+
* itself if the package root cannot be located (defensive; never throws).
|
|
13
|
+
*/
|
|
14
|
+
export declare function getOwnDependencyClosure(): Set<string>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves a binary path for a bundled package, bypassing exports map restrictions.
|
|
3
|
+
*
|
|
4
|
+
* Strategy (tries each in order):
|
|
5
|
+
* 1. Direct subpath — fast path for packages that explicitly export their bin
|
|
6
|
+
* 2. Via package.json — for packages that export ./package.json but not the bin subpath (e.g. eslint)
|
|
7
|
+
* 3. Walk up from main entry — for packages that export neither (e.g. cspell)
|
|
8
|
+
*
|
|
9
|
+
* @param pkgName - The package whose binary to resolve (e.g. `eslint`).
|
|
10
|
+
* @param binRelPath - The bin path relative to the package root (e.g. `bin/eslint.js`).
|
|
11
|
+
* @param options - Resolution options.
|
|
12
|
+
* @param options.paths - Directories to resolve from (passed to `require.resolve`).
|
|
13
|
+
* Use `[process.cwd()]` to prefer the consumer project's copy of the package.
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolvePackageBin(pkgName: string, binRelPath: string, options?: {
|
|
16
|
+
paths?: string[];
|
|
17
|
+
}): string;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type CheckStatus = 'pass' | 'warn' | 'fail' | 'skip';
|
|
2
|
+
export interface CheckResult {
|
|
3
|
+
name: string;
|
|
4
|
+
status: CheckStatus;
|
|
5
|
+
details?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
*/
|
|
10
|
+
export declare class ResultCollector {
|
|
11
|
+
private results;
|
|
12
|
+
/**
|
|
13
|
+
*
|
|
14
|
+
*/
|
|
15
|
+
register(name: string, status: CheckStatus, details?: string): void;
|
|
16
|
+
/**
|
|
17
|
+
*
|
|
18
|
+
*/
|
|
19
|
+
getResults(): CheckResult[];
|
|
20
|
+
/**
|
|
21
|
+
*
|
|
22
|
+
*/
|
|
23
|
+
clear(): void;
|
|
24
|
+
/**
|
|
25
|
+
*
|
|
26
|
+
*/
|
|
27
|
+
getSummary(): {
|
|
28
|
+
passed: number;
|
|
29
|
+
warned: number;
|
|
30
|
+
failed: number;
|
|
31
|
+
skipped: number;
|
|
32
|
+
};
|
|
33
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pr-checkmate",
|
|
3
|
-
"version": "1.22.
|
|
3
|
+
"version": "1.22.2",
|
|
4
4
|
"description": "Automated PR quality checks: linting, formatting, dependency analysis, and spellcheck",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"github-actions",
|
|
@@ -11,11 +11,19 @@
|
|
|
11
11
|
"code-quality",
|
|
12
12
|
"automation"
|
|
13
13
|
],
|
|
14
|
-
"main": "./dist/
|
|
14
|
+
"main": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
15
16
|
"type": "commonjs",
|
|
16
17
|
"bin": {
|
|
17
18
|
"pr-checkmate": "dist/cli.js"
|
|
18
19
|
},
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"default": "./dist/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./package.json": "./package.json"
|
|
26
|
+
},
|
|
19
27
|
"files": [
|
|
20
28
|
"dist",
|
|
21
29
|
"README.md",
|