@intentius/chant-lexicon-github 0.0.22 → 0.1.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.
@@ -1,13 +1,18 @@
1
- import { Composite } from "@intentius/chant";
1
+ import { Composite, mergeDefaults } from "@intentius/chant";
2
+ import type { Step } from "../generated/index";
2
3
 
3
4
  export interface SetupNodeProps {
4
5
  nodeVersion?: string;
5
6
  registryUrl?: string;
6
7
  cache?: string;
7
8
  cacheFilePath?: string;
9
+ defaults?: {
10
+ step?: Partial<ConstructorParameters<typeof Step>[0]>;
11
+ };
8
12
  }
9
13
 
10
14
  export const SetupNode = Composite<SetupNodeProps>((props) => {
15
+ const { defaults } = props;
11
16
  const withObj: Record<string, string> = {};
12
17
  if (props.nodeVersion !== undefined) withObj["node-version"] = props.nodeVersion;
13
18
  if (props.registryUrl !== undefined) withObj["registry-url"] = props.registryUrl;
@@ -16,11 +21,11 @@ export const SetupNode = Composite<SetupNodeProps>((props) => {
16
21
 
17
22
  const { createProperty } = require("@intentius/chant/runtime");
18
23
  const StepClass = createProperty("GitHub::Actions::Step", "github");
19
- const step = new StepClass({
24
+ const step = new StepClass(mergeDefaults({
20
25
  name: "Setup Node.js",
21
26
  uses: "actions/setup-node@v4",
22
27
  ...(Object.keys(withObj).length > 0 ? { with: withObj } : {}),
23
- });
28
+ }, defaults?.step));
24
29
 
25
30
  return { step };
26
31
  }, "SetupNode");
@@ -1,12 +1,17 @@
1
- import { Composite } from "@intentius/chant";
1
+ import { Composite, mergeDefaults } from "@intentius/chant";
2
+ import type { Step } from "../generated/index";
2
3
 
3
4
  export interface SetupPythonProps {
4
5
  pythonVersion?: string;
5
6
  cache?: string;
6
7
  architecture?: string;
8
+ defaults?: {
9
+ step?: Partial<ConstructorParameters<typeof Step>[0]>;
10
+ };
7
11
  }
8
12
 
9
13
  export const SetupPython = Composite<SetupPythonProps>((props) => {
14
+ const { defaults } = props;
10
15
  const withObj: Record<string, string> = {};
11
16
  if (props.pythonVersion !== undefined) withObj["python-version"] = props.pythonVersion;
12
17
  if (props.cache !== undefined) withObj.cache = props.cache;
@@ -14,11 +19,11 @@ export const SetupPython = Composite<SetupPythonProps>((props) => {
14
19
 
15
20
  const { createProperty } = require("@intentius/chant/runtime");
16
21
  const StepClass = createProperty("GitHub::Actions::Step", "github");
17
- const step = new StepClass({
22
+ const step = new StepClass(mergeDefaults({
18
23
  name: "Setup Python",
19
24
  uses: "actions/setup-python@v5",
20
25
  ...(Object.keys(withObj).length > 0 ? { with: withObj } : {}),
21
- });
26
+ }, defaults?.step));
22
27
 
23
28
  return { step };
24
29
  }, "SetupPython");
@@ -1,13 +1,18 @@
1
- import { Composite } from "@intentius/chant";
1
+ import { Composite, mergeDefaults } from "@intentius/chant";
2
+ import type { Step } from "../generated/index";
2
3
 
3
4
  export interface UploadArtifactProps {
4
5
  name: string;
5
6
  path: string;
6
7
  retentionDays?: number;
7
8
  compressionLevel?: number;
9
+ defaults?: {
10
+ step?: Partial<ConstructorParameters<typeof Step>[0]>;
11
+ };
8
12
  }
9
13
 
10
14
  export const UploadArtifact = Composite<UploadArtifactProps>((props) => {
15
+ const { defaults } = props;
11
16
  const withObj: Record<string, string> = {
12
17
  name: props.name,
13
18
  path: props.path,
@@ -17,11 +22,11 @@ export const UploadArtifact = Composite<UploadArtifactProps>((props) => {
17
22
 
18
23
  const { createProperty } = require("@intentius/chant/runtime");
19
24
  const StepClass = createProperty("GitHub::Actions::Step", "github");
20
- const step = new StepClass({
25
+ const step = new StepClass(mergeDefaults({
21
26
  name: "Upload Artifact",
22
27
  uses: "actions/upload-artifact@v4",
23
28
  with: withObj,
24
- });
29
+ }, defaults?.step));
25
30
 
26
31
  return { step };
27
32
  }, "UploadArtifact");
package/src/plugin.ts CHANGED
@@ -6,10 +6,13 @@
6
6
  */
7
7
 
8
8
  import { createRequire } from "module";
9
- import type { LexiconPlugin, IntrinsicDef, SkillDefinition, InitTemplateSet } from "@intentius/chant/lexicon";
9
+ import type { LexiconPlugin, IntrinsicDef, InitTemplateSet } from "@intentius/chant/lexicon";
10
10
  const require = createRequire(import.meta.url);
11
11
  import type { LintRule } from "@intentius/chant/lint/rule";
12
- import type { PostSynthCheck } from "@intentius/chant/lint/post-synth";
12
+ import { discoverPostSynthChecks } from "@intentius/chant/lint/discover";
13
+ import { createSkillsLoader, createDiffTool, createCatalogResource } from "@intentius/chant/lexicon-plugin-helpers";
14
+ import { join, dirname } from "path";
15
+ import { fileURLToPath } from "url";
13
16
  import { githubSerializer } from "./serializer";
14
17
 
15
18
  export const githubPlugin: LexiconPlugin = {
@@ -47,23 +50,9 @@ export const githubPlugin: LexiconPlugin = {
47
50
  ];
48
51
  },
49
52
 
50
- postSynthChecks(): PostSynthCheck[] {
51
- const { gha006 } = require("./lint/post-synth/gha006");
52
- const { gha009 } = require("./lint/post-synth/gha009");
53
- const { gha011 } = require("./lint/post-synth/gha011");
54
- const { gha017 } = require("./lint/post-synth/gha017");
55
- const { gha018 } = require("./lint/post-synth/gha018");
56
- const { gha019 } = require("./lint/post-synth/gha019");
57
- const { gha020 } = require("./lint/post-synth/gha020");
58
- const { gha021 } = require("./lint/post-synth/gha021");
59
- const { gha022 } = require("./lint/post-synth/gha022");
60
- const { gha023 } = require("./lint/post-synth/gha023");
61
- const { gha024 } = require("./lint/post-synth/gha024");
62
- const { gha025 } = require("./lint/post-synth/gha025");
63
- const { gha026 } = require("./lint/post-synth/gha026");
64
- const { gha027 } = require("./lint/post-synth/gha027");
65
- const { gha028 } = require("./lint/post-synth/gha028");
66
- return [gha006, gha009, gha011, gha017, gha018, gha019, gha020, gha021, gha022, gha023, gha024, gha025, gha026, gha027, gha028];
53
+ postSynthChecks() {
54
+ const postSynthDir = join(dirname(fileURLToPath(import.meta.url)), "lint", "post-synth");
55
+ return discoverPostSynthChecks(postSynthDir, import.meta.url);
67
56
  },
68
57
 
69
58
  intrinsics(): IntrinsicDef[] {
@@ -237,48 +226,12 @@ export const build = new Job({
237
226
  },
238
227
 
239
228
  mcpTools() {
240
- return [
241
- {
242
- name: "diff",
243
- description: "Compare current build output against previous output for GitHub Actions",
244
- inputSchema: {
245
- type: "object" as const,
246
- properties: {
247
- path: {
248
- type: "string",
249
- description: "Path to the infrastructure project directory",
250
- },
251
- },
252
- },
253
- async handler(params: Record<string, unknown>): Promise<unknown> {
254
- const { diffCommand } = await import("@intentius/chant/cli/commands/diff");
255
- const result = await diffCommand({
256
- path: (params.path as string) ?? ".",
257
- serializers: [githubSerializer],
258
- });
259
- return result;
260
- },
261
- },
262
- ];
229
+ return [createDiffTool(githubSerializer, "Compare current build output against previous output for GitHub Actions")];
263
230
  },
264
231
 
265
232
  mcpResources() {
266
233
  return [
267
- {
268
- uri: "resource-catalog",
269
- name: "GitHub Actions Entity Catalog",
270
- description: "JSON list of all supported GitHub Actions entity types",
271
- mimeType: "application/json",
272
- async handler(): Promise<string> {
273
- const lexicon = require("./generated/lexicon-github.json") as Record<string, { resourceType: string; kind: string }>;
274
- const entries = Object.entries(lexicon).map(([className, entry]) => ({
275
- className,
276
- resourceType: entry.resourceType,
277
- kind: entry.kind,
278
- }));
279
- return JSON.stringify(entries);
280
- },
281
- },
234
+ createCatalogResource(import.meta.url, "GitHub Actions Entity Catalog", "JSON list of all supported GitHub Actions entity types", "lexicon-github.json"),
282
235
  {
283
236
  uri: "examples/basic-ci",
284
237
  name: "Basic CI Example",
@@ -317,120 +270,64 @@ export const build = new Job({
317
270
  await generateDocs(options);
318
271
  },
319
272
 
320
- skills(): SkillDefinition[] {
321
- const skills: SkillDefinition[] = [
322
- {
323
- name: "chant-github",
324
- description: "GitHub Actions workflow lifecycle — build, validate, deploy",
325
- content: `---
326
- skill: chant-github
327
- description: Build, validate, and deploy GitHub Actions workflows from a chant project
328
- user-invocable: true
329
- ---
330
-
331
- # GitHub Actions Operational Playbook
332
-
333
- ## How chant and GitHub Actions relate
334
-
335
- chant is a **synthesis compiler** it compiles TypeScript source files into \`.github/workflows/*.yml\` (YAML). \`chant build\` does not call GitHub APIs; synthesis is pure and deterministic.
336
-
337
- - Use **chant** for: build, lint, diff (local YAML comparison)
338
- - Use **git + GitHub** for: push, pull requests, workflow monitoring
339
-
340
- ## Build and validate
341
-
342
- \`\`\`bash
343
- chant build src/ --output .github/workflows/ci.yml
344
- chant lint src/
345
- \`\`\`
346
-
347
- ## Deploy
348
-
349
- \`\`\`bash
350
- git add .github/workflows/ci.yml
351
- git commit -m "Update workflow"
352
- git push
353
- \`\`\`
354
- `,
355
- triggers: [
356
- { type: "file-pattern", value: "**/*.github.ts" },
357
- { type: "file-pattern", value: "**/.github/workflows/*.yml" },
358
- { type: "context", value: "github actions" },
359
- { type: "context", value: "workflow" },
360
- ],
361
- parameters: [],
362
- examples: [
363
- {
364
- title: "Basic CI workflow",
365
- description: "Create a CI workflow with build and test",
366
- input: "Create a CI workflow",
367
- output: `new Workflow({ name: "CI", on: { push: { branches: ["main"] }, pull_request: { branches: ["main"] } } })`,
368
- },
369
- ],
370
- },
371
- ];
372
-
373
- // Load file-based skills
374
- const { readFileSync } = require("fs");
375
- const { join, dirname } = require("path");
376
- const { fileURLToPath } = require("url");
377
- const dir = dirname(fileURLToPath(import.meta.url));
378
-
379
- const skillFiles = [
380
- {
381
- file: "github-actions-patterns.md",
382
- name: "github-actions-patterns",
383
- description: "GitHub Actions workflow patterns — triggers, jobs, matrix, caching, artifacts",
384
- triggers: [
385
- { type: "context" as const, value: "github actions" },
386
- { type: "context" as const, value: "workflow" },
387
- { type: "context" as const, value: "matrix" },
388
- { type: "context" as const, value: "cache" },
389
- ],
390
- parameters: [],
391
- examples: [
392
- {
393
- title: "Matrix strategy",
394
- input: "Set up a Node.js matrix build",
395
- output: `new Strategy({ matrix: { "node-version": ["18", "20", "22"] } })`,
396
- },
397
- ],
398
- },
399
- {
400
- file: "github-actions-security.md",
401
- name: "github-actions-security",
402
- description: "GitHub Actions security — secret scanning, OIDC, permissions hardening, supply chain",
403
- triggers: [
404
- { type: "context" as const, value: "github security" },
405
- { type: "context" as const, value: "workflow security" },
406
- { type: "context" as const, value: "oidc" },
407
- { type: "context" as const, value: "permissions" },
408
- ],
409
- parameters: [],
410
- examples: [
411
- {
412
- title: "Permissions hardening",
413
- input: "Lock down workflow permissions",
414
- output: `new Workflow({ permissions: { contents: "read" } })`,
415
- },
416
- ],
417
- },
418
- ];
419
-
420
- for (const skill of skillFiles) {
421
- try {
422
- const content = readFileSync(join(dir, "skills", skill.file), "utf-8");
423
- skills.push({
424
- name: skill.name,
425
- description: skill.description,
426
- content,
427
- triggers: skill.triggers,
428
- parameters: skill.parameters,
429
- examples: skill.examples,
430
- });
431
- } catch { /* skip missing skills */ }
432
- }
433
-
434
- return skills;
435
- },
273
+ skills: createSkillsLoader(import.meta.url, [
274
+ {
275
+ file: "chant-github.md",
276
+ name: "chant-github",
277
+ description: "GitHub Actions workflow lifecycle — build, validate, deploy",
278
+ triggers: [
279
+ { type: "file-pattern", value: "**/*.github.ts" },
280
+ { type: "file-pattern", value: "**/.github/workflows/*.yml" },
281
+ { type: "context", value: "github actions" },
282
+ { type: "context", value: "workflow" },
283
+ ],
284
+ parameters: [],
285
+ examples: [
286
+ {
287
+ title: "Basic CI workflow",
288
+ description: "Create a CI workflow with build and test",
289
+ input: "Create a CI workflow",
290
+ output: `new Workflow({ name: "CI", on: { push: { branches: ["main"] }, pull_request: { branches: ["main"] } } })`,
291
+ },
292
+ ],
293
+ },
294
+ {
295
+ file: "chant-github-patterns.md",
296
+ name: "chant-github-patterns",
297
+ description: "GitHub Actions workflow patterns — triggers, jobs, matrix, caching, artifacts",
298
+ triggers: [
299
+ { type: "context", value: "github actions" },
300
+ { type: "context", value: "workflow" },
301
+ { type: "context", value: "matrix" },
302
+ { type: "context", value: "cache" },
303
+ ],
304
+ parameters: [],
305
+ examples: [
306
+ {
307
+ title: "Matrix strategy",
308
+ input: "Set up a Node.js matrix build",
309
+ output: `new Strategy({ matrix: { "node-version": ["18", "20", "22"] } })`,
310
+ },
311
+ ],
312
+ },
313
+ {
314
+ file: "chant-github-security.md",
315
+ name: "chant-github-security",
316
+ description: "GitHub Actions security — secret scanning, OIDC, permissions hardening, supply chain",
317
+ triggers: [
318
+ { type: "context", value: "github security" },
319
+ { type: "context", value: "workflow security" },
320
+ { type: "context", value: "oidc" },
321
+ { type: "context", value: "permissions" },
322
+ ],
323
+ parameters: [],
324
+ examples: [
325
+ {
326
+ title: "Permissions hardening",
327
+ input: "Lock down workflow permissions",
328
+ output: `new Workflow({ permissions: { contents: "read" } })`,
329
+ },
330
+ ],
331
+ },
332
+ ]),
436
333
  };
@@ -1,6 +1,7 @@
1
1
  ---
2
- skill: github-actions-patterns
2
+ skill: chant-github-patterns
3
3
  description: GitHub Actions workflow patterns — triggers, jobs, matrix, caching, artifacts, permissions, reusable workflows
4
+ user-invocable: true
4
5
  ---
5
6
 
6
7
  # GitHub Actions Patterns
@@ -1,6 +1,7 @@
1
1
  ---
2
- skill: github-actions-security
2
+ skill: chant-github-security
3
3
  description: GitHub Actions security best practices — secret scanning, OIDC, permissions hardening, supply chain security
4
+ user-invocable: true
4
5
  ---
5
6
 
6
7
  # GitHub Actions Security Playbook