@intentius/chant-lexicon-github 0.124.31 → 0.124.32

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 (151) 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.js +84 -0
  13. package/dist/components/generate-op-pipeline.js +440 -0
  14. package/dist/components/generate-op-waves-pipeline.js +158 -0
  15. package/dist/components/generate-pipeline.d.ts.map +1 -1
  16. package/dist/components/generate-pipeline.js +476 -0
  17. package/dist/composites/cache.js +17 -0
  18. package/dist/composites/catalog.js +859 -0
  19. package/dist/composites/checkout.js +25 -0
  20. package/dist/composites/dependabot.js +43 -0
  21. package/dist/composites/deploy-environment.js +38 -0
  22. package/dist/composites/docker-build.js +70 -0
  23. package/dist/composites/download-artifact.js +18 -0
  24. package/dist/composites/go-ci.js +62 -0
  25. package/dist/composites/index.js +15 -0
  26. package/dist/composites/node-ci.js +44 -0
  27. package/dist/composites/node-pipeline.js +96 -0
  28. package/dist/composites/pr-plan-report.js +129 -0
  29. package/dist/composites/python-ci.js +60 -0
  30. package/dist/composites/setup-go.js +18 -0
  31. package/dist/composites/setup-node.js +21 -0
  32. package/dist/composites/setup-python.js +18 -0
  33. package/dist/composites/upload-artifact.js +19 -0
  34. package/dist/coverage.js +32 -0
  35. package/dist/expression.js +177 -0
  36. package/dist/generated/index.js +26 -0
  37. package/dist/generated/runtime.js +4 -0
  38. package/dist/graph-edges.js +174 -0
  39. package/dist/import/generator.js +108 -0
  40. package/dist/import/parser.js +69 -0
  41. package/dist/index.js +22 -0
  42. package/dist/integrity.json +2 -2
  43. package/dist/lint/audit-catalog.js +69 -0
  44. package/dist/lint/audit-lineage.js +168 -0
  45. package/dist/lint/post-synth/gha006.js +50 -0
  46. package/dist/lint/post-synth/gha009.js +35 -0
  47. package/dist/lint/post-synth/gha011.js +34 -0
  48. package/dist/lint/post-synth/gha013.js +40 -0
  49. package/dist/lint/post-synth/gha017.js +25 -0
  50. package/dist/lint/post-synth/gha018.js +33 -0
  51. package/dist/lint/post-synth/gha019.js +58 -0
  52. package/dist/lint/post-synth/gha021.js +42 -0
  53. package/dist/lint/post-synth/gha022.js +44 -0
  54. package/dist/lint/post-synth/gha023.js +37 -0
  55. package/dist/lint/post-synth/gha024.js +32 -0
  56. package/dist/lint/post-synth/gha025.js +33 -0
  57. package/dist/lint/post-synth/gha026.js +32 -0
  58. package/dist/lint/post-synth/gha027.js +46 -0
  59. package/dist/lint/post-synth/gha028.js +28 -0
  60. package/dist/lint/post-synth/gha029.js +56 -0
  61. package/dist/lint/post-synth/gha030.js +35 -0
  62. package/dist/lint/post-synth/gha031.js +75 -0
  63. package/dist/lint/post-synth/gha032.js +35 -0
  64. package/dist/lint/post-synth/gha033.js +39 -0
  65. package/dist/lint/post-synth/gha034.js +35 -0
  66. package/dist/lint/post-synth/gha035.js +50 -0
  67. package/dist/lint/post-synth/gha036.js +37 -0
  68. package/dist/lint/post-synth/gha037.js +41 -0
  69. package/dist/lint/post-synth/gha038.js +35 -0
  70. package/dist/lint/post-synth/gha039.js +34 -0
  71. package/dist/lint/post-synth/gha040.js +36 -0
  72. package/dist/lint/post-synth/gha041.js +32 -0
  73. package/dist/lint/post-synth/gha042.js +33 -0
  74. package/dist/lint/post-synth/gha043.js +35 -0
  75. package/dist/lint/post-synth/gha044.js +36 -0
  76. package/dist/lint/post-synth/gha045.js +33 -0
  77. package/dist/lint/post-synth/gha046.js +55 -0
  78. package/dist/lint/post-synth/gha047.js +44 -0
  79. package/dist/lint/post-synth/gha048.js +34 -0
  80. package/dist/lint/post-synth/gha049.js +36 -0
  81. package/dist/lint/post-synth/gha050.js +37 -0
  82. package/dist/lint/post-synth/gha051.js +38 -0
  83. package/dist/lint/post-synth/gha052.js +35 -0
  84. package/dist/lint/post-synth/gha053.js +34 -0
  85. package/dist/lint/post-synth/gha054.js +35 -0
  86. package/dist/lint/post-synth/gha055.js +44 -0
  87. package/dist/lint/post-synth/gha056.js +32 -0
  88. package/dist/lint/post-synth/gha057.js +35 -0
  89. package/dist/lint/post-synth/gha058.js +42 -0
  90. package/dist/lint/post-synth/gha059.js +119 -0
  91. package/dist/lint/post-synth/gha060.js +129 -0
  92. package/dist/lint/post-synth/gha061.js +78 -0
  93. package/dist/lint/post-synth/gha062.js +65 -0
  94. package/dist/lint/post-synth/gha063.js +56 -0
  95. package/dist/lint/post-synth/gha064.js +47 -0
  96. package/dist/lint/post-synth/gha065.js +125 -0
  97. package/dist/lint/post-synth/gha066.js +40 -0
  98. package/dist/lint/post-synth/gha067.js +75 -0
  99. package/dist/lint/post-synth/gha068.js +47 -0
  100. package/dist/lint/post-synth/gha069.js +99 -0
  101. package/dist/lint/post-synth/index.js +114 -0
  102. package/dist/lint/post-synth/yaml-helpers.js +465 -0
  103. package/dist/lint/rules/data/action-usage-policy.js +16 -0
  104. package/dist/lint/rules/data/advisory-feed.js +15 -0
  105. package/dist/lint/rules/data/deprecated-versions.js +14 -0
  106. package/dist/lint/rules/data/flagged-actions.js +18 -0
  107. package/dist/lint/rules/data/known-action-slugs.js +38 -0
  108. package/dist/lint/rules/data/known-actions.js +12 -0
  109. package/dist/lint/rules/data/preinstalled-tools.js +36 -0
  110. package/dist/lint/rules/data/recommended-inputs.js +9 -0
  111. package/dist/lint/rules/data/risky-features.js +22 -0
  112. package/dist/lint/rules/data/secret-patterns.js +30 -0
  113. package/dist/lint/rules/data/trusted-action-owners.js +12 -0
  114. package/dist/lint/rules/data/untrusted-contexts.js +44 -0
  115. package/dist/lint/rules/deprecated-action-version.js +44 -0
  116. package/dist/lint/rules/detect-secrets.js +45 -0
  117. package/dist/lint/rules/extract-inline-structs.js +55 -0
  118. package/dist/lint/rules/file-job-limit.js +43 -0
  119. package/dist/lint/rules/index.js +16 -0
  120. package/dist/lint/rules/job-timeout.js +53 -0
  121. package/dist/lint/rules/missing-recommended-inputs.js +51 -0
  122. package/dist/lint/rules/no-hardcoded-secrets.js +39 -0
  123. package/dist/lint/rules/no-raw-expressions.js +44 -0
  124. package/dist/lint/rules/suggest-cache.js +60 -0
  125. package/dist/lint/rules/use-condition-builders.js +37 -0
  126. package/dist/lint/rules/use-matrix-builder.js +36 -0
  127. package/dist/lint/rules/use-typed-actions.js +41 -0
  128. package/dist/lint/rules/validate-concurrency.js +59 -0
  129. package/dist/lsp/completions.d.ts.map +1 -1
  130. package/dist/lsp/completions.js +18 -0
  131. package/dist/lsp/hover.d.ts.map +1 -1
  132. package/dist/lsp/hover.js +33 -0
  133. package/dist/manifest.json +1 -1
  134. package/dist/mcp/context-tools.js +152 -0
  135. package/dist/package-cli.js +20 -0
  136. package/dist/plugin.js +344 -0
  137. package/dist/serializer.js +572 -0
  138. package/dist/spec/fetch.js +46 -0
  139. package/dist/validate-cli.js +16 -0
  140. package/dist/validate.js +38 -0
  141. package/dist/variables.js +41 -0
  142. package/package.json +6 -6
  143. package/src/codegen/package.ts +2 -2
  144. package/src/components/__fixtures__/pr-loop-build.github.golden.yml +6 -2
  145. package/src/components/__fixtures__/pr-loop-waves.github.golden.yml +178 -0
  146. package/src/components/__fixtures__/pr-loop.github.golden.yml +6 -2
  147. package/src/components/generate-pipeline.ts +66 -29
  148. package/src/components/generate-pr-pipeline.test.ts +44 -20
  149. package/src/components/generate-pr-waves-pipeline.test.ts +117 -0
  150. package/src/lsp/completions.ts +2 -1
  151. package/src/lsp/hover.ts +2 -1
@@ -0,0 +1,53 @@
1
+ /**
2
+ * The action versions the github lexicon emits, and the commit each release
3
+ * tag points at.
4
+ *
5
+ * Composites emit `<slug>@<major>` by default. With `pin: "sha"` they emit
6
+ * `<slug>@<sha> # <version>`, the form GHA021 and GHA029 accept and GHA059
7
+ * reads the version label from. The serializer writes the `# <version>` part
8
+ * as a YAML comment, so GitHub sees only the SHA.
9
+ *
10
+ * Refresh a row by resolving the release tag to its commit:
11
+ *
12
+ * gh api repos/actions/checkout/commits/v7.0.1 --jq .sha
13
+ *
14
+ * Keep `major` on a version whose action runs on a Node runtime GitHub still
15
+ * supports.
16
+ */
17
+ export const ACTION_PINS = {
18
+ "actions/checkout": {
19
+ major: "v7",
20
+ version: "v7.0.1",
21
+ sha: "3d3c42e5aac5ba805825da76410c181273ba90b1",
22
+ },
23
+ "actions/setup-node": {
24
+ major: "v7",
25
+ version: "v7.0.0",
26
+ sha: "820762786026740c76f36085b0efc47a31fe5020",
27
+ },
28
+ };
29
+ /** The `uses:` value for a pinned action. */
30
+ export function actionRef(slug, pin = "tag") {
31
+ const entry = ACTION_PINS[slug];
32
+ return pin === "sha" ? `${slug}@${entry.sha} # ${entry.version}` : `${slug}@${entry.major}`;
33
+ }
34
+ /** The pin table entry for an action slug, if the lexicon maintains one. */
35
+ export function actionPin(slug) {
36
+ return Object.prototype.hasOwnProperty.call(ACTION_PINS, slug)
37
+ ? ACTION_PINS[slug]
38
+ : undefined;
39
+ }
40
+ const COMPOSITE_FOR = {
41
+ "actions/checkout": "Checkout",
42
+ "actions/setup-node": "SetupNode",
43
+ };
44
+ /**
45
+ * The exact fix a pinning warning names for an action in the pin table, or
46
+ * an empty string for any other action.
47
+ */
48
+ export function pinFixHint(slug) {
49
+ if (!actionPin(slug))
50
+ return "";
51
+ const pinned = slug;
52
+ return ` Use \`uses: ${actionRef(pinned, "sha")}\`, which ${COMPOSITE_FOR[pinned]}({ pin: "sha" }) emits.`;
53
+ }
@@ -0,0 +1,2 @@
1
+ import { generateDocs } from "./docs.js";
2
+ await generateDocs({ verbose: true });
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Documentation generation for GitHub Actions lexicon.
3
+ */
4
+ import { dirname, join } from "path";
5
+ import { fileURLToPath } from "url";
6
+ import { docsPipeline, writeDocsSite } from "@intentius/chant/codegen/docs";
7
+ function serviceFromType(resourceType) {
8
+ const parts = resourceType.split("::");
9
+ return parts.length >= 2 ? parts[1] : "Actions";
10
+ }
11
+ const overview = `The **GitHub Actions** lexicon provides typed constructors for GitHub Actions
12
+ workflow configuration. It covers workflows, jobs, steps, triggers, strategy,
13
+ permissions, concurrency, and more.
14
+
15
+ Install it with:
16
+
17
+ \`\`\`bash
18
+ npm install --save-dev @intentius/chant-lexicon-github
19
+ \`\`\`
20
+
21
+ ## Quick Start
22
+
23
+ {{file:docs-snippets/src/quickstart.ts}}
24
+
25
+ The lexicon provides **3 resources** (Workflow, Job, Dependabot config), **15 composites** (Checkout, SetupNode, SetupGo, SetupPython, CacheAction, UploadArtifact, DownloadArtifact, NodeCI, NodePipeline, PythonCI, DockerBuild, DeployEnvironment, GoCI, Dependabot, PrPlanReport) + **3 presets** (BunPipeline, PnpmPipeline, YarnPipeline), a typed **Expression** system with 24 GitHub and 5 Runner context variables, and **13 lint rules** + **49 post-synth checks** (including a CI/CD supply-chain security pass, GHA029–062).
26
+ `;
27
+ const outputFormat = `The GitHub Actions lexicon serializes resources into **\`.github/workflows/*.yml\`** YAML files.
28
+ Keys use kebab-case for job properties and snake_case for trigger event names.
29
+
30
+ ## Building
31
+
32
+ Run \`chant build\` to produce workflow YAML from your declarations:
33
+
34
+ \`\`\`bash
35
+ chant build src/ --output .github/workflows/ci.yml
36
+ # Or build all workflow files
37
+ chant build
38
+ \`\`\`
39
+
40
+ The generated file includes:
41
+
42
+ - \`name:\` — workflow display name
43
+ - \`on:\` — trigger events (push, pull_request, schedule, workflow_dispatch, etc.)
44
+ - \`permissions:\` — workflow-level GITHUB_TOKEN permissions
45
+ - \`jobs:\` — job definitions with kebab-case keys
46
+
47
+ ## Key conversions
48
+
49
+ | Chant (TypeScript) | YAML output | Rule |
50
+ |--------------------|-------------|------|
51
+ | \`export const buildApp = new Job({...})\` | \`jobs: build-app:\` | Export name → kebab-case job key |
52
+ | \`"runs-on": "ubuntu-latest"\` | \`runs-on: ubuntu-latest\` | Property names match GitHub spec |
53
+ | \`timeoutMinutes: 15\` | \`timeout-minutes: 15\` | camelCase → kebab-case for job properties |
54
+ | \`new Step({ uses: "actions/checkout@v7" })\` | \`- uses: actions/checkout@v7\` | Steps serialize as sequence entries |
55
+
56
+ ## Comments
57
+
58
+ \`Workflow\`, \`Job\` and \`Step\` take a \`comment\`. It is not a workflow key: the serializer writes it as \`#\` lines, one per line of the string, so the reasons a hand-written workflow keeps as YAML comments stay in the file a reader opens on GitHub. A workflow's comment is the file's header, above \`name:\`; a job's goes above its key and a step's above its \`- \`. The Forgejo lexicon renders the same declarations, so its files carry them too.
59
+
60
+ \`\`\`typescript
61
+ export const publish = new Workflow({
62
+ comment: "Publishes on a version tag.\\nKeep the file name: npm's trusted publisher names it.",
63
+ name: "Publish",
64
+ on: { push: { tags: ["v*"] } },
65
+ jobs: {
66
+ publish: new Job({
67
+ "runs-on": "ubuntu-latest",
68
+ steps: [new Step({ comment: "The registry times out now and then; retry once.", run: "npm publish || npm publish" })],
69
+ }),
70
+ },
71
+ });
72
+ \`\`\`
73
+
74
+ \`\`\`yaml
75
+ # Publishes on a version tag.
76
+ # Keep the file name: npm's trusted publisher names it.
77
+
78
+ name: Publish
79
+
80
+ on:
81
+ push:
82
+ tags:
83
+ - v*
84
+
85
+ jobs:
86
+ publish:
87
+ runs-on: ubuntu-latest
88
+ steps:
89
+ # The registry times out now and then; retry once.
90
+ - run: npm publish || npm publish
91
+ \`\`\`
92
+
93
+ ## Validating locally
94
+
95
+ The output is standard GitHub Actions YAML. Validate locally with \`act\` or push to GitHub:
96
+
97
+ \`\`\`bash
98
+ # Using act for local testing
99
+ act -W .github/workflows/ci.yml
100
+
101
+ # Using GitHub's workflow validation (requires push)
102
+ git add .github/workflows/ci.yml
103
+ git push
104
+ \`\`\`
105
+
106
+ ## Compatibility
107
+
108
+ The output is compatible with:
109
+ - GitHub Actions (any GitHub.com or GitHub Enterprise Server)
110
+ - \`act\` local runner
111
+ - VS Code GitHub Actions extension
112
+ - Any tool that processes \`.github/workflows/*.yml\` files`;
113
+ /**
114
+ * Generate documentation for the GitHub Actions lexicon.
115
+ */
116
+ export async function generateDocs(opts) {
117
+ const pkgDir = dirname(dirname(dirname(fileURLToPath(import.meta.url))));
118
+ const config = {
119
+ name: "github",
120
+ displayName: "GitHub Actions",
121
+ description: "Typed constructors for GitHub Actions workflow configuration",
122
+ distDir: join(pkgDir, "dist"),
123
+ outDir: join(pkgDir, "docs"),
124
+ overview,
125
+ outputFormat,
126
+ serviceFromType,
127
+ suppressPages: ["intrinsics"],
128
+ examplesDir: join(pkgDir, "examples"),
129
+ extraSections: [
130
+ {
131
+ title: "Migrating to GitLab CI/CD?",
132
+ content: `The GitLab lexicon ships a typed-compiler migration tool that translates \`.github/workflows/*.yml\` into \`.gitlab-ci.yml\` (or chant TypeScript) with provenance, 33 curated marketplace-action mappings, and optional composite recognition. See [GitLab → Migration from GitHub Actions](/chant/lexicons/gitlab/migration/) or the [\`chant migrate\` CLI reference](/chant/cli/migrate/).`,
133
+ },
134
+ ],
135
+ basePath: "/chant/lexicons/github/",
136
+ };
137
+ const result = await docsPipeline(config);
138
+ writeDocsSite(config, result);
139
+ if (opts?.verbose) {
140
+ console.error(`Generated docs: ${result.stats.resources} resources, ${result.stats.properties} properties, ${result.stats.services} services, ${result.stats.rules} rules`);
141
+ }
142
+ }
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * CLI entry point for GitHub Actions lexicon generation.
4
+ */
5
+ import { dirname } from "path";
6
+ import { fileURLToPath } from "url";
7
+ import { generate, writeGeneratedFiles } from "./generate.js";
8
+ const pkgDir = dirname(dirname(dirname(fileURLToPath(import.meta.url))));
9
+ async function main() {
10
+ const verbose = process.argv.includes("--verbose") || process.argv.includes("-v");
11
+ const force = process.argv.includes("--force") || process.argv.includes("-f");
12
+ console.error("Generating GitHub Actions lexicon...");
13
+ const result = await generate({ verbose, force });
14
+ writeGeneratedFiles(result, pkgDir);
15
+ console.error(`Generated ${result.resources} entities, ${result.properties} property types, ${result.enums} enums`);
16
+ if (result.warnings.length > 0) {
17
+ console.error(`${result.warnings.length} warnings:`);
18
+ for (const w of result.warnings) {
19
+ console.error(` ${w.file}: ${w.error}`);
20
+ }
21
+ }
22
+ }
23
+ main().catch((err) => {
24
+ console.error("Generation failed:", err);
25
+ process.exit(1);
26
+ });
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Lexicon JSON generator — produces lexicon-github.json with metadata
3
+ * for all GitHub Actions entities.
4
+ */
5
+ import { githubShortName } from "./parse.js";
6
+ import { buildRegistry, serializeRegistry, } from "@intentius/chant/codegen/generate-registry";
7
+ /**
8
+ * Generate the lexicon-github.json content.
9
+ */
10
+ export function generateLexiconJSON(results, naming) {
11
+ const registryResources = results.map((r) => ({
12
+ typeName: r.resource.typeName,
13
+ attributes: r.resource.attributes,
14
+ properties: r.resource.properties,
15
+ propertyTypes: r.propertyTypes.map((pt) => ({ name: pt.name, specType: pt.defType })),
16
+ }));
17
+ const entries = buildRegistry(registryResources, naming, {
18
+ shortName: githubShortName,
19
+ buildEntry: (resource, _tsName, _attrs, propConstraints) => {
20
+ const r = results.find((res) => res.resource.typeName === resource.typeName);
21
+ return {
22
+ resourceType: resource.typeName,
23
+ kind: (r?.isProperty ? "property" : "resource"),
24
+ lexicon: "github",
25
+ ...(r?.resource.deprecatedProperties?.length && { deprecatedProperties: r.resource.deprecatedProperties }),
26
+ ...(propConstraints && Object.keys(propConstraints).length > 0 && { constraints: propConstraints }),
27
+ };
28
+ },
29
+ buildPropertyEntry: (resourceType, propertyType) => ({
30
+ resourceType: `${resourceType}.${propertyType}`,
31
+ kind: "property",
32
+ lexicon: "github",
33
+ }),
34
+ });
35
+ return serializeRegistry(entries);
36
+ }
@@ -0,0 +1,108 @@
1
+ /**
2
+ * TypeScript declaration file generator — produces index.d.ts with all
3
+ * GitHub Actions entity classes.
4
+ */
5
+ import { githubShortName } from "./parse.js";
6
+ import { propertyTypeName, extractDefName } from "./naming.js";
7
+ import { writeResourceClass, writeEnumType, } from "@intentius/chant/codegen/generate-typescript";
8
+ /**
9
+ * Generate the complete .d.ts file content.
10
+ */
11
+ export function generateTypeScriptDeclarations(results, naming) {
12
+ const lines = [];
13
+ lines.push("// Code generated by chant github generate. DO NOT EDIT.");
14
+ const resources = [];
15
+ const enums = [];
16
+ for (const r of results) {
17
+ const typeName = r.resource.typeName;
18
+ const tsName = naming.resolve(typeName);
19
+ if (!tsName)
20
+ continue;
21
+ const shortName = githubShortName(typeName);
22
+ const remap = new Map();
23
+ for (const pt of r.propertyTypes) {
24
+ const defName = extractDefName(pt.name, shortName);
25
+ remap.set(pt.name, propertyTypeName(tsName, defName));
26
+ }
27
+ for (const e of r.enums) {
28
+ const defName = extractDefName(e.name, shortName);
29
+ remap.set(e.name, propertyTypeName(tsName, defName));
30
+ }
31
+ const dtsProps = r.resource.properties.map((p) => ({
32
+ name: p.name,
33
+ type: p.tsType,
34
+ required: p.required,
35
+ description: p.description,
36
+ }));
37
+ const dtsAttrs = r.resource.attributes.map((a) => ({
38
+ name: a.name,
39
+ type: a.tsType,
40
+ }));
41
+ resources.push({ tsName, properties: dtsProps, attributes: dtsAttrs, remap });
42
+ for (const alias of naming.aliases(typeName)) {
43
+ resources.push({ tsName: alias, properties: dtsProps, attributes: dtsAttrs, remap });
44
+ }
45
+ for (const e of r.enums) {
46
+ const defName = extractDefName(e.name, shortName);
47
+ const eName = propertyTypeName(tsName, defName);
48
+ enums.push({ tsName: eName, values: e.values });
49
+ }
50
+ }
51
+ resources.sort((a, b) => a.tsName.localeCompare(b.tsName));
52
+ enums.sort((a, b) => a.tsName.localeCompare(b.tsName));
53
+ lines.push("");
54
+ lines.push("// --- GitHub Actions Entity classes ---");
55
+ for (const re of resources) {
56
+ writeResourceClass(lines, re.tsName, re.properties, re.attributes, re.remap);
57
+ }
58
+ if (enums.length > 0) {
59
+ lines.push("");
60
+ lines.push("// --- Enum types ---");
61
+ for (const ee of enums) {
62
+ writeEnumType(lines, ee.tsName, ee.values);
63
+ }
64
+ }
65
+ lines.push("");
66
+ lines.push(staticTypeScript());
67
+ lines.push("");
68
+ return lines.join("\n");
69
+ }
70
+ function staticTypeScript() {
71
+ const lines = [];
72
+ // Inline Expression interface so dist/types/index.d.ts is self-contained
73
+ lines.push("// --- Expression type (inlined for portability) ---");
74
+ lines.push("");
75
+ lines.push("export declare class Expression {");
76
+ lines.push(" constructor(raw: string);");
77
+ lines.push(" toString(): string;");
78
+ lines.push(" valueOf(): string;");
79
+ lines.push(" eq(value: string | Expression): Expression;");
80
+ lines.push(" ne(value: string | Expression): Expression;");
81
+ lines.push(" and(other: Expression): Expression;");
82
+ lines.push(" or(other: Expression): Expression;");
83
+ lines.push(" not(): Expression;");
84
+ lines.push("}");
85
+ lines.push("");
86
+ lines.push("// --- GitHub Context Variables ---");
87
+ lines.push("");
88
+ lines.push("export declare const GitHub: {");
89
+ const ghVars = [
90
+ "Ref", "RefName", "RefType", "Sha", "Actor", "TriggeringActor",
91
+ "Repository", "RepositoryOwner", "EventName", "Event",
92
+ "RunId", "RunNumber", "RunAttempt", "Workflow", "WorkflowRef",
93
+ "Workspace", "Token", "Job", "HeadRef", "BaseRef",
94
+ "ServerUrl", "ApiUrl", "GraphqlUrl", "Action", "ActionPath",
95
+ ];
96
+ for (const v of ghVars) {
97
+ lines.push(` readonly ${v}: Expression;`);
98
+ }
99
+ lines.push("};");
100
+ lines.push("");
101
+ lines.push("export declare const Runner: {");
102
+ const runnerVars = ["Os", "Arch", "Name", "Temp", "ToolCache"];
103
+ for (const v of runnerVars) {
104
+ lines.push(` readonly ${v}: Expression;`);
105
+ }
106
+ lines.push("};");
107
+ return lines.join("\n");
108
+ }
@@ -0,0 +1,111 @@
1
+ /**
2
+ * GitHub Actions generation pipeline — uses core generatePipeline
3
+ * with GitHub-specific fetch, parse, naming, and generation callbacks.
4
+ */
5
+ import { generatePipeline, writeGeneratedArtifacts, } from "@intentius/chant/codegen/generate";
6
+ import { fetchSchemas } from "../spec/fetch.js";
7
+ import { parseWorkflowSchema } from "./parse.js";
8
+ import { NamingStrategy, propertyTypeName, extractDefName } from "./naming.js";
9
+ import { githubShortName } from "./parse.js";
10
+ import { generateLexiconJSON } from "./generate-lexicon.js";
11
+ import { generateTypeScriptDeclarations } from "./generate-typescript.js";
12
+ import { generateRuntimeIndex as coreGenerateRuntimeIndex, } from "@intentius/chant/codegen/generate-runtime-index";
13
+ /**
14
+ * Run the full GitHub Actions generation pipeline.
15
+ */
16
+ export async function generate(opts = {}) {
17
+ let pendingResults = [];
18
+ const config = {
19
+ fetchSchemas: async (fetchOpts) => {
20
+ return fetchSchemas(fetchOpts.force);
21
+ },
22
+ parseSchema: (_typeName, data) => {
23
+ const results = parseWorkflowSchema(data);
24
+ if (results.length === 0)
25
+ return null;
26
+ pendingResults = results.slice(1);
27
+ return results[0];
28
+ },
29
+ createNaming: (results) => new NamingStrategy(results),
30
+ augmentResults: (results, _opts, log) => {
31
+ if (pendingResults.length > 0) {
32
+ results.push(...pendingResults);
33
+ log(`Added ${pendingResults.length} additional entities from single schema`);
34
+ pendingResults = [];
35
+ }
36
+ log(`Total: ${results.length} GitHub Actions entity schemas`);
37
+ return { results };
38
+ },
39
+ generateRegistry: (results, naming) => {
40
+ return generateLexiconJSON(results, naming);
41
+ },
42
+ generateTypes: (results, naming) => {
43
+ return generateTypeScriptDeclarations(results, naming);
44
+ },
45
+ generateRuntimeIndex: (results, naming) => {
46
+ return generateRuntimeIndex(results, naming);
47
+ },
48
+ };
49
+ return generatePipeline(config, opts);
50
+ }
51
+ /**
52
+ * Write generated artifacts to disk.
53
+ */
54
+ export function writeGeneratedFiles(result, baseDir) {
55
+ writeGeneratedArtifacts({
56
+ baseDir,
57
+ files: {
58
+ "lexicon-github.json": result.lexiconJSON,
59
+ "index.d.ts": result.typesDTS,
60
+ "index.ts": result.indexTS,
61
+ "runtime.ts": `/**\n * Runtime factory constructors — re-exported from core.\n */\nexport { createResource, createProperty } from "@intentius/chant/runtime";\n`,
62
+ },
63
+ });
64
+ }
65
+ /**
66
+ * Generate the runtime index.ts with factory constructor exports.
67
+ */
68
+ function generateRuntimeIndex(results, naming) {
69
+ const resourceEntries = [];
70
+ const propertyEntries = [];
71
+ for (const r of results) {
72
+ const typeName = r.resource.typeName;
73
+ const tsName = naming.resolve(typeName);
74
+ if (!tsName)
75
+ continue;
76
+ const attrs = {};
77
+ if (r.isProperty) {
78
+ propertyEntries.push({ tsName, resourceType: typeName });
79
+ for (const alias of naming.aliases(typeName)) {
80
+ propertyEntries.push({ tsName: alias, resourceType: typeName });
81
+ }
82
+ }
83
+ else {
84
+ resourceEntries.push({ tsName, resourceType: typeName, attrs });
85
+ for (const alias of naming.aliases(typeName)) {
86
+ resourceEntries.push({ tsName: alias, resourceType: typeName, attrs });
87
+ }
88
+ }
89
+ const shortName = githubShortName(typeName);
90
+ const ptAliases = naming.propertyTypeAliases(typeName);
91
+ for (const pt of r.propertyTypes) {
92
+ const defName = extractDefName(pt.name, shortName);
93
+ const ptName = propertyTypeName(tsName, defName);
94
+ const ptType = `${typeName}.${pt.defType}`;
95
+ propertyEntries.push({ tsName: ptName, resourceType: ptType });
96
+ if (ptAliases) {
97
+ const aliasName = ptAliases.get(defName);
98
+ if (aliasName) {
99
+ propertyEntries.push({ tsName: aliasName, resourceType: ptType });
100
+ }
101
+ }
102
+ }
103
+ }
104
+ return coreGenerateRuntimeIndex(resourceEntries, propertyEntries, {
105
+ lexiconName: "github",
106
+ pseudoReExports: {
107
+ names: ["GitHub", "Runner"],
108
+ from: "../variables",
109
+ },
110
+ });
111
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * GitHub Actions naming strategy — flat namespace with few collisions.
3
+ */
4
+ import { NamingStrategy as CoreNamingStrategy, } from "@intentius/chant/codegen/naming";
5
+ import { githubShortName, githubServiceName } from "./parse.js";
6
+ export { propertyTypeName, extractDefName } from "@intentius/chant/codegen/naming";
7
+ const githubNamingConfig = {
8
+ priorityNames: {
9
+ "GitHub::Actions::Workflow": "Workflow",
10
+ "GitHub::Actions::Job": "Job",
11
+ "GitHub::Actions::ReusableWorkflowCallJob": "ReusableWorkflowCallJob",
12
+ "GitHub::Actions::Step": "Step",
13
+ "GitHub::Actions::Strategy": "Strategy",
14
+ "GitHub::Actions::Permissions": "Permissions",
15
+ "GitHub::Actions::Concurrency": "Concurrency",
16
+ "GitHub::Actions::Container": "Container",
17
+ "GitHub::Actions::Service": "Service",
18
+ "GitHub::Actions::Environment": "Environment",
19
+ "GitHub::Actions::Defaults": "Defaults",
20
+ "GitHub::Actions::PushTrigger": "PushTrigger",
21
+ "GitHub::Actions::PullRequestTrigger": "PullRequestTrigger",
22
+ "GitHub::Actions::PullRequestTargetTrigger": "PullRequestTargetTrigger",
23
+ "GitHub::Actions::ScheduleTrigger": "ScheduleTrigger",
24
+ "GitHub::Actions::WorkflowDispatchTrigger": "WorkflowDispatchTrigger",
25
+ "GitHub::Actions::WorkflowCallTrigger": "WorkflowCallTrigger",
26
+ "GitHub::Actions::WorkflowRunTrigger": "WorkflowRunTrigger",
27
+ "GitHub::Actions::RepositoryDispatchTrigger": "RepositoryDispatchTrigger",
28
+ "GitHub::Actions::WorkflowInput": "WorkflowInput",
29
+ "GitHub::Actions::WorkflowOutput": "WorkflowOutput",
30
+ "GitHub::Actions::WorkflowSecret": "WorkflowSecret",
31
+ },
32
+ priorityAliases: {},
33
+ priorityPropertyAliases: {},
34
+ serviceAbbreviations: {},
35
+ shortName: githubShortName,
36
+ serviceName: githubServiceName,
37
+ };
38
+ /**
39
+ * GitHub Actions naming strategy.
40
+ */
41
+ export class NamingStrategy extends CoreNamingStrategy {
42
+ constructor(results) {
43
+ const inputs = results.map((r) => ({
44
+ typeName: r.resource.typeName,
45
+ propertyTypes: r.propertyTypes,
46
+ }));
47
+ super(inputs, githubNamingConfig);
48
+ }
49
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * GitHub Actions lexicon packaging — delegates to core packagePipeline.
3
+ */
4
+ import { readFileSync } from "fs";
5
+ import { githubPlugin } from "../plugin.js";
6
+ import { join, dirname } from "path";
7
+ import { moduleSourceDir } from "@intentius/chant/module-source";
8
+ import { packagePipeline, collectSkills, } from "@intentius/chant/codegen/package";
9
+ import { generate } from "./generate.js";
10
+ const pkgDir = dirname(moduleSourceDir(import.meta.url));
11
+ /**
12
+ * Package the GitHub Actions lexicon into a distributable BundleSpec.
13
+ */
14
+ export async function packageLexicon(opts = {}) {
15
+ const pkgJson = JSON.parse(readFileSync(join(pkgDir, "..", "package.json"), "utf-8"));
16
+ return packagePipeline({
17
+ generate: (genOpts) => generate({ verbose: genOpts.verbose, force: genOpts.force }),
18
+ buildManifest: (_genResult) => {
19
+ // Derived from the plugin's own registration (chant #1067) — this
20
+ // used to be a hand-maintained array independent of ../plugin.ts,
21
+ // free to drift from the real registration without anything
22
+ // noticing.
23
+ const intrinsics = githubPlugin.intrinsics?.() ?? [];
24
+ return {
25
+ name: "github",
26
+ version: pkgJson.version ?? "0.0.0",
27
+ chantVersion: ">=0.1.0",
28
+ namespace: "GitHub",
29
+ intrinsics,
30
+ pseudoParameters: {},
31
+ };
32
+ },
33
+ srcDir: pkgDir,
34
+ collectSkills: () => {
35
+ const skillDefs = githubPlugin.skills?.() ?? [];
36
+ return collectSkills(skillDefs);
37
+ },
38
+ version: pkgJson.version ?? "0.0.0",
39
+ }, opts);
40
+ }