pr-checkmate 1.23.5 → 1.23.7

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/LICENSE CHANGED
@@ -36,6 +36,20 @@ Any use not expressly permitted in writing by the Owner is strictly
36
36
  prohibited and constitutes a violation of applicable copyright and
37
37
  intellectual property laws.
38
38
 
39
+ ================================================================================
40
+ PUBLIC MIRROR EXCEPTION
41
+ ================================================================================
42
+
43
+ The restrictions above do not prevent the Owner itself from publishing
44
+ selected non-source materials — this LICENSE, the README, the CONTRIBUTING
45
+ and CODE_OF_CONDUCT files, the documentation/ tree, and the configuration
46
+ template and its JSON schema — to a public repository the Owner controls, for
47
+ the sole purpose of giving consumers of the published npm package a reachable
48
+ repository URL and readable documentation. This exception applies only to
49
+ publication carried out by or on behalf of the Owner; it grants no rights to
50
+ any other party to fork, mirror, re-host, or redistribute the Software, and it
51
+ does not extend to the source code itself.
52
+
39
53
  ================================================================================
40
54
  NO WARRANTY
41
55
  ================================================================================
package/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # ♟️ PR CheckMate
2
2
 
3
- ![Build](https://img.shields.io/github/actions/workflow/status/Mybono/sdk_automation/publish.yml?branch=main&label=CI&color=blue)
3
+ [![npm](https://img.shields.io/npm/v/pr-checkmate?label=npm&color=CB3837&logo=npm&logoColor=white)](https://www.npmjs.com/package/pr-checkmate)
4
+ [![Downloads](https://img.shields.io/npm/dm/pr-checkmate?color=blue)](https://www.npmjs.com/package/pr-checkmate)
4
5
  ![License](https://img.shields.io/badge/license-Proprietary-lightgrey)
5
6
  ![ESLint](https://img.shields.io/badge/ESLint-10-4B32C3?logo=eslint&logoColor=white)
6
7
  ![Prettier](https://img.shields.io/badge/Prettier-3-F7B93E?logo=prettier&logoColor=white)
@@ -9,7 +10,7 @@
9
10
  ![jscpd](https://img.shields.io/badge/jscpd-5-blue)
10
11
  [![API Docs](https://img.shields.io/badge/API_docs-TypeDoc-9600FF?logo=readthedocs&logoColor=white)](https://pr-checkmate-docs.pages.dev)
11
12
 
12
- > PR CheckMate is a universal PR quality checker: one `npm install`, 49 checks across
13
+ > PR CheckMate is a universal PR quality checker: one `npm install`, 51 checks across
13
14
  > 11 languages, running in CI on every pull request. The bundled languages need no
14
15
  > per-language toolchain setup.
15
16
 
@@ -72,6 +73,31 @@ Run all checks:
72
73
  npx pr-checkmate all
73
74
  ```
74
75
 
76
+ ### Running in CI without installing
77
+
78
+ Plenty of repos never add pr-checkmate to `package.json` and call it on the fly in CI
79
+ instead (`npx pr-checkmate`). That works, but there is no `node_modules` to generate a
80
+ config from, so the run silently falls back to the defaults with no file to tune.
81
+ `npx pr-checkmate init` is no help either, since the package is not kept around.
82
+
83
+ Pull the published template instead:
84
+
85
+ ```bash
86
+ curl -fsSL -O https://raw.githubusercontent.com/Mybono/pr_checkmate_public/main/pr-checkmate.json
87
+ ```
88
+
89
+ Commit the file to the repository root and edit it there. Every check appears in it with
90
+ its real default value and a short comment, so switching a check on or off, or changing
91
+ one of its thresholds, is a one-line edit. The JSON schema is published alongside it for
92
+ editor autocompletion, and the template already references it:
93
+
94
+ ```text
95
+ https://raw.githubusercontent.com/Mybono/pr_checkmate_public/main/pr-checkmate.schema.json
96
+ ```
97
+
98
+ Both files are refreshed on every release, so the template never drifts from the
99
+ installed version.
100
+
75
101
  ## GitHub Actions
76
102
 
77
103
  Every workflow follows the same shape: checkout, set up Node, install, run. The
@@ -108,20 +134,24 @@ skipped, not failed.
108
134
 
109
135
  ## Checks
110
136
 
111
- 49 checks, grouped by category and run in parallel within each phase:
137
+ 51 checks, grouped by category and run in parallel within each phase:
112
138
 
113
139
  - Universal git-diff (18) — language-agnostic and bundled: merge-conflict markers,
114
- secret scan, diff security (JS/TS/Python/Go/Kotlin), GitHub Actions and Dockerfile
115
- security, case-collision, custom rules, banned imports, license headers, leftover
116
- debug lines, lockfile drift, large/binary files, TODO/FIXME, missing tests, coverage
117
- presence, DB migration safety, and sensitive-file guard.
140
+ secret scan, diff security (JS/TS/Python/Go/Kotlin), diff smells, GitHub Actions and
141
+ Dockerfile security, case-collision, custom rules, banned imports, license headers,
142
+ leftover debug lines, lockfile drift, large/binary files, TODO/FIXME, missing tests,
143
+ coverage presence, DB migration safety, and sensitive-file guard.
118
144
  - Dependencies (7) — unused/missing, circular, outdated, license compliance, npm audit,
119
145
  a cross-language vuln scan (osv-scanner, opt-in), and a direct-dependency vuln scan
120
146
  (grype, on by default).
121
- - Quality (4) — duplicate code, dead code, multi-language spellcheck, markdown lint.
147
+ - Quality (6) — duplicate code, dead code, multi-language spellcheck, markdown lint, YAML lint, config validation.
122
148
  - PR hygiene (4) — size, title, body, and commit-message convention.
123
149
  - Per-language (16) — lint, format, and type-check for the languages listed above.
124
150
 
151
+ Each check has its own page in the
152
+ [per-check reference](https://github.com/Mybono/pr_checkmate_public/blob/main/documentation/checks/INDEX.md),
153
+ covering when it runs, the config keys it reads, and how to turn it off.
154
+
125
155
  ## Configuration
126
156
 
127
157
  Everything lives in `pr-checkmate.json`. Run `npx pr-checkmate init` to scaffold the
@@ -155,6 +185,9 @@ full file for your detected languages.
155
185
  }
156
186
  ```
157
187
 
188
+ For the complete list of keys each check reads, along with their defaults, see the
189
+ [per-check reference](https://github.com/Mybono/pr_checkmate_public/blob/main/documentation/checks/INDEX.md).
190
+
158
191
  ## PR Summary Comment
159
192
 
160
193
  After `npx pr-checkmate all`, a summary table is posted to the PR and updated in place
package/cspell.json CHANGED
@@ -15,6 +15,7 @@
15
15
  "Accona",
16
16
  "acepto",
17
17
  "Acepto",
18
+ "acmecorp",
18
19
  "ACMR",
19
20
  "ACMRD",
20
21
  "acodec",
@@ -39,6 +40,7 @@
39
40
  "allclose",
40
41
  "Amuta",
41
42
  "análisis",
43
+ "analysers",
42
44
  "Anchore",
43
45
  "androidpublisher",
44
46
  "androidx",
@@ -340,6 +342,7 @@
340
342
  "endoftext",
341
343
  "endtable",
342
344
  "engineio",
345
+ "ENOENT",
343
346
  "eoilist",
344
347
  "Escaneá",
345
348
  "Escaneás",
@@ -684,6 +687,7 @@
684
687
  "mybono",
685
688
  "mydir",
686
689
  "myimage",
690
+ "myinternalservice",
687
691
  "mylib",
688
692
  "myorg",
689
693
  "myprefix",
@@ -812,6 +816,7 @@
812
816
  "preconcurrency",
813
817
  "pretrained",
814
818
  "prettier",
819
+ "println",
815
820
  "Privacidad",
816
821
  "processlist",
817
822
  "progressbar",
@@ -1076,6 +1081,7 @@
1076
1081
  "unsharp",
1077
1082
  "upbit",
1078
1083
  "updateemail",
1084
+ "uppercased",
1079
1085
  "upsell",
1080
1086
  "usecase",
1081
1087
  "usefixtures",
package/dist/cli.js CHANGED
@@ -19,6 +19,7 @@ const COMMAND_TO_CHECK = {
19
19
  'pr-title': 'PR Title',
20
20
  outdated: 'Outdated Deps',
21
21
  markdown: 'Markdown',
22
+ 'yaml-lint': 'YAML Lint',
22
23
  typecheck: 'TypeScript',
23
24
  'diff-smell': 'Diff Smells',
24
25
  'diff-security': 'Diff Security',
@@ -240,6 +240,7 @@ exports.KNOWN_CONFIG_KEYS = new Set([
240
240
  'spellcheck',
241
241
  'cspell',
242
242
  'markdownlint',
243
+ 'yamlLint',
243
244
  'typecheck',
244
245
  // security
245
246
  'security',
@@ -0,0 +1,13 @@
1
+ import { Check } from '../../types';
2
+ /**
3
+ * Bundled YAML linter (the `yaml` package — no runner dependency, always
4
+ * available like Markdown/Spellcheck). Parses every changed `.yml`/`.yaml` file
5
+ * and reports the parser's own errors and warnings: syntax errors, duplicate map
6
+ * keys, tabs used as indentation, and other structural problems. Multi-document
7
+ * files (`---`-separated) are each parsed. ON by default — runs unless
8
+ * `yamlLint.enabled` is explicitly `false`. Findings are a hard error by default
9
+ * (a YAML problem fails the run); downgrade to advisory with
10
+ * `yamlLint.severity: "warn"`. Clients can exclude paths with `yamlLint.ignore`
11
+ * (glob patterns) in pr-checkmate.json.
12
+ */
13
+ export declare const yamlLintCheck: Check;
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.yamlLintCheck = void 0;
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const yaml_1 = require("yaml");
10
+ const utils_1 = require("../../../utils");
11
+ const targets_1 = require("../../targets");
12
+ const types_1 = require("../../types");
13
+ const findings_1 = require("../findings");
14
+ /** First line of a `yaml` error/warning message, stripped of its source excerpt. */
15
+ function shortMessage(message) {
16
+ return message.split('\n')[0].trim();
17
+ }
18
+ /**
19
+ * Bundled YAML linter (the `yaml` package — no runner dependency, always
20
+ * available like Markdown/Spellcheck). Parses every changed `.yml`/`.yaml` file
21
+ * and reports the parser's own errors and warnings: syntax errors, duplicate map
22
+ * keys, tabs used as indentation, and other structural problems. Multi-document
23
+ * files (`---`-separated) are each parsed. ON by default — runs unless
24
+ * `yamlLint.enabled` is explicitly `false`. Findings are a hard error by default
25
+ * (a YAML problem fails the run); downgrade to advisory with
26
+ * `yamlLint.severity: "warn"`. Clients can exclude paths with `yamlLint.ignore`
27
+ * (glob patterns) in pr-checkmate.json.
28
+ */
29
+ exports.yamlLintCheck = {
30
+ name: 'YAML Lint',
31
+ phase: 'blocking',
32
+ applies(ctx) {
33
+ return ctx.config.yamlLint?.enabled !== false;
34
+ },
35
+ async run(ctx) {
36
+ // Keep the CI/workflow dirs that are globally ignored: they hold the very
37
+ // YAML (GitHub Actions, GitLab CI, CircleCI) a YAML linter most needs to see.
38
+ const allTargets = await (0, targets_1.resolveTargetFiles)(ctx, ['*.yml', '*.yaml'], {
39
+ keepDirs: ['.github', '.gitlab', '.circleci'],
40
+ });
41
+ if (allTargets === null)
42
+ return (0, types_1.skip)('git unavailable');
43
+ if (allTargets.length === 0)
44
+ return (0, types_1.skip)('no YAML files');
45
+ const ignore = ctx.config.yamlLint?.ignore ?? [];
46
+ const targets = ignore.length > 0 ? allTargets.filter(f => !(0, utils_1.matchesAnyGlob)(f, ignore)) : allTargets;
47
+ if (targets.length === 0)
48
+ return (0, types_1.skip)('all YAML files ignored');
49
+ const issues = [];
50
+ for (const file of targets) {
51
+ let source;
52
+ try {
53
+ source = node_fs_1.default.readFileSync(node_path_1.default.join(ctx.cwd, file), 'utf-8');
54
+ }
55
+ catch (err) {
56
+ utils_1.logger.warn(`[YAML Lint]: ⚠️ Could not read ${file}: ${err}`);
57
+ continue;
58
+ }
59
+ // parseAllDocuments never throws — it collects problems on each document,
60
+ // so a single malformed file cannot abort the whole check.
61
+ const docs = (0, yaml_1.parseAllDocuments)(source, { prettyErrors: true });
62
+ for (const doc of docs) {
63
+ for (const problem of [...doc.errors, ...doc.warnings]) {
64
+ const pos = problem.linePos?.[0];
65
+ issues.push({
66
+ file,
67
+ line: pos?.line,
68
+ col: pos?.col,
69
+ message: shortMessage(problem.message),
70
+ });
71
+ }
72
+ }
73
+ }
74
+ if (issues.length === 0)
75
+ return (0, types_1.pass)();
76
+ // YAML problems are a hard error by default; a repo may downgrade to `warn`
77
+ // via `yamlLint.severity`.
78
+ const sev = (0, findings_1.severityEmitter)(ctx.config.yamlLint?.severity, 'error');
79
+ issues.slice(0, 10).forEach(i => {
80
+ const where = i.line ? `:${i.line}${i.col ? `:${i.col}` : ''}` : '';
81
+ sev.log(`[YAML Lint]: ${sev.icon} ${i.file}${where} — ${i.message}`);
82
+ });
83
+ if (issues.length > 10)
84
+ sev.log(`[YAML Lint]: ... and ${issues.length - 10} more`);
85
+ return sev.emit(`${issues.length} YAML issue(s) found`);
86
+ },
87
+ };
@@ -45,6 +45,7 @@ const duplicate_check_1 = require("./checks/quality/duplicate-check");
45
45
  const license_header_1 = require("./checks/quality/license-header");
46
46
  const markdown_lint_1 = require("./checks/quality/markdown-lint");
47
47
  const spellcheck_1 = require("./checks/quality/spellcheck");
48
+ const yaml_lint_1 = require("./checks/quality/yaml-lint");
48
49
  const diff_security_1 = require("./checks/security/diff-security");
49
50
  const dockerfile_security_1 = require("./checks/security/dockerfile-security");
50
51
  const migration_safety_1 = require("./checks/security/migration-safety");
@@ -93,6 +94,7 @@ exports.REGISTRY = [
93
94
  outdated_deps_1.outdatedDepsCheck,
94
95
  markdown_lint_1.markdownLintCheck,
95
96
  spellcheck_1.spellcheckCheck,
97
+ yaml_lint_1.yamlLintCheck,
96
98
  python_lint_1.pythonLintCheck,
97
99
  python_typecheck_1.pythonTypecheckCheck,
98
100
  dead_code_1.deadCodeCheck,
@@ -11,7 +11,9 @@ import type { CheckContext } from './types';
11
11
  * longer exists) can never hand a missing path to a downstream tool like ESLint
12
12
  * or Prettier, which crash hard on a non-existent pattern.
13
13
  */
14
- export declare function resolveTargetFiles(ctx: CheckContext, globs: string[]): Promise<string[] | null>;
14
+ export declare function resolveTargetFiles(ctx: CheckContext, globs: string[], opts?: {
15
+ keepDirs?: string[];
16
+ }): Promise<string[] | null>;
15
17
  /**
16
18
  * Like {@link resolveTargetFiles} but restricts results to the configured
17
19
  * `sourcePath`(s). Preserves the semantics of the old `sourcePath` full-scan
@@ -16,9 +16,15 @@ const execa_1 = require("../utils/execa");
16
16
  * curated default), matched on any path segment so nesting depth doesn't matter.
17
17
  * Applied to every check's file list so build/tooling/report dirs are never
18
18
  * scanned, even when committed.
19
+ *
20
+ * `keepDirs` un-ignores specific segments for a single check — e.g. YAML lint
21
+ * keeps the CI dirs (`.github`, `.gitlab`, `.circleci`), which are ignored
22
+ * globally but hold the workflow files a YAML linter most needs to see.
19
23
  */
20
- function excludeIgnoredDirs(files) {
24
+ function excludeIgnoredDirs(files, keepDirs = []) {
21
25
  const ignored = new Set((0, config_1.getIgnoredDirs)());
26
+ for (const dir of keepDirs)
27
+ ignored.delete(dir);
22
28
  if (ignored.size === 0)
23
29
  return files;
24
30
  return files.filter(f => !f.split('/').some(segment => ignored.has(segment)));
@@ -35,7 +41,7 @@ function excludeIgnoredDirs(files) {
35
41
  * longer exists) can never hand a missing path to a downstream tool like ESLint
36
42
  * or Prettier, which crash hard on a non-existent pattern.
37
43
  */
38
- async function resolveTargetFiles(ctx, globs) {
44
+ async function resolveTargetFiles(ctx, globs, opts = {}) {
39
45
  try {
40
46
  const args = ctx.baseSha
41
47
  ? [
@@ -57,7 +63,7 @@ async function resolveTargetFiles(ctx, globs) {
57
63
  const files = excludeIgnoredDirs(stdout
58
64
  .split('\n')
59
65
  .map(f => f.trim())
60
- .filter(Boolean)).filter(f => node_fs_1.default.existsSync(node_path_1.default.join(ctx.cwd, f)));
66
+ .filter(Boolean), opts.keepDirs).filter(f => node_fs_1.default.existsSync(node_path_1.default.join(ctx.cwd, f)));
61
67
  utils_1.logger.info(`[targets]: ${ctx.baseSha ? '📂 Delta' : 'Full scan'}: ${files.length} file(s) for ${globs.join(', ')}`);
62
68
  return files;
63
69
  }
package/dist/init.js CHANGED
@@ -68,6 +68,14 @@ const DEFAULT_CONFIG = {
68
68
  rules: {},
69
69
  ignores: [],
70
70
  },
71
+ // YAML lint (bundled `yaml` parser). Reports syntax errors, duplicate keys,
72
+ // and tab/indentation problems in .yml/.yaml files. Blocking by default
73
+ // (severity "error"); set severity "warn" to make it advisory, or enabled
74
+ // false to disable. `ignore` takes glob patterns to skip (e.g. "charts/**").
75
+ yamlLint: {
76
+ enabled: true,
77
+ ignore: [],
78
+ },
71
79
  // TypeScript type check
72
80
  typecheck: {
73
81
  enabled: true,
@@ -197,6 +197,11 @@ export interface PRCheckMateConfig {
197
197
  configValidation?: {
198
198
  enabled?: boolean;
199
199
  };
200
+ yamlLint?: {
201
+ enabled?: boolean;
202
+ severity?: 'error' | 'warn';
203
+ ignore?: string[];
204
+ };
200
205
  vulnScan?: {
201
206
  enabled?: boolean;
202
207
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pr-checkmate",
3
- "version": "1.23.5",
3
+ "version": "1.23.7",
4
4
  "description": "Automated PR quality checks: linting, formatting, dependency analysis, and spellcheck",
5
5
  "keywords": [
6
6
  "github-actions",
@@ -61,14 +61,14 @@
61
61
  },
62
62
  "repository": {
63
63
  "type": "git",
64
- "url": "git+https://github.com/Mybono/pr_checkmate.git"
64
+ "url": "git+https://github.com/Mybono/pr_checkmate_public.git"
65
65
  },
66
66
  "bugs": {
67
- "url": "https://github.com/Mybono/pr_checkmate/issues"
67
+ "url": "https://github.com/Mybono/pr_checkmate_public/issues"
68
68
  },
69
69
  "homepage": "https://dev.to/deftoexplore/pr-checkmate-stop-debating-style-and-start-coding-ij",
70
70
  "author": "Artur Polishchuk",
71
- "license": "LicenseRef-Proprietary",
71
+ "license": "UNLICENSED",
72
72
  "dependencies": {
73
73
  "@astral-sh/ruff-wasm-nodejs": "^0.15.20",
74
74
  "@commitlint/cli": "^21.2.0",
@@ -99,10 +99,19 @@
99
99
  "prettier": ">=3.0.0",
100
100
  "ts-node": "^10.9.1",
101
101
  "ts-unused-exports": "^11.0.1",
102
- "typescript": "^6.0.3"
102
+ "typescript": "^6.0.3",
103
+ "yaml": "^2.9.0"
103
104
  },
104
105
  "devDependencies": {
105
106
  "standard-version": "^9.5.0",
106
107
  "typedoc": "^0.28.20"
108
+ },
109
+ "overrides": {
110
+ "markdownlint-cli2": {
111
+ "js-yaml": "5.2.2"
112
+ },
113
+ "cosmiconfig": {
114
+ "js-yaml": "4.3.0"
115
+ }
107
116
  }
108
117
  }
@@ -148,6 +148,14 @@
148
148
  "caseCollision": { "$ref": "#/$defs/toggle" },
149
149
  "sensitiveFileGuard": { "$ref": "#/$defs/toggle" },
150
150
  "configValidation": { "$ref": "#/$defs/toggle" },
151
+ "yamlLint": {
152
+ "type": "object",
153
+ "properties": {
154
+ "enabled": { "type": "boolean" },
155
+ "severity": { "enum": ["error", "warn"] },
156
+ "ignore": { "type": "array", "items": { "type": "string" } }
157
+ }
158
+ },
151
159
  "typecheck": { "$ref": "#/$defs/toggle" },
152
160
  "prBody": {
153
161
  "type": "object",
@@ -15,6 +15,7 @@
15
15
  "Accona",
16
16
  "acepto",
17
17
  "Acepto",
18
+ "acmecorp",
18
19
  "ACMR",
19
20
  "ACMRD",
20
21
  "acodec",
@@ -39,6 +40,7 @@
39
40
  "allclose",
40
41
  "Amuta",
41
42
  "análisis",
43
+ "analysers",
42
44
  "Anchore",
43
45
  "androidpublisher",
44
46
  "androidx",
@@ -340,6 +342,7 @@
340
342
  "endoftext",
341
343
  "endtable",
342
344
  "engineio",
345
+ "ENOENT",
343
346
  "eoilist",
344
347
  "Escaneá",
345
348
  "Escaneás",
@@ -684,6 +687,7 @@
684
687
  "mybono",
685
688
  "mydir",
686
689
  "myimage",
690
+ "myinternalservice",
687
691
  "mylib",
688
692
  "myorg",
689
693
  "myprefix",
@@ -812,6 +816,7 @@
812
816
  "preconcurrency",
813
817
  "pretrained",
814
818
  "prettier",
819
+ "println",
815
820
  "Privacidad",
816
821
  "processlist",
817
822
  "progressbar",
@@ -1076,6 +1081,7 @@
1076
1081
  "unsharp",
1077
1082
  "upbit",
1078
1083
  "updateemail",
1084
+ "uppercased",
1079
1085
  "upsell",
1080
1086
  "usecase",
1081
1087
  "usefixtures",
@@ -148,6 +148,14 @@
148
148
  "caseCollision": { "$ref": "#/$defs/toggle" },
149
149
  "sensitiveFileGuard": { "$ref": "#/$defs/toggle" },
150
150
  "configValidation": { "$ref": "#/$defs/toggle" },
151
+ "yamlLint": {
152
+ "type": "object",
153
+ "properties": {
154
+ "enabled": { "type": "boolean" },
155
+ "severity": { "enum": ["error", "warn"] },
156
+ "ignore": { "type": "array", "items": { "type": "string" } }
157
+ }
158
+ },
151
159
  "typecheck": { "$ref": "#/$defs/toggle" },
152
160
  "prBody": {
153
161
  "type": "object",