@sanity/workflow-cli 0.13.0 → 0.14.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/CHANGELOG.md +15 -0
- package/README.md +37 -27
- package/dist/commands/editorial-workflows/abort.d.ts +1 -0
- package/dist/commands/editorial-workflows/abort.js +2 -2
- package/dist/commands/editorial-workflows/definition/delete.d.ts +1 -0
- package/dist/commands/editorial-workflows/definition/delete.js +2 -2
- package/dist/commands/editorial-workflows/definition/diff.d.ts +1 -0
- package/dist/commands/editorial-workflows/definition/diff.js +2 -2
- package/dist/commands/editorial-workflows/deploy.d.ts +2 -1
- package/dist/commands/editorial-workflows/deploy.js +15 -9
- package/dist/commands/editorial-workflows/diagnose.d.ts +1 -0
- package/dist/commands/editorial-workflows/diagnose.js +2 -2
- package/dist/commands/editorial-workflows/fire-action.d.ts +1 -0
- package/dist/commands/editorial-workflows/fire-action.js +2 -2
- package/dist/commands/editorial-workflows/nuke.d.ts +2 -1
- package/dist/commands/editorial-workflows/nuke.js +13 -9
- package/dist/commands/editorial-workflows/set-stage.d.ts +1 -0
- package/dist/commands/editorial-workflows/set-stage.js +2 -2
- package/dist/commands/editorial-workflows/start.d.ts +1 -0
- package/dist/commands/editorial-workflows/start.js +2 -2
- package/dist/lib/context.d.ts +24 -9
- package/dist/lib/context.js +15 -6
- package/dist/lib/flags.d.ts +27 -5
- package/dist/lib/flags.js +17 -1
- package/dist/lib/nuke.d.ts +15 -1
- package/dist/lib/nuke.js +22 -1
- package/dist/lib/select-deployment.d.ts +37 -15
- package/dist/lib/select-deployment.js +49 -23
- package/oclif.manifest.json +131 -19
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @sanity/workflow-cli
|
|
2
2
|
|
|
3
|
+
## 0.14.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 59b40fd: **BREAKING:** deployment selection now keys on the deployment `name`, selected with `--deployment`. Deployment-targeted commands (`start`, `definition diff`, `definition delete`, `nuke`) take `--deployment` as the precise selector; `--tag` still selects while it names exactly one deployment and errors listing the candidates when it spans several. `deploy --tag <tag>` now deploys every deployment carrying the tag (a tag is an environment group); `--deployment` deploys one, `--all-tags` deploys everything, and the three are mutually exclusive. `nuke` requires exactly one of `--deployment` / `--tag`, and refuses when another same-tag deployment sweeps an overlapping resource — guard document ids embed only the tag, so within a shared dataset the sweep cannot tell the deployments' guards apart and would delete the other's live locks. The interactive deploy prompt selects by name with the tag as its description. Read commands keep `--tag` as an optional filter — a repeated tag fans reads out across every resource it is deployed to.
|
|
8
|
+
- de7ccfa: The instance-keyed commands (`diagnose`, `abort`, `set-stage`, `fire-action`) accept `--deployment <name>` to choose which resource to read the instance from — the precise selector consistent with the deployment-targeted commands. `--deployment` names one deployment and reads from the resource it targets; `--tag` stays the optional narrower it was, and the instance's own tag partition still comes from the loaded instance itself, never from the flag. This closes the dead end where a tag repeated across several resources left these commands unable to resolve a resource, and the "spans multiple resources" failures now point at `--deployment` as the remedy.
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- Updated dependencies [24b11dd]
|
|
13
|
+
- Updated dependencies [2005ab7]
|
|
14
|
+
- Updated dependencies [24b11dd]
|
|
15
|
+
- Updated dependencies [59b40fd]
|
|
16
|
+
- @sanity/workflow-engine@0.19.0
|
|
17
|
+
|
|
3
18
|
## 0.13.0
|
|
4
19
|
|
|
5
20
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -49,7 +49,8 @@ project will fail on cross-resource reads.
|
|
|
49
49
|
|
|
50
50
|
The CLI is configured by a `sanity.workflow.ts` (or `.js`/`.mjs`) discovered in
|
|
51
51
|
the directory you run from. It exports a config built with
|
|
52
|
-
`defineWorkflowConfig`, declaring
|
|
52
|
+
`defineWorkflowConfig`, declaring your **deployments** (typically one per
|
|
53
|
+
environment):
|
|
53
54
|
|
|
54
55
|
```ts
|
|
55
56
|
import {defineWorkflowConfig} from '@sanity/workflow-engine/define'
|
|
@@ -60,7 +61,7 @@ export default defineWorkflowConfig({
|
|
|
60
61
|
deployments: [
|
|
61
62
|
{
|
|
62
63
|
expectedMinReaderModel: 2,
|
|
63
|
-
name: 'production',
|
|
64
|
+
name: 'production', // the deployment's unique identity (lowercase letters, digits, dashes)
|
|
64
65
|
tag: 'prod', // the environment partition the engine's docs are scoped to
|
|
65
66
|
workflowResource: {type: 'dataset', id: 'acme.workflows'}, // where those docs live
|
|
66
67
|
resourceAliases: [
|
|
@@ -76,11 +77,20 @@ export default defineWorkflowConfig({
|
|
|
76
77
|
})
|
|
77
78
|
```
|
|
78
79
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
`name` is the deployment's identity: unique across the config and constrained
|
|
81
|
+
to the same grammar as `tag`. Tags group deployments by environment and may
|
|
82
|
+
repeat, as long as no two deployments share both a `workflowResource` and a
|
|
83
|
+
`tag` — that pair is the storage partition, and the config rejects the
|
|
84
|
+
collision naming both entries.
|
|
85
|
+
|
|
86
|
+
Pick a deployment with `--deployment <name>`; with a single deployment configured you
|
|
87
|
+
can omit it. `--tag <tag>` also works on single-deployment commands while the
|
|
88
|
+
tag names exactly one deployment — on `deploy` it targets every deployment
|
|
89
|
+
carrying the tag (a tag is an environment group). With several configured, a
|
|
90
|
+
bare interactive `deploy` presents a keyboard-driven deployment selector (by
|
|
91
|
+
name, tag alongside). In CI or another non-interactive shell, it fails asking
|
|
92
|
+
for `--deployment`, `--tag`, or `--all-tags` instead of blocking for input.
|
|
93
|
+
`--all-tags` deploys every deployment in the config in one run: a failure in one doesn't
|
|
84
94
|
stop the rest — the run continues, prints a summary of what failed, and exits
|
|
85
95
|
non-zero. The client's project + dataset are derived from the deployment's
|
|
86
96
|
`workflowResource`, and `deploy` expands each definition's `@<handle>:`
|
|
@@ -143,26 +153,26 @@ stale compiled output.
|
|
|
143
153
|
|
|
144
154
|
## Command status
|
|
145
155
|
|
|
146
|
-
| Command
|
|
147
|
-
|
|
|
148
|
-
| `deploy`
|
|
149
|
-
| `deploy --all-tags`
|
|
150
|
-
| `deploy --check`
|
|
151
|
-
| `deploy --dry-run`
|
|
152
|
-
| `deploy --only <name>`
|
|
153
|
-
| `start <name>`
|
|
154
|
-
| `list`
|
|
155
|
-
| `show <instance-id>`
|
|
156
|
-
| `diagnose <instance-id>`
|
|
157
|
-
| `tail <instance-id>`
|
|
158
|
-
| `abort <instance-id>`
|
|
159
|
-
| `set-stage <instance-id> --to <stage>`
|
|
160
|
-
| `fire-action <instance-id>`
|
|
161
|
-
| `definition list`
|
|
162
|
-
| `definition show <name>`
|
|
163
|
-
| `definition diff <name>`
|
|
164
|
-
| `definition delete <name>`
|
|
165
|
-
| `nuke --tag <tag>`
|
|
156
|
+
| Command | Status |
|
|
157
|
+
| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
158
|
+
| `deploy` | wired — calls `workflow.deployDefinitions` over the selected deployment's definitions |
|
|
159
|
+
| `deploy --all-tags` | wired — deploys every deployment in the config, continuing past per-deployment failures |
|
|
160
|
+
| `deploy --check` | wired — runs `validateDefinition` over the local batch + a duplicate-name check |
|
|
161
|
+
| `deploy --dry-run` | wired — fetches existing docs and renders a coloured JSON diff per change |
|
|
162
|
+
| `deploy --only <name>` | wired — filters deploy/check/dry-run to one definition by `name` |
|
|
163
|
+
| `start <name>` | wired — calls `workflow.startInstance` (`--field` for input fields) |
|
|
164
|
+
| `list` | wired — `client.fetch` over `sanity.workflow.instance` documents (`--definition <name>` to filter) |
|
|
165
|
+
| `show <instance-id>` | wired — `client.getDocument` |
|
|
166
|
+
| `diagnose <instance-id>` | wired — calls `workflow.diagnose`, classifies why the instance is/isn't progressing |
|
|
167
|
+
| `tail <instance-id>` | wired — `client.listen()` over the instance, prints new history entries |
|
|
168
|
+
| `abort <instance-id>` | wired — calls `workflow.abortInstance` (hard stop: cancels pending effects, removes guards) |
|
|
169
|
+
| `set-stage <instance-id> --to <stage>` | wired — calls `workflow.setStage` (admin override: skips declared transitions/filters; enter lifecycle + cascade still run) |
|
|
170
|
+
| `fire-action <instance-id>` | wired — `workflow.availableActions` lists actions; `workflow.fireAction` fires one |
|
|
171
|
+
| `definition list` | wired — `client.fetch` over `sanity.workflow.definition` documents |
|
|
172
|
+
| `definition show <name>` | wired — `client.fetch`, latest version unless `--version` |
|
|
173
|
+
| `definition diff <name>` | wired — diffs the in-code definition against the deployed latest (`--version` to pin) |
|
|
174
|
+
| `definition delete <name>` | wired — calls `workflow.deleteDefinition` (refuses on live instances unless `--cascade`) |
|
|
175
|
+
| `nuke --deployment <name>` / `nuke --tag <tag>` | wired — dev-period reset (exists only until the versioned upgrade framework): deletes every engine-owned doc for the deployment's tag (instances, definitions, guards across resources); exactly one selector required; refuses while another same-tag deployment sweeps an overlapping resource (guard ids embed only the tag); plan + typed confirm |
|
|
166
176
|
|
|
167
177
|
## Telemetry
|
|
168
178
|
|
|
@@ -10,6 +10,7 @@ export default class Abort extends WorkflowCommand {
|
|
|
10
10
|
};
|
|
11
11
|
static flags: {
|
|
12
12
|
reason: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
deployment: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
14
|
tag: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
15
|
};
|
|
15
16
|
run(): Promise<void>;
|
|
@@ -3,7 +3,7 @@ import { Args, Flags } from '@oclif/core';
|
|
|
3
3
|
import { workflow } from '@sanity/workflow-engine';
|
|
4
4
|
import { WorkflowCommand } from "../../lib/base-command.js";
|
|
5
5
|
import { resolveInstanceContext } from "../../lib/context.js";
|
|
6
|
-
import {
|
|
6
|
+
import { instanceFlags } from "../../lib/flags.js";
|
|
7
7
|
import { buildOperationArgs } from "../../lib/operation-args.js";
|
|
8
8
|
import { runWriteVerb } from "../../lib/ops-report.js";
|
|
9
9
|
export default class Abort extends WorkflowCommand {
|
|
@@ -17,7 +17,7 @@ export default class Abort extends WorkflowCommand {
|
|
|
17
17
|
instanceId: Args.string({ required: true, description: 'Workflow instance id.' }),
|
|
18
18
|
};
|
|
19
19
|
static flags = {
|
|
20
|
-
...
|
|
20
|
+
...instanceFlags,
|
|
21
21
|
reason: Flags.string({ description: 'Reason for aborting (recorded in history).' }),
|
|
22
22
|
};
|
|
23
23
|
async run() {
|
|
@@ -12,6 +12,7 @@ export default class DefinitionDelete extends WorkflowCommand {
|
|
|
12
12
|
version: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
13
|
cascade: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
14
|
reason: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
deployment: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
16
|
tag: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
17
|
};
|
|
17
18
|
run(): Promise<void>;
|
|
@@ -3,7 +3,7 @@ import { Args, Flags } from '@oclif/core';
|
|
|
3
3
|
import { workflow, } from '@sanity/workflow-engine';
|
|
4
4
|
import { WorkflowCommand } from "../../../lib/base-command.js";
|
|
5
5
|
import { resolveContext } from "../../../lib/context.js";
|
|
6
|
-
import {
|
|
6
|
+
import { deploymentFlags } from "../../../lib/flags.js";
|
|
7
7
|
import { baseEngineArgs } from "../../../lib/operation-args.js";
|
|
8
8
|
import { runWriteVerb } from "../../../lib/ops-report.js";
|
|
9
9
|
export default class DefinitionDelete extends WorkflowCommand {
|
|
@@ -20,7 +20,7 @@ export default class DefinitionDelete extends WorkflowCommand {
|
|
|
20
20
|
name: Args.string({ required: true, description: 'Workflow definition name.' }),
|
|
21
21
|
};
|
|
22
22
|
static flags = {
|
|
23
|
-
...
|
|
23
|
+
...deploymentFlags,
|
|
24
24
|
version: Flags.integer({
|
|
25
25
|
description: 'Delete only this deployed version (default: every version).',
|
|
26
26
|
}),
|
|
@@ -9,6 +9,7 @@ export default class DefinitionDiff extends WorkflowCommand {
|
|
|
9
9
|
};
|
|
10
10
|
static flags: {
|
|
11
11
|
version: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
deployment: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
13
|
tag: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
14
|
};
|
|
14
15
|
run(): Promise<void>;
|
|
@@ -5,7 +5,7 @@ import { WorkflowCommand } from "../../../lib/base-command.js";
|
|
|
5
5
|
import { resolveContext } from "../../../lib/context.js";
|
|
6
6
|
import { fetchDeployedDefinition, selectDefinitions, validateOrFail, } from "../../../lib/definitions.js";
|
|
7
7
|
import { diffReport } from "../../../lib/diff.js";
|
|
8
|
-
import {
|
|
8
|
+
import { deploymentFlags } from "../../../lib/flags.js";
|
|
9
9
|
import { deploymentToTarget } from "../../../lib/select-deployment.js";
|
|
10
10
|
export default class DefinitionDiff extends WorkflowCommand {
|
|
11
11
|
static aliases = ['definition:diff'];
|
|
@@ -18,7 +18,7 @@ export default class DefinitionDiff extends WorkflowCommand {
|
|
|
18
18
|
name: Args.string({ required: true, description: 'Workflow definition name.' }),
|
|
19
19
|
};
|
|
20
20
|
static flags = {
|
|
21
|
-
...
|
|
21
|
+
...deploymentFlags,
|
|
22
22
|
version: Flags.integer({ description: 'Deployed version to diff against (default: latest).' }),
|
|
23
23
|
};
|
|
24
24
|
async run() {
|
|
@@ -15,12 +15,13 @@ export default class Deploy extends WorkflowCommand {
|
|
|
15
15
|
static description: string;
|
|
16
16
|
static examples: string[];
|
|
17
17
|
static flags: {
|
|
18
|
+
tag: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
19
|
'all-tags': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
19
20
|
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
20
21
|
check: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
21
22
|
only: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
22
23
|
'share-defs': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
23
|
-
|
|
24
|
+
deployment: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
24
25
|
};
|
|
25
26
|
run(): Promise<void>;
|
|
26
27
|
/** Deploy (or diff, for `--dry-run`) one deployment's definitions.
|
|
@@ -8,9 +8,9 @@ import { clientFor, resolveTokenOrFail } from "../../lib/client.js";
|
|
|
8
8
|
import { selectDefinitions, validateOrFail } from "../../lib/definitions.js";
|
|
9
9
|
import { diffReport } from "../../lib/diff.js";
|
|
10
10
|
import { fail, isAuthRejection } from "../../lib/fail.js";
|
|
11
|
-
import {
|
|
11
|
+
import { deploymentFlags } from "../../lib/flags.js";
|
|
12
12
|
import { loadWorkflowConfig } from "../../lib/load-config.js";
|
|
13
|
-
import { deploymentToTarget, selectDeployments } from "../../lib/select-deployment.js";
|
|
13
|
+
import { deploymentLabel, deploymentToTarget, selectDeployments, } from "../../lib/select-deployment.js";
|
|
14
14
|
import { shareDefinitionsAfterDeploy } from "../../lib/share-definitions.js";
|
|
15
15
|
import { cliTelemetry } from "../../lib/telemetry.js";
|
|
16
16
|
import { groupBanner } from "../../lib/ui.js";
|
|
@@ -18,6 +18,7 @@ export default class Deploy extends WorkflowCommand {
|
|
|
18
18
|
static aliases = ['deploy'];
|
|
19
19
|
static description = 'Validate, diff, and deploy workflow definitions to the resource bound by the selected deployment.';
|
|
20
20
|
static examples = [
|
|
21
|
+
'<%= config.bin %> deploy --deployment review-prod',
|
|
21
22
|
'<%= config.bin %> deploy --tag prod',
|
|
22
23
|
'<%= config.bin %> deploy --all-tags',
|
|
23
24
|
'<%= config.bin %> deploy --check',
|
|
@@ -25,11 +26,15 @@ export default class Deploy extends WorkflowCommand {
|
|
|
25
26
|
'<%= config.bin %> deploy --only productLaunch',
|
|
26
27
|
];
|
|
27
28
|
static flags = {
|
|
28
|
-
...
|
|
29
|
+
...deploymentFlags,
|
|
30
|
+
tag: Flags.string({
|
|
31
|
+
description: 'Workflow environment tag (e.g. prod, test) — deploys every deployment carrying the tag (a tag is an environment group).',
|
|
32
|
+
exclusive: ['deployment'],
|
|
33
|
+
}),
|
|
29
34
|
'all-tags': Flags.boolean({
|
|
30
|
-
description: 'Deploy every deployment in the config, not just
|
|
35
|
+
description: 'Deploy every deployment in the config, not just a selection.',
|
|
31
36
|
default: false,
|
|
32
|
-
exclusive: ['tag'],
|
|
37
|
+
exclusive: ['tag', 'deployment'],
|
|
33
38
|
}),
|
|
34
39
|
'dry-run': Flags.boolean({
|
|
35
40
|
description: 'Validate + diff against the deployed version; do not write.',
|
|
@@ -51,7 +56,11 @@ export default class Deploy extends WorkflowCommand {
|
|
|
51
56
|
const { flags } = await this.parse(Deploy);
|
|
52
57
|
validateModeFlags(flags.check, flags['dry-run']);
|
|
53
58
|
const config = await loadWorkflowConfig();
|
|
54
|
-
const batches = buildBatches(await selectDeployments(config, {
|
|
59
|
+
const batches = buildBatches(await selectDeployments(config, {
|
|
60
|
+
name: flags.deployment,
|
|
61
|
+
tag: flags.tag,
|
|
62
|
+
allTags: flags['all-tags'],
|
|
63
|
+
}), flags.only);
|
|
55
64
|
const log = (line) => this.log(line);
|
|
56
65
|
if (flags.check) {
|
|
57
66
|
await reconcileBatches({
|
|
@@ -145,9 +154,6 @@ export function validateModeFlags(check, dryRun) {
|
|
|
145
154
|
fail('Pass either --check or --dry-run, not both.');
|
|
146
155
|
}
|
|
147
156
|
}
|
|
148
|
-
function deploymentLabel({ name, tag }) {
|
|
149
|
-
return `${name} (${tag})`;
|
|
150
|
-
}
|
|
151
157
|
export function buildBatches(deployments, only) {
|
|
152
158
|
return deployments.map((deployment) => {
|
|
153
159
|
const context = deployments.length > 1 ? `${deploymentLabel(deployment)} — ` : '';
|
|
@@ -40,6 +40,7 @@ export default class Diagnose extends WorkflowCommand {
|
|
|
40
40
|
};
|
|
41
41
|
static flags: {
|
|
42
42
|
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
43
|
+
deployment: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
43
44
|
tag: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
44
45
|
};
|
|
45
46
|
run(): Promise<void>;
|
|
@@ -5,7 +5,7 @@ import logSymbols from 'log-symbols';
|
|
|
5
5
|
import { WorkflowCommand } from "../../lib/base-command.js";
|
|
6
6
|
import { resolveInstanceContext } from "../../lib/context.js";
|
|
7
7
|
import { fail, failureDetail } from "../../lib/fail.js";
|
|
8
|
-
import {
|
|
8
|
+
import { instanceFlags, jsonFlags } from "../../lib/flags.js";
|
|
9
9
|
import { baseEngineArgs } from "../../lib/operation-args.js";
|
|
10
10
|
import { formatTimestamp, sectionHeader, activityIcon } from "../../lib/ui.js";
|
|
11
11
|
import { instanceHeader } from "./show.js";
|
|
@@ -223,7 +223,7 @@ export default class Diagnose extends WorkflowCommand {
|
|
|
223
223
|
instanceId: Args.string({ required: true, description: 'Workflow instance id.' }),
|
|
224
224
|
};
|
|
225
225
|
static flags = {
|
|
226
|
-
...
|
|
226
|
+
...instanceFlags,
|
|
227
227
|
...jsonFlags,
|
|
228
228
|
};
|
|
229
229
|
async run() {
|
|
@@ -41,6 +41,7 @@ export default class FireAction extends WorkflowCommand {
|
|
|
41
41
|
activity: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
42
42
|
action: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
43
43
|
param: import("@oclif/core/interfaces").OptionFlag<string[], import("@oclif/core/interfaces").CustomOptions>;
|
|
44
|
+
deployment: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
44
45
|
tag: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
45
46
|
};
|
|
46
47
|
run(): Promise<void>;
|
|
@@ -5,7 +5,7 @@ import logSymbols from 'log-symbols';
|
|
|
5
5
|
import { WorkflowCommand } from "../../lib/base-command.js";
|
|
6
6
|
import { resolveInstanceContext } from "../../lib/context.js";
|
|
7
7
|
import { fail, failOnThrow, failureDetail } from "../../lib/fail.js";
|
|
8
|
-
import {
|
|
8
|
+
import { instanceFlags, jsonFlags } from "../../lib/flags.js";
|
|
9
9
|
import { baseEngineArgs } from "../../lib/operation-args.js";
|
|
10
10
|
import { cascadeTail, opsAppliedLines, runWriteVerb, } from "../../lib/ops-report.js";
|
|
11
11
|
import { parseParams } from "../../lib/params.js";
|
|
@@ -93,7 +93,7 @@ export default class FireAction extends WorkflowCommand {
|
|
|
93
93
|
instanceId: Args.string({ required: true, description: 'Workflow instance id.' }),
|
|
94
94
|
};
|
|
95
95
|
static flags = {
|
|
96
|
-
...
|
|
96
|
+
...instanceFlags,
|
|
97
97
|
activity: Flags.string({
|
|
98
98
|
description: 'Activity the action belongs to. Required to fire; omit --action to list.',
|
|
99
99
|
}),
|
|
@@ -5,7 +5,8 @@ export default class Nuke extends WorkflowCommand {
|
|
|
5
5
|
static description: string;
|
|
6
6
|
static examples: string[];
|
|
7
7
|
static flags: {
|
|
8
|
-
|
|
8
|
+
deployment: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
tag: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
10
|
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
11
|
};
|
|
11
12
|
run(): Promise<void>;
|
|
@@ -7,7 +7,7 @@ import { clientFor, resolveApiHost, resolveTokenOrFail } from "../../lib/client.
|
|
|
7
7
|
import { dedupeResources } from "../../lib/context.js";
|
|
8
8
|
import { fail } from "../../lib/fail.js";
|
|
9
9
|
import { loadWorkflowConfig } from "../../lib/load-config.js";
|
|
10
|
-
import { confirmationMatches, executeNuke, formatNukeSummary, involvedTargets, planCounts, renderNukePlan, resolveNukePlan, } from "../../lib/nuke.js";
|
|
10
|
+
import { confirmationMatches, executeNuke, formatNukeSummary, involvedTargets, planCounts, refuseOverlappingNuke, renderNukePlan, resolveNukePlan, sweptResources, } from "../../lib/nuke.js";
|
|
11
11
|
import { runWriteVerb } from "../../lib/ops-report.js";
|
|
12
12
|
import { canPromptOnStderr } from "../../lib/prompt.js";
|
|
13
13
|
import { selectDeployment } from "../../lib/select-deployment.js";
|
|
@@ -19,13 +19,17 @@ export default class Nuke extends WorkflowCommand {
|
|
|
19
19
|
'resource). Content documents are never touched. Prints a dry-run plan, then requires you to ' +
|
|
20
20
|
'type back every involved dataset (--force skips the prompt; the plan still prints).';
|
|
21
21
|
static examples = [
|
|
22
|
-
'<%= config.bin %> nuke --
|
|
22
|
+
'<%= config.bin %> nuke --deployment plugin-dev',
|
|
23
23
|
'<%= config.bin %> nuke --tag plugin-dev --force',
|
|
24
24
|
];
|
|
25
25
|
static flags = {
|
|
26
|
+
deployment: Flags.string({
|
|
27
|
+
description: 'The deployment name to reset.',
|
|
28
|
+
exactlyOne: ['deployment', 'tag'],
|
|
29
|
+
}),
|
|
26
30
|
tag: Flags.string({
|
|
27
|
-
description: 'The deployment tag to reset
|
|
28
|
-
|
|
31
|
+
description: 'The deployment tag to reset (while it names exactly one deployment).',
|
|
32
|
+
exactlyOne: ['deployment', 'tag'],
|
|
29
33
|
}),
|
|
30
34
|
force: Flags.boolean({
|
|
31
35
|
description: 'Skip the confirmation prompt (for scripts/CI). The plan still prints.',
|
|
@@ -35,7 +39,8 @@ export default class Nuke extends WorkflowCommand {
|
|
|
35
39
|
async run() {
|
|
36
40
|
const { flags } = await this.parse(Nuke);
|
|
37
41
|
const config = await loadWorkflowConfig();
|
|
38
|
-
const deployment = selectDeployment(config, { tag: flags.tag });
|
|
42
|
+
const deployment = selectDeployment(config, { name: flags.deployment, tag: flags.tag });
|
|
43
|
+
refuseOverlappingNuke(config.deployments, deployment);
|
|
39
44
|
const targets = buildTargets(deployment, await resolveTokenOrFail());
|
|
40
45
|
const plan = await resolveNukePlan({ tag: deployment.tag, targets });
|
|
41
46
|
const apiHost = resolveApiHost() ?? 'https://api.sanity.io (production default)';
|
|
@@ -58,12 +63,11 @@ export default class Nuke extends WorkflowCommand {
|
|
|
58
63
|
}
|
|
59
64
|
}
|
|
60
65
|
function buildTargets(deployment, token) {
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
return dedupeResources([engineResource, ...aliasResources]).map((resource) => ({
|
|
66
|
+
const engineGdr = resourceGdr(deployment.workflowResource);
|
|
67
|
+
return dedupeResources(sweptResources(deployment)).map((resource) => ({
|
|
64
68
|
resource,
|
|
65
69
|
client: clientFor(resource, token),
|
|
66
|
-
holdsEngineDocs: resourceGdr(resource) ===
|
|
70
|
+
holdsEngineDocs: resourceGdr(resource) === engineGdr,
|
|
67
71
|
}));
|
|
68
72
|
}
|
|
69
73
|
async function confirmOrFail(targets) {
|
|
@@ -12,6 +12,7 @@ export default class SetStage extends WorkflowCommand {
|
|
|
12
12
|
static flags: {
|
|
13
13
|
to: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
14
|
reason: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
deployment: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
16
|
tag: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
17
|
};
|
|
17
18
|
run(): Promise<void>;
|
|
@@ -3,7 +3,7 @@ import { Args, Flags } from '@oclif/core';
|
|
|
3
3
|
import { workflow } from '@sanity/workflow-engine';
|
|
4
4
|
import { WorkflowCommand } from "../../lib/base-command.js";
|
|
5
5
|
import { resolveInstanceContext } from "../../lib/context.js";
|
|
6
|
-
import {
|
|
6
|
+
import { instanceFlags } from "../../lib/flags.js";
|
|
7
7
|
import { buildOperationArgs } from "../../lib/operation-args.js";
|
|
8
8
|
import { cascadeTail, opsAppliedLines, runWriteVerb, } from "../../lib/ops-report.js";
|
|
9
9
|
export default class SetStage extends WorkflowCommand {
|
|
@@ -20,7 +20,7 @@ export default class SetStage extends WorkflowCommand {
|
|
|
20
20
|
}),
|
|
21
21
|
};
|
|
22
22
|
static flags = {
|
|
23
|
-
...
|
|
23
|
+
...instanceFlags,
|
|
24
24
|
to: Flags.string({
|
|
25
25
|
required: true,
|
|
26
26
|
description: 'Target stage name.',
|
|
@@ -13,6 +13,7 @@ export default class Start extends WorkflowCommand {
|
|
|
13
13
|
version: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
14
|
field: import("@oclif/core/interfaces").OptionFlag<string[], import("@oclif/core/interfaces").CustomOptions>;
|
|
15
15
|
'instance-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
deployment: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
17
|
tag: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
18
|
};
|
|
18
19
|
run(): Promise<void>;
|
|
@@ -5,7 +5,7 @@ import { WorkflowCommand } from "../../lib/base-command.js";
|
|
|
5
5
|
import { resolveContext } from "../../lib/context.js";
|
|
6
6
|
import { fetchDeployedDefinition } from "../../lib/definitions.js";
|
|
7
7
|
import { fail, failOnThrow, failureDetail } from "../../lib/fail.js";
|
|
8
|
-
import {
|
|
8
|
+
import { deploymentFlags, jsonFlags } from "../../lib/flags.js";
|
|
9
9
|
import { baseEngineArgs } from "../../lib/operation-args.js";
|
|
10
10
|
import { runWriteVerb } from "../../lib/ops-report.js";
|
|
11
11
|
import { parseParams } from "../../lib/params.js";
|
|
@@ -23,7 +23,7 @@ export default class Start extends WorkflowCommand {
|
|
|
23
23
|
name: Args.string({ required: true, description: 'Workflow definition name.' }),
|
|
24
24
|
};
|
|
25
25
|
static flags = {
|
|
26
|
-
...
|
|
26
|
+
...deploymentFlags,
|
|
27
27
|
version: Flags.integer({
|
|
28
28
|
description: 'Definition version to start from (default: highest deployed).',
|
|
29
29
|
}),
|
package/dist/lib/context.d.ts
CHANGED
|
@@ -13,11 +13,12 @@ export interface InstanceContext {
|
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
15
|
* The resolution a WRITE shares: discover the config, pick the deployment for
|
|
16
|
-
* `--tag` (or the sole one), and build an authenticated
|
|
17
|
-
* deployment's resource. A write acts on one specific
|
|
18
|
-
* single, definite target is exactly what it needs.
|
|
16
|
+
* `--deployment` or `--tag` (or the sole one), and build an authenticated
|
|
17
|
+
* client for that deployment's resource. A write acts on one specific
|
|
18
|
+
* deployment, so a single, definite target is exactly what it needs.
|
|
19
19
|
*/
|
|
20
20
|
export declare function resolveContext(flags: {
|
|
21
|
+
deployment?: string | undefined;
|
|
21
22
|
tag?: string | undefined;
|
|
22
23
|
}): Promise<DeploymentContext>;
|
|
23
24
|
/** One resource a read inspects, with its authenticated client. */
|
|
@@ -34,8 +35,9 @@ export interface ReadTarget {
|
|
|
34
35
|
*
|
|
35
36
|
* Untagged, this is every distinct resource the config mentions — a read is
|
|
36
37
|
* harmless to fan out, so "show me what's deployed" spans the whole config.
|
|
37
|
-
* `--tag` narrows to
|
|
38
|
-
* the run, however many
|
|
38
|
+
* `--tag` narrows to the resources deployed under that tag (tags may repeat
|
|
39
|
+
* across deployments). The token resolves once for the run, however many
|
|
40
|
+
* targets it spans.
|
|
39
41
|
*/
|
|
40
42
|
export declare function resolveReadTargets(flags: {
|
|
41
43
|
tag?: string | undefined;
|
|
@@ -44,9 +46,9 @@ export declare function resolveReadTargets(flags: {
|
|
|
44
46
|
* The first occurrence wins its position, so a caller-ordered list (e.g. the
|
|
45
47
|
* engine resource first) keeps its lead entry. */
|
|
46
48
|
export declare function dedupeResources(resources: WorkflowResource[]): WorkflowResource[];
|
|
47
|
-
/** The distinct resources a read targets:
|
|
48
|
-
*
|
|
49
|
-
* mention ({@link dedupeResources}). */
|
|
49
|
+
/** The distinct resources a read targets: every resource deployed under the
|
|
50
|
+
* tag (tags may repeat across deployments), or — untagged — every distinct
|
|
51
|
+
* one the config's deployments mention ({@link dedupeResources}). */
|
|
50
52
|
export declare function resolveReadResources(config: WorkflowConfig, tag: string | undefined): WorkflowResource[];
|
|
51
53
|
/** The single resource a read should target, or fail asking which when the
|
|
52
54
|
* config spans more than one. For the paths that need one definite dataset
|
|
@@ -60,15 +62,28 @@ export declare function resolveReadResource(config: WorkflowConfig, tag: string
|
|
|
60
62
|
* config's declared deployments. An instance id is globally unique and carries
|
|
61
63
|
* its own `tag`, so a command that names one acts on that instance regardless
|
|
62
64
|
* of which tags the config happens to deploy; the config only locates the
|
|
63
|
-
* resource (via {@link
|
|
65
|
+
* resource (via {@link resolveInstanceResource}, no tag filter).
|
|
64
66
|
*
|
|
65
67
|
* Contrast {@link resolveContext}: the deploy/diff/delete path IS scoped to a
|
|
66
68
|
* declared deployment because it acts on the authored definition set (or a
|
|
67
69
|
* definition name, which — unlike an instance id — isn't unique across tags).
|
|
68
70
|
*/
|
|
69
71
|
export declare function resolveInstanceContext(flags: {
|
|
72
|
+
deployment?: string | undefined;
|
|
70
73
|
tag?: string | undefined;
|
|
71
74
|
}, instanceId: string): Promise<InstanceContext>;
|
|
75
|
+
/**
|
|
76
|
+
* Which resource an instance-keyed command reads from: the one `--deployment`
|
|
77
|
+
* names (resolved by its unique deployment name), else the sole or
|
|
78
|
+
* `--tag`-narrowed resource ({@link resolveReadResource}). The instance id is
|
|
79
|
+
* globally unique, so this only locates the resource to look in — never the
|
|
80
|
+
* instance's `tag` partition, which the caller takes from the loaded instance.
|
|
81
|
+
* The shared path behind all four instance-keyed commands.
|
|
82
|
+
*/
|
|
83
|
+
export declare function resolveInstanceResource(config: WorkflowConfig, { deployment, tag }: {
|
|
84
|
+
deployment?: string | undefined;
|
|
85
|
+
tag?: string | undefined;
|
|
86
|
+
}): WorkflowResource;
|
|
72
87
|
/** Fetch an instance by id, exiting cleanly when the resource has no such
|
|
73
88
|
* document — the diagnostic an operator sees on a mistyped id. Split out from
|
|
74
89
|
* {@link resolveInstanceContext} so the not-found path is unit-testable
|
package/dist/lib/context.js
CHANGED
|
@@ -2,11 +2,11 @@ import { assertReadableModel, resourceGdr, } from '@sanity/workflow-engine';
|
|
|
2
2
|
import { clientFor, resolveTokenOrFail } from "./client.js";
|
|
3
3
|
import { fail } from "./fail.js";
|
|
4
4
|
import { loadWorkflowConfig } from "./load-config.js";
|
|
5
|
-
import { selectDeployment } from "./select-deployment.js";
|
|
5
|
+
import { availableDeployments, deploymentsForTag, selectDeployment } from "./select-deployment.js";
|
|
6
6
|
import { resourceLabel } from "./ui.js";
|
|
7
7
|
export async function resolveContext(flags) {
|
|
8
8
|
const config = await loadWorkflowConfig();
|
|
9
|
-
const deployment = selectDeployment(config, { tag: flags.tag });
|
|
9
|
+
const deployment = selectDeployment(config, { name: flags.deployment, tag: flags.tag });
|
|
10
10
|
return { deployment, client: clientFor(deployment.workflowResource, await resolveTokenOrFail()) };
|
|
11
11
|
}
|
|
12
12
|
export async function resolveReadTargets(flags) {
|
|
@@ -20,7 +20,7 @@ export function dedupeResources(resources) {
|
|
|
20
20
|
}
|
|
21
21
|
export function resolveReadResources(config, tag) {
|
|
22
22
|
if (tag !== undefined) {
|
|
23
|
-
return
|
|
23
|
+
return dedupeResources(deploymentsForTag(config, tag).map((deployment) => deployment.workflowResource));
|
|
24
24
|
}
|
|
25
25
|
const resources = dedupeResources(config.deployments.map((d) => d.workflowResource));
|
|
26
26
|
if (resources.length === 0) {
|
|
@@ -34,16 +34,25 @@ export function resolveReadResource(config, tag) {
|
|
|
34
34
|
if (resources.length === 1 && sole !== undefined) {
|
|
35
35
|
return sole;
|
|
36
36
|
}
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
if (tag === undefined) {
|
|
38
|
+
fail('Config spans multiple resources — pass --deployment or --tag to choose one.', availableDeployments(config));
|
|
39
|
+
}
|
|
40
|
+
const carriers = config.deployments.filter((d) => d.tag === tag);
|
|
41
|
+
fail(`Tag "${tag}" spans multiple resources — pass --deployment to choose one.`, availableDeployments(config, carriers));
|
|
39
42
|
}
|
|
40
43
|
export async function resolveInstanceContext(flags, instanceId) {
|
|
41
44
|
const config = await loadWorkflowConfig();
|
|
42
|
-
const workflowResource =
|
|
45
|
+
const workflowResource = resolveInstanceResource(config, flags);
|
|
43
46
|
const client = clientFor(workflowResource, await resolveTokenOrFail());
|
|
44
47
|
const instance = await loadInstanceOrFail(client, instanceId);
|
|
45
48
|
return { client, scope: { tag: instance.tag, workflowResource } };
|
|
46
49
|
}
|
|
50
|
+
export function resolveInstanceResource(config, { deployment, tag }) {
|
|
51
|
+
if (deployment !== undefined) {
|
|
52
|
+
return selectDeployment(config, { name: deployment, tag: undefined }).workflowResource;
|
|
53
|
+
}
|
|
54
|
+
return resolveReadResource(config, tag);
|
|
55
|
+
}
|
|
47
56
|
export async function loadInstanceOrFail(client, instanceId) {
|
|
48
57
|
const instance = await client.getDocument(instanceId, {
|
|
49
58
|
tag: 'instance.load',
|
package/dist/lib/flags.d.ts
CHANGED
|
@@ -1,11 +1,33 @@
|
|
|
1
|
-
/** The environment tag (e.g. prod, test).
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
1
|
+
/** The environment tag (e.g. prod, test). Tags group deployments by
|
|
2
|
+
* environment and may repeat across a config. For the read commands that
|
|
3
|
+
* consume this directly it's an optional query filter — and the resource
|
|
4
|
+
* disambiguator when a config spans more than one. Write commands layer
|
|
5
|
+
* selection semantics on top via {@link deploymentFlags}; instance-keyed
|
|
6
|
+
* commands add `--deployment` alongside it via {@link instanceFlags}. */
|
|
6
7
|
export declare const tagFlags: {
|
|
7
8
|
tag: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
9
|
};
|
|
10
|
+
/** The selectors an instance-keyed command (`diagnose`, `abort`, `set-stage`,
|
|
11
|
+
* `fire-action`) takes. An instance id is globally unique and carries its own
|
|
12
|
+
* `tag`, so these only pick WHICH resource to read it from — never the
|
|
13
|
+
* instance's partition, which always comes from the loaded instance.
|
|
14
|
+
* `--deployment` names one deployment and reads from the resource it targets;
|
|
15
|
+
* `--tag` stays the optional narrower {@link tagFlags} describes. Mutually
|
|
16
|
+
* exclusive; a sole-resource config needs neither. */
|
|
17
|
+
export declare const instanceFlags: {
|
|
18
|
+
deployment: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
|
+
tag: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
|
+
};
|
|
21
|
+
/** The selectors a single-deployment (write) command takes: `--deployment` —
|
|
22
|
+
* the deployment's unique name identity — or `--tag`, which resolves while the
|
|
23
|
+
* tag names exactly one deployment and errors asking for `--deployment` when
|
|
24
|
+
* it spans several. Mutually exclusive; a sole-deployment config needs neither.
|
|
25
|
+
* `deploy` overrides the `tag` description with its group semantics (every
|
|
26
|
+
* deployment carrying the tag). */
|
|
27
|
+
export declare const deploymentFlags: {
|
|
28
|
+
deployment: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
29
|
+
tag: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
30
|
+
};
|
|
9
31
|
export declare const jsonFlags: {
|
|
10
32
|
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
33
|
};
|
package/dist/lib/flags.js
CHANGED
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
import { Flags } from '@oclif/core';
|
|
2
|
+
const tagAsFilterDescription = 'Workflow environment tag (e.g. prod, test) — an optional query filter, and the resource disambiguator when the config spans several.';
|
|
2
3
|
export const tagFlags = {
|
|
4
|
+
tag: Flags.string({ description: tagAsFilterDescription }),
|
|
5
|
+
};
|
|
6
|
+
export const instanceFlags = {
|
|
7
|
+
deployment: Flags.string({
|
|
8
|
+
description: 'Deployment name — read the instance from the resource that deployment targets; the tag partition still comes from the loaded instance.',
|
|
9
|
+
exclusive: ['tag'],
|
|
10
|
+
}),
|
|
11
|
+
tag: Flags.string({ description: tagAsFilterDescription, exclusive: ['deployment'] }),
|
|
12
|
+
};
|
|
13
|
+
export const deploymentFlags = {
|
|
14
|
+
deployment: Flags.string({
|
|
15
|
+
description: 'Deployment name — the unique identity of one deployment in the config.',
|
|
16
|
+
exclusive: ['tag'],
|
|
17
|
+
}),
|
|
3
18
|
tag: Flags.string({
|
|
4
|
-
description: 'Workflow environment tag (e.g. prod, test) — the deployment to
|
|
19
|
+
description: 'Workflow environment tag (e.g. prod, test) — selects the deployment to act on while the tag names exactly one; pass --deployment when it spans several.',
|
|
20
|
+
exclusive: ['deployment'],
|
|
5
21
|
}),
|
|
6
22
|
};
|
|
7
23
|
export const jsonFlags = {
|
package/dist/lib/nuke.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type WorkflowClient, type WorkflowResource } from '@sanity/workflow-engine';
|
|
1
|
+
import { type WorkflowClient, type WorkflowDeployment, type WorkflowResource } from '@sanity/workflow-engine';
|
|
2
2
|
/** A resource a nuke may delete from, with the client that reads/writes it and
|
|
3
3
|
* whether it is the engine's own resource — the only one that holds instances
|
|
4
4
|
* and definitions (guards can co-locate with subjects in any resource). */
|
|
@@ -32,6 +32,20 @@ export interface PlanCounts {
|
|
|
32
32
|
datasets: number;
|
|
33
33
|
total: number;
|
|
34
34
|
}
|
|
35
|
+
/** Every resource a deployment's nuke sweeps: its own workflow resource (which
|
|
36
|
+
* holds instances + definitions + guards) plus each alias-bound resource
|
|
37
|
+
* (guards co-locate with the subjects they lock). */
|
|
38
|
+
export declare function sweptResources(deployment: WorkflowDeployment): WorkflowResource[];
|
|
39
|
+
/**
|
|
40
|
+
* Fail before any nuke work when another same-tag deployment sweeps a resource
|
|
41
|
+
* the selected one does. Guard document ids embed only the tag
|
|
42
|
+
* (`temp.system.guard.<tag>.wf-instance.*`), so within a shared resource the
|
|
43
|
+
* sweep cannot tell such deployments' guards apart — nuking one would delete
|
|
44
|
+
* the others' live locks, invisibly to the plan. Config validation already
|
|
45
|
+
* forbids sharing tag + workflow resource, so an overlap can only arrive
|
|
46
|
+
* through alias bindings.
|
|
47
|
+
*/
|
|
48
|
+
export declare function refuseOverlappingNuke(deployments: WorkflowDeployment[], selected: WorkflowDeployment): void;
|
|
35
49
|
/**
|
|
36
50
|
* Resolve what a tag-scoped nuke would delete, per resource — the dry-run plan
|
|
37
51
|
* printed before any deletion. Instances and definitions are read only from the
|
package/dist/lib/nuke.js
CHANGED
|
@@ -1,8 +1,29 @@
|
|
|
1
1
|
import { styleText } from 'node:util';
|
|
2
|
-
import { GUARD_DOC_TYPE, WORKFLOW_DEFINITION_TYPE, WORKFLOW_INSTANCE_TYPE, tagScopeFilter, } from '@sanity/workflow-engine';
|
|
2
|
+
import { GUARD_DOC_TYPE, WORKFLOW_DEFINITION_TYPE, WORKFLOW_INSTANCE_TYPE, resourceGdr, tagScopeFilter, } from '@sanity/workflow-engine';
|
|
3
|
+
import { fail } from "./fail.js";
|
|
4
|
+
import { deploymentLabel } from "./select-deployment.js";
|
|
3
5
|
import { formatTable, resourceLabel, sectionHeader } from "./ui.js";
|
|
4
6
|
const CHUNK = 200;
|
|
5
7
|
const REQUEST_TAG = 'nuke';
|
|
8
|
+
export function sweptResources(deployment) {
|
|
9
|
+
return [
|
|
10
|
+
deployment.workflowResource,
|
|
11
|
+
...(deployment.resourceAliases ?? []).map((binding) => binding.resource),
|
|
12
|
+
];
|
|
13
|
+
}
|
|
14
|
+
export function refuseOverlappingNuke(deployments, selected) {
|
|
15
|
+
const swept = new Set(sweptResources(selected).map(resourceGdr));
|
|
16
|
+
const clashing = deployments.filter((candidate) => candidate.name !== selected.name &&
|
|
17
|
+
candidate.tag === selected.tag &&
|
|
18
|
+
sweptResources(candidate).some((resource) => swept.has(resourceGdr(resource))));
|
|
19
|
+
if (clashing.length === 0) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
fail(`Refusing to nuke "${deploymentLabel(selected)}" — its guards are indistinguishable ` +
|
|
23
|
+
`from ${clashing.map(deploymentLabel).join(', ')}'s in the shared resource(s).`, `Guard ids embed only the tag, and these deployments share tag "${selected.tag}" plus ` +
|
|
24
|
+
"a swept resource — the sweep would delete the other deployments' live guards. " +
|
|
25
|
+
'Give them distinct tags first.');
|
|
26
|
+
}
|
|
6
27
|
export async function resolveNukePlan(args) {
|
|
7
28
|
const { tag, targets } = args;
|
|
8
29
|
const resources = await Promise.all(targets.map((target) => resolveResourcePlan({ tag, target })));
|
|
@@ -1,32 +1,54 @@
|
|
|
1
1
|
import { type DeployTarget, type WorkflowConfig, type WorkflowDeployment } from '@sanity/workflow-engine';
|
|
2
|
-
type
|
|
2
|
+
type ChooseDeploymentName = (deployments: WorkflowDeployment[]) => Promise<string>;
|
|
3
3
|
interface DeploymentSelectionOptions {
|
|
4
|
+
name: string | undefined;
|
|
4
5
|
tag: string | undefined;
|
|
5
6
|
allTags: boolean;
|
|
6
7
|
interactive?: boolean;
|
|
7
|
-
|
|
8
|
+
chooseName?: ChooseDeploymentName;
|
|
8
9
|
}
|
|
10
|
+
/** The one identity format for a deployment in output — banners, failure
|
|
11
|
+
* summaries, and "available deployments" listings all render it the same
|
|
12
|
+
* way. */
|
|
13
|
+
export declare function deploymentLabel({ name, tag }: Pick<WorkflowDeployment, 'name' | 'tag'>): string;
|
|
9
14
|
/**
|
|
10
|
-
* Pick the deployment for the requested `--tag`.
|
|
11
|
-
* config (enforced by defineWorkflowConfig), so a
|
|
12
|
-
* deployment.
|
|
15
|
+
* Pick the deployment for the requested `--deployment` or `--tag`. Names are
|
|
16
|
+
* unique across a config (enforced by defineWorkflowConfig), so a name resolves
|
|
17
|
+
* exactly one deployment. Tags are repeatable — a tag resolves only while it
|
|
18
|
+
* names exactly one deployment; when it spans several, the failure lists them
|
|
19
|
+
* so `--deployment` can disambiguate.
|
|
13
20
|
*
|
|
14
|
-
* With no
|
|
15
|
-
* (the common single-environment case), otherwise fail asking for
|
|
16
|
-
* a multi-deployment config is ambiguous without
|
|
17
|
-
*
|
|
21
|
+
* With no selector: fall back to the sole deployment when there's exactly one
|
|
22
|
+
* (the common single-environment case), otherwise fail asking for
|
|
23
|
+
* `--deployment` or `--tag` — a multi-deployment config is ambiguous without
|
|
24
|
+
* one. `orAlternative`
|
|
25
|
+
* extends that ambiguity message for callers with another way out (deploy's
|
|
26
|
+
* `--all-tags`).
|
|
18
27
|
*/
|
|
19
|
-
export declare function selectDeployment(config: WorkflowConfig, { tag, orAlternative }: {
|
|
28
|
+
export declare function selectDeployment(config: WorkflowConfig, { name, tag, orAlternative, }: {
|
|
29
|
+
name: string | undefined;
|
|
20
30
|
tag: string | undefined;
|
|
21
31
|
orAlternative?: string;
|
|
22
32
|
}): WorkflowDeployment;
|
|
23
33
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* flag guidance. Deploying everything is an explicit opt-in — never a default.
|
|
34
|
+
* Every deployment carrying `tag`, failing when the tag matches none — the
|
|
35
|
+
* shared resolution for the callers that accept a whole tag group (deploy's
|
|
36
|
+
* tag-as-environment run, the read paths' resource narrowing).
|
|
28
37
|
*/
|
|
29
|
-
export declare function
|
|
38
|
+
export declare function deploymentsForTag(config: WorkflowConfig, tag: string): WorkflowDeployment[];
|
|
39
|
+
/**
|
|
40
|
+
* The deployments a `deploy` run acts on: every one with `--all-tags`, one
|
|
41
|
+
* definite deployment via `--deployment`, every deployment carrying the tag with
|
|
42
|
+
* `--tag` (a tag is an environment group), otherwise the sole deployment. An
|
|
43
|
+
* ambiguous bare interactive run asks which deployment; a run that cannot
|
|
44
|
+
* prompt keeps the explicit flag guidance. Deploying everything is an
|
|
45
|
+
* explicit opt-in — never a default.
|
|
46
|
+
*/
|
|
47
|
+
export declare function selectDeployments(config: WorkflowConfig, { name, tag, allTags, interactive, chooseName }: DeploymentSelectionOptions): Promise<WorkflowDeployment[]>;
|
|
48
|
+
/** The "Available deployments: name (tag), …" hint every ambiguity failure
|
|
49
|
+
* prints — one vocabulary across the write and instance-keyed paths, so a
|
|
50
|
+
* reader always sees both the `--deployment` names and their `--tag`s. */
|
|
51
|
+
export declare function availableDeployments(config: WorkflowConfig, deployments?: WorkflowDeployment[]): string;
|
|
30
52
|
/**
|
|
31
53
|
* Project a deployment into the engine's {@link DeployTarget} — the shape the
|
|
32
54
|
* deploy/diff verbs (`deployDefinitions`, `computeDiffEntries`, `diffEntry`)
|
|
@@ -2,55 +2,81 @@ import { select } from '@sanity/cli-core/ux';
|
|
|
2
2
|
import { resourceAliasesToMap, } from '@sanity/workflow-engine';
|
|
3
3
|
import { fail } from "./fail.js";
|
|
4
4
|
import { canPromptOnStderr } from "./prompt.js";
|
|
5
|
-
export function
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
export function deploymentLabel({ name, tag }) {
|
|
6
|
+
return `${name} (${tag})`;
|
|
7
|
+
}
|
|
8
|
+
export function selectDeployment(config, { name, tag, orAlternative = '', }) {
|
|
9
|
+
if (name !== undefined) {
|
|
10
|
+
const deployment = config.deployments.find((candidate) => candidate.name === name);
|
|
11
|
+
if (deployment === undefined) {
|
|
12
|
+
fail(`No deployment named "${name}".`, availableDeployments(config));
|
|
9
13
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
return deployment;
|
|
15
|
+
}
|
|
16
|
+
if (tag !== undefined) {
|
|
17
|
+
const matches = deploymentsForTag(config, tag);
|
|
18
|
+
const [sole, ...rest] = matches;
|
|
19
|
+
if (sole === undefined || rest.length > 0) {
|
|
20
|
+
fail(`Multiple deployments tagged "${tag}" — pass --deployment to choose one.`, availableDeployments(config, matches));
|
|
13
21
|
}
|
|
14
22
|
return sole;
|
|
15
23
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
24
|
+
if (config.deployments.length > 1) {
|
|
25
|
+
fail(`Multiple deployments configured — pass --deployment or --tag${orAlternative}.`, availableDeployments(config));
|
|
26
|
+
}
|
|
27
|
+
const [sole] = config.deployments;
|
|
28
|
+
if (sole === undefined) {
|
|
29
|
+
fail('No deployments configured.');
|
|
19
30
|
}
|
|
20
|
-
return
|
|
31
|
+
return sole;
|
|
21
32
|
}
|
|
22
|
-
export
|
|
33
|
+
export function deploymentsForTag(config, tag) {
|
|
34
|
+
const matches = config.deployments.filter((candidate) => candidate.tag === tag);
|
|
35
|
+
if (matches.length === 0) {
|
|
36
|
+
fail(`No deployment for tag "${tag}".`, availableDeployments(config));
|
|
37
|
+
}
|
|
38
|
+
return matches;
|
|
39
|
+
}
|
|
40
|
+
export async function selectDeployments(config, { name, tag, allTags, interactive, chooseName = chooseDeploymentName }) {
|
|
23
41
|
if (allTags) {
|
|
24
42
|
return config.deployments;
|
|
25
43
|
}
|
|
26
|
-
if (tag
|
|
44
|
+
if (tag !== undefined) {
|
|
45
|
+
return deploymentsForTag(config, tag);
|
|
46
|
+
}
|
|
47
|
+
if (name === undefined && config.deployments.length > 1) {
|
|
27
48
|
if (!(interactive ?? canPromptOnStderr())) {
|
|
28
49
|
return [
|
|
29
50
|
selectDeployment(config, {
|
|
51
|
+
name,
|
|
30
52
|
tag,
|
|
31
53
|
orAlternative: ', or --all-tags to deploy every deployment',
|
|
32
54
|
}),
|
|
33
55
|
];
|
|
34
56
|
}
|
|
35
|
-
const
|
|
36
|
-
return [selectDeployment(config, { tag:
|
|
57
|
+
const selectedName = await chooseName(config.deployments);
|
|
58
|
+
return [selectDeployment(config, { name: selectedName, tag: undefined })];
|
|
37
59
|
}
|
|
38
60
|
return [
|
|
39
|
-
selectDeployment(config, {
|
|
61
|
+
selectDeployment(config, {
|
|
62
|
+
name,
|
|
63
|
+
tag,
|
|
64
|
+
orAlternative: ', or --all-tags to deploy every deployment',
|
|
65
|
+
}),
|
|
40
66
|
];
|
|
41
67
|
}
|
|
42
|
-
async function
|
|
68
|
+
async function chooseDeploymentName(deployments) {
|
|
43
69
|
return select({
|
|
44
|
-
message: 'Select a deployment
|
|
70
|
+
message: 'Select a deployment',
|
|
45
71
|
choices: deployments.map(({ name, tag }) => ({
|
|
46
|
-
name
|
|
47
|
-
value:
|
|
48
|
-
description:
|
|
72
|
+
name,
|
|
73
|
+
value: name,
|
|
74
|
+
description: `tag: ${tag}`,
|
|
49
75
|
})),
|
|
50
76
|
}, { output: process.stderr });
|
|
51
77
|
}
|
|
52
|
-
function
|
|
53
|
-
return `Available
|
|
78
|
+
export function availableDeployments(config, deployments = config.deployments) {
|
|
79
|
+
return `Available deployments: ${deployments.map(deploymentLabel).join(', ')}`;
|
|
54
80
|
}
|
|
55
81
|
export function deploymentToTarget(deployment) {
|
|
56
82
|
return {
|
package/oclif.manifest.json
CHANGED
|
@@ -17,8 +17,21 @@
|
|
|
17
17
|
"<%= config.bin %> abort wf-instance.abc123 --reason 'superseded by relaunch'"
|
|
18
18
|
],
|
|
19
19
|
"flags": {
|
|
20
|
+
"deployment": {
|
|
21
|
+
"description": "Deployment name — read the instance from the resource that deployment targets; the tag partition still comes from the loaded instance.",
|
|
22
|
+
"exclusive": [
|
|
23
|
+
"tag"
|
|
24
|
+
],
|
|
25
|
+
"name": "deployment",
|
|
26
|
+
"hasDynamicHelp": false,
|
|
27
|
+
"multiple": false,
|
|
28
|
+
"type": "option"
|
|
29
|
+
},
|
|
20
30
|
"tag": {
|
|
21
|
-
"description": "Workflow environment tag (e.g. prod, test) —
|
|
31
|
+
"description": "Workflow environment tag (e.g. prod, test) — an optional query filter, and the resource disambiguator when the config spans several.",
|
|
32
|
+
"exclusive": [
|
|
33
|
+
"deployment"
|
|
34
|
+
],
|
|
22
35
|
"name": "tag",
|
|
23
36
|
"hasDynamicHelp": false,
|
|
24
37
|
"multiple": false,
|
|
@@ -54,6 +67,7 @@
|
|
|
54
67
|
"args": {},
|
|
55
68
|
"description": "Validate, diff, and deploy workflow definitions to the resource bound by the selected deployment.",
|
|
56
69
|
"examples": [
|
|
70
|
+
"<%= config.bin %> deploy --deployment review-prod",
|
|
57
71
|
"<%= config.bin %> deploy --tag prod",
|
|
58
72
|
"<%= config.bin %> deploy --all-tags",
|
|
59
73
|
"<%= config.bin %> deploy --check",
|
|
@@ -61,17 +75,31 @@
|
|
|
61
75
|
"<%= config.bin %> deploy --only productLaunch"
|
|
62
76
|
],
|
|
63
77
|
"flags": {
|
|
78
|
+
"deployment": {
|
|
79
|
+
"description": "Deployment name — the unique identity of one deployment in the config.",
|
|
80
|
+
"exclusive": [
|
|
81
|
+
"tag"
|
|
82
|
+
],
|
|
83
|
+
"name": "deployment",
|
|
84
|
+
"hasDynamicHelp": false,
|
|
85
|
+
"multiple": false,
|
|
86
|
+
"type": "option"
|
|
87
|
+
},
|
|
64
88
|
"tag": {
|
|
65
|
-
"description": "Workflow environment tag (e.g. prod, test) —
|
|
89
|
+
"description": "Workflow environment tag (e.g. prod, test) — deploys every deployment carrying the tag (a tag is an environment group).",
|
|
90
|
+
"exclusive": [
|
|
91
|
+
"deployment"
|
|
92
|
+
],
|
|
66
93
|
"name": "tag",
|
|
67
94
|
"hasDynamicHelp": false,
|
|
68
95
|
"multiple": false,
|
|
69
96
|
"type": "option"
|
|
70
97
|
},
|
|
71
98
|
"all-tags": {
|
|
72
|
-
"description": "Deploy every deployment in the config, not just
|
|
99
|
+
"description": "Deploy every deployment in the config, not just a selection.",
|
|
73
100
|
"exclusive": [
|
|
74
|
-
"tag"
|
|
101
|
+
"tag",
|
|
102
|
+
"deployment"
|
|
75
103
|
],
|
|
76
104
|
"name": "all-tags",
|
|
77
105
|
"allowNo": false,
|
|
@@ -136,8 +164,21 @@
|
|
|
136
164
|
"<%= config.bin %> diagnose wf-instance.abc123 --json"
|
|
137
165
|
],
|
|
138
166
|
"flags": {
|
|
167
|
+
"deployment": {
|
|
168
|
+
"description": "Deployment name — read the instance from the resource that deployment targets; the tag partition still comes from the loaded instance.",
|
|
169
|
+
"exclusive": [
|
|
170
|
+
"tag"
|
|
171
|
+
],
|
|
172
|
+
"name": "deployment",
|
|
173
|
+
"hasDynamicHelp": false,
|
|
174
|
+
"multiple": false,
|
|
175
|
+
"type": "option"
|
|
176
|
+
},
|
|
139
177
|
"tag": {
|
|
140
|
-
"description": "Workflow environment tag (e.g. prod, test) —
|
|
178
|
+
"description": "Workflow environment tag (e.g. prod, test) — an optional query filter, and the resource disambiguator when the config spans several.",
|
|
179
|
+
"exclusive": [
|
|
180
|
+
"deployment"
|
|
181
|
+
],
|
|
141
182
|
"name": "tag",
|
|
142
183
|
"hasDynamicHelp": false,
|
|
143
184
|
"multiple": false,
|
|
@@ -183,8 +224,21 @@
|
|
|
183
224
|
"<%= config.bin %> fire-action wf-instance.abc123 --activity publish --action publish --param note=shipping"
|
|
184
225
|
],
|
|
185
226
|
"flags": {
|
|
227
|
+
"deployment": {
|
|
228
|
+
"description": "Deployment name — read the instance from the resource that deployment targets; the tag partition still comes from the loaded instance.",
|
|
229
|
+
"exclusive": [
|
|
230
|
+
"tag"
|
|
231
|
+
],
|
|
232
|
+
"name": "deployment",
|
|
233
|
+
"hasDynamicHelp": false,
|
|
234
|
+
"multiple": false,
|
|
235
|
+
"type": "option"
|
|
236
|
+
},
|
|
186
237
|
"tag": {
|
|
187
|
-
"description": "Workflow environment tag (e.g. prod, test) —
|
|
238
|
+
"description": "Workflow environment tag (e.g. prod, test) — an optional query filter, and the resource disambiguator when the config spans several.",
|
|
239
|
+
"exclusive": [
|
|
240
|
+
"deployment"
|
|
241
|
+
],
|
|
188
242
|
"name": "tag",
|
|
189
243
|
"hasDynamicHelp": false,
|
|
190
244
|
"multiple": false,
|
|
@@ -249,7 +303,7 @@
|
|
|
249
303
|
],
|
|
250
304
|
"flags": {
|
|
251
305
|
"tag": {
|
|
252
|
-
"description": "Workflow environment tag (e.g. prod, test) —
|
|
306
|
+
"description": "Workflow environment tag (e.g. prod, test) — an optional query filter, and the resource disambiguator when the config spans several.",
|
|
253
307
|
"name": "tag",
|
|
254
308
|
"hasDynamicHelp": false,
|
|
255
309
|
"multiple": false,
|
|
@@ -312,14 +366,20 @@
|
|
|
312
366
|
"args": {},
|
|
313
367
|
"description": "The reset for a dataset holding engine documents the versioned upgrade framework cannot yet migrate: deletes the tag's instances, definitions, and guards (across every alias-bound resource). Content documents are never touched. Prints a dry-run plan, then requires you to type back every involved dataset (--force skips the prompt; the plan still prints).",
|
|
314
368
|
"examples": [
|
|
315
|
-
"<%= config.bin %> nuke --
|
|
369
|
+
"<%= config.bin %> nuke --deployment plugin-dev",
|
|
316
370
|
"<%= config.bin %> nuke --tag plugin-dev --force"
|
|
317
371
|
],
|
|
318
372
|
"flags": {
|
|
373
|
+
"deployment": {
|
|
374
|
+
"description": "The deployment name to reset.",
|
|
375
|
+
"name": "deployment",
|
|
376
|
+
"hasDynamicHelp": false,
|
|
377
|
+
"multiple": false,
|
|
378
|
+
"type": "option"
|
|
379
|
+
},
|
|
319
380
|
"tag": {
|
|
320
|
-
"description": "The deployment tag to reset
|
|
381
|
+
"description": "The deployment tag to reset (while it names exactly one deployment).",
|
|
321
382
|
"name": "tag",
|
|
322
|
-
"required": true,
|
|
323
383
|
"hasDynamicHelp": false,
|
|
324
384
|
"multiple": false,
|
|
325
385
|
"type": "option"
|
|
@@ -398,8 +458,21 @@
|
|
|
398
458
|
"<%= config.bin %> set-stage wf-instance.abc123 --to ready --reason 'unblock for demo'"
|
|
399
459
|
],
|
|
400
460
|
"flags": {
|
|
461
|
+
"deployment": {
|
|
462
|
+
"description": "Deployment name — read the instance from the resource that deployment targets; the tag partition still comes from the loaded instance.",
|
|
463
|
+
"exclusive": [
|
|
464
|
+
"tag"
|
|
465
|
+
],
|
|
466
|
+
"name": "deployment",
|
|
467
|
+
"hasDynamicHelp": false,
|
|
468
|
+
"multiple": false,
|
|
469
|
+
"type": "option"
|
|
470
|
+
},
|
|
401
471
|
"tag": {
|
|
402
|
-
"description": "Workflow environment tag (e.g. prod, test) —
|
|
472
|
+
"description": "Workflow environment tag (e.g. prod, test) — an optional query filter, and the resource disambiguator when the config spans several.",
|
|
473
|
+
"exclusive": [
|
|
474
|
+
"deployment"
|
|
475
|
+
],
|
|
403
476
|
"name": "tag",
|
|
404
477
|
"hasDynamicHelp": false,
|
|
405
478
|
"multiple": false,
|
|
@@ -454,7 +527,7 @@
|
|
|
454
527
|
],
|
|
455
528
|
"flags": {
|
|
456
529
|
"tag": {
|
|
457
|
-
"description": "Workflow environment tag (e.g. prod, test) —
|
|
530
|
+
"description": "Workflow environment tag (e.g. prod, test) — an optional query filter, and the resource disambiguator when the config spans several.",
|
|
458
531
|
"name": "tag",
|
|
459
532
|
"hasDynamicHelp": false,
|
|
460
533
|
"multiple": false,
|
|
@@ -506,8 +579,21 @@
|
|
|
506
579
|
"<%= config.bin %> start productLaunch --instance-id prod.wf-instance.a1b2c3d4e5f6"
|
|
507
580
|
],
|
|
508
581
|
"flags": {
|
|
582
|
+
"deployment": {
|
|
583
|
+
"description": "Deployment name — the unique identity of one deployment in the config.",
|
|
584
|
+
"exclusive": [
|
|
585
|
+
"tag"
|
|
586
|
+
],
|
|
587
|
+
"name": "deployment",
|
|
588
|
+
"hasDynamicHelp": false,
|
|
589
|
+
"multiple": false,
|
|
590
|
+
"type": "option"
|
|
591
|
+
},
|
|
509
592
|
"tag": {
|
|
510
|
-
"description": "Workflow environment tag (e.g. prod, test) — the deployment to
|
|
593
|
+
"description": "Workflow environment tag (e.g. prod, test) — selects the deployment to act on while the tag names exactly one; pass --deployment when it spans several.",
|
|
594
|
+
"exclusive": [
|
|
595
|
+
"deployment"
|
|
596
|
+
],
|
|
511
597
|
"name": "tag",
|
|
512
598
|
"hasDynamicHelp": false,
|
|
513
599
|
"multiple": false,
|
|
@@ -574,7 +660,7 @@
|
|
|
574
660
|
],
|
|
575
661
|
"flags": {
|
|
576
662
|
"tag": {
|
|
577
|
-
"description": "Workflow environment tag (e.g. prod, test) —
|
|
663
|
+
"description": "Workflow environment tag (e.g. prod, test) — an optional query filter, and the resource disambiguator when the config spans several.",
|
|
578
664
|
"name": "tag",
|
|
579
665
|
"hasDynamicHelp": false,
|
|
580
666
|
"multiple": false,
|
|
@@ -614,8 +700,21 @@
|
|
|
614
700
|
"<%= config.bin %> definition delete my-workflow --cascade --reason 'workflow retired'"
|
|
615
701
|
],
|
|
616
702
|
"flags": {
|
|
703
|
+
"deployment": {
|
|
704
|
+
"description": "Deployment name — the unique identity of one deployment in the config.",
|
|
705
|
+
"exclusive": [
|
|
706
|
+
"tag"
|
|
707
|
+
],
|
|
708
|
+
"name": "deployment",
|
|
709
|
+
"hasDynamicHelp": false,
|
|
710
|
+
"multiple": false,
|
|
711
|
+
"type": "option"
|
|
712
|
+
},
|
|
617
713
|
"tag": {
|
|
618
|
-
"description": "Workflow environment tag (e.g. prod, test) — the deployment to
|
|
714
|
+
"description": "Workflow environment tag (e.g. prod, test) — selects the deployment to act on while the tag names exactly one; pass --deployment when it spans several.",
|
|
715
|
+
"exclusive": [
|
|
716
|
+
"deployment"
|
|
717
|
+
],
|
|
619
718
|
"name": "tag",
|
|
620
719
|
"hasDynamicHelp": false,
|
|
621
720
|
"multiple": false,
|
|
@@ -675,8 +774,21 @@
|
|
|
675
774
|
"<%= config.bin %> definition diff productLaunch --version 2"
|
|
676
775
|
],
|
|
677
776
|
"flags": {
|
|
777
|
+
"deployment": {
|
|
778
|
+
"description": "Deployment name — the unique identity of one deployment in the config.",
|
|
779
|
+
"exclusive": [
|
|
780
|
+
"tag"
|
|
781
|
+
],
|
|
782
|
+
"name": "deployment",
|
|
783
|
+
"hasDynamicHelp": false,
|
|
784
|
+
"multiple": false,
|
|
785
|
+
"type": "option"
|
|
786
|
+
},
|
|
678
787
|
"tag": {
|
|
679
|
-
"description": "Workflow environment tag (e.g. prod, test) — the deployment to
|
|
788
|
+
"description": "Workflow environment tag (e.g. prod, test) — selects the deployment to act on while the tag names exactly one; pass --deployment when it spans several.",
|
|
789
|
+
"exclusive": [
|
|
790
|
+
"deployment"
|
|
791
|
+
],
|
|
680
792
|
"name": "tag",
|
|
681
793
|
"hasDynamicHelp": false,
|
|
682
794
|
"multiple": false,
|
|
@@ -718,7 +830,7 @@
|
|
|
718
830
|
],
|
|
719
831
|
"flags": {
|
|
720
832
|
"tag": {
|
|
721
|
-
"description": "Workflow environment tag (e.g. prod, test) —
|
|
833
|
+
"description": "Workflow environment tag (e.g. prod, test) — an optional query filter, and the resource disambiguator when the config spans several.",
|
|
722
834
|
"name": "tag",
|
|
723
835
|
"hasDynamicHelp": false,
|
|
724
836
|
"multiple": false,
|
|
@@ -770,7 +882,7 @@
|
|
|
770
882
|
"description": "Show a deployed workflow definition.",
|
|
771
883
|
"flags": {
|
|
772
884
|
"tag": {
|
|
773
|
-
"description": "Workflow environment tag (e.g. prod, test) —
|
|
885
|
+
"description": "Workflow environment tag (e.g. prod, test) — an optional query filter, and the resource disambiguator when the config spans several.",
|
|
774
886
|
"name": "tag",
|
|
775
887
|
"hasDynamicHelp": false,
|
|
776
888
|
"multiple": false,
|
|
@@ -801,5 +913,5 @@
|
|
|
801
913
|
]
|
|
802
914
|
}
|
|
803
915
|
},
|
|
804
|
-
"version": "0.
|
|
916
|
+
"version": "0.14.0"
|
|
805
917
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/workflow-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Command-line tool for deploying, inspecting, and administering Sanity workflow definitions and instances.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -56,15 +56,15 @@
|
|
|
56
56
|
"jiti": "^2.7.0",
|
|
57
57
|
"log-symbols": "^7.0.1",
|
|
58
58
|
"ora": "^9.4.0",
|
|
59
|
-
"@sanity/workflow-engine": "0.
|
|
59
|
+
"@sanity/workflow-engine": "0.19.0"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@types/diff": "^8.0.0",
|
|
63
63
|
"@types/node": "^24.12.4",
|
|
64
64
|
"oclif": "^4.23.16",
|
|
65
65
|
"vitest": "^4.1.8",
|
|
66
|
-
"@sanity/workflow-engine-test": "0.13.
|
|
67
|
-
"@sanity/workflow-examples": "0.8.
|
|
66
|
+
"@sanity/workflow-engine-test": "0.13.1",
|
|
67
|
+
"@sanity/workflow-examples": "0.8.1"
|
|
68
68
|
},
|
|
69
69
|
"oclif": {
|
|
70
70
|
"bin": "sanity-workflows",
|