pipework 0.274.0 → 0.275.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/CHANGELOG.md +5 -0
- package/REFERENCE.md +3 -1
- package/dist/cli/commands/check.d.ts +8 -1
- package/dist/cli/commands/check.d.ts.map +1 -1
- package/dist/cli/commands/check.js +8 -5
- package/dist/cli/commands/check.js.map +1 -1
- package/dist/cli/commands/lint-settings.d.ts +37 -0
- package/dist/cli/commands/lint-settings.d.ts.map +1 -0
- package/dist/cli/commands/lint-settings.js +196 -0
- package/dist/cli/commands/lint-settings.js.map +1 -0
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/lint.js +75 -18
- package/dist/cli/commands/lint.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +3 -1
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/commands/check.ts +10 -6
- package/src/cli/commands/lint-settings.ts +218 -0
- package/src/cli/commands/lint.ts +70 -19
- package/src/cli/index.ts +3 -1
package/src/cli/commands/lint.ts
CHANGED
|
@@ -3,7 +3,8 @@ import { dirname, relative } from 'node:path'
|
|
|
3
3
|
import { findConfig } from '../../core/config/discover.js'
|
|
4
4
|
import { error } from '../output.js'
|
|
5
5
|
import { builtinConfigArgs, lintPopulation, lintTargets, loadLintIncludes, resolveEslintBin, resolveModulePaths } from './check.js'
|
|
6
|
-
import { parseShard } from './shard.js'
|
|
6
|
+
import { parseShard, type Shard } from './shard.js'
|
|
7
|
+
import { classifyCoverage, settingsDigests } from './lint-settings.js'
|
|
7
8
|
|
|
8
9
|
// eslint options that take their value as the next argument. Anything else starting
|
|
9
10
|
// with `-` is a switch, so the argument after it is a file.
|
|
@@ -38,6 +39,7 @@ export function namesFiles(args: readonly string[]): boolean {
|
|
|
38
39
|
*/
|
|
39
40
|
export async function lintCommand(cwd: string, args: readonly string[]): Promise<number> {
|
|
40
41
|
if (args.includes('--list-files')) return listFiles(cwd, args)
|
|
42
|
+
if (args.includes('--settings-digest')) return settingsDigest(cwd, args)
|
|
41
43
|
const eslintBin = resolveEslintBin(cwd)
|
|
42
44
|
const configPath = findConfig(cwd)
|
|
43
45
|
const root = configPath === null ? cwd : dirname(configPath)
|
|
@@ -64,32 +66,81 @@ export async function lintCommand(cwd: string, args: readonly string[]): Promise
|
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
/**
|
|
67
|
-
* `
|
|
68
|
-
*
|
|
69
|
+
* `--list-files` and `--settings-digest` take only `--shard <i>/<n>` and `--format json`.
|
|
70
|
+
* Returns the parsed options, or null after reporting the problem.
|
|
69
71
|
*/
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
let
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
72
|
+
function parseReportArgs(flag: string, args: readonly string[]): { shard: Shard | undefined; json: boolean } | null {
|
|
73
|
+
let shard: Shard | undefined
|
|
74
|
+
let json = false
|
|
75
|
+
const rest = args.filter(a => a !== flag)
|
|
76
|
+
const bad = (): null => {
|
|
77
|
+
error(`${flag} takes only --shard <i>/<n> and --format json; got ${rest.join(' ')}. It does not run eslint.`)
|
|
78
|
+
return null
|
|
79
|
+
}
|
|
80
|
+
for (let i = 0; i < rest.length; i++) {
|
|
81
|
+
const arg = rest[i]!
|
|
82
|
+
if (arg === '--shard' && i + 1 < rest.length) {
|
|
83
|
+
try {
|
|
84
|
+
shard = parseShard(rest[++i]!)
|
|
85
|
+
} catch (err) {
|
|
86
|
+
error(err instanceof Error ? err.message : String(err))
|
|
87
|
+
return null
|
|
88
|
+
}
|
|
89
|
+
} else if ((arg === '--format' && rest[i + 1] === 'json') || arg === '--format=json') {
|
|
90
|
+
if (arg === '--format') i++
|
|
91
|
+
json = true
|
|
92
|
+
} else {
|
|
93
|
+
return bad()
|
|
79
94
|
}
|
|
80
|
-
} else if (rest.length > 0) {
|
|
81
|
-
error(`--list-files takes only --shard <i>/<n>; got ${rest.join(' ')}. It lists files and does not run eslint.`)
|
|
82
|
-
return 1
|
|
83
95
|
}
|
|
96
|
+
return { shard, json }
|
|
97
|
+
}
|
|
84
98
|
|
|
99
|
+
async function reportPopulation(cwd: string, flag: string, args: readonly string[]) {
|
|
100
|
+
const opts = parseReportArgs(flag, args)
|
|
101
|
+
if (opts === null) return null
|
|
85
102
|
const configPath = findConfig(cwd)
|
|
86
103
|
const root = configPath === null ? cwd : dirname(configPath)
|
|
87
104
|
const scope = await resolveModulePaths(root)
|
|
88
105
|
if (scope.configError !== undefined) {
|
|
89
|
-
error(`Cannot list lint files: pipework.config.ts failed to load: ${scope.configError.message}`)
|
|
90
|
-
return
|
|
106
|
+
error(`Cannot ${flag === '--list-files' ? 'list lint files' : 'digest lint settings'}: pipework.config.ts failed to load: ${scope.configError.message}`)
|
|
107
|
+
return null
|
|
91
108
|
}
|
|
92
|
-
const
|
|
93
|
-
|
|
109
|
+
const includes = await loadLintIncludes(root)
|
|
110
|
+
const population = lintPopulation(root, scope.paths, includes, opts.shard)
|
|
111
|
+
return { ...opts, root, includes, population }
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* `pipework lint --list-files [--shard i/n] [--format json]`: the repo-relative files
|
|
116
|
+
* `check`'s lint pass covers and eslint will lint, one per line. Files the include globs
|
|
117
|
+
* reach but the lint config ignores are left out; `--format json` lists every candidate
|
|
118
|
+
* with `covered` and, when false, why. Nothing is linted.
|
|
119
|
+
*/
|
|
120
|
+
async function listFiles(cwd: string, args: readonly string[]): Promise<number> {
|
|
121
|
+
const ctx = await reportPopulation(cwd, '--list-files', args)
|
|
122
|
+
if (ctx === null) return 1
|
|
123
|
+
const coverage = await classifyCoverage(ctx.root, ctx.population)
|
|
124
|
+
if (ctx.json) {
|
|
125
|
+
process.stdout.write(JSON.stringify(coverage, null, 2) + '\n')
|
|
126
|
+
return 0
|
|
127
|
+
}
|
|
128
|
+
const covered = coverage.filter(c => c.covered).map(c => c.file)
|
|
129
|
+
if (covered.length > 0) process.stdout.write(covered.join('\n') + '\n')
|
|
130
|
+
return 0
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* `pipework lint --settings-digest [--shard i/n] [--format json]`: one sha256 per
|
|
135
|
+
* module (the root pass is `.`) of what decides lint there. Nothing is linted.
|
|
136
|
+
*/
|
|
137
|
+
async function settingsDigest(cwd: string, args: readonly string[]): Promise<number> {
|
|
138
|
+
const ctx = await reportPopulation(cwd, '--settings-digest', args)
|
|
139
|
+
if (ctx === null) return 1
|
|
140
|
+
const coverage = await classifyCoverage(ctx.root, ctx.population)
|
|
141
|
+
const rootPass = ctx.shard === undefined || ctx.shard.index === 1
|
|
142
|
+
const digests = await settingsDigests(ctx.root, ctx.population, ctx.includes, coverage, rootPass)
|
|
143
|
+
if (ctx.json) process.stdout.write(JSON.stringify(digests, null, 2) + '\n')
|
|
144
|
+
else if (digests.length > 0) process.stdout.write(digests.map(d => `${d.module} ${d.digest}`).join('\n') + '\n')
|
|
94
145
|
return 0
|
|
95
146
|
}
|
package/src/cli/index.ts
CHANGED
|
@@ -24,7 +24,8 @@ ${bold('Commands:')}
|
|
|
24
24
|
cardinality [files] @downstream cardinality rules alone (same options)
|
|
25
25
|
startup Startup validation alone: pipework.config.ts loaded, no database
|
|
26
26
|
lint [eslint args] Lint the current module (the workspace at its root) with check's config; every argument goes to eslint
|
|
27
|
-
lint --list-files [--shard i/n]: print the files
|
|
27
|
+
lint --list-files [--shard i/n] [--format json]: print the files eslint will lint (json: every candidate, covered or not), lint nothing
|
|
28
|
+
lint --settings-digest [--shard i/n] [--format json]: print a digest per module of the resolved lint settings, lint nothing
|
|
28
29
|
codemod Fill missing @downstream cardinality across the corpus
|
|
29
30
|
db Database lifecycle: setup, teardown, reset
|
|
30
31
|
alerts unit-fault Record an abnormal systemd stop (ExecStopPost=pipework alerts unit-fault --unit %n)
|
|
@@ -93,6 +94,7 @@ ${bold('Examples:')}
|
|
|
93
94
|
pipework lint # the module you are in, exactly as check lints it
|
|
94
95
|
pipework lint --format json --output-file r.json src/a.ts # only src/a.ts
|
|
95
96
|
pipework lint --list-files --shard 1/4 # the files check's lint pass covers for part 1 of 4, from pipework.config.ts
|
|
97
|
+
pipework lint --settings-digest --format json # per-module digest of what decides lint, for a lint-result cache key
|
|
96
98
|
pipework codemod
|
|
97
99
|
pipework codemod --dry-run
|
|
98
100
|
pipework alerts unit-fault --unit subseam-core.service # reads $SERVICE_RESULT, $EXIT_CODE, $EXIT_STATUS
|