@intentius/chant-lexicon-github 0.124.31 → 0.124.33

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.
Files changed (157) hide show
  1. package/dist/action-pins.js +53 -0
  2. package/dist/codegen/docs-cli.js +2 -0
  3. package/dist/codegen/docs.js +142 -0
  4. package/dist/codegen/generate-cli.js +26 -0
  5. package/dist/codegen/generate-lexicon.js +36 -0
  6. package/dist/codegen/generate-typescript.js +108 -0
  7. package/dist/codegen/generate.js +111 -0
  8. package/dist/codegen/naming.js +49 -0
  9. package/dist/codegen/package.js +40 -0
  10. package/dist/codegen/parse.js +595 -0
  11. package/dist/codegen/patches.js +36 -0
  12. package/dist/components/ci-jobs.d.ts +7 -0
  13. package/dist/components/ci-jobs.d.ts.map +1 -1
  14. package/dist/components/ci-jobs.js +98 -0
  15. package/dist/components/generate-op-pipeline.js +440 -0
  16. package/dist/components/generate-op-waves-pipeline.js +158 -0
  17. package/dist/components/generate-pipeline.d.ts.map +1 -1
  18. package/dist/components/generate-pipeline.js +481 -0
  19. package/dist/composites/cache.js +17 -0
  20. package/dist/composites/catalog.js +859 -0
  21. package/dist/composites/checkout.js +25 -0
  22. package/dist/composites/dependabot.js +43 -0
  23. package/dist/composites/deploy-environment.js +38 -0
  24. package/dist/composites/docker-build.js +70 -0
  25. package/dist/composites/download-artifact.js +18 -0
  26. package/dist/composites/go-ci.js +62 -0
  27. package/dist/composites/index.js +15 -0
  28. package/dist/composites/node-ci.js +44 -0
  29. package/dist/composites/node-pipeline.js +96 -0
  30. package/dist/composites/pr-plan-report.js +129 -0
  31. package/dist/composites/python-ci.js +60 -0
  32. package/dist/composites/setup-go.js +18 -0
  33. package/dist/composites/setup-node.js +21 -0
  34. package/dist/composites/setup-python.js +18 -0
  35. package/dist/composites/upload-artifact.js +19 -0
  36. package/dist/coverage.js +32 -0
  37. package/dist/expression.js +177 -0
  38. package/dist/generated/index.js +26 -0
  39. package/dist/generated/runtime.js +4 -0
  40. package/dist/graph-edges.js +174 -0
  41. package/dist/import/generator.js +108 -0
  42. package/dist/import/parser.js +69 -0
  43. package/dist/index.js +22 -0
  44. package/dist/integrity.json +2 -2
  45. package/dist/lint/audit-catalog.js +69 -0
  46. package/dist/lint/audit-lineage.js +168 -0
  47. package/dist/lint/post-synth/gha006.js +50 -0
  48. package/dist/lint/post-synth/gha009.js +35 -0
  49. package/dist/lint/post-synth/gha011.js +34 -0
  50. package/dist/lint/post-synth/gha013.js +40 -0
  51. package/dist/lint/post-synth/gha017.js +25 -0
  52. package/dist/lint/post-synth/gha018.js +33 -0
  53. package/dist/lint/post-synth/gha019.js +58 -0
  54. package/dist/lint/post-synth/gha021.js +42 -0
  55. package/dist/lint/post-synth/gha022.js +44 -0
  56. package/dist/lint/post-synth/gha023.js +37 -0
  57. package/dist/lint/post-synth/gha024.js +32 -0
  58. package/dist/lint/post-synth/gha025.js +33 -0
  59. package/dist/lint/post-synth/gha026.js +32 -0
  60. package/dist/lint/post-synth/gha027.js +46 -0
  61. package/dist/lint/post-synth/gha028.js +28 -0
  62. package/dist/lint/post-synth/gha029.js +56 -0
  63. package/dist/lint/post-synth/gha030.js +35 -0
  64. package/dist/lint/post-synth/gha031.js +75 -0
  65. package/dist/lint/post-synth/gha032.js +35 -0
  66. package/dist/lint/post-synth/gha033.js +39 -0
  67. package/dist/lint/post-synth/gha034.js +35 -0
  68. package/dist/lint/post-synth/gha035.js +50 -0
  69. package/dist/lint/post-synth/gha036.js +37 -0
  70. package/dist/lint/post-synth/gha037.js +41 -0
  71. package/dist/lint/post-synth/gha038.js +35 -0
  72. package/dist/lint/post-synth/gha039.js +34 -0
  73. package/dist/lint/post-synth/gha040.js +36 -0
  74. package/dist/lint/post-synth/gha041.js +32 -0
  75. package/dist/lint/post-synth/gha042.js +33 -0
  76. package/dist/lint/post-synth/gha043.js +35 -0
  77. package/dist/lint/post-synth/gha044.js +36 -0
  78. package/dist/lint/post-synth/gha045.js +33 -0
  79. package/dist/lint/post-synth/gha046.js +55 -0
  80. package/dist/lint/post-synth/gha047.js +44 -0
  81. package/dist/lint/post-synth/gha048.js +34 -0
  82. package/dist/lint/post-synth/gha049.js +36 -0
  83. package/dist/lint/post-synth/gha050.js +37 -0
  84. package/dist/lint/post-synth/gha051.js +38 -0
  85. package/dist/lint/post-synth/gha052.js +35 -0
  86. package/dist/lint/post-synth/gha053.js +34 -0
  87. package/dist/lint/post-synth/gha054.js +35 -0
  88. package/dist/lint/post-synth/gha055.js +44 -0
  89. package/dist/lint/post-synth/gha056.js +32 -0
  90. package/dist/lint/post-synth/gha057.js +35 -0
  91. package/dist/lint/post-synth/gha058.js +42 -0
  92. package/dist/lint/post-synth/gha059.js +119 -0
  93. package/dist/lint/post-synth/gha060.js +129 -0
  94. package/dist/lint/post-synth/gha061.js +78 -0
  95. package/dist/lint/post-synth/gha062.js +65 -0
  96. package/dist/lint/post-synth/gha063.js +56 -0
  97. package/dist/lint/post-synth/gha064.js +47 -0
  98. package/dist/lint/post-synth/gha065.js +125 -0
  99. package/dist/lint/post-synth/gha066.js +40 -0
  100. package/dist/lint/post-synth/gha067.js +75 -0
  101. package/dist/lint/post-synth/gha068.js +47 -0
  102. package/dist/lint/post-synth/gha069.js +99 -0
  103. package/dist/lint/post-synth/index.js +114 -0
  104. package/dist/lint/post-synth/yaml-helpers.js +465 -0
  105. package/dist/lint/rules/data/action-usage-policy.js +16 -0
  106. package/dist/lint/rules/data/advisory-feed.js +15 -0
  107. package/dist/lint/rules/data/deprecated-versions.js +14 -0
  108. package/dist/lint/rules/data/flagged-actions.js +18 -0
  109. package/dist/lint/rules/data/known-action-slugs.js +38 -0
  110. package/dist/lint/rules/data/known-actions.js +12 -0
  111. package/dist/lint/rules/data/preinstalled-tools.js +36 -0
  112. package/dist/lint/rules/data/recommended-inputs.js +9 -0
  113. package/dist/lint/rules/data/risky-features.js +22 -0
  114. package/dist/lint/rules/data/secret-patterns.js +30 -0
  115. package/dist/lint/rules/data/trusted-action-owners.js +12 -0
  116. package/dist/lint/rules/data/untrusted-contexts.js +44 -0
  117. package/dist/lint/rules/deprecated-action-version.js +44 -0
  118. package/dist/lint/rules/detect-secrets.js +45 -0
  119. package/dist/lint/rules/extract-inline-structs.js +55 -0
  120. package/dist/lint/rules/file-job-limit.js +43 -0
  121. package/dist/lint/rules/index.js +16 -0
  122. package/dist/lint/rules/job-timeout.js +53 -0
  123. package/dist/lint/rules/missing-recommended-inputs.js +51 -0
  124. package/dist/lint/rules/no-hardcoded-secrets.js +39 -0
  125. package/dist/lint/rules/no-raw-expressions.js +44 -0
  126. package/dist/lint/rules/suggest-cache.js +60 -0
  127. package/dist/lint/rules/use-condition-builders.js +37 -0
  128. package/dist/lint/rules/use-matrix-builder.js +36 -0
  129. package/dist/lint/rules/use-typed-actions.js +41 -0
  130. package/dist/lint/rules/validate-concurrency.js +59 -0
  131. package/dist/lsp/completions.d.ts.map +1 -1
  132. package/dist/lsp/completions.js +18 -0
  133. package/dist/lsp/hover.d.ts.map +1 -1
  134. package/dist/lsp/hover.js +33 -0
  135. package/dist/manifest.json +1 -1
  136. package/dist/mcp/context-tools.js +152 -0
  137. package/dist/package-cli.js +20 -0
  138. package/dist/plugin.js +344 -0
  139. package/dist/serializer.js +572 -0
  140. package/dist/spec/fetch.js +46 -0
  141. package/dist/validate-cli.js +16 -0
  142. package/dist/validate.js +38 -0
  143. package/dist/variables.js +41 -0
  144. package/package.json +6 -6
  145. package/src/codegen/package.ts +2 -2
  146. package/src/components/__fixtures__/pr-loop-build.github.golden.yml +6 -2
  147. package/src/components/__fixtures__/pr-loop-record.github.golden.yml +74 -0
  148. package/src/components/__fixtures__/pr-loop-waves.github.golden.yml +178 -0
  149. package/src/components/__fixtures__/pr-loop.github.golden.yml +6 -2
  150. package/src/components/ci-jobs.ts +16 -2
  151. package/src/components/generate-op-pipeline.test.ts +11 -0
  152. package/src/components/generate-op-pipeline.ts +3 -3
  153. package/src/components/generate-pipeline.ts +74 -31
  154. package/src/components/generate-pr-pipeline.test.ts +99 -29
  155. package/src/components/generate-pr-waves-pipeline.test.ts +117 -0
  156. package/src/lsp/completions.ts +2 -1
  157. package/src/lsp/hover.ts +2 -1
@@ -0,0 +1,595 @@
1
+ /**
2
+ * GitHub Actions Workflow JSON Schema parser.
3
+ *
4
+ * Parses the single workflow schema into multiple entity results — one
5
+ * per resource/property entity (Workflow, Job, Step, triggers, etc.).
6
+ */
7
+ import { extractConstraints as coreExtractConstraints, constraintsIsEmpty as coreConstraintsIsEmpty, primaryType, } from "@intentius/chant/codegen/json-schema";
8
+ export { coreConstraintsIsEmpty as constraintsIsEmpty };
9
+ // ── Entity extraction mapping ──────────────────────────────────────
10
+ const RESOURCE_ENTITIES = [
11
+ {
12
+ typeName: "GitHub::Actions::Workflow",
13
+ source: "root",
14
+ description: "A GitHub Actions workflow definition",
15
+ },
16
+ {
17
+ typeName: "GitHub::Actions::Job",
18
+ source: "#/definitions/normalJob",
19
+ description: "A standard CI job",
20
+ },
21
+ {
22
+ typeName: "GitHub::Actions::ReusableWorkflowCallJob",
23
+ source: "#/definitions/reusableWorkflowCallJob",
24
+ description: "A reusable workflow call job (uses: workflow reference)",
25
+ },
26
+ ];
27
+ const PROPERTY_ENTITIES = [
28
+ { typeName: "GitHub::Actions::Step", source: "normalJob:steps:item", description: "A workflow step" },
29
+ { typeName: "GitHub::Actions::Strategy", source: "normalJob:strategy", description: "Job strategy configuration" },
30
+ { typeName: "GitHub::Actions::Permissions", source: "#/definitions/permissions", description: "Workflow or job permissions" },
31
+ { typeName: "GitHub::Actions::Concurrency", source: "#/definitions/concurrency", description: "Concurrency control" },
32
+ { typeName: "GitHub::Actions::Container", source: "#/definitions/container", description: "Container configuration for a job" },
33
+ { typeName: "GitHub::Actions::Service", source: "service", description: "Service container configuration" },
34
+ { typeName: "GitHub::Actions::Environment", source: "#/definitions/environment", description: "Deployment environment" },
35
+ { typeName: "GitHub::Actions::Defaults", source: "#/definitions/defaults", description: "Default settings for all jobs" },
36
+ { typeName: "GitHub::Actions::PushTrigger", source: "event:push", description: "Push event trigger" },
37
+ { typeName: "GitHub::Actions::PullRequestTrigger", source: "event:pull_request", description: "Pull request event trigger" },
38
+ { typeName: "GitHub::Actions::PullRequestTargetTrigger", source: "event:pull_request_target", description: "Pull request target event trigger" },
39
+ { typeName: "GitHub::Actions::ScheduleTrigger", source: "event:schedule", description: "Schedule event trigger" },
40
+ { typeName: "GitHub::Actions::WorkflowDispatchTrigger", source: "event:workflow_dispatch", description: "Workflow dispatch event trigger" },
41
+ { typeName: "GitHub::Actions::WorkflowCallTrigger", source: "event:workflow_call", description: "Workflow call event trigger" },
42
+ { typeName: "GitHub::Actions::WorkflowRunTrigger", source: "event:workflow_run", description: "Workflow run event trigger" },
43
+ { typeName: "GitHub::Actions::RepositoryDispatchTrigger", source: "event:repository_dispatch", description: "Repository dispatch event trigger" },
44
+ { typeName: "GitHub::Actions::WorkflowInput", source: "workflow_call:input", description: "Reusable workflow input parameter" },
45
+ { typeName: "GitHub::Actions::WorkflowOutput", source: "workflow_call:output", description: "Reusable workflow output" },
46
+ { typeName: "GitHub::Actions::WorkflowSecret", source: "workflow_call:secret", description: "Reusable workflow secret" },
47
+ ];
48
+ // ── Parser ─────────────────────────────────────────────────────────
49
+ /**
50
+ * Parse the GitHub Actions Workflow JSON Schema into multiple entity results.
51
+ */
52
+ export function parseWorkflowSchema(data) {
53
+ const schema = JSON.parse(typeof data === "string" ? data : data.toString("utf-8"));
54
+ const results = [];
55
+ for (const entity of RESOURCE_ENTITIES) {
56
+ const result = extractEntity(schema, entity, false);
57
+ if (result)
58
+ results.push(result);
59
+ }
60
+ for (const entity of PROPERTY_ENTITIES) {
61
+ const result = extractEntity(schema, entity, true);
62
+ if (result) {
63
+ result.isProperty = true;
64
+ results.push(result);
65
+ }
66
+ }
67
+ return results;
68
+ }
69
+ function extractEntity(schema, entity, isProperty) {
70
+ const def = resolveSource(schema, entity.source);
71
+ if (!def) {
72
+ // Create minimal entry for entities we know exist but can't resolve from schema
73
+ return {
74
+ resource: {
75
+ typeName: entity.typeName,
76
+ description: entity.description,
77
+ properties: addCommentProperty(entity.typeName, buildFallbackProperties(entity.typeName)),
78
+ attributes: [],
79
+ deprecatedProperties: [],
80
+ },
81
+ propertyTypes: [],
82
+ enums: [],
83
+ };
84
+ }
85
+ const objectDef = findObjectVariant(def, schema);
86
+ const properties = objectDef?.properties
87
+ ? parseProperties(objectDef.properties, new Set(objectDef.required ?? []), schema)
88
+ : buildFallbackProperties(entity.typeName);
89
+ const overrides = PROPERTY_OVERRIDES[entity.typeName];
90
+ if (overrides) {
91
+ for (const prop of properties) {
92
+ if (overrides[prop.name]) {
93
+ prop.tsType = overrides[prop.name];
94
+ }
95
+ }
96
+ }
97
+ addCommentProperty(entity.typeName, properties);
98
+ return {
99
+ resource: {
100
+ typeName: entity.typeName,
101
+ description: entity.description ?? objectDef?.description ?? def.description,
102
+ properties,
103
+ attributes: [],
104
+ deprecatedProperties: mineDeprecatedProperties(properties),
105
+ },
106
+ propertyTypes: [],
107
+ enums: [],
108
+ };
109
+ }
110
+ // ── Source resolution ──────────────────────────────────────────────
111
+ function resolveSource(schema, source) {
112
+ if (source === "root") {
113
+ return { properties: schema.properties, required: schema.required };
114
+ }
115
+ if (source.startsWith("#/definitions/")) {
116
+ const defName = source.slice("#/definitions/".length);
117
+ return schema.definitions?.[defName] ?? null;
118
+ }
119
+ // normalJob:property — resolve from normalJob definition
120
+ if (source.startsWith("normalJob:")) {
121
+ const segments = source.slice("normalJob:".length).split(":");
122
+ let current = schema.definitions?.normalJob ?? null;
123
+ for (const seg of segments) {
124
+ if (!current)
125
+ return null;
126
+ if (seg === "item") {
127
+ if (!current.items)
128
+ return null;
129
+ return findObjectVariant(current.items, schema);
130
+ }
131
+ if (!current.properties?.[seg])
132
+ return null;
133
+ const prop = current.properties[seg];
134
+ current = prop.$ref ? resolveRef(prop.$ref, schema) : prop;
135
+ }
136
+ return current;
137
+ }
138
+ // event:name — resolve trigger event type
139
+ if (source.startsWith("event:")) {
140
+ const eventName = source.slice("event:".length);
141
+ return resolveEventTrigger(schema, eventName);
142
+ }
143
+ // workflow_call:input/output/secret
144
+ if (source.startsWith("workflow_call:")) {
145
+ const part = source.slice("workflow_call:".length);
146
+ return resolveWorkflowCallPart(schema, part);
147
+ }
148
+ // service — from container definitions
149
+ if (source === "service") {
150
+ // Services are containers with additional properties
151
+ const containerDef = schema.definitions?.container;
152
+ return containerDef ?? null;
153
+ }
154
+ return null;
155
+ }
156
+ function resolveEventTrigger(schema, eventName) {
157
+ // Try to find in definitions like eventObject, or under "on" properties
158
+ const defName = `eventObject`;
159
+ const eventDef = schema.definitions?.[defName];
160
+ if (eventDef?.properties?.[eventName]) {
161
+ const prop = eventDef.properties[eventName];
162
+ if (prop.$ref)
163
+ return resolveRef(prop.$ref, schema);
164
+ return prop;
165
+ }
166
+ // Try direct definition names
167
+ const directNames = [
168
+ eventName,
169
+ `${eventName}Event`,
170
+ ];
171
+ for (const name of directNames) {
172
+ if (schema.definitions?.[name]) {
173
+ return schema.definitions[name];
174
+ }
175
+ }
176
+ return null;
177
+ }
178
+ function resolveWorkflowCallPart(schema, part) {
179
+ // Look in workflow_call trigger definition
180
+ const wcDef = schema.definitions?.["eventObject"]?.properties?.workflow_call;
181
+ if (!wcDef)
182
+ return null;
183
+ const resolved = wcDef.$ref ? resolveRef(wcDef.$ref, schema) : wcDef;
184
+ if (!resolved)
185
+ return null;
186
+ const objectDef = findObjectVariant(resolved, schema);
187
+ if (!objectDef?.properties)
188
+ return null;
189
+ const mapping = {
190
+ input: "inputs",
191
+ output: "outputs",
192
+ secret: "secrets",
193
+ };
194
+ const propName = mapping[part] ?? part;
195
+ const prop = objectDef.properties[propName];
196
+ if (!prop)
197
+ return null;
198
+ // Get the "additionalProperties" or "patternProperties" to find the item schema
199
+ const resolvedProp = prop.$ref ? resolveRef(prop.$ref, schema) : prop;
200
+ if (!resolvedProp)
201
+ return null;
202
+ if (resolvedProp.patternProperties) {
203
+ const first = Object.values(resolvedProp.patternProperties)[0];
204
+ if (first)
205
+ return first;
206
+ }
207
+ if (typeof resolvedProp.additionalProperties === "object") {
208
+ return resolvedProp.additionalProperties;
209
+ }
210
+ return resolvedProp;
211
+ }
212
+ function resolveRef(ref, schema) {
213
+ const prefix = "#/definitions/";
214
+ if (!ref.startsWith(prefix))
215
+ return null;
216
+ const defName = ref.slice(prefix.length);
217
+ return schema.definitions?.[defName] ?? null;
218
+ }
219
+ function findObjectVariant(def, schema) {
220
+ if (def.properties)
221
+ return def;
222
+ const variants = def.oneOf ?? def.anyOf;
223
+ if (!variants)
224
+ return null;
225
+ const objectVariants = [];
226
+ for (const v of variants) {
227
+ let resolved = v;
228
+ if (v.$ref && schema) {
229
+ const r = resolveRef(v.$ref, schema);
230
+ if (r)
231
+ resolved = r;
232
+ else
233
+ continue;
234
+ }
235
+ else if (v.$ref) {
236
+ continue;
237
+ }
238
+ if (resolved.properties) {
239
+ objectVariants.push(resolved);
240
+ }
241
+ }
242
+ if (objectVariants.length === 0)
243
+ return null;
244
+ if (objectVariants.length === 1)
245
+ return objectVariants[0];
246
+ // Merge: pick variant with most properties as base
247
+ let best = objectVariants[0];
248
+ let bestCount = Object.keys(best.properties).length;
249
+ for (let i = 1; i < objectVariants.length; i++) {
250
+ const count = Object.keys(objectVariants[i].properties).length;
251
+ if (count > bestCount) {
252
+ best = objectVariants[i];
253
+ bestCount = count;
254
+ }
255
+ }
256
+ const mergedProperties = { ...best.properties };
257
+ for (const variant of objectVariants) {
258
+ if (variant === best)
259
+ continue;
260
+ for (const [propName, propDef] of Object.entries(variant.properties)) {
261
+ if (!(propName in mergedProperties)) {
262
+ mergedProperties[propName] = propDef;
263
+ }
264
+ }
265
+ }
266
+ return { ...best, properties: mergedProperties };
267
+ }
268
+ // ── Property parsing ──────────────────────────────────────────────
269
+ function parseProperties(properties, requiredSet, schema) {
270
+ const result = [];
271
+ for (const [name, prop] of Object.entries(properties)) {
272
+ const tsType = resolvePropertyType(prop, schema);
273
+ result.push({
274
+ name,
275
+ tsType,
276
+ required: requiredSet.has(name),
277
+ description: prop.description,
278
+ enum: prop.enum,
279
+ constraints: coreExtractConstraints(prop),
280
+ });
281
+ }
282
+ return result;
283
+ }
284
+ function resolvePropertyType(prop, schema) {
285
+ if (!prop)
286
+ return "any";
287
+ if (prop.$ref) {
288
+ const def = resolveRef(prop.$ref, schema);
289
+ if (def) {
290
+ if (def.enum && def.enum.length > 0 && !def.properties) {
291
+ return def.enum.map((v) => JSON.stringify(v)).join(" | ");
292
+ }
293
+ if (def.type && !def.properties) {
294
+ return jsonTypeToTs(primaryType(def.type));
295
+ }
296
+ if (def.properties)
297
+ return "Record<string, any>";
298
+ }
299
+ return "any";
300
+ }
301
+ if (prop.enum && prop.enum.length > 0) {
302
+ return prop.enum.map((v) => JSON.stringify(v)).join(" | ");
303
+ }
304
+ if (prop.oneOf || prop.anyOf) {
305
+ const variants = prop.oneOf ?? prop.anyOf ?? [];
306
+ const types = new Set();
307
+ for (const v of variants) {
308
+ types.add(resolvePropertyType(v, schema));
309
+ }
310
+ const uniqueTypes = [...types].filter((t) => t !== "any");
311
+ if (uniqueTypes.length === 0)
312
+ return "any";
313
+ if (uniqueTypes.length === 1)
314
+ return uniqueTypes[0];
315
+ return uniqueTypes.join(" | ");
316
+ }
317
+ const pt = primaryType(prop.type);
318
+ switch (pt) {
319
+ case "string": return "string";
320
+ case "integer":
321
+ case "number": return "number";
322
+ case "boolean": return "boolean";
323
+ case "array":
324
+ if (prop.items) {
325
+ const itemType = resolvePropertyType(prop.items, schema);
326
+ if (itemType.includes(" | "))
327
+ return `(${itemType})[]`;
328
+ return `${itemType}[]`;
329
+ }
330
+ return "any[]";
331
+ case "object": return "Record<string, any>";
332
+ default: return "any";
333
+ }
334
+ }
335
+ function jsonTypeToTs(type) {
336
+ switch (type) {
337
+ case "string": return "string";
338
+ case "integer":
339
+ case "number": return "number";
340
+ case "boolean": return "boolean";
341
+ case "array": return "any[]";
342
+ case "object": return "Record<string, any>";
343
+ default: return "any";
344
+ }
345
+ }
346
+ // ── Property overrides ────────────────────────────────────────────
347
+ const PROPERTY_OVERRIDES = {
348
+ "GitHub::Actions::Workflow": {
349
+ on: "Record<string, any>",
350
+ jobs: "Record<string, any>",
351
+ permissions: "Permissions | string",
352
+ concurrency: "Concurrency | string",
353
+ defaults: "Defaults",
354
+ env: "Record<string, string>",
355
+ },
356
+ "GitHub::Actions::Job": {
357
+ steps: "Step[]",
358
+ strategy: "Strategy",
359
+ permissions: "Permissions | string",
360
+ concurrency: "Concurrency | string",
361
+ container: "Container | string",
362
+ services: "Record<string, Service>",
363
+ environment: "Environment | string",
364
+ defaults: "Defaults",
365
+ env: "Record<string, string>",
366
+ needs: "string[]",
367
+ outputs: "Record<string, string>",
368
+ "runs-on": "string | string[]",
369
+ "timeout-minutes": "number",
370
+ "continue-on-error": "boolean",
371
+ "if": "string",
372
+ },
373
+ "GitHub::Actions::Step": {
374
+ env: "Record<string, string>",
375
+ with: "Record<string, string | number | boolean>",
376
+ "if": "string",
377
+ "timeout-minutes": "number",
378
+ "continue-on-error": "boolean",
379
+ },
380
+ "GitHub::Actions::Strategy": {
381
+ matrix: "Record<string, any>",
382
+ },
383
+ };
384
+ // ── Comments ──────────────────────────────────────────────────────
385
+ /**
386
+ * Entities that carry a `comment`: not a workflow key, but `# ...` lines the
387
+ * serializer writes above the entry (above `name:` for a workflow, the file's
388
+ * header), so the reasons a hand-written workflow keeps as YAML comments
389
+ * reach the rendered file (#3667).
390
+ */
391
+ const COMMENTED_ENTITIES = {
392
+ "GitHub::Actions::Workflow": "YAML comment lines written at the top of the file, above `name:`. Not a workflow key; each line of the string becomes a `#` line",
393
+ "GitHub::Actions::Job": "YAML comment lines written above the job's key. Not a job key; each line of the string becomes a `#` line",
394
+ "GitHub::Actions::ReusableWorkflowCallJob": "YAML comment lines written above the job's key. Not a job key; each line of the string becomes a `#` line",
395
+ "GitHub::Actions::Step": "YAML comment lines written above the step. Not a step key; each line of the string becomes a `#` line",
396
+ };
397
+ function addCommentProperty(typeName, properties) {
398
+ const description = COMMENTED_ENTITIES[typeName];
399
+ if (description && !properties.some((p) => p.name === "comment")) {
400
+ properties.push({ name: "comment", tsType: "string", required: false, description, constraints: {} });
401
+ }
402
+ return properties;
403
+ }
404
+ // ── Fallback properties ───────────────────────────────────────────
405
+ /**
406
+ * Provide fallback properties for entities that can't be resolved from the schema.
407
+ */
408
+ function buildFallbackProperties(typeName) {
409
+ const fallbacks = {
410
+ "GitHub::Actions::Workflow": [
411
+ { name: "name", tsType: "string", required: false, description: "The name of the workflow" },
412
+ { name: "on", tsType: "Record<string, any>", required: true, description: "Event triggers" },
413
+ { name: "jobs", tsType: "Record<string, any>", required: true, description: "Jobs in the workflow" },
414
+ { name: "permissions", tsType: "Permissions | string", required: false, description: "Permissions for the workflow" },
415
+ { name: "env", tsType: "Record<string, string>", required: false, description: "Environment variables" },
416
+ { name: "concurrency", tsType: "Concurrency | string", required: false, description: "Concurrency settings" },
417
+ { name: "defaults", tsType: "Defaults", required: false, description: "Default settings" },
418
+ { name: "run-name", tsType: "string", required: false, description: "Dynamic name for workflow runs" },
419
+ ],
420
+ "GitHub::Actions::Job": [
421
+ { name: "name", tsType: "string", required: false, description: "Job display name" },
422
+ { name: "runs-on", tsType: "string | string[]", required: true, description: "Runner label(s)" },
423
+ { name: "steps", tsType: "Step[]", required: false, description: "Job steps" },
424
+ { name: "needs", tsType: "string[]", required: false, description: "Job dependencies" },
425
+ { name: "if", tsType: "string", required: false, description: "Conditional expression" },
426
+ { name: "permissions", tsType: "Permissions | string", required: false, description: "Permissions" },
427
+ { name: "environment", tsType: "Environment | string", required: false, description: "Deployment environment" },
428
+ { name: "concurrency", tsType: "Concurrency | string", required: false, description: "Concurrency settings" },
429
+ { name: "outputs", tsType: "Record<string, string>", required: false, description: "Job outputs" },
430
+ { name: "env", tsType: "Record<string, string>", required: false, description: "Environment variables" },
431
+ { name: "defaults", tsType: "Defaults", required: false, description: "Default settings" },
432
+ { name: "strategy", tsType: "Strategy", required: false, description: "Strategy (matrix, etc.)" },
433
+ { name: "container", tsType: "Container | string", required: false, description: "Container to run in" },
434
+ { name: "services", tsType: "Record<string, Service>", required: false, description: "Service containers" },
435
+ { name: "timeout-minutes", tsType: "number", required: false, description: "Timeout in minutes" },
436
+ { name: "continue-on-error", tsType: "boolean", required: false, description: "Continue on error" },
437
+ ],
438
+ "GitHub::Actions::ReusableWorkflowCallJob": [
439
+ { name: "uses", tsType: "string", required: true, description: "Reusable workflow reference" },
440
+ { name: "with", tsType: "Record<string, any>", required: false, description: "Inputs for the reusable workflow" },
441
+ { name: "secrets", tsType: "Record<string, any> | string", required: false, description: "Secrets to pass" },
442
+ { name: "needs", tsType: "string[]", required: false, description: "Job dependencies" },
443
+ { name: "if", tsType: "string", required: false, description: "Conditional expression" },
444
+ { name: "permissions", tsType: "Permissions | string", required: false, description: "Permissions" },
445
+ { name: "concurrency", tsType: "Concurrency | string", required: false, description: "Concurrency settings" },
446
+ ],
447
+ "GitHub::Actions::Step": [
448
+ { name: "name", tsType: "string", required: false, description: "Step display name" },
449
+ { name: "uses", tsType: "string", required: false, description: "Action reference" },
450
+ { name: "run", tsType: "string", required: false, description: "Shell command" },
451
+ { name: "with", tsType: "Record<string, string | number | boolean>", required: false, description: "Action inputs. The runner reads each as a string; a number or boolean renders as written (`fetch-depth: 0`)" },
452
+ { name: "env", tsType: "Record<string, string>", required: false, description: "Environment variables" },
453
+ { name: "if", tsType: "string", required: false, description: "Conditional expression" },
454
+ { name: "id", tsType: "string", required: false, description: "Step ID for output references" },
455
+ { name: "shell", tsType: "string", required: false, description: "Shell to use" },
456
+ { name: "working-directory", tsType: "string", required: false, description: "Working directory" },
457
+ { name: "timeout-minutes", tsType: "number", required: false, description: "Timeout in minutes" },
458
+ { name: "continue-on-error", tsType: "boolean", required: false, description: "Continue on error" },
459
+ ],
460
+ "GitHub::Actions::Strategy": [
461
+ { name: "matrix", tsType: "Record<string, any>", required: false, description: "Matrix configuration" },
462
+ { name: "fail-fast", tsType: "boolean", required: false, description: "Cancel all jobs if one fails" },
463
+ { name: "max-parallel", tsType: "number", required: false, description: "Max parallel jobs" },
464
+ ],
465
+ "GitHub::Actions::Permissions": [
466
+ { name: "actions", tsType: '"read" | "write" | "none"', required: false },
467
+ { name: "checks", tsType: '"read" | "write" | "none"', required: false },
468
+ { name: "contents", tsType: '"read" | "write" | "none"', required: false },
469
+ { name: "deployments", tsType: '"read" | "write" | "none"', required: false },
470
+ { name: "id-token", tsType: '"write" | "none"', required: false },
471
+ { name: "issues", tsType: '"read" | "write" | "none"', required: false },
472
+ { name: "packages", tsType: '"read" | "write" | "none"', required: false },
473
+ { name: "pages", tsType: '"read" | "write" | "none"', required: false },
474
+ { name: "pull-requests", tsType: '"read" | "write" | "none"', required: false },
475
+ { name: "security-events", tsType: '"read" | "write" | "none"', required: false },
476
+ { name: "statuses", tsType: '"read" | "write" | "none"', required: false },
477
+ ],
478
+ "GitHub::Actions::Concurrency": [
479
+ { name: "group", tsType: "string", required: true, description: "Concurrency group name" },
480
+ { name: "cancel-in-progress", tsType: "boolean", required: false, description: "Cancel in-progress runs" },
481
+ ],
482
+ "GitHub::Actions::Container": [
483
+ { name: "image", tsType: "string", required: true, description: "Docker image" },
484
+ { name: "credentials", tsType: "Record<string, string>", required: false, description: "Registry credentials" },
485
+ { name: "env", tsType: "Record<string, string>", required: false, description: "Environment variables" },
486
+ { name: "ports", tsType: "(number | string)[]", required: false, description: "Exposed ports: a container port (published on a random host port) or \"host:container\"" },
487
+ { name: "volumes", tsType: "string[]", required: false, description: "Volume mounts" },
488
+ { name: "options", tsType: "string", required: false, description: "Docker options" },
489
+ ],
490
+ "GitHub::Actions::Service": [
491
+ { name: "image", tsType: "string", required: true, description: "Docker image" },
492
+ { name: "credentials", tsType: "Record<string, string>", required: false },
493
+ { name: "env", tsType: "Record<string, string>", required: false },
494
+ { name: "ports", tsType: "(number | string)[]", required: false, description: "Exposed ports: a container port (published on a random host port) or \"host:container\", which a step on the runner reaches at localhost:<host>" },
495
+ { name: "volumes", tsType: "string[]", required: false },
496
+ { name: "options", tsType: "string", required: false },
497
+ ],
498
+ "GitHub::Actions::Environment": [
499
+ { name: "name", tsType: "string", required: true, description: "Environment name" },
500
+ { name: "url", tsType: "string", required: false, description: "Environment URL" },
501
+ ],
502
+ "GitHub::Actions::Defaults": [
503
+ { name: "run", tsType: "Record<string, string>", required: false, description: "Default run settings" },
504
+ ],
505
+ "GitHub::Actions::PushTrigger": [
506
+ { name: "branches", tsType: "string[]", required: false },
507
+ { name: "branches-ignore", tsType: "string[]", required: false },
508
+ { name: "tags", tsType: "string[]", required: false },
509
+ { name: "tags-ignore", tsType: "string[]", required: false },
510
+ { name: "paths", tsType: "string[]", required: false },
511
+ { name: "paths-ignore", tsType: "string[]", required: false },
512
+ ],
513
+ "GitHub::Actions::PullRequestTrigger": [
514
+ { name: "branches", tsType: "string[]", required: false },
515
+ { name: "branches-ignore", tsType: "string[]", required: false },
516
+ { name: "paths", tsType: "string[]", required: false },
517
+ { name: "paths-ignore", tsType: "string[]", required: false },
518
+ { name: "types", tsType: "string[]", required: false },
519
+ ],
520
+ "GitHub::Actions::PullRequestTargetTrigger": [
521
+ { name: "branches", tsType: "string[]", required: false },
522
+ { name: "branches-ignore", tsType: "string[]", required: false },
523
+ { name: "paths", tsType: "string[]", required: false },
524
+ { name: "paths-ignore", tsType: "string[]", required: false },
525
+ { name: "types", tsType: "string[]", required: false },
526
+ ],
527
+ "GitHub::Actions::ScheduleTrigger": [
528
+ { name: "cron", tsType: "string", required: true, description: "POSIX cron expression" },
529
+ ],
530
+ "GitHub::Actions::WorkflowDispatchTrigger": [
531
+ { name: "inputs", tsType: "Record<string, any>", required: false },
532
+ ],
533
+ "GitHub::Actions::WorkflowCallTrigger": [
534
+ { name: "inputs", tsType: "Record<string, any>", required: false },
535
+ { name: "outputs", tsType: "Record<string, any>", required: false },
536
+ { name: "secrets", tsType: "Record<string, any>", required: false },
537
+ ],
538
+ "GitHub::Actions::WorkflowRunTrigger": [
539
+ { name: "workflows", tsType: "string[]", required: false },
540
+ { name: "types", tsType: "string[]", required: false },
541
+ { name: "branches", tsType: "string[]", required: false },
542
+ { name: "branches-ignore", tsType: "string[]", required: false },
543
+ ],
544
+ "GitHub::Actions::RepositoryDispatchTrigger": [
545
+ { name: "types", tsType: "string[]", required: false },
546
+ ],
547
+ "GitHub::Actions::WorkflowInput": [
548
+ { name: "description", tsType: "string", required: false },
549
+ { name: "required", tsType: "boolean", required: false },
550
+ { name: "default", tsType: "string", required: false },
551
+ { name: "type", tsType: '"string" | "boolean" | "number" | "choice" | "environment"', required: false },
552
+ { name: "options", tsType: "string[]", required: false },
553
+ ],
554
+ "GitHub::Actions::WorkflowOutput": [
555
+ { name: "description", tsType: "string", required: false },
556
+ { name: "value", tsType: "string", required: true },
557
+ ],
558
+ "GitHub::Actions::WorkflowSecret": [
559
+ { name: "description", tsType: "string", required: false },
560
+ { name: "required", tsType: "boolean", required: false },
561
+ ],
562
+ };
563
+ const props = fallbacks[typeName];
564
+ if (!props)
565
+ return [];
566
+ return props.map((p) => ({
567
+ ...p,
568
+ constraints: {},
569
+ }));
570
+ }
571
+ // ── Helpers ───────────────────────────────────────────────────────
572
+ const DEPRECATION_RE = /\bDeprecated\b|\bdeprecated\b|\blegacy\b|no longer (available|recommended|used|supported)/i;
573
+ function mineDeprecatedProperties(properties) {
574
+ const deprecated = [];
575
+ for (const prop of properties) {
576
+ if (prop.description && DEPRECATION_RE.test(prop.description)) {
577
+ deprecated.push(prop.name);
578
+ }
579
+ }
580
+ return deprecated;
581
+ }
582
+ /**
583
+ * Extract short name: "GitHub::Actions::Job" → "Job"
584
+ */
585
+ export function githubShortName(typeName) {
586
+ const parts = typeName.split("::");
587
+ return parts[parts.length - 1];
588
+ }
589
+ /**
590
+ * Extract service name: "GitHub::Actions::Job" → "Actions"
591
+ */
592
+ export function githubServiceName(typeName) {
593
+ const parts = typeName.split("::");
594
+ return parts.length >= 2 ? parts[1] : "Actions";
595
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Schema augmentation patches for GitHub Actions Workflow JSON Schema.
3
+ */
4
+ /**
5
+ * Registry of known schema patches.
6
+ * Currently empty — the SchemaStore workflow schema is well-maintained.
7
+ */
8
+ export const schemaPatches = [];
9
+ /**
10
+ * Apply all registered patches to a parsed schema.
11
+ */
12
+ export function applyPatches(schema) {
13
+ const applied = [];
14
+ const skipped = [];
15
+ for (const patch of schemaPatches) {
16
+ const segments = patch.path.split(".");
17
+ let target = schema;
18
+ for (const segment of segments) {
19
+ if (target && typeof target === "object" && segment in target) {
20
+ target = target[segment];
21
+ }
22
+ else {
23
+ target = undefined;
24
+ break;
25
+ }
26
+ }
27
+ if (target) {
28
+ patch.apply(target);
29
+ applied.push(patch.description);
30
+ }
31
+ else {
32
+ skipped.push(`${patch.description} (path "${patch.path}" not found)`);
33
+ }
34
+ }
35
+ return { applied, skipped };
36
+ }
@@ -35,6 +35,13 @@ export declare function jobTokenEnv(gh?: boolean): Record<string, string>;
35
35
  * names none).
36
36
  */
37
37
  export declare function onTrigger(trigger: OpTrigger): Record<string, unknown>;
38
+ /**
39
+ * A push Op's concurrency group (#4169): one per commit under `build:
40
+ * "every"`, so no push cancels or replaces another's run; one per ref under
41
+ * `newest`, so the newest push waits and each build request's tag runs on its
42
+ * own; and the Op's own name otherwise, one run at a time.
43
+ */
44
+ export declare function opConcurrencyGroup(jobName: string, trigger: OpTrigger): string;
38
45
  /**
39
46
  * A workflow document before emission. Every generator's document is one of
40
47
  * these; each leaves out the sections it has no use for.
@@ -1 +1 @@
1
- {"version":3,"file":"ci-jobs.d.ts","sourceRoot":"","sources":["../../src/components/ci-jobs.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAG1D,qGAAqG;AACrG,eAAO,MAAM,eAAe,+BAA+B,CAAC;AAC5D,eAAO,MAAM,iBAAiB,iCAAiC,CAAC;AAEhE,iIAAiI;AACjI,wBAAgB,YAAY,CAAC,WAAW,UAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED,yEAAyE;AACzE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAEjF;AAED,oDAAoD;AACpD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE1G;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAOpG;AAED,6DAA6D;AAC7D,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,UAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE5F;AAED,oGAAoG;AACpG,wBAAgB,WAAW,CAAC,EAAE,UAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAE9D;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASrE;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,qGAAqG;IACrG,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,8BAA8B;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5B,uEAAuE;IACvE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,kCAAkC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,2BAA2B;IAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,kFAAkF;AAClF,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM,CAW/D"}
1
+ {"version":3,"file":"ci-jobs.d.ts","sourceRoot":"","sources":["../../src/components/ci-jobs.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAG1D,qGAAqG;AACrG,eAAO,MAAM,eAAe,+BAA+B,CAAC;AAC5D,eAAO,MAAM,iBAAiB,iCAAiC,CAAC;AAEhE,iIAAiI;AACjI,wBAAgB,YAAY,CAAC,WAAW,UAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED,yEAAyE;AACzE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAEjF;AAED,oDAAoD;AACpD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE1G;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAOpG;AAED,6DAA6D;AAC7D,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,UAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE5F;AAED,oGAAoG;AACpG,wBAAgB,WAAW,CAAC,EAAE,UAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAE9D;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAYrE;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,GAAG,MAAM,CAG9E;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,qGAAqG;IACrG,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,8BAA8B;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5B,uEAAuE;IACvE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,kCAAkC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,2BAA2B;IAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,kFAAkF;AAClF,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM,CAW/D"}