gitlab-catalog-browser 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.
- package/LICENSE +201 -0
- package/README.md +75 -0
- package/bin/gitlab-ci-cli.js +29 -0
- package/dist/api/catalog.d.ts +38 -0
- package/dist/api/catalog.d.ts.map +1 -0
- package/dist/api/catalog.js +72 -0
- package/dist/api/catalog.js.map +1 -0
- package/dist/api/gitlab.d.ts +69 -0
- package/dist/api/gitlab.d.ts.map +1 -0
- package/dist/api/gitlab.js +226 -0
- package/dist/api/gitlab.js.map +1 -0
- package/dist/api/lint.d.ts +61 -0
- package/dist/api/lint.d.ts.map +1 -0
- package/dist/api/lint.js +41 -0
- package/dist/api/lint.js.map +1 -0
- package/dist/cache/schema-cache.d.ts +54 -0
- package/dist/cache/schema-cache.d.ts.map +1 -0
- package/dist/cache/schema-cache.js +124 -0
- package/dist/cache/schema-cache.js.map +1 -0
- package/dist/commands/batch.d.ts +19 -0
- package/dist/commands/batch.d.ts.map +1 -0
- package/dist/commands/batch.js +174 -0
- package/dist/commands/batch.js.map +1 -0
- package/dist/commands/catalog.d.ts +42 -0
- package/dist/commands/catalog.d.ts.map +1 -0
- package/dist/commands/catalog.js +158 -0
- package/dist/commands/catalog.js.map +1 -0
- package/dist/commands/component.d.ts +46 -0
- package/dist/commands/component.d.ts.map +1 -0
- package/dist/commands/component.js +213 -0
- package/dist/commands/component.js.map +1 -0
- package/dist/commands/pipeline.d.ts +61 -0
- package/dist/commands/pipeline.d.ts.map +1 -0
- package/dist/commands/pipeline.js +880 -0
- package/dist/commands/pipeline.js.map +1 -0
- package/dist/commands/setup.d.ts +119 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +391 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/skills.d.ts +39 -0
- package/dist/commands/skills.d.ts.map +1 -0
- package/dist/commands/skills.js +208 -0
- package/dist/commands/skills.js.map +1 -0
- package/dist/commands/validate.d.ts +27 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +201 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/config/loader.d.ts +80 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +217 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/types.d.ts +46 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +45 -0
- package/dist/config/types.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +437 -0
- package/dist/index.js.map +1 -0
- package/dist/output/table.d.ts +28 -0
- package/dist/output/table.d.ts.map +1 -0
- package/dist/output/table.js +67 -0
- package/dist/output/table.js.map +1 -0
- package/dist/types/api.d.ts +66 -0
- package/dist/types/api.d.ts.map +1 -0
- package/dist/types/api.js +61 -0
- package/dist/types/api.js.map +1 -0
- package/dist/types/catalog.d.ts +77 -0
- package/dist/types/catalog.d.ts.map +1 -0
- package/dist/types/catalog.js +5 -0
- package/dist/types/catalog.js.map +1 -0
- package/package.json +60 -0
- package/skill-data/core/reference.md +127 -0
- package/skill-data/core/templates.md +97 -0
- package/skill-data/core/workflows.md +84 -0
- package/skill-data/manifest.json +12 -0
- package/skill-data/templates/basic-pipeline.yml +29 -0
- package/skill-data/templates/docker-build.yml +38 -0
- package/skill-data/templates/multi-stage.yml +43 -0
- package/skills/gitlab-catalog-browser/SKILL.md +49 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Batch command execution handler.
|
|
3
|
+
*
|
|
4
|
+
* Implements `batch` command for executing multiple CLI commands
|
|
5
|
+
* in a single invocation, sequentially.
|
|
6
|
+
*/
|
|
7
|
+
import { execSync } from 'node:child_process';
|
|
8
|
+
import { existsSync } from 'node:fs';
|
|
9
|
+
import { resolve, dirname } from 'node:path';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
// ──────────────────────────────────────────────
|
|
12
|
+
// Path resolution
|
|
13
|
+
// ──────────────────────────────────────────────
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
/**
|
|
16
|
+
* Find the CLI binary path. Tries several strategies:
|
|
17
|
+
* 1. GITLAB_CI_CLI_BIN env var (explicit override)
|
|
18
|
+
* 2. resolve __filename relative to current script (for source runs)
|
|
19
|
+
* 3. Check common locations
|
|
20
|
+
*/
|
|
21
|
+
function findCliPath() {
|
|
22
|
+
// 1. Env var override
|
|
23
|
+
const envBin = process.env.GITLAB_CI_CLI_BIN;
|
|
24
|
+
if (envBin && existsSync(envBin))
|
|
25
|
+
return resolve(envBin);
|
|
26
|
+
// 2. Try the bin/gitlab-ci-cli.js relative to this file
|
|
27
|
+
const binPath = resolve(dirname(__filename), '..', '..', 'bin', 'gitlab-ci-cli.js');
|
|
28
|
+
if (existsSync(binPath))
|
|
29
|
+
return binPath;
|
|
30
|
+
// 3. Try process.argv[1] (the script that started this process)
|
|
31
|
+
if (process.argv[1] && existsSync(process.argv[1]))
|
|
32
|
+
return resolve(process.argv[1]);
|
|
33
|
+
// 4. Fallback: use the same node executable with a known relative path
|
|
34
|
+
return 'gitlab-ci-cli';
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Read JSON commands from stdin.
|
|
38
|
+
*/
|
|
39
|
+
async function readStdinCommands() {
|
|
40
|
+
const chunks = [];
|
|
41
|
+
for await (const chunk of process.stdin) {
|
|
42
|
+
chunks.push(Buffer.from(chunk));
|
|
43
|
+
}
|
|
44
|
+
const content = Buffer.concat(chunks).toString('utf-8');
|
|
45
|
+
const parsed = JSON.parse(content);
|
|
46
|
+
if (!Array.isArray(parsed)) {
|
|
47
|
+
throw new Error('Stdin JSON must be an array of command strings');
|
|
48
|
+
}
|
|
49
|
+
return parsed.map((c) => String(c));
|
|
50
|
+
}
|
|
51
|
+
// ──────────────────────────────────────────────
|
|
52
|
+
// Handlers
|
|
53
|
+
// ──────────────────────────────────────────────
|
|
54
|
+
/**
|
|
55
|
+
* Handle `batch <commands...> [--bail]` or `batch --json` (stdin).
|
|
56
|
+
*/
|
|
57
|
+
export async function handleBatch(commands, _config, options = {}) {
|
|
58
|
+
try {
|
|
59
|
+
// ── Collect commands ─────────────────────
|
|
60
|
+
let cmdList;
|
|
61
|
+
if (options.json) {
|
|
62
|
+
// Read from stdin
|
|
63
|
+
cmdList = await readStdinCommands();
|
|
64
|
+
}
|
|
65
|
+
else if (commands && commands.length > 0) {
|
|
66
|
+
cmdList = commands;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
return {
|
|
70
|
+
exitCode: 1,
|
|
71
|
+
output: options.json
|
|
72
|
+
? JSON.stringify({ success: false, error: 'No commands provided. Pipe JSON to --json or pass commands as arguments.' })
|
|
73
|
+
: 'No commands provided. Pipe JSON to --json or pass commands as arguments.',
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (cmdList.length === 0) {
|
|
77
|
+
return {
|
|
78
|
+
exitCode: 0,
|
|
79
|
+
output: options.json ? JSON.stringify({ results: [], summary: { total: 0, succeeded: 0, failed: 0 } }) : 'No commands to execute.',
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
// ── Execute commands ─────────────────────
|
|
83
|
+
const cliPath = findCliPath();
|
|
84
|
+
const results = [];
|
|
85
|
+
let hasFailure = false;
|
|
86
|
+
for (let i = 0; i < cmdList.length; i++) {
|
|
87
|
+
const cmd = cmdList[i];
|
|
88
|
+
try {
|
|
89
|
+
const fullCmd = `${process.execPath} ${cliPath} ${cmd}`;
|
|
90
|
+
const stdout = execSync(fullCmd, {
|
|
91
|
+
encoding: 'utf-8',
|
|
92
|
+
timeout: 60000,
|
|
93
|
+
maxBuffer: 10 * 1024 * 1024, // 10MB
|
|
94
|
+
});
|
|
95
|
+
results.push({
|
|
96
|
+
command: cmd,
|
|
97
|
+
index: i,
|
|
98
|
+
exitCode: 0,
|
|
99
|
+
stdout: stdout.trimEnd(),
|
|
100
|
+
stderr: '',
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
const execErr = err;
|
|
105
|
+
const exitCode = execErr.status ?? 1;
|
|
106
|
+
const stderr = execErr.stderr?.trimEnd() ?? execErr.message;
|
|
107
|
+
results.push({
|
|
108
|
+
command: cmd,
|
|
109
|
+
index: i,
|
|
110
|
+
exitCode,
|
|
111
|
+
stdout: execErr.stdout?.trimEnd() ?? '',
|
|
112
|
+
stderr,
|
|
113
|
+
});
|
|
114
|
+
hasFailure = true;
|
|
115
|
+
if (options.bail) {
|
|
116
|
+
// Stop at first failure
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// ── Format results ────────────────────────
|
|
122
|
+
const succeeded = results.filter((r) => r.exitCode === 0).length;
|
|
123
|
+
const failed = results.filter((r) => r.exitCode !== 0).length;
|
|
124
|
+
if (options.json) {
|
|
125
|
+
return {
|
|
126
|
+
exitCode: hasFailure ? 1 : 0,
|
|
127
|
+
output: JSON.stringify({
|
|
128
|
+
results: results.map((r) => ({
|
|
129
|
+
command: r.command,
|
|
130
|
+
exit_code: r.exitCode,
|
|
131
|
+
stdout: r.stdout,
|
|
132
|
+
stderr: r.stderr,
|
|
133
|
+
})),
|
|
134
|
+
summary: {
|
|
135
|
+
total: results.length,
|
|
136
|
+
succeeded,
|
|
137
|
+
failed,
|
|
138
|
+
bailed: options.bail && hasFailure,
|
|
139
|
+
},
|
|
140
|
+
}, null, 2),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
// Text output
|
|
144
|
+
const lines = [];
|
|
145
|
+
for (const result of results) {
|
|
146
|
+
const status = result.exitCode === 0 ? '✓' : '✗';
|
|
147
|
+
lines.push(`${status} [${result.index + 1}/${cmdList.length}] ${result.command}`);
|
|
148
|
+
if (result.stdout) {
|
|
149
|
+
lines.push(result.stdout);
|
|
150
|
+
}
|
|
151
|
+
if (result.stderr) {
|
|
152
|
+
lines.push(` Error: ${result.stderr}`);
|
|
153
|
+
}
|
|
154
|
+
lines.push('');
|
|
155
|
+
}
|
|
156
|
+
lines.push(`--- Summary ---`);
|
|
157
|
+
lines.push(`Total: ${results.length}, Succeeded: ${succeeded}, Failed: ${failed}`);
|
|
158
|
+
if (options.bail && hasFailure) {
|
|
159
|
+
lines.push('Batch stopped early due to --bail flag.');
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
exitCode: hasFailure ? 1 : 0,
|
|
163
|
+
output: lines.join('\n'),
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
168
|
+
if (options.json) {
|
|
169
|
+
return { exitCode: 1, output: JSON.stringify({ success: false, error: message }) };
|
|
170
|
+
}
|
|
171
|
+
return { exitCode: 1, output: `Error: ${message}` };
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=batch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch.js","sourceRoot":"","sources":["../../src/commands/batch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Catalog browsing command handlers.
|
|
3
|
+
*
|
|
4
|
+
* Implements `catalog list`, `catalog search`, and `catalog info` commands.
|
|
5
|
+
* Uses the CatalogApi client for GitLab API interactions.
|
|
6
|
+
*/
|
|
7
|
+
import type { GitLabCIConfig } from '../config/types.js';
|
|
8
|
+
export interface CatalogListOptions {
|
|
9
|
+
json?: boolean;
|
|
10
|
+
page?: number;
|
|
11
|
+
perPage?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface CatalogSearchOptions {
|
|
14
|
+
json?: boolean;
|
|
15
|
+
page?: number;
|
|
16
|
+
perPage?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface CatalogInfoOptions {
|
|
19
|
+
json?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Handle `catalog list --org <namespace>`.
|
|
23
|
+
*/
|
|
24
|
+
export declare function handleCatalogList(namespace: string, config: Partial<GitLabCIConfig>, options?: CatalogListOptions): Promise<{
|
|
25
|
+
exitCode: number;
|
|
26
|
+
output: string;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* Handle `catalog search <query>`.
|
|
30
|
+
*/
|
|
31
|
+
export declare function handleCatalogSearch(query: string, config: Partial<GitLabCIConfig>, options?: CatalogSearchOptions): Promise<{
|
|
32
|
+
exitCode: number;
|
|
33
|
+
output: string;
|
|
34
|
+
}>;
|
|
35
|
+
/**
|
|
36
|
+
* Handle `catalog info <full-path>`.
|
|
37
|
+
*/
|
|
38
|
+
export declare function handleCatalogInfo(fullPath: string, config: Partial<GitLabCIConfig>, options?: CatalogInfoOptions): Promise<{
|
|
39
|
+
exitCode: number;
|
|
40
|
+
output: string;
|
|
41
|
+
}>;
|
|
42
|
+
//# sourceMappingURL=catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/commands/catalog.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAOzD,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAeD;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,EAC/B,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAoD/C;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,EAC/B,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAoD/C;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,EAC/B,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAuC/C"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Catalog browsing command handlers.
|
|
3
|
+
*
|
|
4
|
+
* Implements `catalog list`, `catalog search`, and `catalog info` commands.
|
|
5
|
+
* Uses the CatalogApi client for GitLab API interactions.
|
|
6
|
+
*/
|
|
7
|
+
import { CatalogApi } from '../api/catalog.js';
|
|
8
|
+
import { GitLabApiClient } from '../api/gitlab.js';
|
|
9
|
+
import { renderTable, renderDetail } from '../output/table.js';
|
|
10
|
+
import { NotFoundError } from '../types/api.js';
|
|
11
|
+
// ──────────────────────────────────────────────
|
|
12
|
+
// Helpers
|
|
13
|
+
// ──────────────────────────────────────────────
|
|
14
|
+
function createCatalogApi(config) {
|
|
15
|
+
const client = new GitLabApiClient(config);
|
|
16
|
+
return new CatalogApi(client);
|
|
17
|
+
}
|
|
18
|
+
// ──────────────────────────────────────────────
|
|
19
|
+
// Handlers
|
|
20
|
+
// ──────────────────────────────────────────────
|
|
21
|
+
/**
|
|
22
|
+
* Handle `catalog list --org <namespace>`.
|
|
23
|
+
*/
|
|
24
|
+
export async function handleCatalogList(namespace, config, options = {}) {
|
|
25
|
+
try {
|
|
26
|
+
const api = createCatalogApi(config);
|
|
27
|
+
const components = await api.listComponents(namespace, {
|
|
28
|
+
page: options.page,
|
|
29
|
+
perPage: options.perPage,
|
|
30
|
+
});
|
|
31
|
+
if (components.length === 0) {
|
|
32
|
+
return {
|
|
33
|
+
exitCode: 0,
|
|
34
|
+
output: options.json
|
|
35
|
+
? JSON.stringify({ success: true, data: [], message: `No components found in namespace '${namespace}'` })
|
|
36
|
+
: `No components found in namespace '${namespace}'`,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
if (options.json) {
|
|
40
|
+
return {
|
|
41
|
+
exitCode: 0,
|
|
42
|
+
output: JSON.stringify({ success: true, data: components }, null, 2),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const rows = components.map((c) => ({
|
|
46
|
+
Name: c.name,
|
|
47
|
+
Version: c.version,
|
|
48
|
+
Description: c.description ?? '',
|
|
49
|
+
Path: c.full_path,
|
|
50
|
+
}));
|
|
51
|
+
const table = renderTable([
|
|
52
|
+
{ header: 'Name' },
|
|
53
|
+
{ header: 'Version' },
|
|
54
|
+
{ header: 'Description' },
|
|
55
|
+
{ header: 'Path' },
|
|
56
|
+
], rows);
|
|
57
|
+
return { exitCode: 0, output: table };
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
61
|
+
if (options.json) {
|
|
62
|
+
return {
|
|
63
|
+
exitCode: 1,
|
|
64
|
+
output: JSON.stringify({ success: false, error: { message } }),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return { exitCode: 1, output: `Error: ${message}` };
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Handle `catalog search <query>`.
|
|
72
|
+
*/
|
|
73
|
+
export async function handleCatalogSearch(query, config, options = {}) {
|
|
74
|
+
try {
|
|
75
|
+
const api = createCatalogApi(config);
|
|
76
|
+
const components = await api.searchComponents(query, {
|
|
77
|
+
page: options.page,
|
|
78
|
+
perPage: options.perPage,
|
|
79
|
+
});
|
|
80
|
+
if (components.length === 0) {
|
|
81
|
+
return {
|
|
82
|
+
exitCode: 0,
|
|
83
|
+
output: options.json
|
|
84
|
+
? JSON.stringify({ success: true, data: [], message: `No components matching '${query}'` })
|
|
85
|
+
: `No components matching '${query}'`,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
if (options.json) {
|
|
89
|
+
return {
|
|
90
|
+
exitCode: 0,
|
|
91
|
+
output: JSON.stringify({ success: true, data: components }, null, 2),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const rows = components.map((c) => ({
|
|
95
|
+
Name: c.name,
|
|
96
|
+
Version: c.version,
|
|
97
|
+
Description: c.description ?? '',
|
|
98
|
+
Path: c.full_path,
|
|
99
|
+
}));
|
|
100
|
+
const table = renderTable([
|
|
101
|
+
{ header: 'Name' },
|
|
102
|
+
{ header: 'Version' },
|
|
103
|
+
{ header: 'Description' },
|
|
104
|
+
{ header: 'Path' },
|
|
105
|
+
], rows);
|
|
106
|
+
return { exitCode: 0, output: table };
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
110
|
+
if (options.json) {
|
|
111
|
+
return {
|
|
112
|
+
exitCode: 1,
|
|
113
|
+
output: JSON.stringify({ success: false, error: { message } }),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
return { exitCode: 1, output: `Error: ${message}` };
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Handle `catalog info <full-path>`.
|
|
121
|
+
*/
|
|
122
|
+
export async function handleCatalogInfo(fullPath, config, options = {}) {
|
|
123
|
+
try {
|
|
124
|
+
const api = createCatalogApi(config);
|
|
125
|
+
const component = await api.getComponentInfo(fullPath);
|
|
126
|
+
if (options.json) {
|
|
127
|
+
return {
|
|
128
|
+
exitCode: 0,
|
|
129
|
+
output: JSON.stringify({ success: true, data: component }, null, 2),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
const detail = renderDetail([
|
|
133
|
+
{ label: 'Name', value: component.name },
|
|
134
|
+
{ label: 'Path', value: component.full_path },
|
|
135
|
+
{ label: 'Version', value: component.version },
|
|
136
|
+
{ label: 'Description', value: component.description ?? '' },
|
|
137
|
+
{ label: 'Inputs', value: String(component.inputs?.length ?? 0) },
|
|
138
|
+
{ label: 'Jobs', value: String(component.jobs?.length ?? 0) },
|
|
139
|
+
{ label: 'Workflows', value: String(component.workflows?.length ?? 0) },
|
|
140
|
+
]);
|
|
141
|
+
return { exitCode: 0, output: detail };
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
145
|
+
// Give a friendlier message for not-found
|
|
146
|
+
const userMessage = err instanceof NotFoundError
|
|
147
|
+
? `Component '${fullPath}' not found`
|
|
148
|
+
: `Error: ${message}`;
|
|
149
|
+
if (options.json) {
|
|
150
|
+
return {
|
|
151
|
+
exitCode: 1,
|
|
152
|
+
output: JSON.stringify({ success: false, error: { message: userMessage } }),
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
return { exitCode: 1, output: userMessage };
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/commands/catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component schema inspection command handlers.
|
|
3
|
+
*
|
|
4
|
+
* Implements `component schema`, `component inputs`, `component workflows`,
|
|
5
|
+
* and `component jobs` commands.
|
|
6
|
+
*/
|
|
7
|
+
import type { GitLabCIConfig } from '../config/types.js';
|
|
8
|
+
export interface ComponentSchemaOptions {
|
|
9
|
+
version?: string;
|
|
10
|
+
outputFile?: string;
|
|
11
|
+
noCache?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface ComponentInputsOptions {
|
|
14
|
+
json?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Handle `component schema <full-path>`.
|
|
18
|
+
*/
|
|
19
|
+
export declare function handleComponentSchema(fullPath: string, config: Partial<GitLabCIConfig>, options?: ComponentSchemaOptions): Promise<{
|
|
20
|
+
exitCode: number;
|
|
21
|
+
output: string;
|
|
22
|
+
}>;
|
|
23
|
+
/**
|
|
24
|
+
* Handle `component inputs <full-path>`.
|
|
25
|
+
*/
|
|
26
|
+
export declare function handleComponentInputs(fullPath: string, config: Partial<GitLabCIConfig>, options?: ComponentInputsOptions): Promise<{
|
|
27
|
+
exitCode: number;
|
|
28
|
+
output: string;
|
|
29
|
+
}>;
|
|
30
|
+
/**
|
|
31
|
+
* Handle `component workflows <full-path>`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function handleComponentWorkflows(fullPath: string, config: Partial<GitLabCIConfig>): Promise<{
|
|
34
|
+
exitCode: number;
|
|
35
|
+
output: string;
|
|
36
|
+
}>;
|
|
37
|
+
/**
|
|
38
|
+
* Handle `component jobs <full-path>`.
|
|
39
|
+
*/
|
|
40
|
+
export declare function handleComponentJobs(fullPath: string, config: Partial<GitLabCIConfig>, options?: {
|
|
41
|
+
withArtifacts?: boolean;
|
|
42
|
+
}): Promise<{
|
|
43
|
+
exitCode: number;
|
|
44
|
+
output: string;
|
|
45
|
+
}>;
|
|
46
|
+
//# sourceMappingURL=component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../src/commands/component.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAQzD,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAeD;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,EAC/B,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAoD/C;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,EAC/B,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CA4D/C;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,GAC9B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAiC/C;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,EAC/B,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GACxC,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAiD/C"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component schema inspection command handlers.
|
|
3
|
+
*
|
|
4
|
+
* Implements `component schema`, `component inputs`, `component workflows`,
|
|
5
|
+
* and `component jobs` commands.
|
|
6
|
+
*/
|
|
7
|
+
import { writeFileSync } from 'node:fs';
|
|
8
|
+
import { CatalogApi } from '../api/catalog.js';
|
|
9
|
+
import { GitLabApiClient } from '../api/gitlab.js';
|
|
10
|
+
import { renderTable } from '../output/table.js';
|
|
11
|
+
import { NotFoundError } from '../types/api.js';
|
|
12
|
+
import { SchemaCache, buildComponentCacheKey } from '../cache/schema-cache.js';
|
|
13
|
+
// ──────────────────────────────────────────────
|
|
14
|
+
// Helpers
|
|
15
|
+
// ──────────────────────────────────────────────
|
|
16
|
+
function createCatalogApi(config) {
|
|
17
|
+
const client = new GitLabApiClient(config);
|
|
18
|
+
return new CatalogApi(client);
|
|
19
|
+
}
|
|
20
|
+
// ──────────────────────────────────────────────
|
|
21
|
+
// Handlers
|
|
22
|
+
// ──────────────────────────────────────────────
|
|
23
|
+
/**
|
|
24
|
+
* Handle `component schema <full-path>`.
|
|
25
|
+
*/
|
|
26
|
+
export async function handleComponentSchema(fullPath, config, options = {}) {
|
|
27
|
+
try {
|
|
28
|
+
// ── Check cache (unless --no-cache) ─────────
|
|
29
|
+
const cacheKey = buildComponentCacheKey(fullPath, options.version);
|
|
30
|
+
if (!options.noCache) {
|
|
31
|
+
const cache = new SchemaCache();
|
|
32
|
+
const cached = cache.get(cacheKey);
|
|
33
|
+
if (cached) {
|
|
34
|
+
const yamlContent = cached.data.spec ?? '# No schema available';
|
|
35
|
+
const output = `(from cache) ${yamlContent}`;
|
|
36
|
+
if (options.outputFile) {
|
|
37
|
+
writeFileSync(options.outputFile, yamlContent, 'utf-8');
|
|
38
|
+
return {
|
|
39
|
+
exitCode: 0,
|
|
40
|
+
output: `Schema saved to ${options.outputFile} (from cache)`,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return { exitCode: 0, output };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// ── Fetch from API ──────────────────────────
|
|
47
|
+
const api = createCatalogApi(config);
|
|
48
|
+
const component = await api.getComponentInfo(fullPath);
|
|
49
|
+
const yamlContent = component.spec ?? '# No schema available';
|
|
50
|
+
// ── Store in cache ──────────────────────────
|
|
51
|
+
if (!options.noCache) {
|
|
52
|
+
const cache = new SchemaCache();
|
|
53
|
+
cache.set(cacheKey, { spec: yamlContent });
|
|
54
|
+
}
|
|
55
|
+
if (options.outputFile) {
|
|
56
|
+
writeFileSync(options.outputFile, yamlContent, 'utf-8');
|
|
57
|
+
return {
|
|
58
|
+
exitCode: 0,
|
|
59
|
+
output: `Schema saved to ${options.outputFile}`,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return { exitCode: 0, output: yamlContent };
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
66
|
+
const userMessage = err instanceof NotFoundError
|
|
67
|
+
? `Component '${fullPath}' not found`
|
|
68
|
+
: `Error: ${message}`;
|
|
69
|
+
return { exitCode: 1, output: userMessage };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Handle `component inputs <full-path>`.
|
|
74
|
+
*/
|
|
75
|
+
export async function handleComponentInputs(fullPath, config, options = {}) {
|
|
76
|
+
try {
|
|
77
|
+
const api = createCatalogApi(config);
|
|
78
|
+
const component = await api.getComponentInfo(fullPath);
|
|
79
|
+
const inputs = component.inputs ?? [];
|
|
80
|
+
if (inputs.length === 0) {
|
|
81
|
+
return {
|
|
82
|
+
exitCode: 0,
|
|
83
|
+
output: options.json
|
|
84
|
+
? JSON.stringify({ success: true, data: [], message: `Component '${fullPath}' defines no inputs` })
|
|
85
|
+
: `Component '${fullPath}' defines no inputs`,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
if (options.json) {
|
|
89
|
+
return {
|
|
90
|
+
exitCode: 0,
|
|
91
|
+
output: JSON.stringify({ success: true, data: inputs }, null, 2),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const rows = inputs.map((input) => ({
|
|
95
|
+
Name: input.name,
|
|
96
|
+
Type: input.type,
|
|
97
|
+
Required: input.required ? 'Yes' : 'No',
|
|
98
|
+
Default: input.default !== undefined ? String(input.default) : '-',
|
|
99
|
+
Description: input.description ?? '',
|
|
100
|
+
Options: input.options?.join(', ') ?? '',
|
|
101
|
+
Regex: input.regex ?? '',
|
|
102
|
+
}));
|
|
103
|
+
const table = renderTable([
|
|
104
|
+
{ header: 'Name' },
|
|
105
|
+
{ header: 'Type' },
|
|
106
|
+
{ header: 'Required' },
|
|
107
|
+
{ header: 'Default' },
|
|
108
|
+
{ header: 'Description' },
|
|
109
|
+
{ header: 'Options' },
|
|
110
|
+
{ header: 'Regex' },
|
|
111
|
+
], rows);
|
|
112
|
+
return { exitCode: 0, output: table };
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
116
|
+
const userMessage = err instanceof NotFoundError
|
|
117
|
+
? `Component '${fullPath}' not found`
|
|
118
|
+
: `Error: ${message}`;
|
|
119
|
+
if (options.json) {
|
|
120
|
+
return {
|
|
121
|
+
exitCode: 1,
|
|
122
|
+
output: JSON.stringify({ success: false, error: { message: userMessage } }),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
return { exitCode: 1, output: userMessage };
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Handle `component workflows <full-path>`.
|
|
130
|
+
*/
|
|
131
|
+
export async function handleComponentWorkflows(fullPath, config) {
|
|
132
|
+
try {
|
|
133
|
+
const api = createCatalogApi(config);
|
|
134
|
+
const component = await api.getComponentInfo(fullPath);
|
|
135
|
+
const workflows = component.workflows ?? [];
|
|
136
|
+
if (workflows.length === 0) {
|
|
137
|
+
return {
|
|
138
|
+
exitCode: 0,
|
|
139
|
+
output: `Component '${fullPath}' defines no workflows`,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
const lines = [];
|
|
143
|
+
for (const wf of workflows) {
|
|
144
|
+
lines.push(`Workflow: ${wf.name}`);
|
|
145
|
+
lines.push(` Triggers: ${wf.triggers.join(', ')}`);
|
|
146
|
+
lines.push(` Jobs: ${wf.jobs.join(', ')}`);
|
|
147
|
+
if (wf.rules && wf.rules.length > 0) {
|
|
148
|
+
lines.push(` Rules: ${wf.rules.join(', ')}`);
|
|
149
|
+
}
|
|
150
|
+
lines.push('');
|
|
151
|
+
}
|
|
152
|
+
return { exitCode: 0, output: lines.join('\n').trimEnd() };
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
156
|
+
const userMessage = err instanceof NotFoundError
|
|
157
|
+
? `Component '${fullPath}' not found`
|
|
158
|
+
: `Error: ${message}`;
|
|
159
|
+
return { exitCode: 1, output: userMessage };
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Handle `component jobs <full-path>`.
|
|
164
|
+
*/
|
|
165
|
+
export async function handleComponentJobs(fullPath, config, options = {}) {
|
|
166
|
+
try {
|
|
167
|
+
const api = createCatalogApi(config);
|
|
168
|
+
const component = await api.getComponentInfo(fullPath);
|
|
169
|
+
const jobs = component.jobs ?? [];
|
|
170
|
+
if (jobs.length === 0) {
|
|
171
|
+
return {
|
|
172
|
+
exitCode: 0,
|
|
173
|
+
output: `Component '${fullPath}' defines no jobs`,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
const lines = [];
|
|
177
|
+
for (const job of jobs) {
|
|
178
|
+
lines.push(`Job: ${job.name}`);
|
|
179
|
+
lines.push(` Stage: ${job.stage}`);
|
|
180
|
+
if (job.image)
|
|
181
|
+
lines.push(` Image: ${job.image}`);
|
|
182
|
+
lines.push(` Script: ${job.script.join(' && ')}`);
|
|
183
|
+
if (job.variables && Object.keys(job.variables).length > 0) {
|
|
184
|
+
const varsStr = Object.entries(job.variables)
|
|
185
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
186
|
+
.join(', ');
|
|
187
|
+
lines.push(` Variables: ${varsStr}`);
|
|
188
|
+
}
|
|
189
|
+
if (job.rules && job.rules.length > 0) {
|
|
190
|
+
lines.push(` Rules: ${job.rules.join(', ')}`);
|
|
191
|
+
}
|
|
192
|
+
if (job.needs && job.needs.length > 0) {
|
|
193
|
+
lines.push(` Needs: ${job.needs.join(', ')}`);
|
|
194
|
+
if (options.withArtifacts) {
|
|
195
|
+
lines.push(` (artifact dependencies shown)`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (job.when) {
|
|
199
|
+
lines.push(` When: ${job.when}`);
|
|
200
|
+
}
|
|
201
|
+
lines.push('');
|
|
202
|
+
}
|
|
203
|
+
return { exitCode: 0, output: lines.join('\n').trimEnd() };
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
207
|
+
const userMessage = err instanceof NotFoundError
|
|
208
|
+
? `Component '${fullPath}' not found`
|
|
209
|
+
: `Error: ${message}`;
|
|
210
|
+
return { exitCode: 1, output: userMessage };
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=component.js.map
|