@lzear/repo-lint 4.3.0 → 4.4.1
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 +1 -1
- package/dist/bin.js +20 -2
- package/dist/index.js +32 -5
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -83,7 +83,7 @@ const report = await runUpdate({ dry: true })
|
|
|
83
83
|
| `readme-npm-badge` | README has an npm badge |
|
|
84
84
|
| `codacy` | Codacy grade & coverage badges in README, `.codacy.yml` |
|
|
85
85
|
| `license` | `LICENSE` exists |
|
|
86
|
-
| `ci-workflow` |
|
|
86
|
+
| `ci-workflow` | a workflow calls the forge reusable CI workflow |
|
|
87
87
|
| `renovate` | `renovate.json` exists |
|
|
88
88
|
| `pkg-publint` | All published packages pass `publint` |
|
|
89
89
|
| `pkg-attw` | All published packages pass `attw` (ESM-only profile) |
|
package/dist/bin.js
CHANGED
|
@@ -22,6 +22,7 @@ import { maxSatisfying, satisfies } from "semver";
|
|
|
22
22
|
|
|
23
23
|
// src/update.ts
|
|
24
24
|
import { spawnSync } from "child_process";
|
|
25
|
+
import { createHash } from "crypto";
|
|
25
26
|
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
26
27
|
import path from "path";
|
|
27
28
|
import { pathToFileURL } from "url";
|
|
@@ -129,6 +130,17 @@ var readmeIncludes = (dir, needle) => {
|
|
|
129
130
|
const f = path2.join(dir, "README.md");
|
|
130
131
|
return existsSync2(f) && readFileSync2(f, "utf8").includes(needle);
|
|
131
132
|
};
|
|
133
|
+
var FORGE_WORKFLOW_RE = /uses:\s*lzear\/forge\/\.github\/workflows\/ci\.yml@/;
|
|
134
|
+
var isForgeRepo = (dir) => getWorkspaceDirectories(dir).some(
|
|
135
|
+
(d) => readPackage(d)?.name === "@lzear/forge"
|
|
136
|
+
);
|
|
137
|
+
var callsForgeWorkflow = (dir) => {
|
|
138
|
+
const wfDir = path2.join(dir, ".github", "workflows");
|
|
139
|
+
if (!existsSync2(wfDir)) return false;
|
|
140
|
+
return readdirSync(wfDir).filter((f) => /\.ya?ml$/.test(f)).some(
|
|
141
|
+
(f) => FORGE_WORKFLOW_RE.test(readFileSync2(path2.join(wfDir, f), "utf8"))
|
|
142
|
+
);
|
|
143
|
+
};
|
|
132
144
|
var auditCommand = (pm) => {
|
|
133
145
|
switch (pm.name) {
|
|
134
146
|
case "npm":
|
|
@@ -232,10 +244,16 @@ var LOCAL_CHECKS = [
|
|
|
232
244
|
},
|
|
233
245
|
{
|
|
234
246
|
id: "ci-workflow",
|
|
235
|
-
desc: "CI workflow",
|
|
247
|
+
desc: "CI calls forge workflow",
|
|
236
248
|
type: "local",
|
|
237
249
|
publishedOnly: true,
|
|
238
|
-
check: (dir) =>
|
|
250
|
+
check: (dir) => {
|
|
251
|
+
if (callsForgeWorkflow(dir) || isForgeRepo(dir)) return true;
|
|
252
|
+
return {
|
|
253
|
+
pass: false,
|
|
254
|
+
detail: "no workflow calls the forge reusable CI \u2014 replace the local ci.yml copy with:\n jobs:\n ci:\n uses: lzear/forge/.github/workflows/ci.yml@<sha> # vX.Y.Z\n(pin to a commit SHA; renovate keeps it fresh)"
|
|
255
|
+
};
|
|
256
|
+
}
|
|
239
257
|
},
|
|
240
258
|
{
|
|
241
259
|
id: "renovate",
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,7 @@ import { maxSatisfying, satisfies } from "semver";
|
|
|
15
15
|
|
|
16
16
|
// src/update.ts
|
|
17
17
|
import { spawnSync } from "child_process";
|
|
18
|
+
import { createHash } from "crypto";
|
|
18
19
|
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
19
20
|
import path from "path";
|
|
20
21
|
import { pathToFileURL } from "url";
|
|
@@ -297,7 +298,8 @@ var installCommands = (pm) => {
|
|
|
297
298
|
["yarn", "upgrade"]
|
|
298
299
|
] : [
|
|
299
300
|
["yarn", "install"],
|
|
300
|
-
|
|
301
|
+
// '*' alone skips scoped packages (@foo/bar) — needs '@*/*' too
|
|
302
|
+
["yarn", "up", "--recursive", "*", "@*/*"],
|
|
301
303
|
["yarn", "dedupe"]
|
|
302
304
|
];
|
|
303
305
|
case "npm":
|
|
@@ -308,11 +310,13 @@ var installCommands = (pm) => {
|
|
|
308
310
|
];
|
|
309
311
|
}
|
|
310
312
|
};
|
|
313
|
+
var lockfileHash = (dir) => LOCKFILES.map(([f]) => path.join(dir, f)).filter((f) => existsSync(f)).map((f) => createHash("sha256").update(readFileSync(f)).digest("hex")).join("|");
|
|
311
314
|
var stepInstall = (dir, pm) => {
|
|
312
315
|
const base = {
|
|
313
316
|
id: "install",
|
|
314
317
|
desc: `install & refresh lockfile (${pm.name})`
|
|
315
318
|
};
|
|
319
|
+
const before = lockfileHash(dir);
|
|
316
320
|
const lines = [];
|
|
317
321
|
for (const [command, ...arguments_] of installCommands(pm)) {
|
|
318
322
|
lines.push(`$ ${[command, ...arguments_].join(" ")}`);
|
|
@@ -324,12 +328,18 @@ var stepInstall = (dir, pm) => {
|
|
|
324
328
|
return {
|
|
325
329
|
...base,
|
|
326
330
|
pass: false,
|
|
327
|
-
changed:
|
|
331
|
+
changed: lockfileHash(dir) !== before,
|
|
328
332
|
detail: `${lines.join("\n")}
|
|
329
333
|
exited with ${result.status ?? "signal"}`
|
|
330
334
|
};
|
|
331
335
|
}
|
|
332
|
-
|
|
336
|
+
const changed = lockfileHash(dir) !== before;
|
|
337
|
+
return {
|
|
338
|
+
...base,
|
|
339
|
+
pass: true,
|
|
340
|
+
changed,
|
|
341
|
+
detail: changed ? lines.join("\n") : "lockfile unchanged"
|
|
342
|
+
};
|
|
333
343
|
};
|
|
334
344
|
var runUpdate = async (options = {}) => {
|
|
335
345
|
const {
|
|
@@ -423,6 +433,17 @@ var readmeIncludes = (dir, needle) => {
|
|
|
423
433
|
const f = path2.join(dir, "README.md");
|
|
424
434
|
return existsSync2(f) && readFileSync2(f, "utf8").includes(needle);
|
|
425
435
|
};
|
|
436
|
+
var FORGE_WORKFLOW_RE = /uses:\s*lzear\/forge\/\.github\/workflows\/ci\.yml@/;
|
|
437
|
+
var isForgeRepo = (dir) => getWorkspaceDirectories(dir).some(
|
|
438
|
+
(d) => readPackage(d)?.name === "@lzear/forge"
|
|
439
|
+
);
|
|
440
|
+
var callsForgeWorkflow = (dir) => {
|
|
441
|
+
const wfDir = path2.join(dir, ".github", "workflows");
|
|
442
|
+
if (!existsSync2(wfDir)) return false;
|
|
443
|
+
return readdirSync(wfDir).filter((f) => /\.ya?ml$/.test(f)).some(
|
|
444
|
+
(f) => FORGE_WORKFLOW_RE.test(readFileSync2(path2.join(wfDir, f), "utf8"))
|
|
445
|
+
);
|
|
446
|
+
};
|
|
426
447
|
var auditCommand = (pm) => {
|
|
427
448
|
switch (pm.name) {
|
|
428
449
|
case "npm":
|
|
@@ -526,10 +547,16 @@ var LOCAL_CHECKS = [
|
|
|
526
547
|
},
|
|
527
548
|
{
|
|
528
549
|
id: "ci-workflow",
|
|
529
|
-
desc: "CI workflow",
|
|
550
|
+
desc: "CI calls forge workflow",
|
|
530
551
|
type: "local",
|
|
531
552
|
publishedOnly: true,
|
|
532
|
-
check: (dir) =>
|
|
553
|
+
check: (dir) => {
|
|
554
|
+
if (callsForgeWorkflow(dir) || isForgeRepo(dir)) return true;
|
|
555
|
+
return {
|
|
556
|
+
pass: false,
|
|
557
|
+
detail: "no workflow calls the forge reusable CI \u2014 replace the local ci.yml copy with:\n jobs:\n ci:\n uses: lzear/forge/.github/workflows/ci.yml@<sha> # vX.Y.Z\n(pin to a commit SHA; renovate keeps it fresh)"
|
|
558
|
+
};
|
|
559
|
+
}
|
|
533
560
|
},
|
|
534
561
|
{
|
|
535
562
|
id: "renovate",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lzear/repo-lint",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.1",
|
|
4
4
|
"description": "Checks lzear repos against forge standards",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"sherif": "^1"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@lzear/configs": "4.
|
|
54
|
+
"@lzear/configs": "4.4.1",
|
|
55
55
|
"@types/node": "^26",
|
|
56
56
|
"@types/semver": "^7",
|
|
57
57
|
"@vitest/coverage-v8": "^4",
|