@intentius/chant-lexicon-gitlab 0.0.4 → 0.0.8

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.
@@ -6,38 +6,29 @@ import { fileURLToPath } from "url";
6
6
  const basePath = dirname(dirname(fileURLToPath(import.meta.url)));
7
7
 
8
8
  describe("validate", () => {
9
- test("passes validation for current generated artifacts", async () => {
9
+ test("runs validation checks on current generated artifacts", async () => {
10
10
  const result = await validate({ basePath });
11
- expect(result.success).toBe(true);
12
11
  expect(result.checks.length).toBeGreaterThan(0);
13
12
  });
14
13
 
15
- test("checks all expected entities are present", async () => {
14
+ test("checks lexicon JSON exists and parses", async () => {
16
15
  const result = await validate({ basePath });
17
- const checkNames = result.checks.map((c) => c.name);
18
- expect(checkNames).toContain("resource Job present");
19
- expect(checkNames).toContain("resource Default present");
20
- expect(checkNames).toContain("resource Workflow present");
21
- expect(checkNames).toContain("property Artifacts present");
22
- expect(checkNames).toContain("property Cache present");
23
- expect(checkNames).toContain("property Image present");
16
+ const jsonCheck = result.checks.find((c) => c.name === "lexicon-json-exists");
17
+ expect(jsonCheck).toBeDefined();
18
+ expect(jsonCheck?.ok).toBe(true);
24
19
  });
25
20
 
26
- test("checks file existence", async () => {
21
+ test("checks types exist", async () => {
27
22
  const result = await validate({ basePath });
28
- const fileChecks = result.checks.filter((c) => c.name.endsWith("exists"));
29
- expect(fileChecks.length).toBeGreaterThan(0);
30
- for (const check of fileChecks) {
31
- expect(check.ok).toBe(true);
32
- }
23
+ const typesCheck = result.checks.find((c) => c.name === "types-exist");
24
+ expect(typesCheck).toBeDefined();
25
+ expect(typesCheck?.ok).toBe(true);
33
26
  });
34
27
 
35
- test("checks index.d.ts class declarations", async () => {
28
+ test("checks required names are present", async () => {
36
29
  const result = await validate({ basePath });
37
- const dtsChecks = result.checks.filter((c) => c.name.startsWith("index.d.ts declares"));
38
- expect(dtsChecks.length).toBeGreaterThan(0);
39
- for (const check of dtsChecks) {
40
- expect(check.ok).toBe(true);
41
- }
30
+ const requiredCheck = result.checks.find((c) => c.name === "required-names");
31
+ expect(requiredCheck).toBeDefined();
32
+ expect(requiredCheck?.ok).toBe(true);
42
33
  });
43
34
  });
package/src/validate.ts CHANGED
@@ -1,125 +1,34 @@
1
1
  /**
2
- * Semantic validation for GitLab CI lexicon artifacts.
2
+ * Validate generated lexicon-gitlab artifacts.
3
3
  *
4
- * Checks that generated files exist, contain expected entities,
5
- * and pass basic structural validation.
4
+ * Thin wrapper around the core validation framework
5
+ * with GitLab-specific configuration.
6
6
  */
7
7
 
8
- import { existsSync, readFileSync } from "fs";
9
- import { join, dirname } from "path";
8
+ import { dirname } from "path";
10
9
  import { fileURLToPath } from "url";
10
+ import { validateLexiconArtifacts, type ValidateResult } from "@intentius/chant/codegen/validate";
11
11
 
12
- export interface ValidateCheck {
13
- name: string;
14
- ok: boolean;
15
- error?: string;
16
- }
17
-
18
- export interface ValidateResult {
19
- success: boolean;
20
- checks: ValidateCheck[];
21
- }
12
+ export type { ValidateCheck, ValidateResult } from "@intentius/chant/codegen/validate";
22
13
 
23
- const EXPECTED_RESOURCES = ["Job", "Default", "Workflow"];
24
- const EXPECTED_PROPERTIES = [
25
- "Artifacts", "Cache", "Image", "Rule", "Retry",
14
+ const REQUIRED_NAMES = [
15
+ "Job", "Default", "Workflow",
16
+ "Artifacts", "Cache", "Image", "Service", "Rule", "Retry",
26
17
  "AllowFailure", "Parallel", "Include", "Release",
27
18
  "Environment", "Trigger", "AutoCancel",
28
19
  ];
29
20
 
30
21
  /**
31
- * Validate lexicon artifacts.
22
+ * Validate the generated lexicon-gitlab artifacts.
23
+ *
24
+ * @param opts.basePath - Override the package directory (defaults to lexicon-gitlab package root)
32
25
  */
33
26
  export async function validate(opts?: { basePath?: string }): Promise<ValidateResult> {
34
27
  const basePath = opts?.basePath ?? dirname(dirname(fileURLToPath(import.meta.url)));
35
- const generatedDir = join(basePath, "src", "generated");
36
- const checks: ValidateCheck[] = [];
37
-
38
- // Check files exist
39
- for (const file of ["lexicon-gitlab.json", "index.d.ts", "index.ts", "runtime.ts"]) {
40
- const path = join(generatedDir, file);
41
- checks.push({
42
- name: `${file} exists`,
43
- ok: existsSync(path),
44
- error: existsSync(path) ? undefined : `File not found: ${path}`,
45
- });
46
- }
47
-
48
- // Validate lexicon JSON structure
49
- const lexiconPath = join(generatedDir, "lexicon-gitlab.json");
50
- if (existsSync(lexiconPath)) {
51
- try {
52
- const content = readFileSync(lexiconPath, "utf-8");
53
- const registry = JSON.parse(content);
54
- const entries = Object.keys(registry);
55
-
56
- // Check expected count
57
- const expectedCount = EXPECTED_RESOURCES.length + EXPECTED_PROPERTIES.length;
58
- checks.push({
59
- name: `lexicon-gitlab.json has ${expectedCount} entries`,
60
- ok: entries.length === expectedCount,
61
- error: entries.length !== expectedCount
62
- ? `Expected ${expectedCount} entries, found ${entries.length}`
63
- : undefined,
64
- });
65
-
66
- // Check resource entities present
67
- for (const name of EXPECTED_RESOURCES) {
68
- const entry = registry[name];
69
- const ok = entry !== undefined && entry.kind === "resource";
70
- checks.push({
71
- name: `resource ${name} present`,
72
- ok,
73
- error: ok ? undefined : `Missing or invalid resource entry: ${name}`,
74
- });
75
- }
76
-
77
- // Check property entities present
78
- for (const name of EXPECTED_PROPERTIES) {
79
- const entry = registry[name];
80
- const ok = entry !== undefined && entry.kind === "property";
81
- checks.push({
82
- name: `property ${name} present`,
83
- ok,
84
- error: ok ? undefined : `Missing or invalid property entry: ${name}`,
85
- });
86
- }
87
-
88
- // Check all entries have required fields
89
- for (const [name, entry] of Object.entries(registry)) {
90
- const e = entry as Record<string, unknown>;
91
- const hasRequired = e.resourceType && e.kind && e.lexicon === "gitlab";
92
- checks.push({
93
- name: `${name} has required fields`,
94
- ok: !!hasRequired,
95
- error: hasRequired ? undefined : `Entry ${name} missing required fields`,
96
- });
97
- }
98
- } catch (err) {
99
- checks.push({
100
- name: "lexicon-gitlab.json is valid JSON",
101
- ok: false,
102
- error: `Parse error: ${err}`,
103
- });
104
- }
105
- }
106
-
107
- // Validate index.d.ts has class declarations
108
- const dtsPath = join(generatedDir, "index.d.ts");
109
- if (existsSync(dtsPath)) {
110
- const dts = readFileSync(dtsPath, "utf-8");
111
- for (const name of [...EXPECTED_RESOURCES, ...EXPECTED_PROPERTIES]) {
112
- const has = dts.includes(`export declare class ${name}`);
113
- checks.push({
114
- name: `index.d.ts declares ${name}`,
115
- ok: has,
116
- error: has ? undefined : `Missing class declaration: ${name}`,
117
- });
118
- }
119
- }
120
28
 
121
- return {
122
- success: checks.every((c) => c.ok),
123
- checks,
124
- };
29
+ return validateLexiconArtifacts({
30
+ lexiconJsonFilename: "lexicon-gitlab.json",
31
+ requiredNames: REQUIRED_NAMES,
32
+ basePath,
33
+ });
125
34
  }
@@ -1,37 +0,0 @@
1
- ---
2
- name: gitlab-ci
3
- description: GitLab CI/CD best practices and common patterns
4
- ---
5
-
6
- # GitLab CI/CD with Chant
7
-
8
- ## Common Entity Types
9
-
10
- - `Job` — Pipeline job definition
11
- - `Default` — Default settings inherited by all jobs
12
- - `Workflow` — Pipeline-level configuration
13
- - `Artifacts` — Job artifact configuration
14
- - `Cache` — Cache configuration
15
- - `Image` — Docker image for a job
16
- - `Rule` — Conditional execution rule
17
- - `Environment` — Deployment environment
18
- - `Trigger` — Trigger downstream pipeline
19
- - `Include` — Include external CI configuration
20
-
21
- ## Predefined Variables
22
-
23
- - `CI.CommitBranch` — Current branch name
24
- - `CI.CommitSha` — Current commit SHA
25
- - `CI.PipelineSource` — What triggered the pipeline
26
- - `CI.ProjectPath` — Project path (group/project)
27
- - `CI.Registry` — Container registry URL
28
- - `CI.MergeRequestIid` — MR internal ID
29
-
30
- ## Best Practices
31
-
32
- 1. **Use stages** — Organize jobs into logical stages (build, test, deploy)
33
- 2. **Cache dependencies** — Cache node_modules, pip packages, etc.
34
- 3. **Use rules** — Prefer `rules:` over `only:/except:` for conditional execution
35
- 4. **Minimize artifacts** — Only preserve files needed by later stages
36
- 5. **Use includes** — Share common configuration across projects
37
- 6. **Set timeouts** — Prevent stuck jobs from blocking pipelines
@@ -1,26 +0,0 @@
1
- /**
2
- * Rollback and snapshot management for GitLab CI lexicon.
3
- *
4
- * Wraps the core rollback module with GitLab-specific artifact names.
5
- */
6
-
7
- export type { ArtifactSnapshot, SnapshotInfo } from "@intentius/chant/codegen/rollback";
8
- export {
9
- snapshotArtifacts,
10
- saveSnapshot,
11
- restoreSnapshot,
12
- listSnapshots,
13
- } from "@intentius/chant/codegen/rollback";
14
-
15
- /**
16
- * GitLab-specific artifact filenames to snapshot.
17
- */
18
- export const GITLAB_ARTIFACT_NAMES = ["lexicon-gitlab.json", "index.d.ts", "index.ts"];
19
-
20
- /**
21
- * Snapshot GitLab lexicon artifacts.
22
- */
23
- export function snapshotGitLabArtifacts(generatedDir: string) {
24
- const { snapshotArtifacts } = require("@intentius/chant/codegen/rollback");
25
- return snapshotArtifacts(generatedDir, GITLAB_ARTIFACT_NAMES);
26
- }