@sanity/workflow-cli 0.8.0 → 0.9.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/README.md +99 -61
- package/dist/commands/abort.d.ts +5 -7
- package/dist/commands/abort.js +15 -14
- package/dist/commands/definition/delete.d.ts +10 -6
- package/dist/commands/definition/delete.js +8 -11
- package/dist/commands/definition/diff.d.ts +8 -1
- package/dist/commands/definition/diff.js +30 -24
- package/dist/commands/definition/list.d.ts +4 -4
- package/dist/commands/definition/list.js +8 -8
- package/dist/commands/definition/show.d.ts +0 -10
- package/dist/commands/definition/show.js +11 -20
- package/dist/commands/deploy.d.ts +58 -5
- package/dist/commands/deploy.js +134 -27
- package/dist/commands/diagnose.d.ts +5 -1
- package/dist/commands/diagnose.js +18 -28
- package/dist/commands/fire-action.d.ts +15 -28
- package/dist/commands/fire-action.js +37 -72
- package/dist/commands/list.d.ts +2 -2
- package/dist/commands/list.js +8 -8
- package/dist/commands/{retry-activity.d.ts → reset-activity.d.ts} +1 -1
- package/dist/commands/{retry-activity.js → reset-activity.js} +2 -2
- package/dist/commands/set-stage.d.ts +27 -3
- package/dist/commands/set-stage.js +80 -13
- package/dist/commands/show.d.ts +1 -0
- package/dist/commands/show.js +14 -8
- package/dist/commands/start.d.ts +59 -0
- package/dist/commands/start.js +169 -0
- package/dist/commands/tail.d.ts +3 -0
- package/dist/commands/tail.js +9 -5
- package/dist/lib/client.d.ts +11 -14
- package/dist/lib/client.js +45 -33
- package/dist/lib/context.d.ts +62 -0
- package/dist/lib/context.js +82 -0
- package/dist/lib/definitions.d.ts +38 -29
- package/dist/lib/definitions.js +45 -85
- package/dist/lib/diff.js +8 -0
- package/dist/lib/env.d.ts +0 -6
- package/dist/lib/env.js +3 -9
- package/dist/lib/fail.d.ts +6 -0
- package/dist/lib/fail.js +11 -1
- package/dist/lib/flags.d.ts +14 -2
- package/dist/lib/flags.js +24 -3
- package/dist/lib/load-config.d.ts +11 -0
- package/dist/lib/load-config.js +69 -0
- package/dist/lib/operation-args.d.ts +25 -7
- package/dist/lib/operation-args.js +12 -11
- package/dist/lib/ops-report.d.ts +19 -7
- package/dist/lib/ops-report.js +6 -7
- package/dist/lib/params.d.ts +7 -0
- package/dist/lib/params.js +26 -0
- package/dist/lib/select-deployment.d.ts +31 -0
- package/dist/lib/select-deployment.js +58 -0
- package/dist/lib/ui.d.ts +3 -1
- package/dist/lib/ui.js +1 -3
- package/oclif.manifest.json +145 -86
- package/package.json +6 -4
- package/dist/commands/move-stage.d.ts +0 -47
- package/dist/commands/move-stage.js +0 -77
- package/dist/lib/config.d.ts +0 -18
- package/dist/lib/config.js +0 -50
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { resourceAliasesToMap, } from '@sanity/workflow-engine';
|
|
2
|
+
import { fail } from "./fail.js";
|
|
3
|
+
/**
|
|
4
|
+
* Pick the deployment for the requested `--tag`. Tags are unique across a
|
|
5
|
+
* config (enforced by defineWorkflowConfig), so a tag names at most one
|
|
6
|
+
* deployment.
|
|
7
|
+
*
|
|
8
|
+
* With no tag: fall back to the sole deployment when there's exactly one
|
|
9
|
+
* (the common single-environment case), otherwise fail asking for `--tag` —
|
|
10
|
+
* a multi-deployment config is ambiguous without it. `orAlternative` extends
|
|
11
|
+
* that ambiguity message for callers with another way out (deploy's `--all-tags`).
|
|
12
|
+
*/
|
|
13
|
+
export function selectDeployment(config, { tag, orAlternative = '' }) {
|
|
14
|
+
if (tag === undefined) {
|
|
15
|
+
if (config.deployments.length > 1) {
|
|
16
|
+
fail(`Multiple deployments configured — pass --tag${orAlternative}.`, availableTags(config));
|
|
17
|
+
}
|
|
18
|
+
const [sole] = config.deployments;
|
|
19
|
+
if (sole === undefined) {
|
|
20
|
+
fail('No deployments configured.');
|
|
21
|
+
}
|
|
22
|
+
return sole;
|
|
23
|
+
}
|
|
24
|
+
const deployment = config.deployments.find((candidate) => candidate.tag === tag);
|
|
25
|
+
if (deployment === undefined) {
|
|
26
|
+
fail(`No deployment for tag "${tag}".`, availableTags(config));
|
|
27
|
+
}
|
|
28
|
+
return deployment;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The deployments a `deploy` run acts on: every one with `--all-tags`,
|
|
32
|
+
* otherwise a single target via {@link selectDeployment} and its failure
|
|
33
|
+
* modes. Deploying everything is an explicit opt-in — never a default — so an
|
|
34
|
+
* ambiguous bare `deploy` can't fan a write out across environments.
|
|
35
|
+
*/
|
|
36
|
+
export function selectDeployments(config, { tag, allTags }) {
|
|
37
|
+
if (allTags) {
|
|
38
|
+
return config.deployments;
|
|
39
|
+
}
|
|
40
|
+
return [
|
|
41
|
+
selectDeployment(config, { tag, orAlternative: ', or --all-tags to deploy every deployment' }),
|
|
42
|
+
];
|
|
43
|
+
}
|
|
44
|
+
function availableTags(config) {
|
|
45
|
+
return `Available tags: ${config.deployments.map((candidate) => candidate.tag).join(', ')}`;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Project a deployment into the engine's {@link DeployTarget} — the shape the
|
|
49
|
+
* deploy/diff verbs (`deployDefinitions`, `computeDiffEntries`, `diffEntry`)
|
|
50
|
+
* consume — expanding its handle bindings into the alias map in the same step.
|
|
51
|
+
*/
|
|
52
|
+
export function deploymentToTarget(deployment) {
|
|
53
|
+
return {
|
|
54
|
+
tag: deployment.tag,
|
|
55
|
+
workflowResource: deployment.workflowResource,
|
|
56
|
+
resourceAliases: resourceAliasesToMap(deployment.resourceAliases),
|
|
57
|
+
};
|
|
58
|
+
}
|
package/dist/lib/ui.d.ts
CHANGED
|
@@ -9,7 +9,9 @@ export declare function sectionHeader(title: string): string;
|
|
|
9
9
|
* the Sanity CLI's `formatKeyValue` so it folds into the shared helper on
|
|
10
10
|
* merge; pass `padTo` (the longest key's length) to align a block of rows.
|
|
11
11
|
*/
|
|
12
|
-
export declare function formatKeyValue(key
|
|
12
|
+
export declare function formatKeyValue({ key, value, indent, padTo, }: {
|
|
13
|
+
key: string;
|
|
14
|
+
value: string;
|
|
13
15
|
indent?: number;
|
|
14
16
|
padTo?: number;
|
|
15
17
|
}): string;
|
package/dist/lib/ui.js
CHANGED
|
@@ -15,9 +15,7 @@ export function sectionHeader(title) {
|
|
|
15
15
|
* the Sanity CLI's `formatKeyValue` so it folds into the shared helper on
|
|
16
16
|
* merge; pass `padTo` (the longest key's length) to align a block of rows.
|
|
17
17
|
*/
|
|
18
|
-
export function formatKeyValue(key, value,
|
|
19
|
-
const indent = options?.indent ?? 2;
|
|
20
|
-
const padTo = options?.padTo ?? 0;
|
|
18
|
+
export function formatKeyValue({ key, value, indent = 2, padTo = 0, }) {
|
|
21
19
|
const paddedKey = `${key}:`.padEnd(padTo > 0 ? padTo + 1 : key.length + 1);
|
|
22
20
|
return `${' '.repeat(indent)}${styleText('dim', paddedKey)} ${value}`;
|
|
23
21
|
}
|
package/oclif.manifest.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
],
|
|
17
17
|
"flags": {
|
|
18
18
|
"tag": {
|
|
19
|
-
"description": "Workflow environment tag (e.g. prod, test)
|
|
19
|
+
"description": "Workflow environment tag (e.g. prod, test) — the deployment to target for writes; an optional filter for reads.",
|
|
20
20
|
"name": "tag",
|
|
21
21
|
"hasDynamicHelp": false,
|
|
22
22
|
"multiple": false,
|
|
@@ -48,21 +48,31 @@
|
|
|
48
48
|
"deploy": {
|
|
49
49
|
"aliases": [],
|
|
50
50
|
"args": {},
|
|
51
|
-
"description": "Validate, diff, and deploy workflow definitions to the
|
|
51
|
+
"description": "Validate, diff, and deploy workflow definitions to the resource bound by the selected deployment.",
|
|
52
52
|
"examples": [
|
|
53
|
-
"<%= config.bin %> deploy",
|
|
53
|
+
"<%= config.bin %> deploy --tag prod",
|
|
54
|
+
"<%= config.bin %> deploy --all-tags",
|
|
54
55
|
"<%= config.bin %> deploy --check",
|
|
55
56
|
"<%= config.bin %> deploy --dry-run",
|
|
56
57
|
"<%= config.bin %> deploy --only productLaunch"
|
|
57
58
|
],
|
|
58
59
|
"flags": {
|
|
59
60
|
"tag": {
|
|
60
|
-
"description": "Workflow environment tag (e.g. prod, test)
|
|
61
|
+
"description": "Workflow environment tag (e.g. prod, test) — the deployment to target for writes; an optional filter for reads.",
|
|
61
62
|
"name": "tag",
|
|
62
63
|
"hasDynamicHelp": false,
|
|
63
64
|
"multiple": false,
|
|
64
65
|
"type": "option"
|
|
65
66
|
},
|
|
67
|
+
"all-tags": {
|
|
68
|
+
"description": "Deploy every deployment in the config, not just one tag.",
|
|
69
|
+
"exclusive": [
|
|
70
|
+
"tag"
|
|
71
|
+
],
|
|
72
|
+
"name": "all-tags",
|
|
73
|
+
"allowNo": false,
|
|
74
|
+
"type": "boolean"
|
|
75
|
+
},
|
|
66
76
|
"dry-run": {
|
|
67
77
|
"description": "Validate + diff against the deployed version; do not write.",
|
|
68
78
|
"name": "dry-run",
|
|
@@ -76,7 +86,7 @@
|
|
|
76
86
|
"type": "boolean"
|
|
77
87
|
},
|
|
78
88
|
"only": {
|
|
79
|
-
"description": "Limit deploy/check/diff to a single workflow definition by name.",
|
|
89
|
+
"description": "Limit deploy/check/diff to a single workflow definition by name. Every targeted deployment must contain it.",
|
|
80
90
|
"name": "only",
|
|
81
91
|
"hasDynamicHelp": false,
|
|
82
92
|
"multiple": false,
|
|
@@ -115,14 +125,14 @@
|
|
|
115
125
|
],
|
|
116
126
|
"flags": {
|
|
117
127
|
"tag": {
|
|
118
|
-
"description": "Workflow environment tag (e.g. prod, test)
|
|
128
|
+
"description": "Workflow environment tag (e.g. prod, test) — the deployment to target for writes; an optional filter for reads.",
|
|
119
129
|
"name": "tag",
|
|
120
130
|
"hasDynamicHelp": false,
|
|
121
131
|
"multiple": false,
|
|
122
132
|
"type": "option"
|
|
123
133
|
},
|
|
124
134
|
"json": {
|
|
125
|
-
"description": "Emit
|
|
135
|
+
"description": "Emit structured JSON instead of rendered output.",
|
|
126
136
|
"name": "json",
|
|
127
137
|
"allowNo": false,
|
|
128
138
|
"type": "boolean"
|
|
@@ -161,7 +171,7 @@
|
|
|
161
171
|
],
|
|
162
172
|
"flags": {
|
|
163
173
|
"tag": {
|
|
164
|
-
"description": "Workflow environment tag (e.g. prod, test)
|
|
174
|
+
"description": "Workflow environment tag (e.g. prod, test) — the deployment to target for writes; an optional filter for reads.",
|
|
165
175
|
"name": "tag",
|
|
166
176
|
"hasDynamicHelp": false,
|
|
167
177
|
"multiple": false,
|
|
@@ -190,7 +200,7 @@
|
|
|
190
200
|
"type": "option"
|
|
191
201
|
},
|
|
192
202
|
"as": {
|
|
193
|
-
"description": "Attribute the
|
|
203
|
+
"description": "Attribute the write to this Sanity user id (default: a workflow-cli system actor).",
|
|
194
204
|
"name": "as",
|
|
195
205
|
"hasDynamicHelp": false,
|
|
196
206
|
"multiple": false,
|
|
@@ -233,12 +243,12 @@
|
|
|
233
243
|
"examples": [
|
|
234
244
|
"<%= config.bin %> list",
|
|
235
245
|
"<%= config.bin %> list --in-flight",
|
|
236
|
-
"<%= config.bin %> list --
|
|
246
|
+
"<%= config.bin %> list --definition productLaunch",
|
|
237
247
|
"<%= config.bin %> list --tag prod"
|
|
238
248
|
],
|
|
239
249
|
"flags": {
|
|
240
250
|
"tag": {
|
|
241
|
-
"description": "Workflow environment tag (e.g. prod, test)
|
|
251
|
+
"description": "Workflow environment tag (e.g. prod, test) — the deployment to target for writes; an optional filter for reads.",
|
|
242
252
|
"name": "tag",
|
|
243
253
|
"hasDynamicHelp": false,
|
|
244
254
|
"multiple": false,
|
|
@@ -256,9 +266,9 @@
|
|
|
256
266
|
"allowNo": false,
|
|
257
267
|
"type": "boolean"
|
|
258
268
|
},
|
|
259
|
-
"
|
|
260
|
-
"description": "
|
|
261
|
-
"name": "
|
|
269
|
+
"definition": {
|
|
270
|
+
"description": "Only instances of this workflow definition (its `name`; the instance's `definition` field).",
|
|
271
|
+
"name": "definition",
|
|
262
272
|
"hasDynamicHelp": false,
|
|
263
273
|
"multiple": false,
|
|
264
274
|
"type": "option"
|
|
@@ -287,60 +297,7 @@
|
|
|
287
297
|
"list.js"
|
|
288
298
|
]
|
|
289
299
|
},
|
|
290
|
-
"
|
|
291
|
-
"aliases": [],
|
|
292
|
-
"args": {
|
|
293
|
-
"instanceId": {
|
|
294
|
-
"description": "Workflow instance id to move.",
|
|
295
|
-
"name": "instanceId",
|
|
296
|
-
"required": true
|
|
297
|
-
}
|
|
298
|
-
},
|
|
299
|
-
"description": "Move an instance to a new stage. Guards + transition effects run as if the transition fired normally.",
|
|
300
|
-
"examples": [
|
|
301
|
-
"<%= config.bin %> move-stage wf-instance.abc123 --to ready",
|
|
302
|
-
"<%= config.bin %> move-stage wf-instance.abc123 --to ready --reason 'unblock for demo'"
|
|
303
|
-
],
|
|
304
|
-
"flags": {
|
|
305
|
-
"tag": {
|
|
306
|
-
"description": "Workflow environment tag (e.g. prod, test). Overrides WORKFLOW_TAG.",
|
|
307
|
-
"name": "tag",
|
|
308
|
-
"hasDynamicHelp": false,
|
|
309
|
-
"multiple": false,
|
|
310
|
-
"type": "option"
|
|
311
|
-
},
|
|
312
|
-
"to": {
|
|
313
|
-
"description": "Target stage name.",
|
|
314
|
-
"name": "to",
|
|
315
|
-
"required": true,
|
|
316
|
-
"hasDynamicHelp": false,
|
|
317
|
-
"multiple": false,
|
|
318
|
-
"type": "option"
|
|
319
|
-
},
|
|
320
|
-
"reason": {
|
|
321
|
-
"description": "Free-text reason — recorded on the history entry for audit.",
|
|
322
|
-
"name": "reason",
|
|
323
|
-
"hasDynamicHelp": false,
|
|
324
|
-
"multiple": false,
|
|
325
|
-
"type": "option"
|
|
326
|
-
}
|
|
327
|
-
},
|
|
328
|
-
"hasDynamicHelp": false,
|
|
329
|
-
"hiddenAliases": [],
|
|
330
|
-
"id": "move-stage",
|
|
331
|
-
"pluginAlias": "@sanity/workflow-cli",
|
|
332
|
-
"pluginName": "@sanity/workflow-cli",
|
|
333
|
-
"pluginType": "core",
|
|
334
|
-
"strict": true,
|
|
335
|
-
"enableJsonFlag": false,
|
|
336
|
-
"isESM": true,
|
|
337
|
-
"relativePath": [
|
|
338
|
-
"dist",
|
|
339
|
-
"commands",
|
|
340
|
-
"move-stage.js"
|
|
341
|
-
]
|
|
342
|
-
},
|
|
343
|
-
"retry-activity": {
|
|
300
|
+
"reset-activity": {
|
|
344
301
|
"aliases": [],
|
|
345
302
|
"args": {
|
|
346
303
|
"instanceId": {
|
|
@@ -354,12 +311,12 @@
|
|
|
354
311
|
"required": true
|
|
355
312
|
}
|
|
356
313
|
},
|
|
357
|
-
"description": "
|
|
314
|
+
"description": "Reset a failed activity on an in-flight instance — back to pending (re-run) or to skipped (bypass).",
|
|
358
315
|
"flags": {},
|
|
359
316
|
"hasDynamicHelp": false,
|
|
360
317
|
"hidden": true,
|
|
361
318
|
"hiddenAliases": [],
|
|
362
|
-
"id": "
|
|
319
|
+
"id": "reset-activity",
|
|
363
320
|
"pluginAlias": "@sanity/workflow-cli",
|
|
364
321
|
"pluginName": "@sanity/workflow-cli",
|
|
365
322
|
"pluginType": "core",
|
|
@@ -368,20 +325,31 @@
|
|
|
368
325
|
"relativePath": [
|
|
369
326
|
"dist",
|
|
370
327
|
"commands",
|
|
371
|
-
"
|
|
328
|
+
"reset-activity.js"
|
|
372
329
|
]
|
|
373
330
|
},
|
|
374
331
|
"set-stage": {
|
|
375
332
|
"aliases": [],
|
|
376
333
|
"args": {
|
|
377
334
|
"instanceId": {
|
|
378
|
-
"description": "Workflow instance id.",
|
|
335
|
+
"description": "Workflow instance id to move.",
|
|
379
336
|
"name": "instanceId",
|
|
380
337
|
"required": true
|
|
381
338
|
}
|
|
382
339
|
},
|
|
383
|
-
"description": "Force
|
|
340
|
+
"description": "Force an instance into a stage, regardless of its declared transitions and filters — the engine's setStage admin override. The target stage's enter lifecycle still runs (auto-activities start, stage guards reconcile), and the post-move cascade can immediately auto-transition the instance onward.",
|
|
341
|
+
"examples": [
|
|
342
|
+
"<%= config.bin %> set-stage wf-instance.abc123 --to ready",
|
|
343
|
+
"<%= config.bin %> set-stage wf-instance.abc123 --to ready --reason 'unblock for demo'"
|
|
344
|
+
],
|
|
384
345
|
"flags": {
|
|
346
|
+
"tag": {
|
|
347
|
+
"description": "Workflow environment tag (e.g. prod, test) — the deployment to target for writes; an optional filter for reads.",
|
|
348
|
+
"name": "tag",
|
|
349
|
+
"hasDynamicHelp": false,
|
|
350
|
+
"multiple": false,
|
|
351
|
+
"type": "option"
|
|
352
|
+
},
|
|
385
353
|
"to": {
|
|
386
354
|
"description": "Target stage name.",
|
|
387
355
|
"name": "to",
|
|
@@ -391,7 +359,7 @@
|
|
|
391
359
|
"type": "option"
|
|
392
360
|
},
|
|
393
361
|
"reason": {
|
|
394
|
-
"description": "
|
|
362
|
+
"description": "Free-text reason — recorded on the history entry for audit.",
|
|
395
363
|
"name": "reason",
|
|
396
364
|
"hasDynamicHelp": false,
|
|
397
365
|
"multiple": false,
|
|
@@ -399,13 +367,13 @@
|
|
|
399
367
|
}
|
|
400
368
|
},
|
|
401
369
|
"hasDynamicHelp": false,
|
|
402
|
-
"hidden": true,
|
|
403
370
|
"hiddenAliases": [],
|
|
404
371
|
"id": "set-stage",
|
|
405
372
|
"pluginAlias": "@sanity/workflow-cli",
|
|
406
373
|
"pluginName": "@sanity/workflow-cli",
|
|
407
374
|
"pluginType": "core",
|
|
408
375
|
"strict": true,
|
|
376
|
+
"enableJsonFlag": false,
|
|
409
377
|
"isESM": true,
|
|
410
378
|
"relativePath": [
|
|
411
379
|
"dist",
|
|
@@ -428,6 +396,13 @@
|
|
|
428
396
|
"<%= config.bin %> show wf-instance.abc123 --include history"
|
|
429
397
|
],
|
|
430
398
|
"flags": {
|
|
399
|
+
"tag": {
|
|
400
|
+
"description": "Workflow environment tag (e.g. prod, test) — the deployment to target for writes; an optional filter for reads.",
|
|
401
|
+
"name": "tag",
|
|
402
|
+
"hasDynamicHelp": false,
|
|
403
|
+
"multiple": false,
|
|
404
|
+
"type": "option"
|
|
405
|
+
},
|
|
431
406
|
"include": {
|
|
432
407
|
"description": "Optional sections to include in output.",
|
|
433
408
|
"name": "include",
|
|
@@ -455,6 +430,82 @@
|
|
|
455
430
|
"show.js"
|
|
456
431
|
]
|
|
457
432
|
},
|
|
433
|
+
"start": {
|
|
434
|
+
"aliases": [],
|
|
435
|
+
"args": {
|
|
436
|
+
"name": {
|
|
437
|
+
"description": "Workflow definition name.",
|
|
438
|
+
"name": "name",
|
|
439
|
+
"required": true
|
|
440
|
+
}
|
|
441
|
+
},
|
|
442
|
+
"description": "Start a workflow instance from a deployed definition. Supply values for the workflow's input-sourced fields with --field (e.g. the subject document ref).",
|
|
443
|
+
"examples": [
|
|
444
|
+
"<%= config.bin %> start productLaunch",
|
|
445
|
+
"<%= config.bin %> start article-review --field subject='{\"id\":\"dataset:proj:ds:article-1\",\"type\":\"article\"}'",
|
|
446
|
+
"<%= config.bin %> start article-review --as user.xyz --as-role editor",
|
|
447
|
+
"<%= config.bin %> start productLaunch --version 2 --tag prod"
|
|
448
|
+
],
|
|
449
|
+
"flags": {
|
|
450
|
+
"tag": {
|
|
451
|
+
"description": "Workflow environment tag (e.g. prod, test) — the deployment to target for writes; an optional filter for reads.",
|
|
452
|
+
"name": "tag",
|
|
453
|
+
"hasDynamicHelp": false,
|
|
454
|
+
"multiple": false,
|
|
455
|
+
"type": "option"
|
|
456
|
+
},
|
|
457
|
+
"version": {
|
|
458
|
+
"description": "Definition version to start from (default: highest deployed).",
|
|
459
|
+
"name": "version",
|
|
460
|
+
"hasDynamicHelp": false,
|
|
461
|
+
"multiple": false,
|
|
462
|
+
"type": "option"
|
|
463
|
+
},
|
|
464
|
+
"field": {
|
|
465
|
+
"description": "Initial value for a declared input-sourced field, as name=value (repeatable). Values are JSON-parsed, falling back to a string; ref kinds take a JSON object with a GDR `id` and doc `type`.",
|
|
466
|
+
"name": "field",
|
|
467
|
+
"default": [],
|
|
468
|
+
"hasDynamicHelp": false,
|
|
469
|
+
"multiple": true,
|
|
470
|
+
"type": "option"
|
|
471
|
+
},
|
|
472
|
+
"as": {
|
|
473
|
+
"description": "Attribute the write to this Sanity user id (default: a workflow-cli system actor).",
|
|
474
|
+
"name": "as",
|
|
475
|
+
"hasDynamicHelp": false,
|
|
476
|
+
"multiple": false,
|
|
477
|
+
"type": "option"
|
|
478
|
+
},
|
|
479
|
+
"as-role": {
|
|
480
|
+
"description": "Role to attribute to the --as user (repeatable), so role-gated filters pass.",
|
|
481
|
+
"name": "as-role",
|
|
482
|
+
"default": [],
|
|
483
|
+
"hasDynamicHelp": false,
|
|
484
|
+
"multiple": true,
|
|
485
|
+
"type": "option"
|
|
486
|
+
},
|
|
487
|
+
"json": {
|
|
488
|
+
"description": "Emit structured JSON instead of rendered output.",
|
|
489
|
+
"name": "json",
|
|
490
|
+
"allowNo": false,
|
|
491
|
+
"type": "boolean"
|
|
492
|
+
}
|
|
493
|
+
},
|
|
494
|
+
"hasDynamicHelp": false,
|
|
495
|
+
"hiddenAliases": [],
|
|
496
|
+
"id": "start",
|
|
497
|
+
"pluginAlias": "@sanity/workflow-cli",
|
|
498
|
+
"pluginName": "@sanity/workflow-cli",
|
|
499
|
+
"pluginType": "core",
|
|
500
|
+
"strict": true,
|
|
501
|
+
"enableJsonFlag": false,
|
|
502
|
+
"isESM": true,
|
|
503
|
+
"relativePath": [
|
|
504
|
+
"dist",
|
|
505
|
+
"commands",
|
|
506
|
+
"start.js"
|
|
507
|
+
]
|
|
508
|
+
},
|
|
458
509
|
"tail": {
|
|
459
510
|
"aliases": [],
|
|
460
511
|
"args": {
|
|
@@ -468,7 +519,15 @@
|
|
|
468
519
|
"examples": [
|
|
469
520
|
"<%= config.bin %> tail wf-instance.abc123"
|
|
470
521
|
],
|
|
471
|
-
"flags": {
|
|
522
|
+
"flags": {
|
|
523
|
+
"tag": {
|
|
524
|
+
"description": "Workflow environment tag (e.g. prod, test) — the deployment to target for writes; an optional filter for reads.",
|
|
525
|
+
"name": "tag",
|
|
526
|
+
"hasDynamicHelp": false,
|
|
527
|
+
"multiple": false,
|
|
528
|
+
"type": "option"
|
|
529
|
+
}
|
|
530
|
+
},
|
|
472
531
|
"hasDynamicHelp": false,
|
|
473
532
|
"hiddenAliases": [],
|
|
474
533
|
"id": "tail",
|
|
@@ -501,7 +560,7 @@
|
|
|
501
560
|
],
|
|
502
561
|
"flags": {
|
|
503
562
|
"tag": {
|
|
504
|
-
"description": "Workflow environment tag (e.g. prod, test)
|
|
563
|
+
"description": "Workflow environment tag (e.g. prod, test) — the deployment to target for writes; an optional filter for reads.",
|
|
505
564
|
"name": "tag",
|
|
506
565
|
"hasDynamicHelp": false,
|
|
507
566
|
"multiple": false,
|
|
@@ -547,9 +606,9 @@
|
|
|
547
606
|
"definition:diff": {
|
|
548
607
|
"aliases": [],
|
|
549
608
|
"args": {
|
|
550
|
-
"
|
|
609
|
+
"name": {
|
|
551
610
|
"description": "Workflow definition name.",
|
|
552
|
-
"name": "
|
|
611
|
+
"name": "name",
|
|
553
612
|
"required": true
|
|
554
613
|
}
|
|
555
614
|
},
|
|
@@ -560,7 +619,7 @@
|
|
|
560
619
|
],
|
|
561
620
|
"flags": {
|
|
562
621
|
"tag": {
|
|
563
|
-
"description": "Workflow environment tag (e.g. prod, test)
|
|
622
|
+
"description": "Workflow environment tag (e.g. prod, test) — the deployment to target for writes; an optional filter for reads.",
|
|
564
623
|
"name": "tag",
|
|
565
624
|
"hasDynamicHelp": false,
|
|
566
625
|
"multiple": false,
|
|
@@ -600,7 +659,7 @@
|
|
|
600
659
|
],
|
|
601
660
|
"flags": {
|
|
602
661
|
"tag": {
|
|
603
|
-
"description": "Workflow environment tag (e.g. prod, test)
|
|
662
|
+
"description": "Workflow environment tag (e.g. prod, test) — the deployment to target for writes; an optional filter for reads.",
|
|
604
663
|
"name": "tag",
|
|
605
664
|
"hasDynamicHelp": false,
|
|
606
665
|
"multiple": false,
|
|
@@ -614,9 +673,9 @@
|
|
|
614
673
|
"multiple": false,
|
|
615
674
|
"type": "option"
|
|
616
675
|
},
|
|
617
|
-
"
|
|
618
|
-
"description": "Filter to a single workflow definition name (e.g. product-launch)",
|
|
619
|
-
"name": "
|
|
676
|
+
"name": {
|
|
677
|
+
"description": "Filter to a single workflow definition name (e.g. product-launch).",
|
|
678
|
+
"name": "name",
|
|
620
679
|
"hasDynamicHelp": false,
|
|
621
680
|
"multiple": false,
|
|
622
681
|
"type": "option"
|
|
@@ -650,7 +709,7 @@
|
|
|
650
709
|
"description": "Show a deployed workflow definition.",
|
|
651
710
|
"flags": {
|
|
652
711
|
"tag": {
|
|
653
|
-
"description": "Workflow environment tag (e.g. prod, test)
|
|
712
|
+
"description": "Workflow environment tag (e.g. prod, test) — the deployment to target for writes; an optional filter for reads.",
|
|
654
713
|
"name": "tag",
|
|
655
714
|
"hasDynamicHelp": false,
|
|
656
715
|
"multiple": false,
|
|
@@ -681,5 +740,5 @@
|
|
|
681
740
|
]
|
|
682
741
|
}
|
|
683
742
|
},
|
|
684
|
-
"version": "0.
|
|
743
|
+
"version": "0.9.0"
|
|
685
744
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/workflow-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Command-line tool for deploying, inspecting, and administering Sanity workflow definitions and instances.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -46,22 +46,24 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@oclif/core": "^4.11.4",
|
|
48
48
|
"@oclif/plugin-help": "^6.2.50",
|
|
49
|
+
"@sanity/cli-core": "^2.1.1",
|
|
49
50
|
"@sanity/client": "^7.22.1",
|
|
50
51
|
"boxen": "^8.0.1",
|
|
51
52
|
"console-table-printer": "^2.16.0",
|
|
52
53
|
"date-fns": "^4.4.0",
|
|
53
54
|
"diff": "^9.0.0",
|
|
55
|
+
"jiti": "^2.7.0",
|
|
54
56
|
"log-symbols": "^7.0.1",
|
|
55
57
|
"ora": "^9.4.0",
|
|
56
|
-
"@sanity/workflow-engine": "0.
|
|
58
|
+
"@sanity/workflow-engine": "0.14.0"
|
|
57
59
|
},
|
|
58
60
|
"devDependencies": {
|
|
59
61
|
"@types/diff": "^8.0.0",
|
|
60
62
|
"@types/node": "^24.12.4",
|
|
61
63
|
"oclif": "^4.23.16",
|
|
62
64
|
"vitest": "^4.1.8",
|
|
63
|
-
"@sanity/workflow-engine-test": "0.
|
|
64
|
-
"@sanity/workflow-examples": "0.
|
|
65
|
+
"@sanity/workflow-engine-test": "0.9.0",
|
|
66
|
+
"@sanity/workflow-examples": "0.4.0"
|
|
65
67
|
},
|
|
66
68
|
"oclif": {
|
|
67
69
|
"bin": "sanity-workflows",
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { Command } from '@oclif/core';
|
|
2
|
-
import { type SetStageArgs } from '@sanity/workflow-engine';
|
|
3
|
-
import { type WorkflowConfig } from '../lib/config.ts';
|
|
4
|
-
import { type RanOp } from '../lib/ops-report.ts';
|
|
5
|
-
export default class MoveStage extends Command {
|
|
6
|
-
static description: string;
|
|
7
|
-
static examples: string[];
|
|
8
|
-
static args: {
|
|
9
|
-
instanceId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
10
|
-
};
|
|
11
|
-
static flags: {
|
|
12
|
-
to: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
-
reason: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
-
tag: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
-
};
|
|
16
|
-
run(): Promise<void>;
|
|
17
|
-
}
|
|
18
|
-
/** The shared operation args ({@link buildOperationArgs}) plus the
|
|
19
|
-
* setStage-specific target. */
|
|
20
|
-
export declare function buildSetStageArgs(config: WorkflowConfig, instanceId: string, targetStage: string, reason: string | undefined): Omit<SetStageArgs, 'client'>;
|
|
21
|
-
interface SetStageOutcome {
|
|
22
|
-
fired: boolean;
|
|
23
|
-
cascaded: number;
|
|
24
|
-
instance: {
|
|
25
|
-
currentStage: string;
|
|
26
|
-
};
|
|
27
|
-
ranOps?: RanOp[];
|
|
28
|
-
}
|
|
29
|
-
export interface MoveStageReport {
|
|
30
|
-
fired: boolean;
|
|
31
|
-
/** Spinner message — warn copy when not fired, success copy otherwise. */
|
|
32
|
-
message: string;
|
|
33
|
-
/**
|
|
34
|
-
* The full "ops applied" block to print after the spinner — a blank
|
|
35
|
-
* line, the header, and one line per op. Empty when nothing ran (or
|
|
36
|
-
* when the transition didn't fire), so the caller can print it
|
|
37
|
-
* unconditionally.
|
|
38
|
-
*/
|
|
39
|
-
opsLines: string[];
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Turn a `setStage` result into the spinner message + ops block. Pure so
|
|
43
|
-
* the fired / not-fired / cascaded / ops permutations can be asserted
|
|
44
|
-
* without driving a real transition.
|
|
45
|
-
*/
|
|
46
|
-
export declare function moveStageReport(result: SetStageOutcome, to: string): MoveStageReport;
|
|
47
|
-
export {};
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { styleText } from 'node:util';
|
|
2
|
-
import { Args, Command, Flags } from '@oclif/core';
|
|
3
|
-
import { workflow } from '@sanity/workflow-engine';
|
|
4
|
-
import ora from 'ora';
|
|
5
|
-
import { loadClient } from "../lib/client.js";
|
|
6
|
-
import { loadWorkflowConfig } from "../lib/config.js";
|
|
7
|
-
import { fail } from "../lib/fail.js";
|
|
8
|
-
import { tagFlags } from "../lib/flags.js";
|
|
9
|
-
import { buildOperationArgs } from "../lib/operation-args.js";
|
|
10
|
-
import { emitWriteReport, opsAppliedLines } from "../lib/ops-report.js";
|
|
11
|
-
export default class MoveStage extends Command {
|
|
12
|
-
static description = 'Move an instance to a new stage. Guards + transition effects run as if the transition fired normally.';
|
|
13
|
-
static examples = [
|
|
14
|
-
'<%= config.bin %> move-stage wf-instance.abc123 --to ready',
|
|
15
|
-
"<%= config.bin %> move-stage wf-instance.abc123 --to ready --reason 'unblock for demo'",
|
|
16
|
-
];
|
|
17
|
-
static args = {
|
|
18
|
-
instanceId: Args.string({
|
|
19
|
-
required: true,
|
|
20
|
-
description: 'Workflow instance id to move.',
|
|
21
|
-
}),
|
|
22
|
-
};
|
|
23
|
-
static flags = {
|
|
24
|
-
...tagFlags,
|
|
25
|
-
to: Flags.string({
|
|
26
|
-
required: true,
|
|
27
|
-
description: 'Target stage name.',
|
|
28
|
-
}),
|
|
29
|
-
reason: Flags.string({
|
|
30
|
-
description: 'Free-text reason — recorded on the history entry for audit.',
|
|
31
|
-
}),
|
|
32
|
-
};
|
|
33
|
-
async run() {
|
|
34
|
-
const { args, flags } = await this.parse(MoveStage);
|
|
35
|
-
const config = loadWorkflowConfig(flags.tag);
|
|
36
|
-
const client = loadClient();
|
|
37
|
-
const spinner = ora(`Moving ${args.instanceId} → ${flags.to}…`).start();
|
|
38
|
-
try {
|
|
39
|
-
const result = await workflow.setStage({
|
|
40
|
-
client,
|
|
41
|
-
...buildSetStageArgs(config, args.instanceId, flags.to, flags.reason),
|
|
42
|
-
});
|
|
43
|
-
emitWriteReport(spinner, moveStageReport(result, flags.to), (line) => this.log(line));
|
|
44
|
-
}
|
|
45
|
-
catch (error) {
|
|
46
|
-
spinner.fail('Move rejected');
|
|
47
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
48
|
-
fail('setStage error:', message);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
/** The shared operation args ({@link buildOperationArgs}) plus the
|
|
53
|
-
* setStage-specific target. */
|
|
54
|
-
export function buildSetStageArgs(config, instanceId, targetStage, reason) {
|
|
55
|
-
return { ...buildOperationArgs(config, instanceId, reason), targetStage };
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Turn a `setStage` result into the spinner message + ops block. Pure so
|
|
59
|
-
* the fired / not-fired / cascaded / ops permutations can be asserted
|
|
60
|
-
* without driving a real transition.
|
|
61
|
-
*/
|
|
62
|
-
export function moveStageReport(result, to) {
|
|
63
|
-
const stage = styleText('bold', result.instance.currentStage);
|
|
64
|
-
if (!result.fired) {
|
|
65
|
-
return {
|
|
66
|
-
fired: false,
|
|
67
|
-
message: `setStage returned without firing — instance is already at ${stage}`,
|
|
68
|
-
opsLines: [],
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
const tail = result.cascaded > 0 ? `, then cascaded ${result.cascaded} auto-transition(s)` : '';
|
|
72
|
-
return {
|
|
73
|
-
fired: true,
|
|
74
|
-
message: `Now at ${stage} (was → ${to}${tail})`,
|
|
75
|
-
opsLines: opsAppliedLines(result.ranOps),
|
|
76
|
-
};
|
|
77
|
-
}
|