pr-checkmate 3.0.4 → 3.1.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/dist/{cli.js → cjs/cli.js} +30 -30
- package/dist/{config → cjs/config}/index.d.ts +2 -2
- package/dist/{config → cjs/config}/index.js +8 -7
- package/dist/{config → cjs/config}/loader.d.ts +1 -1
- package/dist/{config → cjs/config}/loader.js +8 -8
- package/dist/{core → cjs/core}/checks/dependencies/banned-imports.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/dependencies/banned-imports.js +10 -10
- package/dist/{core → cjs/core}/checks/dependencies/circular-deps.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/dependencies/circular-deps.js +27 -27
- package/dist/{core → cjs/core}/checks/dependencies/dependency-check.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/dependencies/dependency-check.js +17 -17
- package/dist/{core → cjs/core}/checks/dependencies/grype-scan.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/dependencies/grype-scan.js +18 -18
- package/dist/{core → cjs/core}/checks/dependencies/license-check.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/dependencies/license-check.js +12 -12
- package/dist/{core → cjs/core}/checks/dependencies/npm-audit.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/dependencies/npm-audit.js +14 -14
- package/dist/{core → cjs/core}/checks/dependencies/outdated-deps.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/dependencies/outdated-deps.js +14 -14
- package/dist/{core → cjs/core}/checks/dependencies/vuln-scan.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/dependencies/vuln-scan.js +14 -14
- package/dist/{core → cjs/core}/checks/findings.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/findings.js +16 -16
- package/dist/{core → cjs/core}/checks/git/custom-rules.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/git/custom-rules.js +19 -19
- package/dist/{core → cjs/core}/checks/git/diff-smell.d.ts +2 -2
- package/dist/{core → cjs/core}/checks/git/diff-smell.js +13 -13
- package/dist/{core → cjs/core}/checks/git/large-files.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/git/large-files.js +15 -15
- package/dist/{core → cjs/core}/checks/git/leftover-debug.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/git/leftover-debug.js +13 -13
- package/dist/{core → cjs/core}/checks/git/lockfile-drift.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/git/lockfile-drift.js +12 -12
- package/dist/{core → cjs/core}/checks/git/merge-conflict.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/git/merge-conflict.js +15 -15
- package/dist/{core → cjs/core}/checks/git/missing-tests.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/git/missing-tests.js +15 -15
- package/dist/{core → cjs/core}/checks/git/todo-fixme.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/git/todo-fixme.js +11 -11
- package/dist/{core → cjs/core}/checks/languages/cpp-format.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/languages/cpp-format.js +18 -18
- package/dist/{core → cjs/core}/checks/languages/external-checks.d.ts +9 -9
- package/dist/{core → cjs/core}/checks/languages/external-checks.js +10 -10
- package/dist/{core → cjs/core}/checks/languages/external-runner.d.ts +2 -2
- package/dist/{core → cjs/core}/checks/languages/external-runner.js +21 -21
- package/dist/{core → cjs/core}/checks/languages/go-format.d.ts +1 -1
- package/dist/cjs/core/checks/languages/go-format.js +202 -0
- package/dist/cjs/core/checks/languages/lint.d.ts +2 -0
- package/dist/{core → cjs/core}/checks/languages/lint.js +21 -21
- package/dist/{core → cjs/core}/checks/languages/prettier.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/languages/prettier.js +18 -18
- package/dist/{core → cjs/core}/checks/languages/python-format.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/languages/python-format.js +14 -14
- package/dist/{core → cjs/core}/checks/languages/python-lint.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/languages/python-lint.js +13 -13
- package/dist/{core → cjs/core}/checks/languages/python-typecheck.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/languages/python-typecheck.js +29 -29
- package/dist/{core → cjs/core}/checks/languages/typecheck.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/languages/typecheck.js +13 -13
- package/dist/{core → cjs/core}/checks/pr/commitlint.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/pr/commitlint.js +12 -12
- package/dist/{core → cjs/core}/checks/pr/pr-body.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/pr/pr-body.js +8 -8
- package/dist/{core → cjs/core}/checks/pr/pr-size-check.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/pr/pr-size-check.js +10 -10
- package/dist/{core → cjs/core}/checks/pr/pr-title-lint.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/pr/pr-title-lint.js +8 -8
- package/dist/{core → cjs/core}/checks/quality/case-collision.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/quality/case-collision.js +7 -7
- package/dist/{core → cjs/core}/checks/quality/config-validation.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/quality/config-validation.js +9 -9
- package/dist/{core → cjs/core}/checks/quality/coverage.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/quality/coverage.js +4 -4
- package/dist/{core → cjs/core}/checks/quality/dead-code.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/quality/dead-code.js +23 -23
- package/dist/{core → cjs/core}/checks/quality/duplicate-check.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/quality/duplicate-check.js +22 -22
- package/dist/{core → cjs/core}/checks/quality/license-header.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/quality/license-header.js +16 -16
- package/dist/{core → cjs/core}/checks/quality/markdown-lint.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/quality/markdown-lint.js +17 -17
- package/dist/{core → cjs/core}/checks/quality/package-size.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/quality/package-size.js +12 -12
- package/dist/{core → cjs/core}/checks/quality/spellcheck.d.ts +2 -2
- package/dist/{core → cjs/core}/checks/quality/spellcheck.js +18 -18
- package/dist/{core → cjs/core}/checks/quality/symlinks.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/quality/symlinks.js +8 -8
- package/dist/{core → cjs/core}/checks/quality/yaml-lint.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/quality/yaml-lint.js +12 -12
- package/dist/{core → cjs/core}/checks/security/diff-security.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/security/diff-security.js +15 -15
- package/dist/{core → cjs/core}/checks/security/dockerfile-security.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/security/dockerfile-security.js +16 -16
- package/dist/{core → cjs/core}/checks/security/migration-safety.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/security/migration-safety.js +17 -17
- package/dist/{core → cjs/core}/checks/security/security.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/security/security.js +21 -21
- package/dist/{core → cjs/core}/checks/security/sensitive-file-guard.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/security/sensitive-file-guard.js +14 -14
- package/dist/{core → cjs/core}/checks/security/workflow-security.d.ts +2 -2
- package/dist/{core → cjs/core}/checks/security/workflow-security.js +14 -14
- package/dist/{core → cjs/core}/checks/tool-install.d.ts +1 -1
- package/dist/{core → cjs/core}/checks/tool-install.js +2 -2
- package/dist/{core → cjs/core}/context.d.ts +1 -1
- package/dist/{core → cjs/core}/context.js +16 -16
- package/dist/cjs/core/index.d.ts +4 -0
- package/dist/{core → cjs/core}/index.js +7 -7
- package/dist/{core → cjs/core}/install/cache.js +2 -2
- package/dist/{core → cjs/core}/install/doctor.d.ts +4 -4
- package/dist/{core → cjs/core}/install/doctor.js +34 -34
- package/dist/{core → cjs/core}/install/ensure.d.ts +2 -2
- package/dist/{core → cjs/core}/install/ensure.js +15 -14
- package/dist/{core → cjs/core}/install/lock.js +4 -4
- package/dist/{core → cjs/core}/install/prepare.d.ts +4 -4
- package/dist/{core → cjs/core}/install/prepare.js +13 -13
- package/dist/{core → cjs/core}/install/profiles.d.ts +2 -2
- package/dist/{core → cjs/core}/install/reuse.d.ts +1 -1
- package/dist/{core → cjs/core}/install/reuse.js +4 -4
- package/dist/{core → cjs/core}/registry.d.ts +1 -1
- package/dist/cjs/core/registry.js +112 -0
- package/dist/{core → cjs/core}/reporters.d.ts +1 -1
- package/dist/{core → cjs/core}/reporters.js +28 -28
- package/dist/{core → cjs/core}/run-checks.d.ts +2 -2
- package/dist/{core → cjs/core}/run-checks.js +31 -31
- package/dist/{core → cjs/core}/targets.d.ts +1 -1
- package/dist/{core → cjs/core}/targets.js +20 -20
- package/dist/{core → cjs/core}/types.d.ts +3 -3
- package/dist/cjs/index.d.ts +12 -0
- package/dist/{index.js → cjs/index.js} +18 -18
- package/dist/{init.js → cjs/init.js} +68 -56
- package/dist/{interfaces → cjs/interfaces}/index.d.ts +3 -3
- package/dist/cjs/package.json +1 -0
- package/dist/{scripts → cjs/scripts}/copy-configs.js +22 -7
- package/dist/{scripts → cjs/scripts}/generate-install-manifests.js +2 -2
- package/dist/{scripts → cjs/scripts}/publish-github.js +4 -4
- package/dist/{utils → cjs/utils}/detect-language.js +12 -12
- package/dist/cjs/utils/execa.js +46 -0
- package/dist/{utils → cjs/utils}/git.js +2 -2
- package/dist/{utils → cjs/utils}/http.js +2 -2
- package/dist/cjs/utils/index.d.ts +15 -0
- package/dist/{utils → cjs/utils}/index.js +13 -13
- package/dist/{utils → cjs/utils}/own-deps.d.ts +2 -0
- package/dist/{utils → cjs/utils}/own-deps.js +1 -0
- package/dist/{utils → cjs/utils}/package-version.js +2 -1
- package/dist/{utils → cjs/utils}/resolve-bin.js +2 -1
- package/dist/{utils → cjs/utils}/update-notifier.js +4 -4
- package/dist/esm/cli.d.ts +2 -0
- package/dist/esm/cli.js +137 -0
- package/dist/esm/config/constants.d.ts +153 -0
- package/dist/esm/config/constants.js +360 -0
- package/dist/esm/config/index.d.ts +40 -0
- package/dist/esm/config/index.js +60 -0
- package/dist/esm/config/loader.d.ts +6 -0
- package/dist/esm/config/loader.js +191 -0
- package/dist/esm/config/pr-checkmate-workflow-docker.yml +79 -0
- package/dist/esm/config/pr-checkmate-workflow.yml +92 -0
- package/dist/esm/core/checks/dependencies/banned-imports.d.ts +2 -0
- package/dist/esm/core/checks/dependencies/banned-imports.js +70 -0
- package/dist/esm/core/checks/dependencies/circular-deps.d.ts +2 -0
- package/dist/esm/core/checks/dependencies/circular-deps.js +155 -0
- package/dist/esm/core/checks/dependencies/dependency-check.d.ts +43 -0
- package/dist/esm/core/checks/dependencies/dependency-check.js +174 -0
- package/dist/esm/core/checks/dependencies/grype-scan.d.ts +22 -0
- package/dist/esm/core/checks/dependencies/grype-scan.js +112 -0
- package/dist/esm/core/checks/dependencies/license-check.d.ts +2 -0
- package/dist/esm/core/checks/dependencies/license-check.js +61 -0
- package/dist/esm/core/checks/dependencies/npm-audit.d.ts +6 -0
- package/dist/esm/core/checks/dependencies/npm-audit.js +80 -0
- package/dist/esm/core/checks/dependencies/outdated-deps.d.ts +2 -0
- package/dist/esm/core/checks/dependencies/outdated-deps.js +66 -0
- package/dist/esm/core/checks/dependencies/vuln-scan.d.ts +2 -0
- package/dist/esm/core/checks/dependencies/vuln-scan.js +54 -0
- package/dist/esm/core/checks/findings.d.ts +299 -0
- package/dist/esm/core/checks/findings.js +701 -0
- package/dist/esm/core/checks/git/custom-rules.d.ts +2 -0
- package/dist/esm/core/checks/git/custom-rules.js +106 -0
- package/dist/esm/core/checks/git/diff-smell.d.ts +19 -0
- package/dist/esm/core/checks/git/diff-smell.js +69 -0
- package/dist/esm/core/checks/git/large-files.d.ts +2 -0
- package/dist/esm/core/checks/git/large-files.js +112 -0
- package/dist/esm/core/checks/git/leftover-debug.d.ts +2 -0
- package/dist/esm/core/checks/git/leftover-debug.js +89 -0
- package/dist/esm/core/checks/git/lockfile-drift.d.ts +2 -0
- package/dist/esm/core/checks/git/lockfile-drift.js +114 -0
- package/dist/esm/core/checks/git/merge-conflict.d.ts +2 -0
- package/dist/esm/core/checks/git/merge-conflict.js +117 -0
- package/dist/esm/core/checks/git/missing-tests.d.ts +2 -0
- package/dist/esm/core/checks/git/missing-tests.js +105 -0
- package/dist/esm/core/checks/git/todo-fixme.d.ts +7 -0
- package/dist/esm/core/checks/git/todo-fixme.js +80 -0
- package/dist/esm/core/checks/languages/cpp-format.d.ts +7 -0
- package/dist/esm/core/checks/languages/cpp-format.js +91 -0
- package/dist/esm/core/checks/languages/external-checks.d.ts +77 -0
- package/dist/esm/core/checks/languages/external-checks.js +197 -0
- package/dist/esm/core/checks/languages/external-runner.d.ts +119 -0
- package/dist/esm/core/checks/languages/external-runner.js +138 -0
- package/dist/esm/core/checks/languages/go-format.d.ts +8 -0
- package/dist/{core → esm/core}/checks/languages/go-format.js +29 -35
- package/dist/esm/core/checks/languages/lint.d.ts +2 -0
- package/dist/esm/core/checks/languages/lint.js +92 -0
- package/dist/esm/core/checks/languages/prettier.d.ts +2 -0
- package/dist/esm/core/checks/languages/prettier.js +85 -0
- package/dist/esm/core/checks/languages/python-format.d.ts +7 -0
- package/dist/esm/core/checks/languages/python-format.js +61 -0
- package/dist/esm/core/checks/languages/python-lint.d.ts +9 -0
- package/dist/esm/core/checks/languages/python-lint.js +55 -0
- package/dist/esm/core/checks/languages/python-typecheck.d.ts +14 -0
- package/dist/esm/core/checks/languages/python-typecheck.js +184 -0
- package/dist/esm/core/checks/languages/ruff-shared.d.ts +10 -0
- package/dist/esm/core/checks/languages/ruff-shared.js +35 -0
- package/dist/esm/core/checks/languages/typecheck.d.ts +2 -0
- package/dist/esm/core/checks/languages/typecheck.js +61 -0
- package/dist/esm/core/checks/pr/commitlint.d.ts +2 -0
- package/dist/esm/core/checks/pr/commitlint.js +102 -0
- package/dist/esm/core/checks/pr/pr-body.d.ts +2 -0
- package/dist/esm/core/checks/pr/pr-body.js +43 -0
- package/dist/esm/core/checks/pr/pr-size-check.d.ts +2 -0
- package/dist/esm/core/checks/pr/pr-size-check.js +42 -0
- package/dist/esm/core/checks/pr/pr-title-lint.d.ts +2 -0
- package/dist/esm/core/checks/pr/pr-title-lint.js +31 -0
- package/dist/esm/core/checks/quality/case-collision.d.ts +8 -0
- package/dist/esm/core/checks/quality/case-collision.js +39 -0
- package/dist/esm/core/checks/quality/config-validation.d.ts +11 -0
- package/dist/esm/core/checks/quality/config-validation.js +188 -0
- package/dist/esm/core/checks/quality/coverage.d.ts +2 -0
- package/dist/esm/core/checks/quality/coverage.js +62 -0
- package/dist/esm/core/checks/quality/dead-code.d.ts +2 -0
- package/dist/esm/core/checks/quality/dead-code.js +124 -0
- package/dist/esm/core/checks/quality/duplicate-check.d.ts +2 -0
- package/dist/esm/core/checks/quality/duplicate-check.js +141 -0
- package/dist/esm/core/checks/quality/license-header.d.ts +7 -0
- package/dist/esm/core/checks/quality/license-header.js +81 -0
- package/dist/esm/core/checks/quality/markdown-lint.d.ts +2 -0
- package/dist/esm/core/checks/quality/markdown-lint.js +104 -0
- package/dist/esm/core/checks/quality/package-size.d.ts +36 -0
- package/dist/esm/core/checks/quality/package-size.js +196 -0
- package/dist/esm/core/checks/quality/spellcheck.d.ts +77 -0
- package/dist/esm/core/checks/quality/spellcheck.js +296 -0
- package/dist/esm/core/checks/quality/symlinks.d.ts +16 -0
- package/dist/esm/core/checks/quality/symlinks.js +57 -0
- package/dist/esm/core/checks/quality/yaml-lint.d.ts +20 -0
- package/dist/esm/core/checks/quality/yaml-lint.js +116 -0
- package/dist/esm/core/checks/security/diff-security.d.ts +2 -0
- package/dist/esm/core/checks/security/diff-security.js +354 -0
- package/dist/esm/core/checks/security/dockerfile-security.d.ts +2 -0
- package/dist/esm/core/checks/security/dockerfile-security.js +98 -0
- package/dist/esm/core/checks/security/migration-safety.d.ts +2 -0
- package/dist/esm/core/checks/security/migration-safety.js +137 -0
- package/dist/esm/core/checks/security/security.d.ts +63 -0
- package/dist/esm/core/checks/security/security.js +201 -0
- package/dist/esm/core/checks/security/sensitive-file-guard.d.ts +2 -0
- package/dist/esm/core/checks/security/sensitive-file-guard.js +160 -0
- package/dist/esm/core/checks/security/workflow-security.d.ts +12 -0
- package/dist/esm/core/checks/security/workflow-security.js +100 -0
- package/dist/esm/core/checks/tool-install.d.ts +102 -0
- package/dist/esm/core/checks/tool-install.js +66 -0
- package/dist/esm/core/commands.d.ts +27 -0
- package/dist/esm/core/commands.js +89 -0
- package/dist/esm/core/context.d.ts +62 -0
- package/dist/esm/core/context.js +241 -0
- package/dist/esm/core/index.d.ts +4 -0
- package/dist/esm/core/index.js +4 -0
- package/dist/esm/core/install/cache.d.ts +58 -0
- package/dist/esm/core/install/cache.js +142 -0
- package/dist/esm/core/install/doctor.d.ts +35 -0
- package/dist/esm/core/install/doctor.js +164 -0
- package/dist/esm/core/install/ensure.d.ts +77 -0
- package/dist/esm/core/install/ensure.js +269 -0
- package/dist/esm/core/install/lock.d.ts +34 -0
- package/dist/esm/core/install/lock.js +92 -0
- package/dist/esm/core/install/merge.d.ts +47 -0
- package/dist/esm/core/install/merge.js +85 -0
- package/dist/esm/core/install/prepare.d.ts +76 -0
- package/dist/esm/core/install/prepare.js +142 -0
- package/dist/esm/core/install/profiles.d.ts +78 -0
- package/dist/esm/core/install/profiles.js +192 -0
- package/dist/esm/core/install/reuse.d.ts +41 -0
- package/dist/esm/core/install/reuse.js +100 -0
- package/dist/esm/core/registry.d.ts +6 -0
- package/dist/esm/core/registry.js +109 -0
- package/dist/esm/core/reporters.d.ts +18 -0
- package/dist/esm/core/reporters.js +266 -0
- package/dist/esm/core/run-checks.d.ts +33 -0
- package/dist/esm/core/run-checks.js +293 -0
- package/dist/esm/core/targets.d.ts +140 -0
- package/dist/esm/core/targets.js +213 -0
- package/dist/esm/core/types.d.ts +195 -0
- package/dist/esm/core/types.js +38 -0
- package/dist/esm/index.d.ts +12 -0
- package/dist/esm/index.js +15 -0
- package/dist/esm/init.d.ts +38 -0
- package/dist/esm/init.js +421 -0
- package/dist/esm/interfaces/index.d.ts +432 -0
- package/dist/esm/interfaces/index.js +2 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/scripts/copy-configs.d.ts +1 -0
- package/dist/esm/scripts/copy-configs.js +64 -0
- package/dist/esm/scripts/generate-install-manifests.d.ts +39 -0
- package/dist/esm/scripts/generate-install-manifests.js +115 -0
- package/dist/esm/scripts/publish-github.d.ts +1 -0
- package/dist/esm/scripts/publish-github.js +45 -0
- package/dist/esm/utils/ci.d.ts +11 -0
- package/dist/esm/utils/ci.js +40 -0
- package/dist/esm/utils/detect-language.d.ts +48 -0
- package/dist/esm/utils/detect-language.js +234 -0
- package/dist/esm/utils/direct-deps.d.ts +21 -0
- package/dist/esm/utils/direct-deps.js +220 -0
- package/dist/esm/utils/execa.d.ts +22 -0
- package/dist/{utils → esm/utils}/execa.js +1 -4
- package/dist/esm/utils/git.d.ts +14 -0
- package/dist/esm/utils/git.js +21 -0
- package/dist/esm/utils/glob.d.ts +24 -0
- package/dist/esm/utils/glob.js +40 -0
- package/dist/esm/utils/http.d.ts +59 -0
- package/dist/esm/utils/http.js +115 -0
- package/dist/esm/utils/index.d.ts +15 -0
- package/dist/esm/utils/index.js +26 -0
- package/dist/esm/utils/logger.d.ts +65 -0
- package/dist/esm/utils/logger.js +157 -0
- package/dist/esm/utils/own-deps.d.ts +16 -0
- package/dist/esm/utils/own-deps.js +107 -0
- package/dist/esm/utils/package-version.d.ts +4 -0
- package/dist/esm/utils/package-version.js +38 -0
- package/dist/esm/utils/pool.d.ts +49 -0
- package/dist/esm/utils/pool.js +113 -0
- package/dist/esm/utils/resolve-bin.d.ts +67 -0
- package/dist/esm/utils/resolve-bin.js +156 -0
- package/dist/esm/utils/result-collector.d.ts +33 -0
- package/dist/esm/utils/result-collector.js +44 -0
- package/dist/esm/utils/update-notifier.d.ts +19 -0
- package/dist/esm/utils/update-notifier.js +108 -0
- package/install-manifests/core/package-lock.json +4 -4
- package/install-manifests/core/package.json +1 -1
- package/package.json +15 -13
- package/dist/core/checks/languages/lint.d.ts +0 -2
- package/dist/core/index.d.ts +0 -4
- package/dist/core/registry.js +0 -112
- package/dist/index.d.ts +0 -12
- package/dist/utils/index.d.ts +0 -15
- /package/dist/{cli.d.ts → cjs/cli.d.ts} +0 -0
- /package/dist/{config → cjs/config}/constants.d.ts +0 -0
- /package/dist/{config → cjs/config}/constants.js +0 -0
- /package/dist/{config → cjs/config}/pr-checkmate-workflow-docker.yml +0 -0
- /package/dist/{config → cjs/config}/pr-checkmate-workflow.yml +0 -0
- /package/dist/{core → cjs/core}/checks/languages/ruff-shared.d.ts +0 -0
- /package/dist/{core → cjs/core}/checks/languages/ruff-shared.js +0 -0
- /package/dist/{core → cjs/core}/commands.d.ts +0 -0
- /package/dist/{core → cjs/core}/commands.js +0 -0
- /package/dist/{core → cjs/core}/install/cache.d.ts +0 -0
- /package/dist/{core → cjs/core}/install/lock.d.ts +0 -0
- /package/dist/{core → cjs/core}/install/merge.d.ts +0 -0
- /package/dist/{core → cjs/core}/install/merge.js +0 -0
- /package/dist/{core → cjs/core}/install/profiles.js +0 -0
- /package/dist/{core → cjs/core}/types.js +0 -0
- /package/dist/{init.d.ts → cjs/init.d.ts} +0 -0
- /package/dist/{interfaces → cjs/interfaces}/index.js +0 -0
- /package/dist/{scripts → cjs/scripts}/copy-configs.d.ts +0 -0
- /package/dist/{scripts → cjs/scripts}/generate-install-manifests.d.ts +0 -0
- /package/dist/{scripts → cjs/scripts}/publish-github.d.ts +0 -0
- /package/dist/{utils → cjs/utils}/ci.d.ts +0 -0
- /package/dist/{utils → cjs/utils}/ci.js +0 -0
- /package/dist/{utils → cjs/utils}/detect-language.d.ts +0 -0
- /package/dist/{utils → cjs/utils}/direct-deps.d.ts +0 -0
- /package/dist/{utils → cjs/utils}/direct-deps.js +0 -0
- /package/dist/{utils → cjs/utils}/execa.d.ts +0 -0
- /package/dist/{utils → cjs/utils}/git.d.ts +0 -0
- /package/dist/{utils → cjs/utils}/glob.d.ts +0 -0
- /package/dist/{utils → cjs/utils}/glob.js +0 -0
- /package/dist/{utils → cjs/utils}/http.d.ts +0 -0
- /package/dist/{utils → cjs/utils}/logger.d.ts +0 -0
- /package/dist/{utils → cjs/utils}/logger.js +0 -0
- /package/dist/{utils → cjs/utils}/package-version.d.ts +0 -0
- /package/dist/{utils → cjs/utils}/pool.d.ts +0 -0
- /package/dist/{utils → cjs/utils}/pool.js +0 -0
- /package/dist/{utils → cjs/utils}/resolve-bin.d.ts +0 -0
- /package/dist/{utils → cjs/utils}/result-collector.d.ts +0 -0
- /package/dist/{utils → cjs/utils}/result-collector.js +0 -0
- /package/dist/{utils → cjs/utils}/update-notifier.d.ts +0 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { Check, CheckContext, type Language } from '../../types.js';
|
|
2
|
+
import { type ExternalTool } from '../tool-install.js';
|
|
3
|
+
/**
|
|
4
|
+
* The one shape every check that shells out to somebody else's linter has.
|
|
5
|
+
*
|
|
6
|
+
* Eleven of these were written by copying a neighbour, and copying is what they
|
|
7
|
+
* had in common: `resolveTargetFiles` → `execa` → the same seven-line comment
|
|
8
|
+
* about `ENOENT` → split the output → log ten lines and a "… and N more". Of the
|
|
9
|
+
* ~600 lines that produced, about sixty said anything specific to a language.
|
|
10
|
+
*
|
|
11
|
+
* The cost of that was not the duplication. It was that each copy diverged
|
|
12
|
+
* slightly, so a fix landed in one of eleven places: the `git unavailable` skip
|
|
13
|
+
* was missing from some, the ten-line truncation counted differently in others,
|
|
14
|
+
* and `⏭️ ktlint: ktlint not installed` outlived four rewrites of the message it
|
|
15
|
+
* was supposed to match. Behaviour that is meant to be identical everywhere
|
|
16
|
+
* belongs in one function; what is genuinely per-language belongs in a table.
|
|
17
|
+
*
|
|
18
|
+
* Two factories rather than one, because a linter and a formatter differ in the
|
|
19
|
+
* only part that matters — a linter reads output, a formatter runs twice and may
|
|
20
|
+
* write. Folding them together would mean a spec with half its fields unused.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Config blocks that gate a language check with `enabled: false`.
|
|
24
|
+
*
|
|
25
|
+
* Named as a union rather than typed as `keyof PRCheckMateConfig` so a spec
|
|
26
|
+
* cannot point at `reporter` or `install` and typecheck.
|
|
27
|
+
*/
|
|
28
|
+
type LanguageConfigKey = 'csharp' | 'go' | 'kotlin' | 'php' | 'ruby' | 'rust' | 'shellcheck' | 'swift';
|
|
29
|
+
/**
|
|
30
|
+
* A finished tool run, with "the tool is not here" as a case of its own rather
|
|
31
|
+
* than an exception.
|
|
32
|
+
*/
|
|
33
|
+
type ToolRun = {
|
|
34
|
+
missing: true;
|
|
35
|
+
} | {
|
|
36
|
+
missing: false;
|
|
37
|
+
exitCode: number | undefined;
|
|
38
|
+
stdout: string;
|
|
39
|
+
stderr: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Run an external tool, telling an absent binary apart from a failing one.
|
|
43
|
+
*
|
|
44
|
+
* execa v9 with `reject: false` does NOT throw on a missing binary — it resolves
|
|
45
|
+
* with `code: 'ENOENT'`. Detecting that on the result rather than in a
|
|
46
|
+
* `try`/`catch` (which never fires here) is the difference between an honest skip
|
|
47
|
+
* and a missing linter reporting a clean pass. This comment used to be repeated
|
|
48
|
+
* verbatim in eleven files, which is roughly how long it takes for one of the
|
|
49
|
+
* copies to lose it.
|
|
50
|
+
*/
|
|
51
|
+
export declare function runTool(ctx: CheckContext, bin: string, args: string[]): Promise<ToolRun>;
|
|
52
|
+
/** The fields both factories read; each adds the part that differs. */
|
|
53
|
+
interface ExternalSpecBase {
|
|
54
|
+
/** Display name — the report row, and the log prefix. */
|
|
55
|
+
name: string;
|
|
56
|
+
/** The binary to run. */
|
|
57
|
+
bin: string;
|
|
58
|
+
/** Key into the install-hint table, so the skip says how to fix itself. */
|
|
59
|
+
tool: ExternalTool;
|
|
60
|
+
/**
|
|
61
|
+
* How to name the tool in the skip. Omit when the check's own name already is
|
|
62
|
+
* the binary's name, or the message stutters (`ktlint: ktlint not installed`).
|
|
63
|
+
*/
|
|
64
|
+
toolLabel?: string;
|
|
65
|
+
/** Pathspecs the check operates on, e.g. `['*.kt', '*.kts']`. */
|
|
66
|
+
globs: string[];
|
|
67
|
+
/**
|
|
68
|
+
* Language gate. Omit for a check that applies to any repository — ShellCheck
|
|
69
|
+
* runs wherever there is a `.sh`, and shell is not a detected language.
|
|
70
|
+
*/
|
|
71
|
+
language?: Language;
|
|
72
|
+
/** Config block whose `enabled: false` switches the check off. */
|
|
73
|
+
configKey: LanguageConfigKey;
|
|
74
|
+
/** Plural noun for the nothing-to-do pass: `no Kotlin files changed`. */
|
|
75
|
+
subject: string;
|
|
76
|
+
}
|
|
77
|
+
/** A check that runs somebody else's linter and reports what it said. */
|
|
78
|
+
export interface ExternalLintSpec extends ExternalSpecBase {
|
|
79
|
+
/**
|
|
80
|
+
* Arguments for the run. Given `ctx` as well as the files because not every
|
|
81
|
+
* linter takes a file list — `go vet` works per package and SwiftLint per
|
|
82
|
+
* directory, and for those the resolved targets only decide whether to run.
|
|
83
|
+
*/
|
|
84
|
+
args(ctx: CheckContext, targets: string[]): string[];
|
|
85
|
+
/** Which output lines are findings. Default: every non-blank line. */
|
|
86
|
+
keep?(line: string): boolean;
|
|
87
|
+
/** How to phrase the count. Default: `N issue(s)`. */
|
|
88
|
+
summary?(lines: string[], targets: string[]): string;
|
|
89
|
+
/** Read stderr ahead of stdout, for tools that diagnose there. */
|
|
90
|
+
stderrFirst?: boolean;
|
|
91
|
+
}
|
|
92
|
+
/** A check that runs somebody else's formatter, read-only unless `write`. */
|
|
93
|
+
export interface ExternalFormatSpec extends ExternalSpecBase {
|
|
94
|
+
/** Singular noun for the verdicts: `PHP code needs formatting`. */
|
|
95
|
+
code: string;
|
|
96
|
+
/** Arguments for the read-only pass. */
|
|
97
|
+
checkArgs(targets: string[]): string[];
|
|
98
|
+
/** Arguments for the pass that rewrites files. */
|
|
99
|
+
writeArgs(targets: string[]): string[];
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Build an informational lint check from its spec.
|
|
103
|
+
*
|
|
104
|
+
* Informational for all of them, and not a field: these checks depend on a tool
|
|
105
|
+
* we do not ship, so on a runner without it they cannot distinguish clean code
|
|
106
|
+
* from unexamined code. A gate that silently stops gating is worse than no gate,
|
|
107
|
+
* and a client who wants one promotes the check with `severity`.
|
|
108
|
+
*/
|
|
109
|
+
export declare function defineExternalLint(spec: ExternalLintSpec): Check;
|
|
110
|
+
/**
|
|
111
|
+
* Build a format check from its spec: detect, then rewrite only when asked.
|
|
112
|
+
*
|
|
113
|
+
* The two passes are deliberate. A check run must never change the tree unless
|
|
114
|
+
* the caller said `write`, and in `write` mode CI needs the files actually
|
|
115
|
+
* rewritten so it can commit them — so the read-only pass is the one that decides
|
|
116
|
+
* the verdict, and the second only carries it out.
|
|
117
|
+
*/
|
|
118
|
+
export declare function defineExternalFormat(spec: ExternalFormatSpec): Check;
|
|
119
|
+
export {};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { execa } from '../../../utils/execa.js';
|
|
2
|
+
import { logger } from '../../../utils/index.js';
|
|
3
|
+
import { resolveTargets } from '../../targets.js';
|
|
4
|
+
import { pass, warn, } from '../../types.js';
|
|
5
|
+
import { logSample } from '../findings.js';
|
|
6
|
+
import { notInstalled } from '../tool-install.js';
|
|
7
|
+
/**
|
|
8
|
+
* Run an external tool, telling an absent binary apart from a failing one.
|
|
9
|
+
*
|
|
10
|
+
* execa v9 with `reject: false` does NOT throw on a missing binary — it resolves
|
|
11
|
+
* with `code: 'ENOENT'`. Detecting that on the result rather than in a
|
|
12
|
+
* `try`/`catch` (which never fires here) is the difference between an honest skip
|
|
13
|
+
* and a missing linter reporting a clean pass. This comment used to be repeated
|
|
14
|
+
* verbatim in eleven files, which is roughly how long it takes for one of the
|
|
15
|
+
* copies to lose it.
|
|
16
|
+
*/
|
|
17
|
+
export async function runTool(ctx, bin, args) {
|
|
18
|
+
const result = await execa(bin, args, { cwd: ctx.cwd, reject: false });
|
|
19
|
+
if (result.code === 'ENOENT')
|
|
20
|
+
return { missing: true };
|
|
21
|
+
return {
|
|
22
|
+
missing: false,
|
|
23
|
+
exitCode: result.exitCode,
|
|
24
|
+
stdout: result.stdout,
|
|
25
|
+
stderr: result.stderr,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/** Both streams as one blob — some tools diagnose on stdout, some on stderr. */
|
|
29
|
+
function combinedOutput(run, stderrFirst) {
|
|
30
|
+
const streams = stderrFirst ? [run.stderr, run.stdout] : [run.stdout, run.stderr];
|
|
31
|
+
return streams.filter(Boolean).join('\n').trim();
|
|
32
|
+
}
|
|
33
|
+
/** Every non-blank line is a finding, unless a spec says otherwise. */
|
|
34
|
+
function isNotBlank(line) {
|
|
35
|
+
return line.trim().length > 0;
|
|
36
|
+
}
|
|
37
|
+
/** `N issue(s)`, unless a spec phrases its count differently. */
|
|
38
|
+
function countIssues(lines) {
|
|
39
|
+
return `${lines.length} issue(s)`;
|
|
40
|
+
}
|
|
41
|
+
/** Whether a language check is switched on for this repository. */
|
|
42
|
+
function isEnabled(ctx, key, language) {
|
|
43
|
+
if (ctx.config[key]?.enabled === false)
|
|
44
|
+
return false;
|
|
45
|
+
return language === undefined || ctx.languages.includes(language);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Assemble the `Check` both factories return, given the part that differs.
|
|
49
|
+
*
|
|
50
|
+
* Everything here is identical between a linter and a formatter — the name, the
|
|
51
|
+
* `applies` gate, and resolving the files — and only `phase` and `work` are not.
|
|
52
|
+
* Kept as a third function rather than merged into one factory with a flag,
|
|
53
|
+
* because the two specs are genuinely different shapes: a linter reads output, a
|
|
54
|
+
* formatter runs twice and may write. One factory would mean a spec with half its
|
|
55
|
+
* fields unused, which is the trade this file's header argues against.
|
|
56
|
+
*/
|
|
57
|
+
function defineExternal(spec, phase, work) {
|
|
58
|
+
return {
|
|
59
|
+
name: spec.name,
|
|
60
|
+
phase,
|
|
61
|
+
applies(ctx) {
|
|
62
|
+
return isEnabled(ctx, spec.configKey, spec.language);
|
|
63
|
+
},
|
|
64
|
+
async run(ctx) {
|
|
65
|
+
const targets = await resolveTargets(ctx, spec.globs, {
|
|
66
|
+
onEmpty: { pass: `no ${spec.subject} changed` },
|
|
67
|
+
});
|
|
68
|
+
if (!Array.isArray(targets))
|
|
69
|
+
return targets;
|
|
70
|
+
return work(ctx, targets);
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Build an informational lint check from its spec.
|
|
76
|
+
*
|
|
77
|
+
* Informational for all of them, and not a field: these checks depend on a tool
|
|
78
|
+
* we do not ship, so on a runner without it they cannot distinguish clean code
|
|
79
|
+
* from unexamined code. A gate that silently stops gating is worse than no gate,
|
|
80
|
+
* and a client who wants one promotes the check with `severity`.
|
|
81
|
+
*/
|
|
82
|
+
export function defineExternalLint(spec) {
|
|
83
|
+
return defineExternal(spec, 'informational', async (ctx, targets) => {
|
|
84
|
+
const run = await runTool(ctx, spec.bin, spec.args(ctx, targets));
|
|
85
|
+
if (run.missing)
|
|
86
|
+
return notInstalled(spec.tool, spec.toolLabel);
|
|
87
|
+
const output = combinedOutput(run, spec.stderrFirst);
|
|
88
|
+
// Exit 0 is the tool's verdict. Empty output on a non-zero exit is a tool
|
|
89
|
+
// that objected without saying to what, and there is nothing to put in a
|
|
90
|
+
// report either way — so both are a pass rather than a warn reading
|
|
91
|
+
// "0 issue(s)".
|
|
92
|
+
if (run.exitCode === 0 || !output) {
|
|
93
|
+
logger.info(`[${spec.name}]: ✅ No issues found`);
|
|
94
|
+
return pass();
|
|
95
|
+
}
|
|
96
|
+
const lines = output.split('\n').filter(spec.keep ?? isNotBlank);
|
|
97
|
+
// The tool objected and none of its output matched what this check knows how
|
|
98
|
+
// to read — a build error ahead of the lint pass, usually. Naming the exit
|
|
99
|
+
// code is thin, but a clean pass over an objection is a lie.
|
|
100
|
+
const summary = lines.length > 0
|
|
101
|
+
? (spec.summary ?? countIssues)(lines, targets)
|
|
102
|
+
: `${spec.bin} exited ${run.exitCode ?? 'without a code'} with no readable diagnostics`;
|
|
103
|
+
logSample(spec.name, `${summary}:`, lines);
|
|
104
|
+
return warn(summary);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Build a format check from its spec: detect, then rewrite only when asked.
|
|
109
|
+
*
|
|
110
|
+
* The two passes are deliberate. A check run must never change the tree unless
|
|
111
|
+
* the caller said `write`, and in `write` mode CI needs the files actually
|
|
112
|
+
* rewritten so it can commit them — so the read-only pass is the one that decides
|
|
113
|
+
* the verdict, and the second only carries it out.
|
|
114
|
+
*/
|
|
115
|
+
export function defineExternalFormat(spec) {
|
|
116
|
+
return defineExternal(spec, 'format', async (ctx, targets) => {
|
|
117
|
+
const dry = await runTool(ctx, spec.bin, spec.checkArgs(targets));
|
|
118
|
+
if (dry.missing)
|
|
119
|
+
return notInstalled(spec.tool, spec.toolLabel);
|
|
120
|
+
if (dry.exitCode === 0)
|
|
121
|
+
return pass();
|
|
122
|
+
if (!ctx.write) {
|
|
123
|
+
logger.warn(`[${spec.name}]: ⚠️ ${spec.code} needs formatting`);
|
|
124
|
+
return warn(`${spec.code} needs formatting (run with write to fix)`);
|
|
125
|
+
}
|
|
126
|
+
const fix = await runTool(ctx, spec.bin, spec.writeArgs(targets));
|
|
127
|
+
// `missing` cannot happen here — the same binary answered a moment ago — but
|
|
128
|
+
// it is a case of the type, and collapsing it into the failure branch is both
|
|
129
|
+
// correct and shorter than asserting it away.
|
|
130
|
+
if (fix.missing || fix.exitCode !== 0) {
|
|
131
|
+
const detail = fix.missing ? '' : `\n${fix.stderr}`;
|
|
132
|
+
logger.warn(`[${spec.name}]: ⚠️ ${spec.bin} failed to rewrite files${detail}`);
|
|
133
|
+
return warn(`${spec.bin} failed to rewrite files`);
|
|
134
|
+
}
|
|
135
|
+
logger.info(`[${spec.name}]: ✅ Reformatted ${spec.code}`);
|
|
136
|
+
return pass(`reformatted ${spec.code}`);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Check } from '../../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Formats changed Go files with gofmt — the runner's own when it has one, and a
|
|
4
|
+
* bundled WASM build otherwise, so the check has no runner dependency at all.
|
|
5
|
+
* Read-only in check mode; rewrites in place when `write`, so CI can auto-commit
|
|
6
|
+
* — mirrors the Prettier/C++/Ruff format checks.
|
|
7
|
+
*/
|
|
8
|
+
export declare const goFormatCheck: Check;
|
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const node_url_1 = require("node:url");
|
|
10
|
-
const utils_1 = require("../../../utils");
|
|
11
|
-
const targets_1 = require("../../targets");
|
|
12
|
-
const types_1 = require("../../types");
|
|
13
|
-
const tool_install_1 = require("../tool-install");
|
|
14
|
-
const external_runner_1 = require("./external-runner");
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { logger, resolvePackageBin } from '../../../utils/index.js';
|
|
5
|
+
import { resolveTargets } from '../../targets.js';
|
|
6
|
+
import { pass, warn } from '../../types.js';
|
|
7
|
+
import { notInstalled } from '../tool-install.js';
|
|
8
|
+
import { runTool } from './external-runner.js';
|
|
15
9
|
const GO_GLOBS = ['*.go'];
|
|
16
10
|
/**
|
|
17
11
|
* Load the bundled WASM gofmt, or explain why it could not be loaded.
|
|
@@ -35,12 +29,12 @@ const GO_GLOBS = ['*.go'];
|
|
|
35
29
|
*/
|
|
36
30
|
async function loadBundledGofmt() {
|
|
37
31
|
try {
|
|
38
|
-
const entry =
|
|
39
|
-
const mod = (await import(
|
|
32
|
+
const entry = resolvePackageBin('@wasm-fmt/gofmt', 'gofmt_node.js');
|
|
33
|
+
const mod = (await import(pathToFileURL(entry).href));
|
|
40
34
|
return mod.format;
|
|
41
35
|
}
|
|
42
36
|
catch (err) {
|
|
43
|
-
|
|
37
|
+
logger.warn(`[Go Format]: ⚠️ bundled gofmt could not be loaded\n${err}`);
|
|
44
38
|
return null;
|
|
45
39
|
}
|
|
46
40
|
}
|
|
@@ -61,14 +55,14 @@ async function loadBundledGofmt() {
|
|
|
61
55
|
*/
|
|
62
56
|
function verdictFor(ctx, unformatted) {
|
|
63
57
|
if (unformatted.length === 0)
|
|
64
|
-
return
|
|
58
|
+
return pass();
|
|
65
59
|
if (!ctx.write) {
|
|
66
|
-
|
|
67
|
-
unformatted.slice(0, 10).forEach(file =>
|
|
68
|
-
return
|
|
60
|
+
logger.warn(`[Go Format]: ⚠️ ${unformatted.length} Go file(s) need formatting`);
|
|
61
|
+
unformatted.slice(0, 10).forEach(file => logger.warn(` ${file}`));
|
|
62
|
+
return warn(`${unformatted.length} file(s) need formatting (run with write to fix)`);
|
|
69
63
|
}
|
|
70
|
-
|
|
71
|
-
return
|
|
64
|
+
logger.info(`[Go Format]: ✅ Reformatted ${unformatted.length} Go file(s)`);
|
|
65
|
+
return pass(`reformatted ${unformatted.length} file(s)`);
|
|
72
66
|
}
|
|
73
67
|
/**
|
|
74
68
|
* Format with the runner's own `gofmt`, when it has one.
|
|
@@ -83,7 +77,7 @@ function verdictFor(ctx, unformatted) {
|
|
|
83
77
|
* @returns The outcome, or `null` when there is no system `gofmt` to ask.
|
|
84
78
|
*/
|
|
85
79
|
async function formatWithSystemGofmt(ctx, targets) {
|
|
86
|
-
const list = await
|
|
80
|
+
const list = await runTool(ctx, 'gofmt', ['-l', ...targets]);
|
|
87
81
|
if (list.missing)
|
|
88
82
|
return null;
|
|
89
83
|
const unformatted = list.stdout.split('\n').filter(Boolean);
|
|
@@ -91,10 +85,10 @@ async function formatWithSystemGofmt(ctx, targets) {
|
|
|
91
85
|
// having been considered at all.
|
|
92
86
|
if (unformatted.length === 0 || !ctx.write)
|
|
93
87
|
return verdictFor(ctx, unformatted);
|
|
94
|
-
const fix = await
|
|
88
|
+
const fix = await runTool(ctx, 'gofmt', ['-w', ...unformatted]);
|
|
95
89
|
if (fix.missing || fix.exitCode !== 0) {
|
|
96
|
-
|
|
97
|
-
return
|
|
90
|
+
logger.warn(`[Go Format]: ⚠️ gofmt -w failed\n${fix.missing ? '' : fix.stderr}`);
|
|
91
|
+
return warn('gofmt failed to rewrite files');
|
|
98
92
|
}
|
|
99
93
|
return verdictFor(ctx, unformatted);
|
|
100
94
|
}
|
|
@@ -109,10 +103,10 @@ async function formatWithSystemGofmt(ctx, targets) {
|
|
|
109
103
|
function formatWithBundledGofmt(ctx, targets, format) {
|
|
110
104
|
const unformatted = [];
|
|
111
105
|
for (const rel of targets) {
|
|
112
|
-
const abs =
|
|
106
|
+
const abs = path.join(ctx.cwd, rel);
|
|
113
107
|
let content;
|
|
114
108
|
try {
|
|
115
|
-
content =
|
|
109
|
+
content = fs.readFileSync(abs, 'utf-8');
|
|
116
110
|
}
|
|
117
111
|
catch {
|
|
118
112
|
continue; // renamed or removed between the diff and the read
|
|
@@ -125,14 +119,14 @@ function formatWithBundledGofmt(ctx, targets, format) {
|
|
|
125
119
|
// gofmt parses before it formats, so a throw here is a syntax error. That
|
|
126
120
|
// is Go Vet's finding to report, not a formatting verdict — and calling it
|
|
127
121
|
// one sends people looking for a style problem that does not exist.
|
|
128
|
-
|
|
122
|
+
logger.warn(`[Go Format]: ⚠️ could not parse ${rel} (syntax error?)\n${err}`);
|
|
129
123
|
continue;
|
|
130
124
|
}
|
|
131
125
|
if (formatted === content)
|
|
132
126
|
continue;
|
|
133
127
|
unformatted.push(rel);
|
|
134
128
|
if (ctx.write)
|
|
135
|
-
|
|
129
|
+
fs.writeFileSync(abs, formatted);
|
|
136
130
|
}
|
|
137
131
|
return verdictFor(ctx, unformatted);
|
|
138
132
|
}
|
|
@@ -142,14 +136,14 @@ function formatWithBundledGofmt(ctx, targets, format) {
|
|
|
142
136
|
* Read-only in check mode; rewrites in place when `write`, so CI can auto-commit
|
|
143
137
|
* — mirrors the Prettier/C++/Ruff format checks.
|
|
144
138
|
*/
|
|
145
|
-
|
|
139
|
+
export const goFormatCheck = {
|
|
146
140
|
name: 'Go Format',
|
|
147
141
|
phase: 'format',
|
|
148
142
|
applies(ctx) {
|
|
149
143
|
return ctx.config.go?.enabled !== false && ctx.languages.includes('go');
|
|
150
144
|
},
|
|
151
145
|
async run(ctx) {
|
|
152
|
-
const targets = await
|
|
146
|
+
const targets = await resolveTargets(ctx, GO_GLOBS, {
|
|
153
147
|
onEmpty: { pass: 'no Go files changed' },
|
|
154
148
|
});
|
|
155
149
|
if (!Array.isArray(targets))
|
|
@@ -162,8 +156,8 @@ exports.goFormatCheck = {
|
|
|
162
156
|
// loaded, which means a partial install of this package. Installing Go is
|
|
163
157
|
// the fix a client can actually act on.
|
|
164
158
|
if (!format)
|
|
165
|
-
return
|
|
166
|
-
|
|
159
|
+
return notInstalled('gofmt', 'gofmt');
|
|
160
|
+
logger.debug('[Go Format]: no system gofmt — using the bundled WASM formatter');
|
|
167
161
|
return formatWithBundledGofmt(ctx, targets, format);
|
|
168
162
|
},
|
|
169
163
|
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { hasLocalConfig, getSourcePaths, getPackageConfigPath, IGNORE_PATTERNS, } from '../../../config/index.js';
|
|
2
|
+
import { execa } from '../../../utils/execa.js';
|
|
3
|
+
import { logger, resolvePackageBin } from '../../../utils/index.js';
|
|
4
|
+
import { clientToolPaths } from '../../install/reuse.js';
|
|
5
|
+
import { resolveScopedTargetFiles } from '../../targets.js';
|
|
6
|
+
import { pass, fail, warn, skip } from '../../types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Resolve the ESLint binary under the client's `install.reuseLocal` policy.
|
|
9
|
+
*
|
|
10
|
+
* A repo pinned to ESLint 8 with a legacy `.eslintrc.*` must run ITS ESLint —
|
|
11
|
+
* ours does not read eslintrc — so when the client owns the config the version is
|
|
12
|
+
* not asked about. When the config is the flat one WE generate, it is: ESLint 8
|
|
13
|
+
* cannot read it, and reusing their copy there produced a failure about our
|
|
14
|
+
* configuration rather than about their code. That asymmetry is the whole reason
|
|
15
|
+
* `clientOwnsConfig` exists (ticket 064, lever A).
|
|
16
|
+
*/
|
|
17
|
+
function resolveESLintBin(ctx, clientOwnsConfig) {
|
|
18
|
+
return resolvePackageBin('eslint', 'bin/eslint.js', {
|
|
19
|
+
paths: clientToolPaths('eslint', ctx, { clientOwnsConfig }),
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
async function getESLintMajorVersion(eslintBin) {
|
|
23
|
+
try {
|
|
24
|
+
const { stdout } = await execa(process.execPath, [eslintBin, '--version']);
|
|
25
|
+
const match = stdout.match(/v?(\d+)\./);
|
|
26
|
+
return match ? parseInt(match[1], 10) : 8;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return 8;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export const lintCheck = {
|
|
33
|
+
name: 'ESLint',
|
|
34
|
+
phase: 'blocking',
|
|
35
|
+
applies(ctx) {
|
|
36
|
+
return ctx.languages.includes('typescript') || ctx.languages.includes('javascript');
|
|
37
|
+
},
|
|
38
|
+
async run(ctx) {
|
|
39
|
+
const targets = await resolveScopedTargetFiles(ctx, ['*.ts', '*.tsx', '*.js', '*.jsx'], getSourcePaths(ctx.cwd));
|
|
40
|
+
if (targets === null)
|
|
41
|
+
return skip('git unavailable');
|
|
42
|
+
if (targets.length === 0)
|
|
43
|
+
return pass('no TypeScript/JavaScript files to lint');
|
|
44
|
+
// Whose config decides whose binary, so this is read BEFORE resolving one.
|
|
45
|
+
// It used to be the other way round, which is how a client's ESLint 8 ended
|
|
46
|
+
// up pointed at the flat config we generate.
|
|
47
|
+
const hasLocal = hasLocalConfig(['eslint.config.mjs', 'eslint.config.js', '.eslintrc.js', '.eslintrc.json', '.eslintrc'], ctx.cwd);
|
|
48
|
+
const eslintBin = resolveESLintBin(ctx, hasLocal);
|
|
49
|
+
const version = await getESLintMajorVersion(eslintBin);
|
|
50
|
+
const args = [...targets];
|
|
51
|
+
// `--ext` is an eslintrc-only flag. Under flat config (ESLint 9+) it is
|
|
52
|
+
// obsolete — extensions come from the config's `files` glob — and in
|
|
53
|
+
// ESLint 10 passing it makes explicit files fall back to the default JS
|
|
54
|
+
// parser, breaking TypeScript linting. Only pass it on the legacy path.
|
|
55
|
+
if (version < 9)
|
|
56
|
+
args.push('--ext', '.ts,.tsx,.js,.jsx');
|
|
57
|
+
// Files are named explicitly, so any of them that the config ignores produces a
|
|
58
|
+
// "File ignored because of a matching ignore pattern" warning. That is a fact
|
|
59
|
+
// about the config, not about the client's code, and a whole-repo run surfaces
|
|
60
|
+
// one per ignored-but-tracked file (`.eslintrc.js`, generated sources). The flag
|
|
61
|
+
// suppresses the warning only — nothing changes about which files are linted.
|
|
62
|
+
if (version >= 9)
|
|
63
|
+
args.push('--no-warn-ignored');
|
|
64
|
+
// Only auto-fix when the caller allows file mutations.
|
|
65
|
+
if (ctx.write)
|
|
66
|
+
args.push('--fix');
|
|
67
|
+
if (hasLocal) {
|
|
68
|
+
logger.info(`[ESLint]: Using local config (${targets.length} file(s))`);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
const configFile = version >= 9 ? 'eslint.config.mjs' : '.eslintrc.js';
|
|
72
|
+
args.push('--config', getPackageConfigPath(configFile));
|
|
73
|
+
logger.info(`[ESLint]: Using pr-checkmate config (ESLint v${version}, ${configFile})`);
|
|
74
|
+
}
|
|
75
|
+
IGNORE_PATTERNS.forEach(p => args.push('--ignore-pattern', p));
|
|
76
|
+
const result = await execa(process.execPath, [eslintBin, ...args], {
|
|
77
|
+
cwd: ctx.cwd,
|
|
78
|
+
stdio: 'inherit',
|
|
79
|
+
reject: false,
|
|
80
|
+
});
|
|
81
|
+
if (result.exitCode === 0)
|
|
82
|
+
return pass();
|
|
83
|
+
// ESLint exits 1 for lint errors and 2 for a fatal error — a config it cannot
|
|
84
|
+
// load, an unresolvable plugin, a parser it cannot construct. Only the
|
|
85
|
+
// former is the client's code. Treating exit 2 as "lint errors found" turned
|
|
86
|
+
// a config incompatibility (often between our bundled config and the client's
|
|
87
|
+
// toolchain) into a red gate on their PR, and named the wrong cause.
|
|
88
|
+
if (result.exitCode === 1)
|
|
89
|
+
return fail('lint errors found');
|
|
90
|
+
return warn(`eslint failed to run (exit ${result.exitCode ?? 'killed'})${hasLocal ? '' : ' — using the pr-checkmate config'}`);
|
|
91
|
+
},
|
|
92
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { getPackageConfigPath, hasLocalConfig, IGNORE_PATTERNS, getSourcePaths, } from '../../../config/index.js';
|
|
4
|
+
import { execa } from '../../../utils/execa.js';
|
|
5
|
+
import { logger, cleanupTempFile, resolvePackageBin } from '../../../utils/index.js';
|
|
6
|
+
import { resolveScopedTargetFiles } from '../../targets.js';
|
|
7
|
+
import { pass, warn, skip } from '../../types.js';
|
|
8
|
+
function loadUserPrettierConfig(cwd) {
|
|
9
|
+
const configPath = path.join(cwd, 'pr-checkmate.json');
|
|
10
|
+
if (!fs.existsSync(configPath))
|
|
11
|
+
return {};
|
|
12
|
+
try {
|
|
13
|
+
return JSON.parse(fs.readFileSync(configPath, 'utf-8')).prettier?.rules || {};
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
logger.warn(`[Prettier]: ⚠️ Failed to read prettier config: ${err}`);
|
|
17
|
+
return {};
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function createTempPrettierConfig(cwd) {
|
|
21
|
+
const defaultConfig = JSON.parse(fs.readFileSync(getPackageConfigPath('.prettierrc'), 'utf-8'));
|
|
22
|
+
const merged = { ...defaultConfig, ...loadUserPrettierConfig(cwd) };
|
|
23
|
+
const tempConfigPath = path.join(cwd, '.prettierrc.temp.json');
|
|
24
|
+
fs.writeFileSync(tempConfigPath, JSON.stringify(merged, null, 2));
|
|
25
|
+
return tempConfigPath;
|
|
26
|
+
}
|
|
27
|
+
function createTempIgnoreFile(cwd) {
|
|
28
|
+
const file = path.join(cwd, '.prettierignore.temp');
|
|
29
|
+
fs.writeFileSync(file, IGNORE_PATTERNS.join('\n'), 'utf-8');
|
|
30
|
+
return file;
|
|
31
|
+
}
|
|
32
|
+
export const prettierCheck = {
|
|
33
|
+
name: 'Prettier',
|
|
34
|
+
phase: 'format',
|
|
35
|
+
applies(ctx) {
|
|
36
|
+
return ctx.languages.includes('typescript') || ctx.languages.includes('javascript');
|
|
37
|
+
},
|
|
38
|
+
async run(ctx) {
|
|
39
|
+
const targets = await resolveScopedTargetFiles(ctx, ['*.ts', '*.tsx', '*.js', '*.jsx', '*.json', '*.md'], getSourcePaths(ctx.cwd));
|
|
40
|
+
if (targets === null)
|
|
41
|
+
return skip('git unavailable');
|
|
42
|
+
if (targets.length === 0)
|
|
43
|
+
return pass('no files to format');
|
|
44
|
+
const projectIgnore = path.join(ctx.cwd, '.prettierignore');
|
|
45
|
+
const gitignore = path.join(ctx.cwd, '.gitignore');
|
|
46
|
+
let tempIgnore = null;
|
|
47
|
+
let ignorePath;
|
|
48
|
+
if (fs.existsSync(projectIgnore))
|
|
49
|
+
ignorePath = projectIgnore;
|
|
50
|
+
else if (fs.existsSync(gitignore))
|
|
51
|
+
ignorePath = gitignore;
|
|
52
|
+
else
|
|
53
|
+
ignorePath = tempIgnore = createTempIgnoreFile(ctx.cwd);
|
|
54
|
+
const hasLocal = hasLocalConfig(['.prettierrc', '.prettierrc.json', '.prettierrc.js', 'prettier.config.js'], ctx.cwd);
|
|
55
|
+
// write=true → format in place; write=false → report-only (`--check`, never mutates files).
|
|
56
|
+
const mode = ctx.write ? '--write' : '--check';
|
|
57
|
+
let tempConfig = null;
|
|
58
|
+
let args;
|
|
59
|
+
if (hasLocal) {
|
|
60
|
+
args = [mode, ...targets, '--ignore-path', ignorePath];
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
tempConfig = createTempPrettierConfig(ctx.cwd);
|
|
64
|
+
args = [mode, ...targets, '--config', tempConfig, '--ignore-path', ignorePath];
|
|
65
|
+
}
|
|
66
|
+
const prettierBin = resolvePackageBin('prettier', 'bin/prettier.cjs');
|
|
67
|
+
try {
|
|
68
|
+
const result = await execa(process.execPath, [prettierBin, ...args], {
|
|
69
|
+
cwd: ctx.cwd,
|
|
70
|
+
stdio: 'inherit',
|
|
71
|
+
reject: false,
|
|
72
|
+
});
|
|
73
|
+
if (result.exitCode === 0)
|
|
74
|
+
return pass();
|
|
75
|
+
// In --check mode a non-zero exit means "some files are not formatted".
|
|
76
|
+
return warn(ctx.write ? 'prettier failed' : 'unformatted files (run with write to fix)');
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
if (tempIgnore)
|
|
80
|
+
cleanupTempFile(tempIgnore);
|
|
81
|
+
if (tempConfig)
|
|
82
|
+
cleanupTempFile(tempConfig);
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Check } from '../../types.js';
|
|
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,61 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { logger } from '../../../utils/index.js';
|
|
4
|
+
import { resolveTargetFiles } from '../../targets.js';
|
|
5
|
+
import { pass, warn, skip } from '../../types.js';
|
|
6
|
+
import { PY_GLOBS, createRuffWorkspace } from './ruff-shared.js';
|
|
7
|
+
/**
|
|
8
|
+
* Formats changed Python files with Ruff's formatter (WASM, no Python/pip needed).
|
|
9
|
+
* Read-only in check mode (`warn` when files differ from formatted output); rewrites
|
|
10
|
+
* files in place when `write` so CI can auto-commit — mirrors the Prettier/C++ checks.
|
|
11
|
+
*/
|
|
12
|
+
export const pythonFormatCheck = {
|
|
13
|
+
name: 'Ruff Format',
|
|
14
|
+
phase: 'format',
|
|
15
|
+
applies(ctx) {
|
|
16
|
+
return (ctx.config.python?.enabled !== false &&
|
|
17
|
+
ctx.config.python?.ruff?.format !== false &&
|
|
18
|
+
ctx.languages.includes('python'));
|
|
19
|
+
},
|
|
20
|
+
async run(ctx) {
|
|
21
|
+
const targets = await resolveTargetFiles(ctx, PY_GLOBS);
|
|
22
|
+
if (targets === null)
|
|
23
|
+
return skip('git unavailable');
|
|
24
|
+
if (targets.length === 0)
|
|
25
|
+
return pass('no Python files changed');
|
|
26
|
+
const workspace = createRuffWorkspace();
|
|
27
|
+
let unformatted = 0;
|
|
28
|
+
for (const rel of targets) {
|
|
29
|
+
const abs = path.join(ctx.cwd, rel);
|
|
30
|
+
let content;
|
|
31
|
+
try {
|
|
32
|
+
content = fs.readFileSync(abs, 'utf-8');
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
continue; // renamed/removed between diff and read — skip
|
|
36
|
+
}
|
|
37
|
+
let formatted;
|
|
38
|
+
try {
|
|
39
|
+
formatted = workspace.format(content);
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
// A syntax error makes Ruff throw — that's a lint concern, not a format failure.
|
|
43
|
+
logger.warn(`[Ruff Format]: ⚠️ Could not format ${rel} (syntax error?)\n${err}`);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (formatted === content)
|
|
47
|
+
continue;
|
|
48
|
+
unformatted += 1;
|
|
49
|
+
if (ctx.write)
|
|
50
|
+
fs.writeFileSync(abs, formatted);
|
|
51
|
+
}
|
|
52
|
+
if (unformatted === 0)
|
|
53
|
+
return pass();
|
|
54
|
+
if (!ctx.write) {
|
|
55
|
+
logger.warn(`[Ruff Format]: ⚠️ ${unformatted} Python file(s) need formatting`);
|
|
56
|
+
return warn(`${unformatted} file(s) need formatting (run with write to fix)`);
|
|
57
|
+
}
|
|
58
|
+
logger.info(`[Ruff Format]: ✅ Reformatted ${unformatted} Python file(s)`);
|
|
59
|
+
return pass(`reformatted ${unformatted} file(s)`);
|
|
60
|
+
},
|
|
61
|
+
};
|