@formigio/fazemos-cli 0.10.54 → 0.10.58
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/dist/commands/image.d.ts +29 -0
- package/dist/commands/image.js +255 -0
- package/dist/commands/image.js.map +1 -0
- package/dist/commands/profiles.d.ts +37 -0
- package/dist/commands/profiles.js +370 -0
- package/dist/commands/profiles.js.map +1 -0
- package/dist/index.js +114 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F48-B — Execution Profiles CLI commands.
|
|
3
|
+
*
|
|
4
|
+
* Exports `registerProfilesCommands(program)` which wires the following
|
|
5
|
+
* subcommands under `fazemos profiles`:
|
|
6
|
+
*
|
|
7
|
+
* fazemos profiles create <name>
|
|
8
|
+
* → POST /api/projects/:projectId/profiles {name, model, description, baseVersion, cpu, memory, networkPlacement}
|
|
9
|
+
* Owner/admin only. Returns { profile }.
|
|
10
|
+
*
|
|
11
|
+
* fazemos profiles list
|
|
12
|
+
* → GET /api/projects/:projectId/profiles
|
|
13
|
+
* All project members. Returns metadata list.
|
|
14
|
+
*
|
|
15
|
+
* fazemos profiles show <name>
|
|
16
|
+
* → GET /api/projects/:projectId/profiles/:name
|
|
17
|
+
* All project members. Full profile detail including build source + latest build.
|
|
18
|
+
*
|
|
19
|
+
* fazemos profiles delete <name> [-y]
|
|
20
|
+
* → DELETE /api/projects/:projectId/profiles/:name (owner/admin)
|
|
21
|
+
* Soft-deletes profile row. Prompts for confirmation unless --yes / -y is passed.
|
|
22
|
+
*
|
|
23
|
+
* fazemos profiles register-source <name>
|
|
24
|
+
* → POST /api/projects/:projectId/profiles/:name/source
|
|
25
|
+
* Owner/admin. Registers/replaces Model B build source. credentialSecretName
|
|
26
|
+
* is a POINTER (name of a project_secrets row); value is NEVER stored or logged.
|
|
27
|
+
*
|
|
28
|
+
* fazemos profiles register-image <name> [B2 DEFERRED — stub]
|
|
29
|
+
* fazemos profiles admit <name> [B2 DEFERRED — stub]
|
|
30
|
+
*
|
|
31
|
+
* Auth: all commands require a valid Cognito session + active project context.
|
|
32
|
+
* Project ID is threaded in the URL path so noProjectHeader: true on every call.
|
|
33
|
+
*
|
|
34
|
+
* Spec: F48-phaseB-partner-custom-images-manifest.yaml §cli / §api
|
|
35
|
+
*/
|
|
36
|
+
import chalk from 'chalk';
|
|
37
|
+
import { createInterface } from 'readline';
|
|
38
|
+
import { api, ApiError, resolveProjectIdBySlug } from '../api.js';
|
|
39
|
+
// ── Project resolution ────────────────────────────────────────────────────────
|
|
40
|
+
/**
|
|
41
|
+
* Resolve the active project ID for a profiles command.
|
|
42
|
+
* Mirrors the pattern from commands/secrets.ts.
|
|
43
|
+
*/
|
|
44
|
+
async function requireProjectForProfiles(slugOverride) {
|
|
45
|
+
let projectId;
|
|
46
|
+
try {
|
|
47
|
+
projectId = await resolveProjectIdBySlug(slugOverride);
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
console.error(chalk.red(err?.message ?? String(err)));
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
if (!projectId) {
|
|
54
|
+
console.error(chalk.red('Error: requirement missing: project'));
|
|
55
|
+
console.error('');
|
|
56
|
+
console.error(chalk.gray('Set one with: fazemos projects switch <slug>'));
|
|
57
|
+
console.error(chalk.gray('Or pass: --project <slug>'));
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
return projectId;
|
|
61
|
+
}
|
|
62
|
+
// ── Confirmation prompt ───────────────────────────────────────────────────────
|
|
63
|
+
function confirmPrompt(message) {
|
|
64
|
+
return new Promise((resolve) => {
|
|
65
|
+
const rl = createInterface({
|
|
66
|
+
input: process.stdin,
|
|
67
|
+
output: process.stdout,
|
|
68
|
+
});
|
|
69
|
+
rl.question(`${message} [y/N] `, (answer) => {
|
|
70
|
+
rl.close();
|
|
71
|
+
resolve(answer.trim().toLowerCase() === 'y');
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
// ── Profile formatting helpers ────────────────────────────────────────────────
|
|
76
|
+
function statusColor(status) {
|
|
77
|
+
switch (status) {
|
|
78
|
+
case 'ready': return chalk.green(status);
|
|
79
|
+
case 'building': return chalk.yellow(status);
|
|
80
|
+
case 'failed': return chalk.red(status);
|
|
81
|
+
case 'disabled': return chalk.gray(status);
|
|
82
|
+
default: return chalk.gray(status); // draft / unknown
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function admissionColor(status) {
|
|
86
|
+
switch (status) {
|
|
87
|
+
case 'admitted': return chalk.green(status);
|
|
88
|
+
case 'rejected': return chalk.red(status);
|
|
89
|
+
case 'pending': return chalk.yellow(status);
|
|
90
|
+
case 'not_required': return chalk.gray(status);
|
|
91
|
+
default: return chalk.gray(status);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function printProfile(p) {
|
|
95
|
+
console.log('');
|
|
96
|
+
console.log(`${chalk.cyan(p.name)} ${statusColor(p.status)} ${chalk.gray('[' + p.model + ']')}`);
|
|
97
|
+
if (p.description)
|
|
98
|
+
console.log(` ${p.description}`);
|
|
99
|
+
console.log(` ID: ${p.id}`);
|
|
100
|
+
console.log(` Status: ${statusColor(p.status)}`);
|
|
101
|
+
console.log(` Model: ${p.model}`);
|
|
102
|
+
console.log(` Base version: ${p.baseVersion ?? '(none)'}`);
|
|
103
|
+
console.log(` CPU / Memory: ${p.cpu ?? '(default)'} / ${p.memory ?? '(default)'}`);
|
|
104
|
+
console.log(` Network: ${p.networkPlacement}`);
|
|
105
|
+
console.log(` IAM tier: ${p.iamTier}`);
|
|
106
|
+
console.log(` Admission status: ${admissionColor(p.admissionStatus)}`);
|
|
107
|
+
console.log(` Task-def family: ${p.taskDefFamily ?? '(none)'}`);
|
|
108
|
+
console.log(` Image URI: ${p.imageUri ?? '(none)'}`);
|
|
109
|
+
console.log(` Created: ${p.createdAt ? new Date(p.createdAt).toLocaleString() : ''}`);
|
|
110
|
+
console.log(` Updated: ${p.updatedAt ? new Date(p.updatedAt).toLocaleString() : ''}`);
|
|
111
|
+
if (p.source) {
|
|
112
|
+
console.log(' Source:');
|
|
113
|
+
console.log(` Repo: ${p.source.repoUrl}`);
|
|
114
|
+
console.log(` Ref: ${p.source.ref}`);
|
|
115
|
+
console.log(` Manifest path: ${p.source.manifestPath ?? 'fazemos-image.yaml'}`);
|
|
116
|
+
console.log(` Credential: ${p.source.credentialSecretName} ${chalk.gray('(secret pointer — value never shown)')}`);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
console.log(' Source: (none registered)');
|
|
120
|
+
}
|
|
121
|
+
if (p.latestBuild) {
|
|
122
|
+
const b = p.latestBuild;
|
|
123
|
+
console.log(' Latest build:');
|
|
124
|
+
console.log(` Build ID: ${b.buildId}`);
|
|
125
|
+
console.log(` Status: ${statusColor(b.status)}`);
|
|
126
|
+
console.log(` Resolved SHA: ${b.resolvedSha ?? '(pending)'}`);
|
|
127
|
+
console.log(` Image digest: ${b.imageDigest ?? '(pending)'}`);
|
|
128
|
+
console.log(` Created: ${b.createdAt ? new Date(b.createdAt).toLocaleString() : ''}`);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
console.log(' Latest build: (none)');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function handleProfileError(err) {
|
|
135
|
+
if (err instanceof ApiError) {
|
|
136
|
+
if (err.code === 'INSUFFICIENT_ROLE') {
|
|
137
|
+
console.error(chalk.red('Error: Only project owners and admins can perform this action'));
|
|
138
|
+
}
|
|
139
|
+
else if (err.code === 'PROFILE_NOT_FOUND') {
|
|
140
|
+
console.error(chalk.red('Error: Profile not found'));
|
|
141
|
+
}
|
|
142
|
+
else if (err.code === 'INVALID_NAME') {
|
|
143
|
+
console.error(chalk.red('Error: Profile name format invalid (slug, max 64 chars)'));
|
|
144
|
+
}
|
|
145
|
+
else if (err.code === 'INVALID_MODEL') {
|
|
146
|
+
console.error(chalk.red("Error: --model must be 'fazemos-build' or 'byo-image'"));
|
|
147
|
+
}
|
|
148
|
+
else if (err.code === 'INVALID_NETWORK_PLACEMENT') {
|
|
149
|
+
console.error(chalk.red("Error: --network must be 'default' or 'fazemos-static-egress'"));
|
|
150
|
+
}
|
|
151
|
+
else if (err.code === 'CREDENTIAL_SECRET_NOT_FOUND') {
|
|
152
|
+
console.error(chalk.red('Error: Credential secret not found — run `fazemos secrets set <NAME>` first'));
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
console.error(chalk.red(err.message));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
console.error(chalk.red(err?.message ?? String(err)));
|
|
160
|
+
}
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
163
|
+
// ── Command registration ──────────────────────────────────────────────────────
|
|
164
|
+
export function registerProfilesCommands(program) {
|
|
165
|
+
const profiles = program
|
|
166
|
+
.command('profiles')
|
|
167
|
+
.description('Execution profile management (F48-B — partner custom images)');
|
|
168
|
+
// ── profiles create ────────────────────────────────────────────────────────
|
|
169
|
+
profiles
|
|
170
|
+
.command('create')
|
|
171
|
+
.description('Create a new execution profile (owner/admin only). ' +
|
|
172
|
+
'Model B (fazemos-build) is the default: Fazemos builds the image from your repo. ' +
|
|
173
|
+
'Model A (byo-image) brings your own image — requires admission gate (Phase B.2).')
|
|
174
|
+
.argument('<name>', 'Profile name — slug format, unique per project (max 64 chars)')
|
|
175
|
+
.option('--model <model>', "Execution model: 'fazemos-build' (default) or 'byo-image'", 'fazemos-build')
|
|
176
|
+
.option('--base <version>', 'Base contract version (e.g. fazemos-agent-base:v1)')
|
|
177
|
+
.option('--cpu <n>', 'CPU units override (e.g. 1024 = 1 vCPU)', parseInt)
|
|
178
|
+
.option('--memory <n>', 'Memory MiB override (e.g. 2048)', parseInt)
|
|
179
|
+
.option('--network <placement>', "Network placement: 'default' or 'fazemos-static-egress'")
|
|
180
|
+
.option('--description <text>', 'Human-readable description of this profile')
|
|
181
|
+
.option('--project <slug>', 'Override active project for this call')
|
|
182
|
+
.action(async (name, opts) => {
|
|
183
|
+
try {
|
|
184
|
+
const projectId = await requireProjectForProfiles(opts.project);
|
|
185
|
+
// Map CLI flag values to API values
|
|
186
|
+
const modelMap = {
|
|
187
|
+
'fazemos-build': 'fazemos_build',
|
|
188
|
+
'byo-image': 'byo_image',
|
|
189
|
+
};
|
|
190
|
+
const apiModel = modelMap[opts.model];
|
|
191
|
+
if (!apiModel) {
|
|
192
|
+
console.error(chalk.red("Error: --model must be 'fazemos-build' or 'byo-image'"));
|
|
193
|
+
process.exit(1);
|
|
194
|
+
}
|
|
195
|
+
const body = { name, model: apiModel };
|
|
196
|
+
if (opts.description)
|
|
197
|
+
body.description = opts.description;
|
|
198
|
+
if (opts.base)
|
|
199
|
+
body.baseVersion = opts.base;
|
|
200
|
+
if (opts.cpu != null)
|
|
201
|
+
body.cpu = opts.cpu;
|
|
202
|
+
if (opts.memory != null)
|
|
203
|
+
body.memory = opts.memory;
|
|
204
|
+
if (opts.network)
|
|
205
|
+
body.networkPlacement = opts.network;
|
|
206
|
+
const data = await api('POST', `/api/projects/${projectId}/profiles`, body, { noProjectHeader: true });
|
|
207
|
+
const p = data.profile;
|
|
208
|
+
console.log(chalk.green(`Profile '${p.name}' created.`));
|
|
209
|
+
printProfile(p);
|
|
210
|
+
}
|
|
211
|
+
catch (err) {
|
|
212
|
+
handleProfileError(err);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
// ── profiles list ──────────────────────────────────────────────────────────
|
|
216
|
+
profiles
|
|
217
|
+
.command('list')
|
|
218
|
+
.description('List execution profiles in the active project')
|
|
219
|
+
.option('--project <slug>', 'Override active project for this call')
|
|
220
|
+
.option('--json', 'Output raw JSON')
|
|
221
|
+
.action(async (opts) => {
|
|
222
|
+
try {
|
|
223
|
+
const projectId = await requireProjectForProfiles(opts.project);
|
|
224
|
+
const data = await api('GET', `/api/projects/${projectId}/profiles`, undefined, { noProjectHeader: true });
|
|
225
|
+
const items = data.profiles ?? [];
|
|
226
|
+
if (opts.json) {
|
|
227
|
+
console.log(JSON.stringify(data, null, 2));
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
if (items.length === 0) {
|
|
231
|
+
console.log(chalk.yellow('No profiles'));
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const nameW = Math.max(4, ...items.map((p) => String(p.name ?? '').length));
|
|
235
|
+
const modelW = Math.max(5, ...items.map((p) => String(p.model ?? '').length));
|
|
236
|
+
const statusW = Math.max(6, ...items.map((p) => String(p.status ?? '').length));
|
|
237
|
+
const header = [
|
|
238
|
+
'NAME'.padEnd(nameW),
|
|
239
|
+
'MODEL'.padEnd(modelW),
|
|
240
|
+
'STATUS'.padEnd(statusW),
|
|
241
|
+
'IMAGE URI',
|
|
242
|
+
].join(' ');
|
|
243
|
+
console.log(chalk.gray(header));
|
|
244
|
+
console.log(chalk.gray('─'.repeat(header.length + 20)));
|
|
245
|
+
for (const p of items) {
|
|
246
|
+
const imageUri = p.imageUri ? p.imageUri.slice(0, 48) + (p.imageUri.length > 48 ? '…' : '') : '(none)';
|
|
247
|
+
console.log([
|
|
248
|
+
String(p.name ?? '').padEnd(nameW),
|
|
249
|
+
String(p.model ?? '').padEnd(modelW),
|
|
250
|
+
String(p.status ?? '').padEnd(statusW),
|
|
251
|
+
imageUri,
|
|
252
|
+
].join(' '));
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
catch (err) {
|
|
256
|
+
handleProfileError(err);
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
// ── profiles show ──────────────────────────────────────────────────────────
|
|
260
|
+
profiles
|
|
261
|
+
.command('show')
|
|
262
|
+
.description('Show execution profile detail (build source, latest build, admission status)')
|
|
263
|
+
.argument('<name>', 'Profile name')
|
|
264
|
+
.option('--project <slug>', 'Override active project for this call')
|
|
265
|
+
.option('--json', 'Output raw JSON')
|
|
266
|
+
.action(async (name, opts) => {
|
|
267
|
+
try {
|
|
268
|
+
const projectId = await requireProjectForProfiles(opts.project);
|
|
269
|
+
const data = await api('GET', `/api/projects/${projectId}/profiles/${encodeURIComponent(name)}`, undefined, { noProjectHeader: true });
|
|
270
|
+
if (opts.json) {
|
|
271
|
+
console.log(JSON.stringify(data, null, 2));
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
printProfile(data.profile);
|
|
275
|
+
}
|
|
276
|
+
catch (err) {
|
|
277
|
+
handleProfileError(err);
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
// ── profiles delete ────────────────────────────────────────────────────────
|
|
281
|
+
profiles
|
|
282
|
+
.command('delete')
|
|
283
|
+
.description('Delete (soft-delete) an execution profile (owner/admin only)')
|
|
284
|
+
.argument('<name>', 'Profile name')
|
|
285
|
+
.option('--project <slug>', 'Override active project for this call')
|
|
286
|
+
.option('-y, --yes', 'Skip confirmation prompt')
|
|
287
|
+
.action(async (name, opts) => {
|
|
288
|
+
try {
|
|
289
|
+
const projectId = await requireProjectForProfiles(opts.project);
|
|
290
|
+
if (!opts.yes) {
|
|
291
|
+
const confirmed = await confirmPrompt(`Delete profile ${chalk.cyan(name)}? This soft-deletes the profile and any associated builds.`);
|
|
292
|
+
if (!confirmed) {
|
|
293
|
+
console.log('Aborted.');
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
await api('DELETE', `/api/projects/${projectId}/profiles/${encodeURIComponent(name)}`, undefined, { noProjectHeader: true });
|
|
298
|
+
console.log(chalk.green(`Profile '${name}' deleted.`));
|
|
299
|
+
}
|
|
300
|
+
catch (err) {
|
|
301
|
+
handleProfileError(err);
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
// ── profiles register-source ───────────────────────────────────────────────
|
|
305
|
+
profiles
|
|
306
|
+
.command('register-source')
|
|
307
|
+
.description('Register (or replace) the Model B build source for a profile (owner/admin only). ' +
|
|
308
|
+
'--credential is the NAME of a project secret (set via `fazemos secrets set`). ' +
|
|
309
|
+
'The secret value is read directly by the build service — it is NEVER returned by this command.')
|
|
310
|
+
.argument('<name>', 'Profile name')
|
|
311
|
+
.requiredOption('--repo <url>', 'Partner repository URL (e.g. git@github.com:org/repo.git)')
|
|
312
|
+
.requiredOption('--ref <ref>', 'Branch, tag, or commit SHA to build from')
|
|
313
|
+
.requiredOption('--credential <secret-name>', 'Name of a project secret holding the deploy key / PAT')
|
|
314
|
+
.option('--manifest <path>', 'Path to fazemos-image.yaml in the repo (default: fazemos-image.yaml)', 'fazemos-image.yaml')
|
|
315
|
+
.option('--project <slug>', 'Override active project for this call')
|
|
316
|
+
.action(async (name, opts) => {
|
|
317
|
+
try {
|
|
318
|
+
const projectId = await requireProjectForProfiles(opts.project);
|
|
319
|
+
const body = {
|
|
320
|
+
repoUrl: opts.repo,
|
|
321
|
+
ref: opts.ref,
|
|
322
|
+
credentialSecretName: opts.credential,
|
|
323
|
+
manifestPath: opts.manifest,
|
|
324
|
+
};
|
|
325
|
+
const data = await api('POST', `/api/projects/${projectId}/profiles/${encodeURIComponent(name)}/source`, body, { noProjectHeader: true });
|
|
326
|
+
console.log(chalk.green(`Build source registered for profile '${name}'.`));
|
|
327
|
+
console.log(` Repo: ${opts.repo}`);
|
|
328
|
+
console.log(` Ref: ${opts.ref}`);
|
|
329
|
+
console.log(` Manifest: ${opts.manifest}`);
|
|
330
|
+
console.log(` Credential: ${opts.credential} ${chalk.gray('(secret pointer — value never shown)')}`);
|
|
331
|
+
console.log('');
|
|
332
|
+
console.log(chalk.gray('Next step: run `fazemos image build ' + name + '` to trigger a build.'));
|
|
333
|
+
const p = data.profile;
|
|
334
|
+
if (p)
|
|
335
|
+
printProfile(p);
|
|
336
|
+
}
|
|
337
|
+
catch (err) {
|
|
338
|
+
handleProfileError(err);
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
// ── profiles register-image [B2 DEFERRED] ─────────────────────────────────
|
|
342
|
+
profiles
|
|
343
|
+
.command('register-image')
|
|
344
|
+
.description('[B2 DEFERRED] Register a BYO (Model A) image URI for a profile. ' +
|
|
345
|
+
'Not available in Phase B.1 — open a GitHub issue to track B.2 delivery.')
|
|
346
|
+
.argument('<name>', 'Profile name')
|
|
347
|
+
.option('--image-uri <uri>', 'Partner ECR image URI (digest-addressable)')
|
|
348
|
+
.option('--signing-key <path|inline>', 'Partner signing public key (file path or inline PEM)')
|
|
349
|
+
.option('--project <slug>', 'Override active project for this call')
|
|
350
|
+
.action(async (_name, _opts) => {
|
|
351
|
+
console.error(chalk.red('Error: `profiles register-image` is not available in Phase B.1.'));
|
|
352
|
+
console.error(chalk.gray('Model A (BYO image + admission gate) is deferred to Phase B.2.'));
|
|
353
|
+
console.error(chalk.gray('Use `fazemos profiles register-source` + `fazemos image build` for Model B (Fazemos-builds).'));
|
|
354
|
+
process.exit(1);
|
|
355
|
+
});
|
|
356
|
+
// ── profiles admit [B2 DEFERRED] ──────────────────────────────────────────
|
|
357
|
+
profiles
|
|
358
|
+
.command('admit')
|
|
359
|
+
.description('[B2 DEFERRED] Run the Model A admission gate (scan + signature verify + digest-pin) for a profile. ' +
|
|
360
|
+
'Not available in Phase B.1.')
|
|
361
|
+
.argument('<name>', 'Profile name')
|
|
362
|
+
.option('--scan-only', 'Run vulnerability scan only, do not fully admit')
|
|
363
|
+
.option('--project <slug>', 'Override active project for this call')
|
|
364
|
+
.action(async (_name, _opts) => {
|
|
365
|
+
console.error(chalk.red('Error: `profiles admit` is not available in Phase B.1.'));
|
|
366
|
+
console.error(chalk.gray('Model A admission gate (scan + signature verification) is deferred to Phase B.2.'));
|
|
367
|
+
process.exit(1);
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
//# sourceMappingURL=profiles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiles.js","sourceRoot":"","sources":["../../src/commands/profiles.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -26,6 +26,8 @@ import { registerFtrCommand } from './ftr.js';
|
|
|
26
26
|
import { registerScheduleCommands } from './schedule.js';
|
|
27
27
|
import { registerApprovalsCommands } from './approvals.js';
|
|
28
28
|
import { registerSecretsCommands } from './commands/secrets.js';
|
|
29
|
+
import { registerProfilesCommands } from './commands/profiles.js';
|
|
30
|
+
import { registerImageCommands } from './commands/image.js';
|
|
29
31
|
import { parseExecutionsJson, resolveWaitOptions, waitForPipelines, buildAwsCommand, validateExecutionEntry, } from './wait-for-pipeline.js';
|
|
30
32
|
import { readFileSync, readdirSync, writeFileSync, mkdirSync, existsSync, statSync } from 'fs';
|
|
31
33
|
import { fileURLToPath } from 'url';
|
|
@@ -5640,6 +5642,94 @@ pipelines
|
|
|
5640
5642
|
process.exit(1);
|
|
5641
5643
|
}
|
|
5642
5644
|
});
|
|
5645
|
+
// ── OPERATOR-RECOVERY-BUNDLE — `pl reconcile <instanceId>` ──
|
|
5646
|
+
// Idempotent operator-safe healing command (spec §2).
|
|
5647
|
+
// Re-runs the DAG resolver, detects stranded steps (queued/in_progress with
|
|
5648
|
+
// no live execution), gates through canLaunch, re-launches eligible ones,
|
|
5649
|
+
// and returns a structured JSON report (launched, skipped, stalled).
|
|
5650
|
+
//
|
|
5651
|
+
// POST /api/pipeline-instances/:id/reconcile
|
|
5652
|
+
// Auth: owner or admin only
|
|
5653
|
+
//
|
|
5654
|
+
// Distinct from pl rematerialize (P-TOOL-1): rematerialize rebases onto the
|
|
5655
|
+
// TEMPLATE (schema/content-side); reconcile re-launches missing EXECUTIONS on
|
|
5656
|
+
// the instance as-is (runtime-side only). Different jobs kept separate.
|
|
5657
|
+
pipelines
|
|
5658
|
+
.command('reconcile')
|
|
5659
|
+
.description('Idempotent operator recovery: re-runs the DAG resolver, detects stranded steps ' +
|
|
5660
|
+
'(queued/in_progress with no live execution), and re-launches eligible ones. ' +
|
|
5661
|
+
'Safe to run multiple times — the second call fires nothing if the first succeeded. ' +
|
|
5662
|
+
'Owner/admin only. Distinct from rematerialize: this heals EXECUTIONS, not the template schema.')
|
|
5663
|
+
.argument('<instanceId>', 'Pipeline instance ID')
|
|
5664
|
+
.option('--json', 'Print the raw API response as JSON (machine-readable)')
|
|
5665
|
+
.action(async (instanceId, opts) => {
|
|
5666
|
+
try {
|
|
5667
|
+
const path = `/api/pipeline-instances/${instanceId}/reconcile`;
|
|
5668
|
+
const data = (await api('POST', path, {}));
|
|
5669
|
+
if (opts.json) {
|
|
5670
|
+
console.log(JSON.stringify(data, null, 2));
|
|
5671
|
+
return;
|
|
5672
|
+
}
|
|
5673
|
+
// Human-readable reconcile report
|
|
5674
|
+
const reconciledAt = data?.reconciled_at ? new Date(data.reconciled_at).toLocaleString() : 'unknown';
|
|
5675
|
+
console.log(chalk.bold(`Reconcile — instance ${instanceId}`));
|
|
5676
|
+
console.log(chalk.gray(` Reconciled at : ${reconciledAt}`));
|
|
5677
|
+
console.log(chalk.gray(` DAG resolver : ${data?.dag_resolver_ran ? 'ran' : 'skipped'}`));
|
|
5678
|
+
console.log(chalk.gray(` Steps verified: ${data?.steps_verified ?? 0}`));
|
|
5679
|
+
console.log();
|
|
5680
|
+
// Launched
|
|
5681
|
+
const launched = Array.isArray(data?.launched) ? data.launched : [];
|
|
5682
|
+
if (launched.length > 0) {
|
|
5683
|
+
console.log(chalk.green(` Launched (${launched.length}):`));
|
|
5684
|
+
for (const s of launched) {
|
|
5685
|
+
console.log(chalk.green(` ✓ ${s.step_name} (${s.step_id}) → execution ${s.execution_id}` +
|
|
5686
|
+
(s.assigned_to ? ` [agent: ${s.assigned_to}]` : '')));
|
|
5687
|
+
}
|
|
5688
|
+
}
|
|
5689
|
+
else {
|
|
5690
|
+
console.log(chalk.gray(' Launched: (none)'));
|
|
5691
|
+
}
|
|
5692
|
+
// Skipped (canLaunch=false due to pause/budget/fan-out)
|
|
5693
|
+
const skipped = Array.isArray(data?.skipped) ? data.skipped : [];
|
|
5694
|
+
if (skipped.length > 0) {
|
|
5695
|
+
console.log(chalk.yellow(`\n Skipped — canLaunch blocked (${skipped.length}):`));
|
|
5696
|
+
for (const s of skipped) {
|
|
5697
|
+
console.log(chalk.yellow(` ⚠ ${s.step_name} (${s.step_id}) [${s.reason}]: ${s.detail}`));
|
|
5698
|
+
}
|
|
5699
|
+
}
|
|
5700
|
+
// Stalled (governance signal — queued, no execution, canLaunch=false for other reason)
|
|
5701
|
+
const stalled = Array.isArray(data?.stalled) ? data.stalled : [];
|
|
5702
|
+
if (stalled.length > 0) {
|
|
5703
|
+
console.log(chalk.red(`\n Stalled — governance signal (${stalled.length}):`));
|
|
5704
|
+
for (const s of stalled) {
|
|
5705
|
+
console.log(chalk.red(` ✗ ${s.step_name} (${s.step_id}) [status: ${s.status}]: ${s.detail}`));
|
|
5706
|
+
}
|
|
5707
|
+
}
|
|
5708
|
+
console.log();
|
|
5709
|
+
if (launched.length === 0 && skipped.length === 0 && stalled.length === 0) {
|
|
5710
|
+
console.log(chalk.green('No stranded steps found — instance is healthy.'));
|
|
5711
|
+
}
|
|
5712
|
+
else {
|
|
5713
|
+
const summary = [];
|
|
5714
|
+
if (launched.length > 0)
|
|
5715
|
+
summary.push(chalk.green(`${launched.length} launched`));
|
|
5716
|
+
if (skipped.length > 0)
|
|
5717
|
+
summary.push(chalk.yellow(`${skipped.length} skipped`));
|
|
5718
|
+
if (stalled.length > 0)
|
|
5719
|
+
summary.push(chalk.red(`${stalled.length} stalled`));
|
|
5720
|
+
console.log(`Summary: ${summary.join(', ')}`);
|
|
5721
|
+
}
|
|
5722
|
+
}
|
|
5723
|
+
catch (err) {
|
|
5724
|
+
// 403 owner/admin gate
|
|
5725
|
+
if (err instanceof ApiError && err.status === 403) {
|
|
5726
|
+
console.error(chalk.red(`Permission denied: ${err.message}`));
|
|
5727
|
+
process.exit(1);
|
|
5728
|
+
}
|
|
5729
|
+
console.error(chalk.red(err.message));
|
|
5730
|
+
process.exit(1);
|
|
5731
|
+
}
|
|
5732
|
+
});
|
|
5643
5733
|
pipelines
|
|
5644
5734
|
.command('set-params')
|
|
5645
5735
|
.description('Set instance parameters (atomic update)')
|
|
@@ -6260,6 +6350,7 @@ program
|
|
|
6260
6350
|
.option('--repos <repos>', 'Comma-separated repo names to clone (overrides agent config)', (v) => v.split(','))
|
|
6261
6351
|
.option('--model <model>', 'Model override (e.g., opus, sonnet)')
|
|
6262
6352
|
.option('--budget <usd>', 'Max budget override in USD', parseNumber)
|
|
6353
|
+
.option('--profile <name>', 'Named execution profile (F48-B). Threaded into POST /api/executions context as context.profile. Tracking-only in B.1 — does not change runtime resolution.')
|
|
6263
6354
|
.action(async (sourceId, opts) => {
|
|
6264
6355
|
try {
|
|
6265
6356
|
const validTypes = ['action', 'commitment', 'pipeline_step'];
|
|
@@ -6392,6 +6483,13 @@ program
|
|
|
6392
6483
|
}
|
|
6393
6484
|
if (opts.prompt)
|
|
6394
6485
|
context.prompt = opts.prompt;
|
|
6486
|
+
// [F48-B LD-14] --profile threads the named profile into context.profile
|
|
6487
|
+
// for tracking/dispatch. In Phase B.1 this field is recorded on the
|
|
6488
|
+
// executions row but does NOT drive runtime resolution — the nb-scanning
|
|
6489
|
+
// path continues through the unchanged Phase-A tools path. B.2 will wire
|
|
6490
|
+
// the DB-backed resolver at executionService.ts.
|
|
6491
|
+
if (opts.profile)
|
|
6492
|
+
context.profile = opts.profile;
|
|
6395
6493
|
// [F24 §3.3 / D2] Forward --no-auto-complete intent. The CLI guard
|
|
6396
6494
|
// above suppresses this for pipeline_step (forwardSuppress is false
|
|
6397
6495
|
// in that case). Agent's buildSelfReportingInstructions reads
|
|
@@ -10227,6 +10325,22 @@ registerApprovalsCommands(program);
|
|
|
10227
10325
|
// set supports interactive masked input, --value-from <file>, positional arg,
|
|
10228
10326
|
// and piped stdin. delete prompts for confirmation unless --yes / -y is passed.
|
|
10229
10327
|
registerSecretsCommands(program);
|
|
10328
|
+
// ── F48-B — Execution Profiles: profiles create / list / show / delete / register-source ────
|
|
10329
|
+
// Registers `profiles` top-level command and sub-commands.
|
|
10330
|
+
// All calls use project ID in the URL path (/api/projects/:projectId/profiles/...);
|
|
10331
|
+
// noProjectHeader: true on every call (path-scoped, not header-scoped).
|
|
10332
|
+
// create/delete/register-source: owner/admin only (server-side gate).
|
|
10333
|
+
// list/show: all project members.
|
|
10334
|
+
// register-image / admit: B2 DEFERRED stubs (print friendly error + exit 1).
|
|
10335
|
+
registerProfilesCommands(program);
|
|
10336
|
+
// ── F48-B — Image Builds: image build / status / list ───────────────────────
|
|
10337
|
+
// Registers `image` top-level command with build, status, and list sub-commands.
|
|
10338
|
+
// All calls use project ID in the URL path (/api/projects/:projectId/profiles/:name/builds[/:id]);
|
|
10339
|
+
// noProjectHeader: true on every call.
|
|
10340
|
+
// build: owner/admin only. status/list: all project members.
|
|
10341
|
+
// When codebuildEnabled=false on a build response, the note field is surfaced
|
|
10342
|
+
// to the user (infrastructure not yet deployed).
|
|
10343
|
+
registerImageCommands(program);
|
|
10230
10344
|
// Skip auto-parse only when running under Vitest (which sets process.env.VITEST).
|
|
10231
10345
|
// Tests import `program` and drive it via `program.parseAsync(...)` after mocking
|
|
10232
10346
|
// `./api.js`. In every other context — direct invocation, npx tsx, OR the bin
|