@sanity/workflow-cli 0.13.0 → 0.20.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.
Files changed (33) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +40 -27
  3. package/dist/commands/editorial-workflows/abort.d.ts +1 -0
  4. package/dist/commands/editorial-workflows/abort.js +2 -2
  5. package/dist/commands/editorial-workflows/definition/delete.d.ts +1 -0
  6. package/dist/commands/editorial-workflows/definition/delete.js +2 -2
  7. package/dist/commands/editorial-workflows/definition/diff.d.ts +1 -0
  8. package/dist/commands/editorial-workflows/definition/diff.js +2 -2
  9. package/dist/commands/editorial-workflows/deploy.d.ts +2 -1
  10. package/dist/commands/editorial-workflows/deploy.js +15 -9
  11. package/dist/commands/editorial-workflows/diagnose.d.ts +1 -0
  12. package/dist/commands/editorial-workflows/diagnose.js +2 -2
  13. package/dist/commands/editorial-workflows/fire-action.d.ts +1 -0
  14. package/dist/commands/editorial-workflows/fire-action.js +2 -2
  15. package/dist/commands/editorial-workflows/nuke.d.ts +2 -1
  16. package/dist/commands/editorial-workflows/nuke.js +13 -9
  17. package/dist/commands/editorial-workflows/set-stage.d.ts +1 -0
  18. package/dist/commands/editorial-workflows/set-stage.js +2 -2
  19. package/dist/commands/editorial-workflows/start.d.ts +1 -0
  20. package/dist/commands/editorial-workflows/start.js +2 -2
  21. package/dist/lib/context.d.ts +36 -13
  22. package/dist/lib/context.js +27 -6
  23. package/dist/lib/fail.js +1 -1
  24. package/dist/lib/flags.d.ts +27 -5
  25. package/dist/lib/flags.js +17 -1
  26. package/dist/lib/nuke.d.ts +15 -14
  27. package/dist/lib/nuke.js +27 -8
  28. package/dist/lib/prompt.d.ts +14 -0
  29. package/dist/lib/prompt.js +4 -0
  30. package/dist/lib/select-deployment.d.ts +41 -16
  31. package/dist/lib/select-deployment.js +55 -38
  32. package/oclif.manifest.json +131 -19
  33. package/package.json +8 -5
package/CHANGELOG.md CHANGED
@@ -1,5 +1,42 @@
1
1
  # @sanity/workflow-cli
2
2
 
3
+ ## 0.20.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 6e2a066: Ambiguous deployment/resource selection now prompts on an interactive terminal instead of only erroring. When a config has several deployments and no selector is given, `start`, `definition diff`, and `definition delete` show the same deployment picker `deploy` already offered. The instance-targeted commands (`abort`, `set-stage`, `fire-action`, `diagnose`) show that picker too when the config spans several resources — the interactive counterpart to their `--deployment` selector, reading from the chosen deployment's resource. Non-interactive runs (CI, piped output) keep the existing errors asking for `--deployment`/`--tag`, and `nuke` still requires an explicit selector — for a destructive command, naming exactly what is swept is the right friction.
8
+ - 7c4dd86: Reduce guard lifecycle request volume and chunk orphan cleanup transactions.
9
+ - e860898: **BREAKING:** Published Editorial Workflows packages now ship as one fixed release stack and require exact-version peers for every shared runtime package. Install the matching stack so the engine, reactive core, adapters, tools, and UI cannot silently load private or version-skewed copies.
10
+
11
+ ### Patch Changes
12
+
13
+ - efb4cd9: Error detail below the ✖ headline is no longer dimmed. Validation output, auth hints, and errors caught by command wrappers now render in legible red so the information users need to act on remains readable.
14
+ - Updated dependencies [bce09fc]
15
+ - Updated dependencies [efb4cd9]
16
+ - Updated dependencies [46b0285]
17
+ - Updated dependencies [ab5e454]
18
+ - Updated dependencies [8a76c67]
19
+ - Updated dependencies [e3122cc]
20
+ - Updated dependencies [7e8f459]
21
+ - Updated dependencies [98e488e]
22
+ - Updated dependencies [7c4dd86]
23
+ - @sanity/workflow-engine@0.20.0
24
+
25
+ ## 0.14.0
26
+
27
+ ### Minor Changes
28
+
29
+ - 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.
30
+ - 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.
31
+
32
+ ### Patch Changes
33
+
34
+ - Updated dependencies [24b11dd]
35
+ - Updated dependencies [2005ab7]
36
+ - Updated dependencies [24b11dd]
37
+ - Updated dependencies [59b40fd]
38
+ - @sanity/workflow-engine@0.19.0
39
+
3
40
  ## 0.13.0
4
41
 
5
42
  ### 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 one **deployment** per environment:
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,23 @@ export default defineWorkflowConfig({
76
77
  })
77
78
  ```
78
79
 
79
- Pick a deployment with `--tag <tag>`; with a single deployment configured you
80
- can omit it. With several configured, a bare interactive `deploy` presents a
81
- keyboard-driven tag selector. In CI or another non-interactive shell, it fails
82
- asking for `--tag` or `--all-tags` instead of blocking for input. `--all-tags`
83
- deploys every deployment in the config in one run: a failure in one doesn't
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 run presents a keyboard-driven deployment selector (by name,
91
+ tag alongside) — on `deploy`, `start`, and `definition diff`/`delete`, and on
92
+ the instance-targeted commands (`abort`, `set-stage`, `fire-action`,
93
+ `diagnose`) when the config spans several resources. In CI or another
94
+ non-interactive shell, the command fails asking for `--deployment` or `--tag`
95
+ (`deploy` also suggests `--all-tags`) instead of blocking for input.
96
+ `--all-tags` deploys every deployment in the config in one run: a failure in one doesn't
84
97
  stop the rest — the run continues, prints a summary of what failed, and exits
85
98
  non-zero. The client's project + dataset are derived from the deployment's
86
99
  `workflowResource`, and `deploy` expands each definition's `@<handle>:`
@@ -143,26 +156,26 @@ stale compiled output.
143
156
 
144
157
  ## Command status
145
158
 
146
- | Command | Status |
147
- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
148
- | `deploy` | wired — calls `workflow.deployDefinitions` over the selected deployment's definitions |
149
- | `deploy --all-tags` | wired — deploys every deployment in the config, continuing past per-deployment failures |
150
- | `deploy --check` | wired — runs `validateDefinition` over the local batch + a duplicate-name check |
151
- | `deploy --dry-run` | wired — fetches existing docs and renders a coloured JSON diff per change |
152
- | `deploy --only <name>` | wired — filters deploy/check/dry-run to one definition by `name` |
153
- | `start <name>` | wired — calls `workflow.startInstance` (`--field` for input fields) |
154
- | `list` | wired — `client.fetch` over `sanity.workflow.instance` documents (`--definition <name>` to filter) |
155
- | `show <instance-id>` | wired — `client.getDocument` |
156
- | `diagnose <instance-id>` | wired — calls `workflow.diagnose`, classifies why the instance is/isn't progressing |
157
- | `tail <instance-id>` | wired — `client.listen()` over the instance, prints new history entries |
158
- | `abort <instance-id>` | wired — calls `workflow.abortInstance` (hard stop: cancels pending effects, removes guards) |
159
- | `set-stage <instance-id> --to <stage>` | wired — calls `workflow.setStage` (admin override: skips declared transitions/filters; enter lifecycle + cascade still run) |
160
- | `fire-action <instance-id>` | wired — `workflow.availableActions` lists actions; `workflow.fireAction` fires one |
161
- | `definition list` | wired — `client.fetch` over `sanity.workflow.definition` documents |
162
- | `definition show <name>` | wired — `client.fetch`, latest version unless `--version` |
163
- | `definition diff <name>` | wired — diffs the in-code definition against the deployed latest (`--version` to pin) |
164
- | `definition delete <name>` | wired — calls `workflow.deleteDefinition` (refuses on live instances unless `--cascade`) |
165
- | `nuke --tag <tag>` | wired — dev-period reset (exists only until the versioned upgrade framework): deletes every engine-owned doc for the tag (instances, definitions, guards across resources); plan + typed confirm |
159
+ | Command | Status |
160
+ | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
161
+ | `deploy` | wired — calls `workflow.deployDefinitions` over the selected deployment's definitions |
162
+ | `deploy --all-tags` | wired — deploys every deployment in the config, continuing past per-deployment failures |
163
+ | `deploy --check` | wired — runs `validateDefinition` over the local batch + a duplicate-name check |
164
+ | `deploy --dry-run` | wired — fetches existing docs and renders a coloured JSON diff per change |
165
+ | `deploy --only <name>` | wired — filters deploy/check/dry-run to one definition by `name` |
166
+ | `start <name>` | wired — calls `workflow.startInstance` (`--field` for input fields) |
167
+ | `list` | wired — `client.fetch` over `sanity.workflow.instance` documents (`--definition <name>` to filter) |
168
+ | `show <instance-id>` | wired — `client.getDocument` |
169
+ | `diagnose <instance-id>` | wired — calls `workflow.diagnose`, classifies why the instance is/isn't progressing |
170
+ | `tail <instance-id>` | wired — `client.listen()` over the instance, prints new history entries |
171
+ | `abort <instance-id>` | wired — calls `workflow.abortInstance` (hard stop: cancels pending effects, removes guards) |
172
+ | `set-stage <instance-id> --to <stage>` | wired — calls `workflow.setStage` (admin override: skips declared transitions/filters; enter lifecycle + cascade still run) |
173
+ | `fire-action <instance-id>` | wired — `workflow.availableActions` lists actions; `workflow.fireAction` fires one |
174
+ | `definition list` | wired — `client.fetch` over `sanity.workflow.definition` documents |
175
+ | `definition show <name>` | wired — `client.fetch`, latest version unless `--version` |
176
+ | `definition diff <name>` | wired — diffs the in-code definition against the deployed latest (`--version` to pin) |
177
+ | `definition delete <name>` | wired — calls `workflow.deleteDefinition` (refuses on live instances unless `--cascade`) |
178
+ | `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
179
 
167
180
  ## Telemetry
168
181
 
@@ -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 { tagFlags } from "../../lib/flags.js";
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
- ...tagFlags,
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 { tagFlags } from "../../../lib/flags.js";
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
- ...tagFlags,
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 { tagFlags } from "../../../lib/flags.js";
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
- ...tagFlags,
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
- tag: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
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 { tagFlags } from "../../lib/flags.js";
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
- ...tagFlags,
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 one tag.',
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, { tag: flags.tag, allTags: flags['all-tags'] }), flags.only);
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 { jsonFlags, tagFlags } from "../../lib/flags.js";
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
- ...tagFlags,
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 { jsonFlags, tagFlags } from "../../lib/flags.js";
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
- ...tagFlags,
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
- tag: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
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 --tag plugin-dev',
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. Required a destructive reset never guesses the environment.',
28
- required: true,
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 = await 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 engineResource = deployment.workflowResource;
62
- const aliasResources = (deployment.resourceAliases ?? []).map((binding) => binding.resource);
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) === resourceGdr(engineResource),
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 { tagFlags } from "../../lib/flags.js";
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
- ...tagFlags,
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 { jsonFlags, tagFlags } from "../../lib/flags.js";
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
- ...tagFlags,
26
+ ...deploymentFlags,
27
27
  version: Flags.integer({
28
28
  description: 'Definition version to start from (default: highest deployed).',
29
29
  }),
@@ -1,6 +1,7 @@
1
1
  import type { SanityClient } from '@sanity/client';
2
2
  import { type WorkflowConfig, type WorkflowDeployment, type WorkflowInstance, type WorkflowResource } from '@sanity/workflow-engine';
3
3
  import type { EngineScope } from './operation-args.ts';
4
+ import { type ChooseDeploymentName } from './select-deployment.ts';
4
5
  export interface DeploymentContext {
5
6
  deployment: WorkflowDeployment;
6
7
  client: SanityClient;
@@ -13,11 +14,12 @@ export interface InstanceContext {
13
14
  }
14
15
  /**
15
16
  * The resolution a WRITE shares: discover the config, pick the deployment for
16
- * `--tag` (or the sole one), and build an authenticated client for that
17
- * deployment's resource. A write acts on one specific deployment, so a
18
- * single, definite target is exactly what it needs.
17
+ * `--deployment` or `--tag` (or the sole one), and build an authenticated
18
+ * client for that deployment's resource. A write acts on one specific
19
+ * deployment, so a single, definite target is exactly what it needs.
19
20
  */
20
21
  export declare function resolveContext(flags: {
22
+ deployment?: string | undefined;
21
23
  tag?: string | undefined;
22
24
  }): Promise<DeploymentContext>;
23
25
  /** One resource a read inspects, with its authenticated client. */
@@ -34,8 +36,9 @@ export interface ReadTarget {
34
36
  *
35
37
  * Untagged, this is every distinct resource the config mentions — a read is
36
38
  * harmless to fan out, so "show me what's deployed" spans the whole config.
37
- * `--tag` narrows to that deployment's resource. The token resolves once for
38
- * the run, however many targets it spans.
39
+ * `--tag` narrows to the resources deployed under that tag (tags may repeat
40
+ * across deployments). The token resolves once for the run, however many
41
+ * targets it spans.
39
42
  */
40
43
  export declare function resolveReadTargets(flags: {
41
44
  tag?: string | undefined;
@@ -44,14 +47,15 @@ export declare function resolveReadTargets(flags: {
44
47
  * The first occurrence wins its position, so a caller-ordered list (e.g. the
45
48
  * engine resource first) keeps its lead entry. */
46
49
  export declare function dedupeResources(resources: WorkflowResource[]): WorkflowResource[];
47
- /** The distinct resources a read targets: the tagged deployment's sole
48
- * resource, or — untagged — every distinct one the config's deployments
49
- * mention ({@link dedupeResources}). */
50
+ /** The distinct resources a read targets: every resource deployed under the
51
+ * tag (tags may repeat across deployments), or — untagged — every distinct
52
+ * one the config's deployments mention ({@link dedupeResources}). */
50
53
  export declare function resolveReadResources(config: WorkflowConfig, tag: string | undefined): WorkflowResource[];
51
- /** The single resource a read should target, or fail asking which when the
52
- * config spans more than one. For the paths that need one definite dataset
53
- * (the instance-targeted verbs); listings fan out via
54
- * {@link resolveReadResources} instead. */
54
+ /** The single resource an instance-keyed command reads from when it isn't
55
+ * disambiguated interactively: the sole resource, the `--tag`-narrowed one, or
56
+ * a `fail` asking for `--deployment`/`--tag` when the config spans several. The
57
+ * interactive picker lives in {@link resolveInstanceResource}; listings fan out
58
+ * via {@link resolveReadResources} instead. */
55
59
  export declare function resolveReadResource(config: WorkflowConfig, tag: string | undefined): WorkflowResource;
56
60
  /**
57
61
  * The resolution an instance-id-targeted command shares, read or write: an
@@ -60,15 +64,34 @@ export declare function resolveReadResource(config: WorkflowConfig, tag: string
60
64
  * config's declared deployments. An instance id is globally unique and carries
61
65
  * its own `tag`, so a command that names one acts on that instance regardless
62
66
  * of which tags the config happens to deploy; the config only locates the
63
- * resource (via {@link resolveReadResource}, no tag filter).
67
+ * resource (via {@link resolveInstanceResource}, no tag filter).
64
68
  *
65
69
  * Contrast {@link resolveContext}: the deploy/diff/delete path IS scoped to a
66
70
  * declared deployment because it acts on the authored definition set (or a
67
71
  * definition name, which — unlike an instance id — isn't unique across tags).
68
72
  */
69
73
  export declare function resolveInstanceContext(flags: {
74
+ deployment?: string | undefined;
70
75
  tag?: string | undefined;
71
76
  }, instanceId: string): Promise<InstanceContext>;
77
+ /**
78
+ * Which resource an instance-keyed command reads from: the one `--deployment`
79
+ * names (resolved by its unique deployment name); otherwise, when the config
80
+ * spans several resources, an interactive terminal is prompted to pick a
81
+ * deployment ({@link canPromptOnStderr}) — its resource is the read source, the
82
+ * interactive counterpart to `--deployment`. A run that can't prompt falls to
83
+ * the sole or `--tag`-narrowed resource, or the ambiguity error
84
+ * ({@link resolveReadResource}). The instance id is globally unique, so this
85
+ * only locates the resource to look in — never the instance's `tag` partition,
86
+ * which the caller takes from the loaded instance. The shared path behind all
87
+ * four instance-keyed commands.
88
+ */
89
+ export declare function resolveInstanceResource(config: WorkflowConfig, { deployment, tag, interactive, chooseDeployment, }: {
90
+ deployment?: string | undefined;
91
+ tag?: string | undefined;
92
+ interactive?: boolean | undefined;
93
+ chooseDeployment?: ChooseDeploymentName | undefined;
94
+ }): Promise<WorkflowResource>;
72
95
  /** Fetch an instance by id, exiting cleanly when the resource has no such
73
96
  * document — the diagnostic an operator sees on a mistyped id. Split out from
74
97
  * {@link resolveInstanceContext} so the not-found path is unit-testable