@sanity/workflow-cli 0.11.0 → 0.13.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 +66 -0
- package/README.md +75 -46
- package/dist/commands/{abort.d.ts → editorial-workflows/abort.d.ts} +3 -2
- package/dist/commands/{abort.js → editorial-workflows/abort.js} +7 -6
- package/dist/commands/{definition → editorial-workflows/definition}/delete.d.ts +3 -2
- package/dist/commands/{definition → editorial-workflows/definition}/delete.js +6 -5
- package/dist/commands/{definition → editorial-workflows/definition}/diff.d.ts +2 -1
- package/dist/commands/{definition → editorial-workflows/definition}/diff.js +7 -6
- package/dist/commands/{definition → editorial-workflows/definition}/list.d.ts +5 -1
- package/dist/commands/{definition → editorial-workflows/definition}/list.js +27 -24
- package/dist/commands/{definition → editorial-workflows/definition}/show.d.ts +3 -2
- package/dist/commands/{definition → editorial-workflows/definition}/show.js +9 -8
- package/dist/commands/{deploy.d.ts → editorial-workflows/deploy.d.ts} +2 -1
- package/dist/commands/{deploy.js → editorial-workflows/deploy.js} +14 -13
- package/dist/commands/{diagnose.d.ts → editorial-workflows/diagnose.d.ts} +2 -1
- package/dist/commands/{diagnose.js → editorial-workflows/diagnose.js} +7 -6
- package/dist/commands/{fire-action.d.ts → editorial-workflows/fire-action.d.ts} +3 -2
- package/dist/commands/{fire-action.js → editorial-workflows/fire-action.js} +8 -7
- package/dist/commands/{list.d.ts → editorial-workflows/list.d.ts} +4 -1
- package/dist/commands/{list.js → editorial-workflows/list.js} +33 -28
- package/dist/commands/editorial-workflows/nuke.d.ts +12 -0
- package/dist/commands/editorial-workflows/nuke.js +77 -0
- package/dist/commands/{reset-activity.d.ts → editorial-workflows/reset-activity.d.ts} +2 -1
- package/dist/commands/{reset-activity.js → editorial-workflows/reset-activity.js} +2 -1
- package/dist/commands/{set-stage.d.ts → editorial-workflows/set-stage.d.ts} +4 -3
- package/dist/commands/{set-stage.js → editorial-workflows/set-stage.js} +6 -5
- package/dist/commands/{show.d.ts → editorial-workflows/show.d.ts} +2 -1
- package/dist/commands/{show.js → editorial-workflows/show.js} +40 -26
- package/dist/commands/{start.d.ts → editorial-workflows/start.d.ts} +20 -4
- package/dist/commands/{start.js → editorial-workflows/start.js} +58 -16
- package/dist/commands/{tail.d.ts → editorial-workflows/tail.d.ts} +2 -1
- package/dist/commands/{tail.js → editorial-workflows/tail.js} +10 -8
- package/dist/hooks/finally/telemetry.js +2 -2
- package/dist/hooks/prerun/telemetry.d.ts +4 -3
- package/dist/lib/base-command.d.ts +4 -6
- package/dist/lib/base-command.js +6 -0
- package/dist/lib/client.d.ts +8 -0
- package/dist/lib/client.js +1 -1
- package/dist/lib/context.d.ts +6 -2
- package/dist/lib/context.js +9 -7
- package/dist/lib/definitions.js +2 -2
- package/dist/lib/flags.d.ts +4 -3
- package/dist/lib/nuke.d.ts +89 -0
- package/dist/lib/nuke.js +111 -0
- package/dist/lib/operation-args.d.ts +3 -1
- package/dist/lib/ops-report.d.ts +2 -1
- package/dist/lib/prompt.d.ts +11 -0
- package/dist/lib/prompt.js +4 -0
- package/dist/lib/select-deployment.d.ts +12 -7
- package/dist/lib/select-deployment.js +26 -1
- package/dist/lib/share-definitions.d.ts +23 -28
- package/dist/lib/share-definitions.js +30 -40
- package/dist/lib/telemetry-setup.d.ts +2 -2
- package/dist/lib/telemetry.d.ts +18 -10
- package/dist/lib/telemetry.js +5 -2
- package/dist/lib/ui.d.ts +12 -0
- package/dist/lib/ui.js +9 -0
- package/oclif.manifest.json +138 -46
- package/package.json +11 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,71 @@
|
|
|
1
1
|
# @sanity/workflow-cli
|
|
2
2
|
|
|
3
|
+
## 0.13.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 58f8211: Every command's canonical oclif id now nests under the `editorial-workflows` topic, making the package mountable as a plugin of the `sanity` CLI (`sanity editorial-workflows deploy`) without colliding with host commands. The standalone surface is unchanged: the bare forms (`sanity-workflows deploy`, `sanity-workflows definition list`, …) remain as aliases of the nested ids.
|
|
8
|
+
- 00c089d: **BREAKING:** Require every definition deployment and workflow deployment configuration to state an `expectedMinReaderModel` literal that exactly matches the installed engine's writer capability.
|
|
9
|
+
|
|
10
|
+
Deploy and definition-diff paths now reject missing or stale acknowledgements before client access or telemetry, with a structured error and readers-first rollout guidance.
|
|
11
|
+
|
|
12
|
+
- 53661fa: Prompt interactive deploys to select a configured deployment tag when several are available and no selector flag was supplied. Render Ctrl+C prompt cancellations without a stack trace.
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- 82e4a4e: Fix definition sharing to honor its opt-out contract: deploys now share newly created definition versions by default in every environment, including CI, `DO_NOT_TRACK`, and non-TTY runs. The first interactive run shows a mandatory disclosure rather than a consent choice, every other flagless run prints a clear status block with the explicit opt-in and opt-out flags, and only `--no-share-defs` suppresses sharing for that invocation.
|
|
17
|
+
- 9126299: **BREAKING:** Delete persisted stage guard documents when their stage exits, and remove the lifted-record `GUARD_LIFTED_PREDICATE` and `isGuardLifted` exports.
|
|
18
|
+
|
|
19
|
+
Guard deletion now uses the observed document revision so stale exit reconciliation cannot delete a guard reactivated by a newer stage visit. Reactive guard streams contain only active persisted guards.
|
|
20
|
+
|
|
21
|
+
- Updated dependencies [239d9f6]
|
|
22
|
+
- Updated dependencies [3af2ca0]
|
|
23
|
+
- Updated dependencies [7276702]
|
|
24
|
+
- Updated dependencies [58f8211]
|
|
25
|
+
- Updated dependencies [00c089d]
|
|
26
|
+
- Updated dependencies [71cd58e]
|
|
27
|
+
- Updated dependencies [cd03973]
|
|
28
|
+
- Updated dependencies [d26cc1a]
|
|
29
|
+
- Updated dependencies [9126299]
|
|
30
|
+
- Updated dependencies [72018af]
|
|
31
|
+
- Updated dependencies [5cd8ffd]
|
|
32
|
+
- Updated dependencies [b82bda4]
|
|
33
|
+
- Updated dependencies [55a54b3]
|
|
34
|
+
- Updated dependencies [b82bda4]
|
|
35
|
+
- Updated dependencies [4490442]
|
|
36
|
+
- Updated dependencies [1540dce]
|
|
37
|
+
- @sanity/workflow-engine@0.18.0
|
|
38
|
+
|
|
39
|
+
## 0.12.0
|
|
40
|
+
|
|
41
|
+
### Minor Changes
|
|
42
|
+
|
|
43
|
+
- e3a7ba2: `start` gains `--instance-id` — for retries: the id is the start's idempotency key, so passing the id of a start that failed partway resumes it instead of creating a duplicate (an already-settled start replays as a no-op). A start whose first auto-advance fails after the instance was created and primed (`StartNotSettledError`) now reports as STARTED with the cause and the retry id — a warn, not the "Start rejected" failure path — and the `--json` payload carries `{instanceId, notSettled: true, detail}`. A start that fails before priming (`StartNotPrimedError`) still fails, with the `--instance-id` retry hint appended so the operator can resume instead of duplicating.
|
|
44
|
+
- a8ace4d: New `nuke --tag <tag>` command — the dev-period big red button that deletes every engine-owned document for a deployment tag: instances, definitions, and guard docs (matched by instance-id prefix, so guards orphaned by earlier partial deletions are swept too) across the deployment's workflow resource and every alias-bound resource. Content documents are never touched. The command always prints a per-dataset dry-run plan, then requires typing back every involved `project.dataset` target; `--force` skips the prompt for scripts/CI (the plan still prints). Unlike `definition delete` (the governed lifecycle path), `nuke` deletes raw docs without reading them, so it works on pre-amendment shapes a newer engine can no longer read — the sanctioned reset while the versioned upgrade framework doesn't exist.
|
|
45
|
+
- 5a1a9fe: Direct reads of engine-owned documents adopt the data-model gate (`assertReadableModel`): the CLI's instance and definition reads (`show`, `tail`, `list`, `definition show`, `definition list`, deploy lookups, the share read-back) and the MCP tools that interpret rows from the ungated `engine.query` escape hatch (`list_workflow_definitions`, `list_workflow_instances`, the definition lookup behind `start_workflow` / `get_workflow_definition`). A document written by a newer engine data model now fails with the governed "upgrade `@sanity/workflow-engine`" error instead of rendering unchecked; list projections carry the stamp pair so projected rows gate too.
|
|
46
|
+
|
|
47
|
+
### Patch Changes
|
|
48
|
+
|
|
49
|
+
- 092a0d4: **BREAKING:** runtime-supplied refs written into field state are gated on the deployment's declared resource surface.
|
|
50
|
+
- A `doc.ref` / `doc.refs` / `release.ref` value a caller or effect handler supplies — start `initialFields` input, an action's param-sourced op values, `editField` values, effect-completion ops — must target a declared resource: the `workflowResource` itself or a resource the `resourceClients` resolver serves. An off-surface ref throws the new `RefResourceUndeclaredError` and the commit aborts, instead of writing cleanly and failing later when something dereferences it. The check is advisory like every engine check; stored documents are unchanged.
|
|
51
|
+
- Definition-authored refs are exempt: literal `initialValue` seeds, `type: 'query'` texts, spawn `with` projections, and op values that bind no action param were validated (and alias-expanded) at deploy, so they materialize into field state without re-checking.
|
|
52
|
+
- Resource aliases stay a deploy-time abstraction: `deployDefinitions({definitions, resourceAliases?})` expands every `@<alias>:` reference to its physical GDR before fingerprinting, and nothing alias-shaped survives past deploy — the runtime holds no alias map, and an alias-shaped ref supplied to a runtime verb is rejected as malformed like any other non-GDR string.
|
|
53
|
+
- `createBench` takes `serveResources` (dataset siblings served — and thereby declared — straight from the bench's own store) plus a raw `resourceClients` resolver for anything beyond same-store siblings. The engine also exports `sameResource` alongside the existing GDR helpers.
|
|
54
|
+
- The CLI wires no `resourceClients`, so refs supplied at runtime through it (`start --field`, `fire-action` ref params) admit the workflow resource only.
|
|
55
|
+
|
|
56
|
+
- Updated dependencies [f9389e5]
|
|
57
|
+
- Updated dependencies [d0c62ea]
|
|
58
|
+
- Updated dependencies [c3eed2e]
|
|
59
|
+
- Updated dependencies [df4bd80]
|
|
60
|
+
- Updated dependencies [092a0d4]
|
|
61
|
+
- Updated dependencies [5a1a9fe]
|
|
62
|
+
- Updated dependencies [e3a7ba2]
|
|
63
|
+
- Updated dependencies [30fed9e]
|
|
64
|
+
- Updated dependencies [1321ba5]
|
|
65
|
+
- Updated dependencies [e683875]
|
|
66
|
+
- Updated dependencies [a8ace4d]
|
|
67
|
+
- @sanity/workflow-engine@0.17.0
|
|
68
|
+
|
|
3
69
|
## 0.11.0
|
|
4
70
|
|
|
5
71
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -20,6 +20,19 @@ pnpm --filter @sanity/workflow-cli dev list --include-completed
|
|
|
20
20
|
pnpm --filter @sanity/workflow-cli dev show wf-instance.abc123
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
+
The package is an [oclif](https://oclif.io) plugin: every command's canonical
|
|
24
|
+
id nests under the `editorial-workflows` topic
|
|
25
|
+
(`sanity-workflows editorial-workflows deploy`), so mounting the package into
|
|
26
|
+
the `sanity` CLI's plugin list surfaces the same commands as
|
|
27
|
+
`sanity editorial-workflows …` without its canonical ids colliding with the
|
|
28
|
+
host's own commands (the sanity CLI already has a `deploy`). The bare forms
|
|
29
|
+
used throughout this README (`deploy`, `definition list`, …) are aliases of
|
|
30
|
+
the nested ids and are the standalone binary's stable surface. oclif registers
|
|
31
|
+
plugin aliases in a host unconditionally (an id collision resolves by plugin
|
|
32
|
+
priority, host first), so a host mount would also surface these bare aliases
|
|
33
|
+
at its root — trimming or hiding them for the mounted context is part of the
|
|
34
|
+
host-side mount work, not something a host can configure away.
|
|
35
|
+
|
|
23
36
|
Authenticate once with `sanity login` (the CLI reads that session token); for
|
|
24
37
|
CI, set `SANITY_AUTH_TOKEN` instead. Then create a `sanity.workflow.ts` in the
|
|
25
38
|
directory you run from — see [Configuration](#configuration).
|
|
@@ -46,6 +59,7 @@ import {articleReview, urlDraft} from './src/workflows.ts'
|
|
|
46
59
|
export default defineWorkflowConfig({
|
|
47
60
|
deployments: [
|
|
48
61
|
{
|
|
62
|
+
expectedMinReaderModel: 2,
|
|
49
63
|
name: 'production',
|
|
50
64
|
tag: 'prod', // the environment partition the engine's docs are scoped to
|
|
51
65
|
workflowResource: {type: 'dataset', id: 'acme.workflows'}, // where those docs live
|
|
@@ -63,22 +77,33 @@ export default defineWorkflowConfig({
|
|
|
63
77
|
```
|
|
64
78
|
|
|
65
79
|
Pick a deployment with `--tag <tag>`; with a single deployment configured you
|
|
66
|
-
can omit it
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
|
84
|
+
stop the rest — the run continues, prints a summary of what failed, and exits
|
|
85
|
+
non-zero. The client's project + dataset are derived from the deployment's
|
|
86
|
+
`workflowResource`, and `deploy` expands each definition's `@<handle>:`
|
|
87
|
+
reference to the bound physical resource. An invalid config fails with a clean,
|
|
88
|
+
path-prefixed error before the command runs.
|
|
73
89
|
|
|
74
90
|
`resourceAliases` is only for content that lives in a _different_ resource from
|
|
75
91
|
`workflowResource`. A definition can reference a document in the **same**
|
|
76
92
|
resource by bare id, no alias needed — bare ids root at `workflowResource` at
|
|
77
|
-
runtime.
|
|
78
|
-
|
|
93
|
+
runtime. Bindings exist at deploy time only: `deploy` expands each `@<handle>:`
|
|
94
|
+
reference to its bound physical GDR, and nothing alias-shaped survives into the
|
|
95
|
+
deployed definition or the runtime. Rule of thumb: **different resource →
|
|
96
|
+
bind an alias; same resource → use a bare id and omit `resourceAliases`
|
|
79
97
|
entirely.** So the simplest single-dataset setup is just a `workflowResource`
|
|
80
98
|
and `definitions`, with no `resourceAliases` at all.
|
|
81
99
|
|
|
100
|
+
Refs supplied at runtime (`start --field`, `fire-action` ref params) are gated
|
|
101
|
+
separately: they may target the `workflowResource` itself, and anything else is
|
|
102
|
+
rejected at the write with `RefResourceUndeclaredError`. The CLI wires no
|
|
103
|
+
`resourceClients` resolver, so it has no way to widen that surface — a runtime
|
|
104
|
+
foreign-resource ref goes through an engine consumer that serves the target
|
|
105
|
+
resource, not through the CLI.
|
|
106
|
+
|
|
82
107
|
| Var | Purpose |
|
|
83
108
|
| ------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
84
109
|
| `SANITY_AUTH_TOKEN` | Explicit token for CI / scripted use — wins over the `sanity login` session (editor role for writes) |
|
|
@@ -118,25 +143,26 @@ stale compiled output.
|
|
|
118
143
|
|
|
119
144
|
## Command status
|
|
120
145
|
|
|
121
|
-
| Command | Status
|
|
122
|
-
| -------------------------------------- |
|
|
123
|
-
| `deploy` | wired — calls `workflow.deployDefinitions` over the selected deployment's definitions
|
|
124
|
-
| `deploy --all-tags` | wired — deploys every deployment in the config, continuing past per-deployment failures
|
|
125
|
-
| `deploy --check` | wired — runs `validateDefinition` over the local batch + a duplicate-name check
|
|
126
|
-
| `deploy --dry-run` | wired — fetches existing docs and renders a coloured JSON diff per change
|
|
127
|
-
| `deploy --only <name>` | wired — filters deploy/check/dry-run to one definition by `name`
|
|
128
|
-
| `start <name>` | wired — calls `workflow.startInstance` (`--field` for input fields)
|
|
129
|
-
| `list` | wired — `client.fetch` over `sanity.workflow.instance` documents (`--definition <name>` to filter)
|
|
130
|
-
| `show <instance-id>` | wired — `client.getDocument`
|
|
131
|
-
| `diagnose <instance-id>` | wired — calls `workflow.diagnose`, classifies why the instance is/isn't progressing
|
|
132
|
-
| `tail <instance-id>` | wired — `client.listen()` over the instance, prints new history entries
|
|
133
|
-
| `abort <instance-id>` | wired — calls `workflow.abortInstance` (hard stop: cancels pending effects,
|
|
134
|
-
| `set-stage <instance-id> --to <stage>` | wired — calls `workflow.setStage` (admin override: skips declared transitions/filters; enter lifecycle + cascade still run)
|
|
135
|
-
| `fire-action <instance-id>` | wired — `workflow.availableActions` lists actions; `workflow.fireAction` fires one
|
|
136
|
-
| `definition list` | wired — `client.fetch` over `sanity.workflow.definition` documents
|
|
137
|
-
| `definition show <name>` | wired — `client.fetch`, latest version unless `--version`
|
|
138
|
-
| `definition diff <name>` | wired — diffs the in-code definition against the deployed latest (`--version` to pin)
|
|
139
|
-
| `definition delete <name>` | wired — calls `workflow.deleteDefinition` (refuses on live instances unless `--cascade`)
|
|
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 |
|
|
140
166
|
|
|
141
167
|
## Telemetry
|
|
142
168
|
|
|
@@ -145,8 +171,9 @@ per-command trace (`Editorial Workflows CLI Command Executed` — the command id
|
|
|
145
171
|
names of declared flags used, never their values, and a success flag) plus
|
|
146
172
|
the engine's adoption events from the operations it drives. Consent is the
|
|
147
173
|
account-wide status managed by `npx sanity telemetry enable|disable|status`;
|
|
148
|
-
CI and trueish `DO_NOT_TRACK` suppress everything (except a
|
|
149
|
-
which forces that deploy's telemetry
|
|
174
|
+
CI and trueish `DO_NOT_TRACK` suppress everything (except a deploy that may share
|
|
175
|
+
new definitions, which forces that deploy's telemetry unless `--no-share-defs`
|
|
176
|
+
is passed — see [Definition sharing](#definition-sharing)),
|
|
150
177
|
and a session that isn't logged in sends nothing. A one-time notice on stderr
|
|
151
178
|
discloses collection on first use.
|
|
152
179
|
|
|
@@ -166,25 +193,27 @@ definition-feedback endpoint, not the telemetry pipeline; telemetry carries
|
|
|
166
193
|
only a content-free marker (content hash plus structural counts) per shared
|
|
167
194
|
definition and a per-invocation decision event.
|
|
168
195
|
|
|
169
|
-
Sharing is **opt-out**. Pass `--share-defs` to
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
account-level `sanity telemetry disable` still applies. A failed share
|
|
180
|
-
warns, never failing a completed deploy.
|
|
196
|
+
Sharing is **opt-out in every environment**. Pass `--no-share-defs` to decline
|
|
197
|
+
for one invocation. With neither flag, the first interactive deploy prints a
|
|
198
|
+
full notice before sending and remembers that the notice was shown; every later
|
|
199
|
+
flagless deploy prints a status block showing that sharing is on by default and
|
|
200
|
+
showing runnable shell examples for the default, explicit opt-in, and opt-out
|
|
201
|
+
forms; the explicit flags suppress the status block. Unattended runs (CI,
|
|
202
|
+
`DO_NOT_TRACK`, or a non-TTY pipe) also share by default and print that status
|
|
203
|
+
block in their logs.
|
|
204
|
+
A flagless deploy or explicit `--share-defs` forces that deploy's telemetry
|
|
205
|
+
through the environment gate so donated definitions retain their content-free
|
|
206
|
+
markers; account-level `sanity telemetry disable` still applies. A failed share
|
|
207
|
+
only warns, never failing a completed deploy.
|
|
181
208
|
|
|
182
209
|
## Known gaps
|
|
183
210
|
|
|
184
|
-
- **
|
|
185
|
-
|
|
186
|
-
`sanity
|
|
187
|
-
plugin
|
|
211
|
+
- **Not mounted in the `sanity` CLI yet.** The package side is mount-ready —
|
|
212
|
+
commands nest under the `editorial-workflows` oclif topic (see
|
|
213
|
+
[Run](#run)) — but the `sanity` CLI does not list this package in its
|
|
214
|
+
plugin array, so the commands ship only through the standalone
|
|
215
|
+
`sanity-workflows` binary today. The host-side mount (and what happens to
|
|
216
|
+
the bare aliases inside a host) is a separate piece of work.
|
|
188
217
|
- **No true bypass.** `set-stage` is the engine's `setStage` admin
|
|
189
218
|
override: it skips the definition's declared transitions and filters, but
|
|
190
219
|
the target stage's enter lifecycle and the post-move cascade still run. A
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type WorkflowInstance } from '@sanity/workflow-engine';
|
|
2
|
-
import { WorkflowCommand } from '
|
|
3
|
-
import { type WriteReport } from '
|
|
2
|
+
import { WorkflowCommand } from '../../lib/base-command.ts';
|
|
3
|
+
import { type WriteReport } from '../../lib/ops-report.ts';
|
|
4
4
|
export default class Abort extends WorkflowCommand {
|
|
5
|
+
static aliases: string[];
|
|
5
6
|
static description: string;
|
|
6
7
|
static examples: string[];
|
|
7
8
|
static args: {
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { styleText } from 'node:util';
|
|
2
2
|
import { Args, Flags } from '@oclif/core';
|
|
3
3
|
import { workflow } from '@sanity/workflow-engine';
|
|
4
|
-
import { WorkflowCommand } from "
|
|
5
|
-
import { resolveInstanceContext } from "
|
|
6
|
-
import { tagFlags } from "
|
|
7
|
-
import { buildOperationArgs } from "
|
|
8
|
-
import { runWriteVerb } from "
|
|
4
|
+
import { WorkflowCommand } from "../../lib/base-command.js";
|
|
5
|
+
import { resolveInstanceContext } from "../../lib/context.js";
|
|
6
|
+
import { tagFlags } from "../../lib/flags.js";
|
|
7
|
+
import { buildOperationArgs } from "../../lib/operation-args.js";
|
|
8
|
+
import { runWriteVerb } from "../../lib/ops-report.js";
|
|
9
9
|
export default class Abort extends WorkflowCommand {
|
|
10
|
-
static
|
|
10
|
+
static aliases = ['abort'];
|
|
11
|
+
static description = 'Abort an in-flight workflow instance — a hard stop: pending effects are cancelled, stage guards removed, and the instance is marked terminal where it stands.';
|
|
11
12
|
static examples = [
|
|
12
13
|
'<%= config.bin %> abort wf-instance.abc123',
|
|
13
14
|
"<%= config.bin %> abort wf-instance.abc123 --reason 'superseded by relaunch'",
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type DeleteDefinitionArgs, type DeleteDefinitionResult } from '@sanity/workflow-engine';
|
|
2
|
-
import { WorkflowCommand } from '
|
|
3
|
-
import { type EngineScope } from '
|
|
2
|
+
import { WorkflowCommand } from '../../../lib/base-command.ts';
|
|
3
|
+
import { type EngineScope } from '../../../lib/operation-args.ts';
|
|
4
4
|
export default class DefinitionDelete extends WorkflowCommand {
|
|
5
|
+
static aliases: string[];
|
|
5
6
|
static description: string;
|
|
6
7
|
static examples: string[];
|
|
7
8
|
static args: {
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { styleText } from 'node:util';
|
|
2
2
|
import { Args, Flags } from '@oclif/core';
|
|
3
3
|
import { workflow, } from '@sanity/workflow-engine';
|
|
4
|
-
import { WorkflowCommand } from "
|
|
5
|
-
import { resolveContext } from "
|
|
6
|
-
import { tagFlags } from "
|
|
7
|
-
import { baseEngineArgs } from "
|
|
8
|
-
import { runWriteVerb } from "
|
|
4
|
+
import { WorkflowCommand } from "../../../lib/base-command.js";
|
|
5
|
+
import { resolveContext } from "../../../lib/context.js";
|
|
6
|
+
import { tagFlags } from "../../../lib/flags.js";
|
|
7
|
+
import { baseEngineArgs } from "../../../lib/operation-args.js";
|
|
8
|
+
import { runWriteVerb } from "../../../lib/ops-report.js";
|
|
9
9
|
export default class DefinitionDelete extends WorkflowCommand {
|
|
10
|
+
static aliases = ['definition:delete'];
|
|
10
11
|
static description = 'Delete a deployed workflow definition (every version, or one via --version). ' +
|
|
11
12
|
'Refuses while non-terminal instances exist unless --cascade aborts them first — ' +
|
|
12
13
|
'instances are aborted in place, never deleted.';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type WorkflowDefinition } from '@sanity/workflow-engine';
|
|
2
|
-
import { WorkflowCommand } from '
|
|
2
|
+
import { WorkflowCommand } from '../../../lib/base-command.ts';
|
|
3
3
|
export default class DefinitionDiff extends WorkflowCommand {
|
|
4
|
+
static aliases: string[];
|
|
4
5
|
static description: string;
|
|
5
6
|
static examples: string[];
|
|
6
7
|
static args: {
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { Args, Flags } from '@oclif/core';
|
|
2
2
|
import { diffEntry } from '@sanity/workflow-engine';
|
|
3
3
|
import ora from 'ora';
|
|
4
|
-
import { WorkflowCommand } from "
|
|
5
|
-
import { resolveContext } from "
|
|
6
|
-
import { fetchDeployedDefinition, selectDefinitions, validateOrFail } from "
|
|
7
|
-
import { diffReport } from "
|
|
8
|
-
import { tagFlags } from "
|
|
9
|
-
import { deploymentToTarget } from "
|
|
4
|
+
import { WorkflowCommand } from "../../../lib/base-command.js";
|
|
5
|
+
import { resolveContext } from "../../../lib/context.js";
|
|
6
|
+
import { fetchDeployedDefinition, selectDefinitions, validateOrFail, } from "../../../lib/definitions.js";
|
|
7
|
+
import { diffReport } from "../../../lib/diff.js";
|
|
8
|
+
import { tagFlags } from "../../../lib/flags.js";
|
|
9
|
+
import { deploymentToTarget } from "../../../lib/select-deployment.js";
|
|
10
10
|
export default class DefinitionDiff extends WorkflowCommand {
|
|
11
|
+
static aliases = ['definition:diff'];
|
|
11
12
|
static description = 'Diff an in-code definition against the deployed version (latest by default).';
|
|
12
13
|
static examples = [
|
|
13
14
|
'<%= config.bin %> definition diff productLaunch',
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { WorkflowCommand } from '
|
|
1
|
+
import { WorkflowCommand } from '../../../lib/base-command.ts';
|
|
2
2
|
interface DefinitionListFlags {
|
|
3
3
|
tag?: string | undefined;
|
|
4
4
|
name?: string | undefined;
|
|
5
5
|
limit: number;
|
|
6
6
|
}
|
|
7
7
|
export interface DefinitionListRow {
|
|
8
|
+
_id: string;
|
|
8
9
|
name: string;
|
|
9
10
|
version: number;
|
|
10
11
|
title: string;
|
|
@@ -13,12 +14,15 @@ export interface DefinitionListRow {
|
|
|
13
14
|
inFlightCount: number;
|
|
14
15
|
totalInstances: number;
|
|
15
16
|
_createdAt: string;
|
|
17
|
+
modelVersion?: number | null;
|
|
18
|
+
minReaderModel?: number | null;
|
|
16
19
|
}
|
|
17
20
|
export declare function buildDefinitionListQuery(flags: DefinitionListFlags): {
|
|
18
21
|
groq: string;
|
|
19
22
|
params: Record<string, unknown>;
|
|
20
23
|
};
|
|
21
24
|
export default class DefinitionList extends WorkflowCommand {
|
|
25
|
+
static aliases: string[];
|
|
22
26
|
static description: string;
|
|
23
27
|
static examples: string[];
|
|
24
28
|
static flags: {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Flags } from '@oclif/core';
|
|
2
|
-
import { WORKFLOW_DEFINITION_TYPE, WORKFLOW_INSTANCE_TYPE, inFlightFilter, tagScopeFilter, } from '@sanity/workflow-engine';
|
|
2
|
+
import { WORKFLOW_DEFINITION_TYPE, WORKFLOW_INSTANCE_TYPE, assertReadableModel, inFlightFilter, tagScopeFilter, } from '@sanity/workflow-engine';
|
|
3
3
|
import logSymbols from 'log-symbols';
|
|
4
|
-
import { WorkflowCommand } from "
|
|
5
|
-
import { resolveReadTargets } from "
|
|
6
|
-
import { tagFlags } from "
|
|
7
|
-
import { runReadAcrossTargets } from "
|
|
8
|
-
import {
|
|
4
|
+
import { WorkflowCommand } from "../../../lib/base-command.js";
|
|
5
|
+
import { resolveReadTargets } from "../../../lib/context.js";
|
|
6
|
+
import { tagFlags } from "../../../lib/flags.js";
|
|
7
|
+
import { runReadAcrossTargets } from "../../../lib/read-fanout.js";
|
|
8
|
+
import { logClippedTable } from "../../../lib/ui.js";
|
|
9
9
|
export function buildDefinitionListQuery(flags) {
|
|
10
10
|
const params = { limit: flags.limit + 1 };
|
|
11
11
|
const filters = [`_type == "${WORKFLOW_DEFINITION_TYPE}"`];
|
|
@@ -25,11 +25,14 @@ export function buildDefinitionListQuery(flags) {
|
|
|
25
25
|
}
|
|
26
26
|
const instanceMatch = instanceFilters.join(' && ');
|
|
27
27
|
const groq = `*[${filters.join(' && ')}] | order(name asc, version desc) [0...$limit]{
|
|
28
|
+
_id,
|
|
28
29
|
name,
|
|
29
30
|
version,
|
|
30
31
|
title,
|
|
31
32
|
tag,
|
|
32
33
|
_createdAt,
|
|
34
|
+
modelVersion,
|
|
35
|
+
minReaderModel,
|
|
33
36
|
"stageCount": count(stages),
|
|
34
37
|
"inFlightCount": count(*[${instanceMatch} && ${inFlightFilter()}]),
|
|
35
38
|
"totalInstances": count(*[${instanceMatch}])
|
|
@@ -37,6 +40,7 @@ export function buildDefinitionListQuery(flags) {
|
|
|
37
40
|
return { groq, params };
|
|
38
41
|
}
|
|
39
42
|
export default class DefinitionList extends WorkflowCommand {
|
|
43
|
+
static aliases = ['definition:list'];
|
|
40
44
|
static description = 'List deployed workflow definitions.';
|
|
41
45
|
static examples = [
|
|
42
46
|
'<%= config.bin %> definition list',
|
|
@@ -60,29 +64,28 @@ export default class DefinitionList extends WorkflowCommand {
|
|
|
60
64
|
targets,
|
|
61
65
|
log: (line) => this.log(line),
|
|
62
66
|
run: async ({ client }) => {
|
|
63
|
-
const fetched = await client.fetch(groq, params, {
|
|
67
|
+
const fetched = (await client.fetch(groq, params, {
|
|
64
68
|
tag: 'definition.list',
|
|
65
|
-
});
|
|
69
|
+
})).map(assertReadableModel);
|
|
66
70
|
if (!fetched.length) {
|
|
67
71
|
this.log(`${logSymbols.info} no definitions found`);
|
|
68
72
|
return;
|
|
69
73
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
r
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
74
|
+
logClippedTable({
|
|
75
|
+
rows: fetched,
|
|
76
|
+
limit: flags.limit,
|
|
77
|
+
headers: ['workflow', 'title', 'tag', 'stages', 'in flight', 'instances', 'created'],
|
|
78
|
+
toCells: (r) => [
|
|
79
|
+
`${r.name} v${r.version}`,
|
|
80
|
+
r.title,
|
|
81
|
+
r.tag,
|
|
82
|
+
String(r.stageCount),
|
|
83
|
+
String(r.inFlightCount),
|
|
84
|
+
String(r.totalInstances),
|
|
85
|
+
r._createdAt,
|
|
86
|
+
],
|
|
87
|
+
log: (line) => this.log(line),
|
|
88
|
+
});
|
|
86
89
|
},
|
|
87
90
|
});
|
|
88
91
|
if (failures.length > 0) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type DeployedDefinition, type WorkflowDefinition, type WorkflowResource } from '@sanity/workflow-engine';
|
|
2
|
-
import { WorkflowCommand } from '
|
|
3
|
-
import { type ReadTarget } from '
|
|
2
|
+
import { WorkflowCommand } from '../../../lib/base-command.ts';
|
|
3
|
+
import { type ReadTarget } from '../../../lib/context.ts';
|
|
4
4
|
export default class DefinitionShow extends WorkflowCommand {
|
|
5
|
+
static aliases: string[];
|
|
5
6
|
static description: string;
|
|
6
7
|
static args: {
|
|
7
8
|
name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { styleText } from 'node:util';
|
|
2
2
|
import { Args, Flags } from '@oclif/core';
|
|
3
|
-
import { isTerminalStage, } from '@sanity/workflow-engine';
|
|
3
|
+
import { assertReadableModel, isTerminalStage, } from '@sanity/workflow-engine';
|
|
4
4
|
import logSymbols from 'log-symbols';
|
|
5
|
-
import { WorkflowCommand } from "
|
|
6
|
-
import { resolveReadTargets, soleHitOrFail } from "
|
|
7
|
-
import { buildDefinitionShowQuery, buildDefinitionTagsQuery } from "
|
|
8
|
-
import { fail } from "
|
|
9
|
-
import { tagFlags } from "
|
|
10
|
-
import { formatKeyValue, resourceLabel, sectionHeader } from "
|
|
5
|
+
import { WorkflowCommand } from "../../../lib/base-command.js";
|
|
6
|
+
import { resolveReadTargets, soleHitOrFail } from "../../../lib/context.js";
|
|
7
|
+
import { buildDefinitionShowQuery, buildDefinitionTagsQuery } from "../../../lib/definitions.js";
|
|
8
|
+
import { fail } from "../../../lib/fail.js";
|
|
9
|
+
import { tagFlags } from "../../../lib/flags.js";
|
|
10
|
+
import { formatKeyValue, resourceLabel, sectionHeader } from "../../../lib/ui.js";
|
|
11
11
|
export default class DefinitionShow extends WorkflowCommand {
|
|
12
|
+
static aliases = ['definition:show'];
|
|
12
13
|
static description = 'Show a deployed workflow definition.';
|
|
13
14
|
static args = {
|
|
14
15
|
name: Args.string({ required: true, description: 'Workflow definition name.' }),
|
|
@@ -64,7 +65,7 @@ export async function fetchDefinitionHits({ targets, groq, params, }) {
|
|
|
64
65
|
const def = await target.client.fetch(groq, params, {
|
|
65
66
|
tag: 'definition.show',
|
|
66
67
|
});
|
|
67
|
-
return def === null ? undefined : { resource: target.resource, def };
|
|
68
|
+
return def === null ? undefined : { resource: target.resource, def: assertReadableModel(def) };
|
|
68
69
|
}));
|
|
69
70
|
return probes.filter((hit) => hit !== undefined);
|
|
70
71
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type DeployDefinitionResult, type WorkflowDefinition, type WorkflowDeployment } from '@sanity/workflow-engine';
|
|
2
|
-
import { WorkflowCommand } from '
|
|
2
|
+
import { WorkflowCommand } from '../../lib/base-command.ts';
|
|
3
3
|
/** A deployment paired with the definitions selected + validated for it. */
|
|
4
4
|
interface DeployBatch {
|
|
5
5
|
deployment: WorkflowDeployment;
|
|
@@ -11,6 +11,7 @@ interface DeployFailure {
|
|
|
11
11
|
message: string;
|
|
12
12
|
}
|
|
13
13
|
export default class Deploy extends WorkflowCommand {
|
|
14
|
+
static aliases: string[];
|
|
14
15
|
static description: string;
|
|
15
16
|
static examples: string[];
|
|
16
17
|
static flags: {
|
|
@@ -3,18 +3,19 @@ import { Flags } from '@oclif/core';
|
|
|
3
3
|
import { computeDiffEntries, errorMessage, workflow, } from '@sanity/workflow-engine';
|
|
4
4
|
import logSymbols from 'log-symbols';
|
|
5
5
|
import ora from 'ora';
|
|
6
|
-
import { WorkflowCommand } from "
|
|
7
|
-
import { clientFor, resolveTokenOrFail } from "
|
|
8
|
-
import { selectDefinitions, validateOrFail } from "
|
|
9
|
-
import { diffReport } from "
|
|
10
|
-
import { fail, isAuthRejection } from "
|
|
11
|
-
import { tagFlags } from "
|
|
12
|
-
import { loadWorkflowConfig } from "
|
|
13
|
-
import { deploymentToTarget, selectDeployments } from "
|
|
14
|
-
import { shareDefinitionsAfterDeploy } from "
|
|
15
|
-
import { cliTelemetry } from "
|
|
16
|
-
import { groupBanner } from "
|
|
6
|
+
import { WorkflowCommand } from "../../lib/base-command.js";
|
|
7
|
+
import { clientFor, resolveTokenOrFail } from "../../lib/client.js";
|
|
8
|
+
import { selectDefinitions, validateOrFail } from "../../lib/definitions.js";
|
|
9
|
+
import { diffReport } from "../../lib/diff.js";
|
|
10
|
+
import { fail, isAuthRejection } from "../../lib/fail.js";
|
|
11
|
+
import { tagFlags } from "../../lib/flags.js";
|
|
12
|
+
import { loadWorkflowConfig } from "../../lib/load-config.js";
|
|
13
|
+
import { deploymentToTarget, selectDeployments } from "../../lib/select-deployment.js";
|
|
14
|
+
import { shareDefinitionsAfterDeploy } from "../../lib/share-definitions.js";
|
|
15
|
+
import { cliTelemetry } from "../../lib/telemetry.js";
|
|
16
|
+
import { groupBanner } from "../../lib/ui.js";
|
|
17
17
|
export default class Deploy extends WorkflowCommand {
|
|
18
|
+
static aliases = ['deploy'];
|
|
18
19
|
static description = 'Validate, diff, and deploy workflow definitions to the resource bound by the selected deployment.';
|
|
19
20
|
static examples = [
|
|
20
21
|
'<%= config.bin %> deploy --tag prod',
|
|
@@ -43,14 +44,14 @@ export default class Deploy extends WorkflowCommand {
|
|
|
43
44
|
}),
|
|
44
45
|
'share-defs': Flags.boolean({
|
|
45
46
|
allowNo: true,
|
|
46
|
-
description: 'Share the definition documents newly created by this deploy with Sanity — the full document, verbatim (structure, names, filters, effect configuration, seeded values), plus its deployment coordinates (project and dataset, or resource id); never content documents, instances, or your Sanity auth token.
|
|
47
|
+
description: 'Share the definition documents newly created by this deploy with Sanity — the full document, verbatim (structure, names, filters, effect configuration, seeded values), plus its deployment coordinates (project and dataset, or resource id); never content documents, instances, or your Sanity auth token. Sharing is the default in every environment, including CI / non-TTY / DO_NOT_TRACK. Use --no-share-defs to opt out.',
|
|
47
48
|
}),
|
|
48
49
|
};
|
|
49
50
|
async run() {
|
|
50
51
|
const { flags } = await this.parse(Deploy);
|
|
51
52
|
validateModeFlags(flags.check, flags['dry-run']);
|
|
52
53
|
const config = await loadWorkflowConfig();
|
|
53
|
-
const batches = buildBatches(selectDeployments(config, { tag: flags.tag, allTags: flags['all-tags'] }), flags.only);
|
|
54
|
+
const batches = buildBatches(await selectDeployments(config, { tag: flags.tag, allTags: flags['all-tags'] }), flags.only);
|
|
54
55
|
const log = (line) => this.log(line);
|
|
55
56
|
if (flags.check) {
|
|
56
57
|
await reconcileBatches({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Diagnosis, type DiagnoseInput, type SuggestedRemediation, type WorkflowEvaluation } from '@sanity/workflow-engine';
|
|
2
|
-
import { WorkflowCommand } from '
|
|
2
|
+
import { WorkflowCommand } from '../../lib/base-command.ts';
|
|
3
3
|
/** The `--json` transitions payload: raw derived state (atom GROQ, negation,
|
|
4
4
|
* pivotality, solvable requirement) — structure for scripts, never baked
|
|
5
5
|
* English. Pure so the shape is a testable contract. */
|
|
@@ -32,6 +32,7 @@ export declare function renderDiagnosis({ diagnosis, input, remediations, explan
|
|
|
32
32
|
explanations?: ReadonlyMap<string, string> | undefined;
|
|
33
33
|
}): string[];
|
|
34
34
|
export default class Diagnose extends WorkflowCommand {
|
|
35
|
+
static aliases: string[];
|
|
35
36
|
static description: string;
|
|
36
37
|
static examples: string[];
|
|
37
38
|
static args: {
|