@pmelab/gtd 21.1.0 → 22.0.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/.claude-plugin/plugin.json +1 -1
- package/README.md +4 -1
- package/dist/gtd.bundle.mjs +242 -40
- package/dist/workflows.mjs +19415 -47
- package/package.json +2 -1
- package/schema.json +2 -2
- package/src/flows/factory.test.ts +94 -0
- package/src/flows/factory.ts +116 -0
- package/src/flows/index.ts +1 -0
- package/src/workflows/bundled.ts +9 -4
- package/src/workflows/options.test.ts +52 -0
- package/src/workflows/options.ts +38 -0
package/README.md
CHANGED
|
@@ -512,7 +512,10 @@ can add its own. `gtd --workflow <name>` starts any workflow by name.
|
|
|
512
512
|
The workflow itself is a plain async TypeScript function, and the
|
|
513
513
|
`gtd.config.ts` at the repository root names it: the one `gtd install` writes
|
|
514
514
|
re-exports the shipped workflows from `@pmelab/gtd/workflows`, and the pieces
|
|
515
|
-
they are built from are exported for yours to reuse.
|
|
515
|
+
they are built from are exported for yours to reuse. Each shipped workflow is a
|
|
516
|
+
factory — `feature({ testCommand: "npm run ci" })` — whose options gtd validates
|
|
517
|
+
when it loads the config: a misspelled or mistyped one fails every command,
|
|
518
|
+
naming the workflow, the key and what was expected. See
|
|
516
519
|
[Configuration](https://github.com/pmelab/gtd/blob/main/docs/configuration.md) —
|
|
517
520
|
and remember gtd evaluates that file on every command. A shared workflow package
|
|
518
521
|
bundling its own `@pmelab/gtd` is checked against the running gtd and refused,
|
package/dist/gtd.bundle.mjs
CHANGED
|
@@ -32693,6 +32693,71 @@ const requireRevert = (edited, base) => {
|
|
|
32693
32693
|
refuse(`gtd land: require-revert: ${residue.join(", ")} still differ from ${base}~1 — the revert did not take. Run \`git checkout ${base}~1 -- ${quoted}\`, then \`gtd land\` again.`);
|
|
32694
32694
|
};
|
|
32695
32695
|
//#endregion
|
|
32696
|
+
//#region src/flows/factory.ts
|
|
32697
|
+
const FACTORY = Symbol.for("@pmelab/gtd/workflow-factory");
|
|
32698
|
+
/**
|
|
32699
|
+
* Define a workflow configured by options. `schema` is any Standard Schema
|
|
32700
|
+
* (https://standardschema.dev); it should reject unknown keys, so a removed or
|
|
32701
|
+
* misspelled option fails at load. Exported from `gtd.config.ts`, the factory
|
|
32702
|
+
* itself and a call's result are both workflows.
|
|
32703
|
+
*/
|
|
32704
|
+
const defineWorkflow = (schema, build) => {
|
|
32705
|
+
const internals = {
|
|
32706
|
+
schema,
|
|
32707
|
+
build
|
|
32708
|
+
};
|
|
32709
|
+
const factory = (options) => ({
|
|
32710
|
+
[FACTORY]: {
|
|
32711
|
+
...internals,
|
|
32712
|
+
options
|
|
32713
|
+
},
|
|
32714
|
+
then: () => {
|
|
32715
|
+
throw new Error("a configured workflow is not a flow — compose fixFlow/reviewFlow instead");
|
|
32716
|
+
}
|
|
32717
|
+
});
|
|
32718
|
+
return Object.assign(factory, { [FACTORY]: internals });
|
|
32719
|
+
};
|
|
32720
|
+
const internalsOf = (value) => (typeof value === "function" || typeof value === "object" && value !== null) && FACTORY in value ? value[FACTORY] : void 0;
|
|
32721
|
+
const isFactoryWorkflow = (value) => internalsOf(value) !== void 0;
|
|
32722
|
+
const segment = (key) => {
|
|
32723
|
+
const raw = typeof key === "object" ? key.key : key;
|
|
32724
|
+
return typeof raw === "number" ? raw : String(raw);
|
|
32725
|
+
};
|
|
32726
|
+
/**
|
|
32727
|
+
* Validate a factory workflow's options — those it was called with, `overrides`
|
|
32728
|
+
* on top — and build it. `undefined` for an export that is no factory workflow.
|
|
32729
|
+
*/
|
|
32730
|
+
const configure$1 = (value, overrides = {}) => {
|
|
32731
|
+
const internals = internalsOf(value);
|
|
32732
|
+
if (internals === void 0) return void 0;
|
|
32733
|
+
const options = {
|
|
32734
|
+
...internals.options,
|
|
32735
|
+
...overrides
|
|
32736
|
+
};
|
|
32737
|
+
const result = internals.schema["~standard"].validate(options);
|
|
32738
|
+
if (result instanceof Promise) return {
|
|
32739
|
+
ok: false,
|
|
32740
|
+
issues: [{
|
|
32741
|
+
path: [],
|
|
32742
|
+
message: "the options schema validates asynchronously — gtd needs a synchronous one"
|
|
32743
|
+
}]
|
|
32744
|
+
};
|
|
32745
|
+
if (result.issues !== void 0) return {
|
|
32746
|
+
ok: false,
|
|
32747
|
+
issues: result.issues.length === 0 ? [{
|
|
32748
|
+
path: [],
|
|
32749
|
+
message: "the options schema rejected them without saying why"
|
|
32750
|
+
}] : result.issues.map((issue) => ({
|
|
32751
|
+
path: (issue.path ?? []).map(segment),
|
|
32752
|
+
message: issue.message
|
|
32753
|
+
}))
|
|
32754
|
+
};
|
|
32755
|
+
return {
|
|
32756
|
+
ok: true,
|
|
32757
|
+
build: internals.build(result.value)
|
|
32758
|
+
};
|
|
32759
|
+
};
|
|
32760
|
+
//#endregion
|
|
32696
32761
|
//#region src/flows/index.ts
|
|
32697
32762
|
var flows_exports = /* @__PURE__ */ __exportAll({
|
|
32698
32763
|
FLOWS_PROTOCOL: () => 1,
|
|
@@ -32706,12 +32771,15 @@ var flows_exports = /* @__PURE__ */ __exportAll({
|
|
|
32706
32771
|
checkScript: () => checkScript,
|
|
32707
32772
|
codeChanges: () => codeChanges,
|
|
32708
32773
|
codeThreads: () => codeThreads,
|
|
32774
|
+
configure: () => configure$1,
|
|
32775
|
+
defineWorkflow: () => defineWorkflow,
|
|
32709
32776
|
env: () => env,
|
|
32710
32777
|
glob: () => glob,
|
|
32711
32778
|
hasThreadFor: () => hasThreadFor,
|
|
32712
32779
|
head: () => head,
|
|
32713
32780
|
human: () => human,
|
|
32714
32781
|
installContext: () => installContext,
|
|
32782
|
+
isFactoryWorkflow: () => isFactoryWorkflow,
|
|
32715
32783
|
judge: () => judge,
|
|
32716
32784
|
moveScript: () => moveScript,
|
|
32717
32785
|
numeric: () => numeric,
|
|
@@ -49589,10 +49657,10 @@ const replay = async (input) => {
|
|
|
49589
49657
|
};
|
|
49590
49658
|
//#endregion
|
|
49591
49659
|
//#region src/workflow/ConfigSchema.ts
|
|
49592
|
-
/** The `vars:` shape: a flat name -> scalar map (`compileVarsMap` coerces every scalar to a string). */
|
|
49660
|
+
/** The `vars:` shape: a flat name -> scalar map (`compileVarsMap` coerces every scalar to a string). Its names are the workflow's business, never core's. */
|
|
49593
49661
|
const varsJsonSchema = {
|
|
49594
49662
|
type: "object",
|
|
49595
|
-
description: "Flat name -> scalar map merged into the workflow's process settings (defaults), pinned for the whole process at its start. Scalars are coerced to strings.",
|
|
49663
|
+
description: "Flat name -> scalar map merged into the workflow's process settings (defaults), pinned for the whole process at its start. A workflow built by a factory receives these entries as options and validates them itself. Scalars are coerced to strings.",
|
|
49596
49664
|
additionalProperties: { type: [
|
|
49597
49665
|
"string",
|
|
49598
49666
|
"number",
|
|
@@ -49602,7 +49670,7 @@ const varsJsonSchema = {
|
|
|
49602
49670
|
/** The `env:` shape: environment settings, read live on every invocation and never pinned to a process. */
|
|
49603
49671
|
const envJsonSchema = {
|
|
49604
49672
|
type: "object",
|
|
49605
|
-
description: "Flat name -> scalar map merged into the workflow's environment settings (envDefaults) — values that change how a step runs on this machine
|
|
49673
|
+
description: "Flat name -> scalar map merged into the workflow's environment settings (envDefaults) — values that change how a step runs on this machine. A workflow built by a factory receives these entries as options and validates them itself. Read fresh on every gtd call, never pinned to a process. GTD_<NAME> environment variables override these entries. Scalars are coerced to strings.",
|
|
49606
49674
|
additionalProperties: { type: [
|
|
49607
49675
|
"string",
|
|
49608
49676
|
"number",
|
|
@@ -57008,11 +57076,12 @@ const load = gen(function* () {
|
|
|
57008
57076
|
catch: (e) => new GtdError(`gtd: ${e instanceof Error ? e.message : String(e)}`)
|
|
57009
57077
|
});
|
|
57010
57078
|
const loaded = yield* try_({
|
|
57011
|
-
try: () => loadWorkflows(module, shipped),
|
|
57079
|
+
try: () => loadWorkflows(module, shipped, compiled),
|
|
57012
57080
|
catch: (e) => new GtdError(`gtd config:\n - ${module.filepath}: ${e instanceof Error ? e.message : String(e)}`)
|
|
57013
57081
|
});
|
|
57014
|
-
const diagnostics = report(wrongKindDiagnostics(loaded.
|
|
57082
|
+
const diagnostics = report([...loaded.diagnostics, ...wrongKindDiagnostics(loaded.settings, compiled)], [...rcOrder, module.filepath]);
|
|
57015
57083
|
yield* failOnErrors(diagnostics);
|
|
57084
|
+
if (loaded.default === void 0) return yield* die("unreachable: a default fails to build only with an error reported");
|
|
57016
57085
|
const initial = yield* firstStep(loaded.default, headTree(yield* Workspace));
|
|
57017
57086
|
const steering = loaded.file.steering;
|
|
57018
57087
|
const define = (entry) => ({
|
|
@@ -57034,8 +57103,8 @@ const load = gen(function* () {
|
|
|
57034
57103
|
const resolve = (name, entry) => ({
|
|
57035
57104
|
name,
|
|
57036
57105
|
def: define(entry),
|
|
57037
|
-
vars: { ...entry.
|
|
57038
|
-
env: { ...entry.
|
|
57106
|
+
vars: { ...entry.defaults },
|
|
57107
|
+
env: { ...entry.envDefaults }
|
|
57039
57108
|
});
|
|
57040
57109
|
const defaultWorkflow = resolve(loaded.default.name, loaded.default);
|
|
57041
57110
|
return {
|
|
@@ -57056,9 +57125,9 @@ const load = gen(function* () {
|
|
|
57056
57125
|
};
|
|
57057
57126
|
});
|
|
57058
57127
|
/** A name under the wrong key (or under both) in a `.gtdrc` layer: each is an error at its own origin. */
|
|
57059
|
-
const wrongKindDiagnostics = (
|
|
57060
|
-
const isEnvOnly = (key) => Object.hasOwn(
|
|
57061
|
-
const isVarOnly = (key) => Object.hasOwn(
|
|
57128
|
+
const wrongKindDiagnostics = (settings, compiled) => {
|
|
57129
|
+
const isEnvOnly = (key) => Object.hasOwn(settings.envDefaults, key);
|
|
57130
|
+
const isVarOnly = (key) => Object.hasOwn(settings.defaults, key);
|
|
57062
57131
|
const error = (path, message, origin) => ({
|
|
57063
57132
|
severity: "error",
|
|
57064
57133
|
path,
|
|
@@ -57179,16 +57248,20 @@ const RESERVED_EXPORTS = /* @__PURE__ */ new Set([
|
|
|
57179
57248
|
"access",
|
|
57180
57249
|
"doors"
|
|
57181
57250
|
]);
|
|
57251
|
+
/** The rules every declared setting meets, whether a file's export or a factory's build. */
|
|
57252
|
+
const checkSettings = (defaults, envDefaults, declares) => {
|
|
57253
|
+
for (const [kind, record] of [["defaults", defaults], ["envDefaults", envDefaults]]) for (const [name, setting] of Object.entries(record)) {
|
|
57254
|
+
if (!isSettingName(name)) throw new Error(`${declares(kind)} ${JSON.stringify(name)}, not a valid setting name — ${SETTING_NAME_RULE}`);
|
|
57255
|
+
if (typeof setting !== "string") throw new Error(`${declares(kind)} ${JSON.stringify(name)}, whose value is not a string`);
|
|
57256
|
+
}
|
|
57257
|
+
const both = Object.keys(defaults).filter((name) => Object.hasOwn(envDefaults, name));
|
|
57258
|
+
if (both.length > 0) throw new Error(`${both.map((name) => `"${name}"`).join(", ")} declared in both "defaults" and "envDefaults" — a setting is a process setting or an environment setting, not both`);
|
|
57259
|
+
};
|
|
57182
57260
|
/** A module's per-file exports: `defaults`, `envDefaults`, `steering`, `skills`, `access`, `summary`, `base`. */
|
|
57183
57261
|
const fileFrom = (exports, origin, dependencyFiles) => {
|
|
57184
57262
|
const defaults = stringRecord(exports, "defaults");
|
|
57185
57263
|
const envDefaults = stringRecord(exports, "envDefaults");
|
|
57186
|
-
|
|
57187
|
-
const bad = Object.keys(record).find((name) => !isSettingName(name));
|
|
57188
|
-
if (bad !== void 0) throw new Error(`the "${exportName}" export declares ${JSON.stringify(bad)}, not a valid setting name — ${SETTING_NAME_RULE}`);
|
|
57189
|
-
}
|
|
57190
|
-
const both = Object.keys(defaults).filter((name) => Object.hasOwn(envDefaults, name));
|
|
57191
|
-
if (both.length > 0) throw new Error(`${both.map((name) => `"${name}"`).join(", ")} declared in both "defaults" and "envDefaults" — a setting is a process setting or an environment setting, not both`);
|
|
57264
|
+
checkSettings(defaults, envDefaults, (kind) => `the "${kind}" export declares`);
|
|
57192
57265
|
return {
|
|
57193
57266
|
defaults,
|
|
57194
57267
|
envDefaults,
|
|
@@ -57243,42 +57316,171 @@ const checkDoors = (declared, catalogue) => {
|
|
|
57243
57316
|
};
|
|
57244
57317
|
const namespaceOf = (exported) => typeof exported === "object" && exported !== null ? exported : {};
|
|
57245
57318
|
/**
|
|
57246
|
-
* Evaluate `gtd.config.ts`. Every exported function
|
|
57247
|
-
* a workflow named by its export. `cache` is jiti's OWN
|
|
57248
|
-
* (unrelated to the instance's `moduleCache: false`) —
|
|
57249
|
-
* in has the side effect of collecting every real file
|
|
57250
|
-
* evaluating this module, module AND every relative import it
|
|
57251
|
-
* transitively.
|
|
57319
|
+
* Evaluate `gtd.config.ts`. Every exported function or factory workflow but
|
|
57320
|
+
* the reserved names is a workflow named by its export. `cache` is jiti's OWN
|
|
57321
|
+
* per-call module cache (unrelated to the instance's `moduleCache: false`) —
|
|
57322
|
+
* passing an empty object in has the side effect of collecting every real file
|
|
57323
|
+
* jiti resolved evaluating this module, module AND every relative import it
|
|
57324
|
+
* pulled in, transitively.
|
|
57252
57325
|
*/
|
|
57253
|
-
const loadWorkflows = (module, shipped) => {
|
|
57326
|
+
const loadWorkflows = (module, shipped, compiled) => {
|
|
57254
57327
|
const cache = {};
|
|
57255
57328
|
const exports = namespaceOf(jiti(shipped).evalModule(module.source, {
|
|
57256
57329
|
filename: module.filepath,
|
|
57257
57330
|
cache
|
|
57258
57331
|
}));
|
|
57259
57332
|
const file = fileFrom(exports, module.filepath, Object.keys(cache));
|
|
57260
|
-
const
|
|
57261
|
-
|
|
57262
|
-
|
|
57263
|
-
|
|
57264
|
-
|
|
57265
|
-
|
|
57333
|
+
const exported = Object.entries(exports).filter(([name, value]) => !RESERVED_EXPORTS.has(name) && isWorkflow(value));
|
|
57334
|
+
const value = defaultExport(exports);
|
|
57335
|
+
const defaultName = exported.find(([, other]) => other === value)?.[0] ?? "default";
|
|
57336
|
+
const built = /* @__PURE__ */ new Map();
|
|
57337
|
+
const rejections = [];
|
|
57338
|
+
const declarers = declarersOf([...exported, [defaultName, value]], file, compiled);
|
|
57339
|
+
for (const [name, entry] of [...exported, [defaultName, value]]) if (!built.has(entry)) built.set(entry, buildWorkflow(name, entry, file, compiled, rejections, declarers));
|
|
57340
|
+
const catalogue = new Map(exported.flatMap(([name, entry]) => {
|
|
57341
|
+
const workflow = built.get(entry);
|
|
57342
|
+
return workflow === void 0 ? [] : [[name, workflow]];
|
|
57343
|
+
}));
|
|
57344
|
+
const defaultWorkflow = built.get(value);
|
|
57345
|
+
return {
|
|
57346
|
+
file,
|
|
57347
|
+
catalogue,
|
|
57348
|
+
doors: rejections.length > 0 ? /* @__PURE__ */ new Map() : checkDoors(doorsFrom(exports), catalogue),
|
|
57349
|
+
default: defaultWorkflow && {
|
|
57350
|
+
...defaultWorkflow,
|
|
57351
|
+
name: defaultName
|
|
57352
|
+
},
|
|
57353
|
+
settings: mergeSettings([...built.values()].filter((w) => w !== void 0)),
|
|
57354
|
+
diagnostics: nameRejections(rejections)
|
|
57355
|
+
};
|
|
57356
|
+
};
|
|
57357
|
+
const isWorkflow = (value) => typeof value === "function" || isFactoryWorkflow(value);
|
|
57358
|
+
const defaultExport = (exports) => {
|
|
57359
|
+
const value = exports.default;
|
|
57360
|
+
if (value === void 0) throw new Error("no default export — export the workflow an ordinary start runs (`gtd install` scaffolds one)");
|
|
57361
|
+
if (!isWorkflow(value)) throw new Error("the default export is not a function");
|
|
57362
|
+
return value;
|
|
57363
|
+
};
|
|
57364
|
+
const mergeSettings = (all) => ({
|
|
57365
|
+
defaults: Object.assign({}, ...all.map((s) => s.defaults)),
|
|
57366
|
+
envDefaults: Object.assign({}, ...all.map((s) => s.envDefaults))
|
|
57367
|
+
});
|
|
57368
|
+
/** Each setting name, with who declares it: the file's exports, or a factory's own build. */
|
|
57369
|
+
const declarersOf = (exported, file, compiled) => {
|
|
57370
|
+
const declarers = /* @__PURE__ */ new Map();
|
|
57371
|
+
const declare = (key, who) => {
|
|
57372
|
+
declarers.set(key, (declarers.get(key) ?? /* @__PURE__ */ new Set()).add(who));
|
|
57373
|
+
};
|
|
57374
|
+
for (const key of [...Object.keys(file.defaults), ...Object.keys(file.envDefaults)]) declare(key, file);
|
|
57375
|
+
for (const [, value] of exported) {
|
|
57376
|
+
const own = ownBuild(value, {
|
|
57377
|
+
...compiled.rcVars,
|
|
57378
|
+
...compiled.rcEnv
|
|
57266
57379
|
});
|
|
57380
|
+
if (own?.ok) for (const key of [...Object.keys(own.build.defaults ?? {}), ...Object.keys(own.build.envDefaults ?? {})]) declare(key, value);
|
|
57381
|
+
}
|
|
57382
|
+
return declarers;
|
|
57383
|
+
};
|
|
57384
|
+
/**
|
|
57385
|
+
* A factory's build as its call alone gives it — or, when the call fails, with
|
|
57386
|
+
* the `.gtdrc` values for just the options it flagged, since a name the factory
|
|
57387
|
+
* itself rejects is its own.
|
|
57388
|
+
*/
|
|
57389
|
+
const ownBuild = (value, rc) => {
|
|
57390
|
+
const bare = configure$1(value);
|
|
57391
|
+
if (bare === void 0 || bare.ok) return bare;
|
|
57392
|
+
const flagged = new Set(bare.issues.map((issue) => issue.path[0]));
|
|
57393
|
+
return configure$1(value, Object.fromEntries(Object.entries(rc).filter(([key]) => flagged.has(key))));
|
|
57394
|
+
};
|
|
57395
|
+
/**
|
|
57396
|
+
* One exported workflow: a plain flow as-is, a factory validated and built.
|
|
57397
|
+
* `.gtdrc` `vars:`/`env:` values reach a factory as options, so the factory
|
|
57398
|
+
* judges them — except a name some other loaded workflow declares and this one
|
|
57399
|
+
* does not, which belongs to that workflow.
|
|
57400
|
+
*/
|
|
57401
|
+
const buildWorkflow = (name, value, file, compiled, rejections, declarers) => {
|
|
57402
|
+
if (configure$1(value) === void 0) return {
|
|
57403
|
+
flow: value,
|
|
57404
|
+
file,
|
|
57405
|
+
defaults: file.defaults,
|
|
57406
|
+
envDefaults: file.envDefaults
|
|
57407
|
+
};
|
|
57408
|
+
const belongsElsewhere = (key) => {
|
|
57409
|
+
const who = declarers.get(key);
|
|
57410
|
+
return who !== void 0 && !who.has(value);
|
|
57411
|
+
};
|
|
57412
|
+
const overrides = Object.fromEntries(Object.entries({
|
|
57413
|
+
...compiled.rcVars,
|
|
57414
|
+
...compiled.rcEnv
|
|
57415
|
+
}).filter(([key]) => !belongsElsewhere(key)));
|
|
57416
|
+
const result = configure$1(value, overrides);
|
|
57417
|
+
if (!result.ok) {
|
|
57418
|
+
for (const issue of result.issues) rejections.push(optionDiagnostic(name, issue, overrides, file, compiled));
|
|
57419
|
+
return;
|
|
57267
57420
|
}
|
|
57268
|
-
const flow = exports.default;
|
|
57269
|
-
if (flow === void 0) throw new Error("no default export — export the workflow an ordinary start runs (`gtd install` scaffolds one)");
|
|
57270
|
-
if (typeof flow !== "function") throw new Error("the default export is not a function");
|
|
57271
|
-
const name = [...catalogue].find(([, entry]) => entry.flow === flow)?.[0] ?? "default";
|
|
57272
57421
|
return {
|
|
57422
|
+
flow: result.build.flow,
|
|
57273
57423
|
file,
|
|
57274
|
-
|
|
57275
|
-
|
|
57276
|
-
|
|
57277
|
-
|
|
57278
|
-
|
|
57279
|
-
|
|
57280
|
-
|
|
57424
|
+
...builtSettings(name, file, result.build)
|
|
57425
|
+
};
|
|
57426
|
+
};
|
|
57427
|
+
/** A factory's settings over its file's, held to the rules a file's own exports are. */
|
|
57428
|
+
const builtSettings = (name, file, build) => {
|
|
57429
|
+
checkSettings(build.defaults ?? {}, build.envDefaults ?? {}, (kind) => `workflow "${name}" builds ${kind}`);
|
|
57430
|
+
const defaults = {
|
|
57431
|
+
...file.defaults,
|
|
57432
|
+
...build.defaults
|
|
57433
|
+
};
|
|
57434
|
+
const envDefaults = {
|
|
57435
|
+
...file.envDefaults,
|
|
57436
|
+
...build.envDefaults
|
|
57281
57437
|
};
|
|
57438
|
+
checkSettings(defaults, envDefaults, (kind) => `workflow "${name}" builds ${kind}`);
|
|
57439
|
+
return {
|
|
57440
|
+
defaults,
|
|
57441
|
+
envDefaults
|
|
57442
|
+
};
|
|
57443
|
+
};
|
|
57444
|
+
/** A rejected option, reported where its value came from: the innermost `.gtdrc` that set it, else `gtd.config.ts`. */
|
|
57445
|
+
const optionDiagnostic = (workflow, issue, overrides, file, compiled) => {
|
|
57446
|
+
const [key] = issue.path;
|
|
57447
|
+
const message = `${issue.path.length > 0 ? `option "${issue.path.join(".")}"` : "options"}: ${issue.message}`;
|
|
57448
|
+
if (!(typeof key === "string" && Object.hasOwn(overrides, key))) return {
|
|
57449
|
+
workflow,
|
|
57450
|
+
severity: "error",
|
|
57451
|
+
path: issue.path,
|
|
57452
|
+
message,
|
|
57453
|
+
origin: file.origin
|
|
57454
|
+
};
|
|
57455
|
+
const kind = Object.hasOwn(compiled.rcEnv, key) ? "env" : "vars";
|
|
57456
|
+
const origin = [...kind === "env" ? compiled.envKeys : compiled.varsKeys].reverse().find((entry) => entry.key === key)?.origin;
|
|
57457
|
+
return {
|
|
57458
|
+
workflow,
|
|
57459
|
+
severity: "error",
|
|
57460
|
+
path: [kind, ...issue.path],
|
|
57461
|
+
message,
|
|
57462
|
+
origin: origin ?? file.origin
|
|
57463
|
+
};
|
|
57464
|
+
};
|
|
57465
|
+
const nameRejections = (rejections) => {
|
|
57466
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
57467
|
+
for (const rejection of rejections) {
|
|
57468
|
+
const key = JSON.stringify([
|
|
57469
|
+
rejection.origin,
|
|
57470
|
+
rejection.path,
|
|
57471
|
+
rejection.message
|
|
57472
|
+
]);
|
|
57473
|
+
const group = grouped.get(key);
|
|
57474
|
+
if (group === void 0) grouped.set(key, {
|
|
57475
|
+
first: rejection,
|
|
57476
|
+
workflows: [rejection.workflow]
|
|
57477
|
+
});
|
|
57478
|
+
else group.workflows.push(rejection.workflow);
|
|
57479
|
+
}
|
|
57480
|
+
return [...grouped.values()].map(({ first: { workflow: _, ...diagnostic }, workflows }) => ({
|
|
57481
|
+
...diagnostic,
|
|
57482
|
+
message: `${workflows.length > 1 ? "workflows" : "workflow"} ${workflows.map((w) => `"${w}"`).join(", ")} ${diagnostic.message}`
|
|
57483
|
+
}));
|
|
57282
57484
|
};
|
|
57283
57485
|
const headTree = (workspace) => {
|
|
57284
57486
|
let entries;
|