@sanity/runtime-cli 15.1.3 → 15.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -20
- package/dist/actions/blueprints/blueprint.js +1 -1
- package/dist/actions/blueprints/operations.d.ts +30 -0
- package/dist/actions/blueprints/operations.js +50 -0
- package/dist/actions/blueprints/stacks.d.ts +2 -2
- package/dist/actions/blueprints/wait-for-operation.d.ts +30 -0
- package/dist/actions/blueprints/wait-for-operation.js +88 -0
- package/dist/actions/functions/test.js +1 -1
- package/dist/actions/node.js +1 -1
- package/dist/actions/sanity/examples.js +1 -1
- package/dist/baseCommands.js +1 -0
- package/dist/commands/blueprints/deploy.js +3 -1
- package/dist/commands/blueprints/destroy.js +3 -1
- package/dist/cores/blueprints/deploy.js +43 -78
- package/dist/cores/blueprints/destroy.js +41 -57
- package/dist/cores/functions/add.js +1 -1
- package/dist/cores/functions/build.js +1 -1
- package/dist/cores/functions/env/add.js +2 -2
- package/dist/cores/functions/env/list.js +2 -2
- package/dist/cores/functions/env/remove.js +2 -2
- package/dist/cores/functions/logs.js +2 -2
- package/dist/cores/functions/test.js +13 -3
- package/dist/cores/index.d.ts +2 -0
- package/dist/server/handlers/invoke.js +17 -5
- package/dist/utils/blueprints/group-resources.d.ts +8 -0
- package/dist/utils/blueprints/group-resources.js +29 -0
- package/dist/utils/blueprints/resolve-deployed-resources.d.ts +17 -0
- package/dist/utils/blueprints/resolve-deployed-resources.js +29 -0
- package/dist/utils/{validate/index.d.ts → blueprints/validate-resources.d.ts} +0 -1
- package/dist/utils/{validate/index.js → blueprints/validate-resources.js} +0 -1
- package/dist/utils/exit-codes.d.ts +15 -0
- package/dist/utils/exit-codes.js +15 -0
- package/dist/utils/{build-payload.d.ts → functions/build-payload.d.ts} +1 -1
- package/dist/utils/{build-payload.js → functions/build-payload.js} +1 -1
- package/dist/utils/{child-process-wrapper.js → functions/child-process-wrapper.js} +63 -0
- package/dist/utils/{find-function.d.ts → functions/find.d.ts} +1 -1
- package/dist/utils/{find-function.js → functions/find.js} +2 -2
- package/dist/utils/{invoke-local.d.ts → functions/invoke-local.d.ts} +1 -1
- package/dist/utils/{invoke-local.js → functions/invoke-local.js} +10 -8
- package/dist/utils/functions/prepare-asset.js +2 -2
- package/dist/utils/{transpile/transpile-function.d.ts → functions/transpile/function.d.ts} +1 -1
- package/dist/utils/{transpile/transpile-function.js → functions/transpile/function.js} +3 -3
- package/dist/utils/types.d.ts +4 -0
- package/oclif.manifest.json +3 -3
- package/package.json +2 -2
- /package/dist/utils/{other → external}/github.d.ts +0 -0
- /package/dist/utils/{other → external}/github.js +0 -0
- /package/dist/utils/{other → external}/npmjs.d.ts +0 -0
- /package/dist/utils/{other → external}/npmjs.js +0 -0
- /package/dist/utils/functions/{getFolderSize.d.ts → get-folder-size.d.ts} +0 -0
- /package/dist/utils/functions/{getFolderSize.js → get-folder-size.js} +0 -0
- /package/dist/utils/functions/{packageJsonUtils.d.ts → package-json.d.ts} +0 -0
- /package/dist/utils/functions/{packageJsonUtils.js → package-json.js} +0 -0
- /package/dist/utils/functions/{resolve-function-auth.d.ts → resolve-auth.d.ts} +0 -0
- /package/dist/utils/functions/{resolve-function-auth.js → resolve-auth.js} +0 -0
- /package/dist/utils/{transpile → functions/transpile}/cleanup-source-maps.d.ts +0 -0
- /package/dist/utils/{transpile → functions/transpile}/cleanup-source-maps.js +0 -0
- /package/dist/utils/{transpile → functions/transpile}/find-up.d.ts +0 -0
- /package/dist/utils/{transpile → functions/transpile}/find-up.js +0 -0
- /package/dist/utils/{pnpm.d.ts → functions/transpile/pnpm.d.ts} +0 -0
- /package/dist/utils/{pnpm.js → functions/transpile/pnpm.js} +0 -0
- /package/dist/utils/{transpile → functions/transpile}/verify-handler.d.ts +0 -0
- /package/dist/utils/{transpile → functions/transpile}/verify-handler.js +0 -0
- /package/dist/utils/{validate/resource.d.ts → functions/validate-name.d.ts} +0 -0
- /package/dist/utils/{validate/resource.js → functions/validate-name.js} +0 -0
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ $ npm install -g @sanity/runtime-cli
|
|
|
20
20
|
$ sanity-run COMMAND
|
|
21
21
|
running command...
|
|
22
22
|
$ sanity-run (--version)
|
|
23
|
-
@sanity/runtime-cli/15.1.
|
|
23
|
+
@sanity/runtime-cli/15.1.5 linux-x64 node-v24.16.0
|
|
24
24
|
$ sanity-run --help [COMMAND]
|
|
25
25
|
USAGE
|
|
26
26
|
$ sanity-run COMMAND
|
|
@@ -103,7 +103,7 @@ EXAMPLES
|
|
|
103
103
|
$ sanity-run blueprints add function --name my-function --fn-type document-create --fn-type document-update --lang js
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
-
_See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.
|
|
106
|
+
_See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.5/src/commands/blueprints/add.ts)_
|
|
107
107
|
|
|
108
108
|
## `sanity-run blueprints config`
|
|
109
109
|
|
|
@@ -140,7 +140,7 @@ EXAMPLES
|
|
|
140
140
|
$ sanity-run blueprints config --edit --project-id <projectId> --stack <name-or-id>
|
|
141
141
|
```
|
|
142
142
|
|
|
143
|
-
_See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.
|
|
143
|
+
_See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.5/src/commands/blueprints/config.ts)_
|
|
144
144
|
|
|
145
145
|
## `sanity-run blueprints deploy`
|
|
146
146
|
|
|
@@ -175,6 +175,9 @@ DESCRIPTION
|
|
|
175
175
|
|
|
176
176
|
Set SANITY_ASSET_TIMEOUT (seconds) to override the 60-second timeout for processing resource assets.
|
|
177
177
|
|
|
178
|
+
Exit codes: 0 deployed, 2 deployment failed, 75 deployment accepted but completion could not be confirmed (rerun
|
|
179
|
+
'blueprints info' to check).
|
|
180
|
+
|
|
178
181
|
EXAMPLES
|
|
179
182
|
$ sanity-run blueprints deploy
|
|
180
183
|
|
|
@@ -191,7 +194,7 @@ EXAMPLES
|
|
|
191
194
|
$ sanity-run blueprints deploy --new-stack-name <new-name>
|
|
192
195
|
```
|
|
193
196
|
|
|
194
|
-
_See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.
|
|
197
|
+
_See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.5/src/commands/blueprints/deploy.ts)_
|
|
195
198
|
|
|
196
199
|
## `sanity-run blueprints destroy`
|
|
197
200
|
|
|
@@ -220,13 +223,16 @@ DESCRIPTION
|
|
|
220
223
|
|
|
221
224
|
Use this to clean up test environments or decommission a Stack you no longer need.
|
|
222
225
|
|
|
226
|
+
Exit codes: 0 destroyed, 2 destruction failed, 75 destruction accepted but completion could not be confirmed (rerun
|
|
227
|
+
'blueprints info' to check).
|
|
228
|
+
|
|
223
229
|
EXAMPLES
|
|
224
230
|
$ sanity-run blueprints destroy
|
|
225
231
|
|
|
226
232
|
$ sanity-run blueprints destroy --stack <name-or-id> --project-id <projectId> --force --no-wait
|
|
227
233
|
```
|
|
228
234
|
|
|
229
|
-
_See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.
|
|
235
|
+
_See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.5/src/commands/blueprints/destroy.ts)_
|
|
230
236
|
|
|
231
237
|
## `sanity-run blueprints doctor`
|
|
232
238
|
|
|
@@ -257,7 +263,7 @@ EXAMPLES
|
|
|
257
263
|
$ sanity-run blueprints doctor --fix
|
|
258
264
|
```
|
|
259
265
|
|
|
260
|
-
_See code: [src/commands/blueprints/doctor.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.
|
|
266
|
+
_See code: [src/commands/blueprints/doctor.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.5/src/commands/blueprints/doctor.ts)_
|
|
261
267
|
|
|
262
268
|
## `sanity-run blueprints info`
|
|
263
269
|
|
|
@@ -294,7 +300,7 @@ EXAMPLES
|
|
|
294
300
|
$ sanity-run blueprints info --organization-id <orgId> --stack <name-or-id>
|
|
295
301
|
```
|
|
296
302
|
|
|
297
|
-
_See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.
|
|
303
|
+
_See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.5/src/commands/blueprints/info.ts)_
|
|
298
304
|
|
|
299
305
|
## `sanity-run blueprints init [DIR]`
|
|
300
306
|
|
|
@@ -353,7 +359,7 @@ EXAMPLES
|
|
|
353
359
|
$ sanity-run blueprints init old-stack --type <json|js|ts> --project-id <projectId> --stack-id <existingStackId>
|
|
354
360
|
```
|
|
355
361
|
|
|
356
|
-
_See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.
|
|
362
|
+
_See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.5/src/commands/blueprints/init.ts)_
|
|
357
363
|
|
|
358
364
|
## `sanity-run blueprints logs`
|
|
359
365
|
|
|
@@ -399,7 +405,7 @@ EXAMPLES
|
|
|
399
405
|
$ sanity-run blueprints logs --before 2026-05-01T00:00:00Z
|
|
400
406
|
```
|
|
401
407
|
|
|
402
|
-
_See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.
|
|
408
|
+
_See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.5/src/commands/blueprints/logs.ts)_
|
|
403
409
|
|
|
404
410
|
## `sanity-run blueprints mint-deploy-token`
|
|
405
411
|
|
|
@@ -444,7 +450,7 @@ EXAMPLES
|
|
|
444
450
|
$ sanity-run blueprints mint-deploy-token --organization-id <orgId>
|
|
445
451
|
```
|
|
446
452
|
|
|
447
|
-
_See code: [src/commands/blueprints/mint-deploy-token.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.
|
|
453
|
+
_See code: [src/commands/blueprints/mint-deploy-token.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.5/src/commands/blueprints/mint-deploy-token.ts)_
|
|
448
454
|
|
|
449
455
|
## `sanity-run blueprints plan`
|
|
450
456
|
|
|
@@ -477,7 +483,7 @@ EXAMPLES
|
|
|
477
483
|
$ sanity-run blueprints plan --organization-id <orgId> --stack <name-or-id>
|
|
478
484
|
```
|
|
479
485
|
|
|
480
|
-
_See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.
|
|
486
|
+
_See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.5/src/commands/blueprints/plan.ts)_
|
|
481
487
|
|
|
482
488
|
## `sanity-run blueprints promote`
|
|
483
489
|
|
|
@@ -513,7 +519,7 @@ EXAMPLES
|
|
|
513
519
|
$ sanity-run blueprints promote --new-stack-name <new-name>
|
|
514
520
|
```
|
|
515
521
|
|
|
516
|
-
_See code: [src/commands/blueprints/promote.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.
|
|
522
|
+
_See code: [src/commands/blueprints/promote.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.5/src/commands/blueprints/promote.ts)_
|
|
517
523
|
|
|
518
524
|
## `sanity-run blueprints stacks`
|
|
519
525
|
|
|
@@ -549,7 +555,7 @@ EXAMPLES
|
|
|
549
555
|
$ sanity-run blueprints stacks --organization-id <organizationId> --include-projects
|
|
550
556
|
```
|
|
551
557
|
|
|
552
|
-
_See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.
|
|
558
|
+
_See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.5/src/commands/blueprints/stacks.ts)_
|
|
553
559
|
|
|
554
560
|
## `sanity-run functions add`
|
|
555
561
|
|
|
@@ -601,7 +607,7 @@ EXAMPLES
|
|
|
601
607
|
$ sanity-run functions add --name my-function --type document-create --type document-update --lang js
|
|
602
608
|
```
|
|
603
609
|
|
|
604
|
-
_See code: [src/commands/functions/add.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.
|
|
610
|
+
_See code: [src/commands/functions/add.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.5/src/commands/functions/add.ts)_
|
|
605
611
|
|
|
606
612
|
## `sanity-run functions dev`
|
|
607
613
|
|
|
@@ -636,7 +642,7 @@ EXAMPLES
|
|
|
636
642
|
$ sanity-run functions dev --timeout 60
|
|
637
643
|
```
|
|
638
644
|
|
|
639
|
-
_See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.
|
|
645
|
+
_See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.5/src/commands/functions/dev.ts)_
|
|
640
646
|
|
|
641
647
|
## `sanity-run functions env add NAME KEY VALUE`
|
|
642
648
|
|
|
@@ -666,7 +672,7 @@ EXAMPLES
|
|
|
666
672
|
$ sanity-run functions env add MyFunction API_URL https://api.example.com/
|
|
667
673
|
```
|
|
668
674
|
|
|
669
|
-
_See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.
|
|
675
|
+
_See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.5/src/commands/functions/env/add.ts)_
|
|
670
676
|
|
|
671
677
|
## `sanity-run functions env list NAME`
|
|
672
678
|
|
|
@@ -693,7 +699,7 @@ EXAMPLES
|
|
|
693
699
|
$ sanity-run functions env list MyFunction
|
|
694
700
|
```
|
|
695
701
|
|
|
696
|
-
_See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.
|
|
702
|
+
_See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.5/src/commands/functions/env/list.ts)_
|
|
697
703
|
|
|
698
704
|
## `sanity-run functions env remove NAME KEY`
|
|
699
705
|
|
|
@@ -722,7 +728,7 @@ EXAMPLES
|
|
|
722
728
|
$ sanity-run functions env remove MyFunction API_URL
|
|
723
729
|
```
|
|
724
730
|
|
|
725
|
-
_See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.
|
|
731
|
+
_See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.5/src/commands/functions/env/remove.ts)_
|
|
726
732
|
|
|
727
733
|
## `sanity-run functions logs [NAME]`
|
|
728
734
|
|
|
@@ -762,7 +768,7 @@ EXAMPLES
|
|
|
762
768
|
$ sanity-run functions logs <name> --delete
|
|
763
769
|
```
|
|
764
770
|
|
|
765
|
-
_See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.
|
|
771
|
+
_See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.5/src/commands/functions/logs.ts)_
|
|
766
772
|
|
|
767
773
|
## `sanity-run functions test [NAME]`
|
|
768
774
|
|
|
@@ -819,7 +825,7 @@ EXAMPLES
|
|
|
819
825
|
$ sanity-run functions test <name> --event update --data-before '{ "title": "before" }' --data-after '{ "title": "after" }'
|
|
820
826
|
```
|
|
821
827
|
|
|
822
|
-
_See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.
|
|
828
|
+
_See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v15.1.5/src/commands/functions/test.ts)_
|
|
823
829
|
|
|
824
830
|
## `sanity-run help [COMMAND]`
|
|
825
831
|
|
|
@@ -6,7 +6,7 @@ import blueprintParserValidator from '@sanity/blueprints-parser';
|
|
|
6
6
|
import * as find from 'empathic/find';
|
|
7
7
|
import { createJiti } from 'jiti';
|
|
8
8
|
import { SANITY_FUNCTION_DOCUMENT, SANITY_FUNCTION_MEDIA_LIBRARY_ASSET, SANITY_FUNCTION_SCHEDULED, } from '../../constants.js';
|
|
9
|
-
import { validateResources } from '../../utils/validate
|
|
9
|
+
import { validateResources } from '../../utils/blueprints/validate-resources.js';
|
|
10
10
|
import { backfillProjectBasedStackId, readConfigFile, } from './config.js';
|
|
11
11
|
import { resolveIds } from './resolve.js';
|
|
12
12
|
const SUPPORTED_FILE_EXTENSIONS = ['.json', '.js', '.mjs', '.ts'];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Logger } from '../../utils/logger.js';
|
|
2
|
+
import type { ActionResponse, AuthParams, StackOperation } from '../../utils/types.js';
|
|
3
|
+
/** Delay before the first operation poll. Override with SANITY_OPERATION_POLL_INITIAL_DELAY_MS. */
|
|
4
|
+
export declare const OPERATION_POLL_INITIAL_DELAY_MS: number;
|
|
5
|
+
/** Interval between operation status polls. Override with SANITY_OPERATION_POLL_INTERVAL_MS. */
|
|
6
|
+
export declare const OPERATION_POLL_INTERVAL_MS: number;
|
|
7
|
+
/** Consecutive failed polls tolerated before giving up on confirming status. */
|
|
8
|
+
export declare const OPERATION_POLL_MAX_CONSECUTIVE_ERRORS = 5;
|
|
9
|
+
/**
|
|
10
|
+
* Classify a single poll. Terminal status -> 'completed'/'failed'. 404 ->
|
|
11
|
+
* 'pending' (read-replica lag). Other failed responses -> 'error'. The caller
|
|
12
|
+
* decides whether an 'error' is retryable.
|
|
13
|
+
*/
|
|
14
|
+
export declare function classifyOperationPoll(options: {
|
|
15
|
+
ok: boolean;
|
|
16
|
+
httpStatus: number | undefined;
|
|
17
|
+
operation: StackOperation | undefined;
|
|
18
|
+
}): 'pending' | 'completed' | 'failed' | 'error';
|
|
19
|
+
interface GetOperationResponse extends ActionResponse {
|
|
20
|
+
operation: StackOperation;
|
|
21
|
+
response?: Response;
|
|
22
|
+
}
|
|
23
|
+
export declare function getOperation({ stackId, operationId, auth, logger, includeDestroyed, }: {
|
|
24
|
+
stackId: string;
|
|
25
|
+
operationId: string;
|
|
26
|
+
auth: AuthParams;
|
|
27
|
+
logger: Logger;
|
|
28
|
+
includeDestroyed?: boolean;
|
|
29
|
+
}): Promise<GetOperationResponse>;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import getHeaders from '../../utils/get-headers.js';
|
|
2
|
+
import { createTracedFetch } from '../../utils/traced-fetch.js';
|
|
3
|
+
import { stacksUrl } from './stacks.js';
|
|
4
|
+
const envMs = (value, fallback) => {
|
|
5
|
+
if (!value)
|
|
6
|
+
return fallback;
|
|
7
|
+
const parsed = Number(value);
|
|
8
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
|
|
9
|
+
};
|
|
10
|
+
/** Delay before the first operation poll. Override with SANITY_OPERATION_POLL_INITIAL_DELAY_MS. */
|
|
11
|
+
export const OPERATION_POLL_INITIAL_DELAY_MS = envMs(process.env.SANITY_OPERATION_POLL_INITIAL_DELAY_MS, 1000);
|
|
12
|
+
/** Interval between operation status polls. Override with SANITY_OPERATION_POLL_INTERVAL_MS. */
|
|
13
|
+
export const OPERATION_POLL_INTERVAL_MS = envMs(process.env.SANITY_OPERATION_POLL_INTERVAL_MS, 1500);
|
|
14
|
+
/** Consecutive failed polls tolerated before giving up on confirming status. */
|
|
15
|
+
export const OPERATION_POLL_MAX_CONSECUTIVE_ERRORS = 5;
|
|
16
|
+
/**
|
|
17
|
+
* Classify a single poll. Terminal status -> 'completed'/'failed'. 404 ->
|
|
18
|
+
* 'pending' (read-replica lag). Other failed responses -> 'error'. The caller
|
|
19
|
+
* decides whether an 'error' is retryable.
|
|
20
|
+
*/
|
|
21
|
+
export function classifyOperationPoll(options) {
|
|
22
|
+
const { ok, httpStatus, operation } = options;
|
|
23
|
+
if (ok) {
|
|
24
|
+
if (operation?.status === 'COMPLETED')
|
|
25
|
+
return 'completed';
|
|
26
|
+
if (operation?.status === 'FAILED')
|
|
27
|
+
return 'failed';
|
|
28
|
+
return 'pending';
|
|
29
|
+
}
|
|
30
|
+
if (httpStatus === 404)
|
|
31
|
+
return 'pending';
|
|
32
|
+
return 'error';
|
|
33
|
+
}
|
|
34
|
+
export async function getOperation({ stackId, operationId, auth, logger, includeDestroyed, }) {
|
|
35
|
+
const fetchFn = createTracedFetch(logger);
|
|
36
|
+
const url = new URL(`${stacksUrl}/${stackId}/operations/${operationId}`);
|
|
37
|
+
if (includeDestroyed)
|
|
38
|
+
url.searchParams.append('includeDestroyed', 'true');
|
|
39
|
+
const response = await fetchFn(url.toString(), {
|
|
40
|
+
method: 'GET',
|
|
41
|
+
headers: getHeaders(auth),
|
|
42
|
+
});
|
|
43
|
+
const data = await response.json();
|
|
44
|
+
return {
|
|
45
|
+
ok: response.ok,
|
|
46
|
+
error: response.ok ? null : data.message,
|
|
47
|
+
operation: data,
|
|
48
|
+
response,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -38,7 +38,7 @@ export declare function createEmptyStack({ token, scopeType, scopeId, name, logg
|
|
|
38
38
|
}): Promise<Stack>;
|
|
39
39
|
interface UpdateStackResponse extends ActionResponse {
|
|
40
40
|
stack: Stack & {
|
|
41
|
-
operationId
|
|
41
|
+
operationId: string;
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
44
|
export declare function updateStack({ stackId, stackMutation, auth, logger, }: {
|
|
@@ -99,7 +99,7 @@ export declare function planStack({ stackId, document, auth, logger, }: {
|
|
|
99
99
|
}): Promise<PlanStackResponse>;
|
|
100
100
|
interface DestroyStackResponse extends ActionResponse {
|
|
101
101
|
stack: Stack & {
|
|
102
|
-
operationId
|
|
102
|
+
operationId: string;
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
105
|
export declare function resolveStackIdByNameOrId(value: string, auth: AuthParams, logger: Logger): Promise<string>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Logger } from '../../utils/logger.js';
|
|
2
|
+
import type { AuthParams } from '../../utils/types.js';
|
|
3
|
+
/** Result of waiting for a deploy/destroy operation to settle. */
|
|
4
|
+
export type OperationOutcome = {
|
|
5
|
+
type: 'completed';
|
|
6
|
+
} | {
|
|
7
|
+
type: 'failed';
|
|
8
|
+
logHints: string[];
|
|
9
|
+
} | {
|
|
10
|
+
type: 'unconfirmed';
|
|
11
|
+
error?: string;
|
|
12
|
+
};
|
|
13
|
+
export interface WaitForOperationOptions {
|
|
14
|
+
stackId: string;
|
|
15
|
+
operationId: string;
|
|
16
|
+
auth: AuthParams;
|
|
17
|
+
log: Logger;
|
|
18
|
+
bin: string;
|
|
19
|
+
verbose?: boolean;
|
|
20
|
+
/** Keep the operation queryable after the stack is gone (destroy). */
|
|
21
|
+
includeDestroyed?: boolean;
|
|
22
|
+
/** Noun for the idle message, e.g. "deployment" or "destruction". */
|
|
23
|
+
progressNoun: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Stream logs and poll an operation until it settles.
|
|
27
|
+
* handles log-stream lifecycle, retry budget, and idle messaging;
|
|
28
|
+
* the caller maps the returned outcome to its own result/messaging.
|
|
29
|
+
*/
|
|
30
|
+
export declare function waitForOperation(options: WaitForOperationOptions): Promise<OperationOutcome>;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { setTimeout as sleep } from 'node:timers/promises';
|
|
2
|
+
import { createHintCollector } from '../../utils/blueprints/hints.js';
|
|
3
|
+
import { setupLogPolling } from './logs-polling.js';
|
|
4
|
+
import { classifyOperationPoll, getOperation, OPERATION_POLL_INITIAL_DELAY_MS, OPERATION_POLL_INTERVAL_MS, OPERATION_POLL_MAX_CONSECUTIVE_ERRORS, } from './operations.js';
|
|
5
|
+
/**
|
|
6
|
+
* Stream logs and poll an operation until it settles.
|
|
7
|
+
* handles log-stream lifecycle, retry budget, and idle messaging;
|
|
8
|
+
* the caller maps the returned outcome to its own result/messaging.
|
|
9
|
+
*/
|
|
10
|
+
export async function waitForOperation(options) {
|
|
11
|
+
const { stackId, operationId, auth, log, bin, verbose = false, includeDestroyed, progressNoun, } = options;
|
|
12
|
+
const logHints = createHintCollector(bin);
|
|
13
|
+
let logStreamCleanup = null;
|
|
14
|
+
try {
|
|
15
|
+
let lastLogAt = Date.now();
|
|
16
|
+
let idleMessageShown = false;
|
|
17
|
+
let consecutiveErrors = 0;
|
|
18
|
+
let lastStatus;
|
|
19
|
+
logStreamCleanup = setupLogPolling({
|
|
20
|
+
stackId,
|
|
21
|
+
operationId,
|
|
22
|
+
auth,
|
|
23
|
+
log,
|
|
24
|
+
verbose,
|
|
25
|
+
onActivity: () => {
|
|
26
|
+
lastLogAt = Date.now();
|
|
27
|
+
},
|
|
28
|
+
onLogEntry: (logEntry) => logHints.inspectLog(logEntry),
|
|
29
|
+
});
|
|
30
|
+
// balk in case read replica lags
|
|
31
|
+
await sleep(OPERATION_POLL_INITIAL_DELAY_MS);
|
|
32
|
+
while (true) {
|
|
33
|
+
const { ok, error: pollError, operation, response, } = await getOperation({
|
|
34
|
+
stackId,
|
|
35
|
+
operationId,
|
|
36
|
+
auth,
|
|
37
|
+
logger: log,
|
|
38
|
+
includeDestroyed,
|
|
39
|
+
});
|
|
40
|
+
const httpStatus = response?.status;
|
|
41
|
+
const state = classifyOperationPoll({ ok, httpStatus, operation });
|
|
42
|
+
if (state === 'completed') {
|
|
43
|
+
if (logStreamCleanup)
|
|
44
|
+
logStreamCleanup();
|
|
45
|
+
log('');
|
|
46
|
+
return { type: 'completed' };
|
|
47
|
+
}
|
|
48
|
+
if (state === 'failed') {
|
|
49
|
+
if (logStreamCleanup)
|
|
50
|
+
logStreamCleanup();
|
|
51
|
+
log('');
|
|
52
|
+
return { type: 'failed', logHints: logHints.getSuggestions() };
|
|
53
|
+
}
|
|
54
|
+
// tolerate a few consecutive errors; the operation was accepted and may still be running
|
|
55
|
+
if (state === 'error') {
|
|
56
|
+
consecutiveErrors += 1;
|
|
57
|
+
log.verbose(`Could not read ${progressNoun} status (HTTP ${httpStatus ?? 'unknown'}${pollError ? `: ${pollError}` : ''}); retrying (${consecutiveErrors}/${OPERATION_POLL_MAX_CONSECUTIVE_ERRORS}).`);
|
|
58
|
+
if (consecutiveErrors >= OPERATION_POLL_MAX_CONSECUTIVE_ERRORS) {
|
|
59
|
+
if (logStreamCleanup)
|
|
60
|
+
logStreamCleanup();
|
|
61
|
+
log('');
|
|
62
|
+
return { type: 'unconfirmed', error: pollError ?? undefined };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
consecutiveErrors = 0;
|
|
67
|
+
if (httpStatus === 404) {
|
|
68
|
+
log.verbose(`Waiting for ${progressNoun} status (HTTP 404); retrying.`);
|
|
69
|
+
}
|
|
70
|
+
else if (operation && operation.status !== lastStatus) {
|
|
71
|
+
log.verbose(`${progressNoun} operation status: ${operation.status}.`);
|
|
72
|
+
lastStatus = operation.status;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (!idleMessageShown && Date.now() - lastLogAt > 60_000) {
|
|
76
|
+
log(`No new activity for 60 seconds. The ${progressNoun} is still running on Sanity servers.`);
|
|
77
|
+
log(`You can safely exit and check status later with \`npx ${bin} blueprints info\`.`);
|
|
78
|
+
idleMessageShown = true;
|
|
79
|
+
}
|
|
80
|
+
await sleep(OPERATION_POLL_INTERVAL_MS);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
if (logStreamCleanup)
|
|
85
|
+
logStreamCleanup();
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import invoke from '../../utils/invoke-local.js';
|
|
1
|
+
import invoke from '../../utils/functions/invoke-local.js';
|
|
2
2
|
export async function testAction(resource, payload, context, options) {
|
|
3
3
|
try {
|
|
4
4
|
const { json, logs, error } = await invoke(resource, payload, context, options);
|
package/dist/actions/node.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { dirname, extname, join } from 'node:path';
|
|
3
|
-
import { getLatestNpmVersion } from '../utils/
|
|
3
|
+
import { getLatestNpmVersion } from '../utils/external/npmjs.js';
|
|
4
4
|
export async function writeOrUpdateNodeDependency(nearFilePath, dependency, logger) {
|
|
5
5
|
const dir = dirname(nearFilePath);
|
|
6
6
|
const extension = extname(nearFilePath);
|
|
@@ -4,7 +4,7 @@ import { dirname, join } from 'node:path';
|
|
|
4
4
|
import { pipeline } from 'node:stream/promises';
|
|
5
5
|
import { createGunzip } from 'node:zlib';
|
|
6
6
|
import { extract } from 'tar-stream';
|
|
7
|
-
import { gitHubRequest } from '../../utils/
|
|
7
|
+
import { gitHubRequest } from '../../utils/external/github.js';
|
|
8
8
|
export const EXAMPLES_CACHE_DIR = join(tmpdir(), 'sanity-examples');
|
|
9
9
|
const EXAMPLE_TYPES = {
|
|
10
10
|
blueprint: { repo: 'sanity-io/sanity', dir: 'examples/blueprints' },
|
package/dist/baseCommands.js
CHANGED
|
@@ -14,7 +14,9 @@ Use --no-wait to queue the deployment and return immediately without waiting for
|
|
|
14
14
|
|
|
15
15
|
Use --fn-installer to force which package manager to use when deploying functions.
|
|
16
16
|
|
|
17
|
-
Set SANITY_ASSET_TIMEOUT (seconds) to override the 60-second timeout for processing resource assets
|
|
17
|
+
Set SANITY_ASSET_TIMEOUT (seconds) to override the 60-second timeout for processing resource assets.
|
|
18
|
+
|
|
19
|
+
Exit codes: 0 deployed, 2 deployment failed, 75 deployment accepted but completion could not be confirmed (rerun 'blueprints info' to check).`;
|
|
18
20
|
static examples = [
|
|
19
21
|
'<%= config.bin %> <%= command.id %>',
|
|
20
22
|
'<%= config.bin %> <%= command.id %> --message "Enable staging dataset"',
|
|
@@ -9,7 +9,9 @@ export default class DestroyCommand extends ResolvedCommand {
|
|
|
9
9
|
|
|
10
10
|
This is a destructive operation. You will be prompted to confirm unless --force is specified.
|
|
11
11
|
|
|
12
|
-
Use this to clean up test environments or decommission a Stack you no longer need
|
|
12
|
+
Use this to clean up test environments or decommission a Stack you no longer need.
|
|
13
|
+
|
|
14
|
+
Exit codes: 0 destroyed, 2 destruction failed, 75 destruction accepted but completion could not be confirmed (rerun 'blueprints info' to check).`;
|
|
13
15
|
static examples = [
|
|
14
16
|
'<%= config.bin %> <%= command.id %>',
|
|
15
17
|
'<%= config.bin %> <%= command.id %> --stack <name-or-id> --project-id <projectId> --force --no-wait',
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { setTimeout as sleep } from 'node:timers/promises';
|
|
2
1
|
import { stashAsset } from '../../actions/blueprints/assets.js';
|
|
3
|
-
import { setupLogPolling } from '../../actions/blueprints/logs-polling.js';
|
|
4
2
|
import { getStack, updateStack } from '../../actions/blueprints/stacks.js';
|
|
3
|
+
import { waitForOperation } from '../../actions/blueprints/wait-for-operation.js';
|
|
5
4
|
import { checkUserPermission } from '../../actions/sanity/access.js';
|
|
6
5
|
import { createHintCollector } from '../../utils/blueprints/hints.js';
|
|
7
6
|
import { niceId } from '../../utils/display/presenters.js';
|
|
7
|
+
import { CODE_OPERATION_UNCONFIRMED, EXIT_OPERATION_UNCONFIRMED } from '../../utils/exit-codes.js';
|
|
8
8
|
import { styleText } from '../../utils/style-text.js';
|
|
9
9
|
import { isAssetResource } from '../../utils/types.js';
|
|
10
10
|
const DEFAULT_ASSET_TIMEOUT = 60;
|
|
@@ -91,90 +91,55 @@ export async function blueprintDeployCore(options) {
|
|
|
91
91
|
const legacyWarning = await legacyPermissionsNoticePromise;
|
|
92
92
|
return {
|
|
93
93
|
success: true,
|
|
94
|
-
json: { stackId
|
|
94
|
+
json: { stackId, resources },
|
|
95
95
|
data: { resources },
|
|
96
96
|
warnings: legacyWarning ? [legacyWarning] : undefined,
|
|
97
97
|
};
|
|
98
98
|
}
|
|
99
99
|
log(styleText('dim', 'Stack deployment progress:'));
|
|
100
100
|
log('');
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if (!ok) {
|
|
120
|
-
if (logStreamCleanup)
|
|
121
|
-
logStreamCleanup();
|
|
122
|
-
return {
|
|
123
|
-
success: false,
|
|
124
|
-
error: 'Failed to check Stack deployment status',
|
|
125
|
-
suggestions: [
|
|
126
|
-
'The deployment may still be running on Sanity servers.',
|
|
127
|
-
`Run \`npx ${bin} blueprints info\` to check status.`,
|
|
128
|
-
],
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
const operation = currentStack.recentOperation;
|
|
132
|
-
if (!operation) {
|
|
133
|
-
if (logStreamCleanup)
|
|
134
|
-
logStreamCleanup();
|
|
135
|
-
return { success: false, error: 'No Stack deployment operation found' };
|
|
136
|
-
}
|
|
137
|
-
if (operation.status === 'FAILED') {
|
|
138
|
-
if (logStreamCleanup)
|
|
139
|
-
logStreamCleanup();
|
|
140
|
-
log('');
|
|
141
|
-
return {
|
|
142
|
-
success: false,
|
|
143
|
-
error: 'Stack deployment failed',
|
|
144
|
-
suggestions: [
|
|
145
|
-
...logHints.getSuggestions(),
|
|
146
|
-
'Review the deployment output above for error details.',
|
|
147
|
-
`Run \`npx ${bin} blueprints logs --verbose\` for more context.`,
|
|
148
|
-
`Run \`npx ${bin} blueprints plan\` to identify issues with your Blueprint.`,
|
|
149
|
-
],
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
if (operation.status === 'COMPLETED') {
|
|
153
|
-
if (logStreamCleanup)
|
|
154
|
-
logStreamCleanup();
|
|
155
|
-
log('');
|
|
156
|
-
log(styleText(['bold', 'green'], 'Stack deployment completed!'));
|
|
157
|
-
const legacyWarning = await legacyPermissionsNoticePromise;
|
|
158
|
-
return {
|
|
159
|
-
success: true,
|
|
160
|
-
json: { stackId: stack.id, resources },
|
|
161
|
-
data: { resources },
|
|
162
|
-
warnings: legacyWarning ? [legacyWarning] : undefined,
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
if (!idleMessageShown && Date.now() - lastLogAt > 60_000) {
|
|
166
|
-
log(`No new activity for 60 seconds. The deployment is still running on Sanity servers.`);
|
|
167
|
-
log(`You can safely exit and check status later with \`npx ${bin} blueprints info\`.`);
|
|
168
|
-
idleMessageShown = true;
|
|
169
|
-
}
|
|
170
|
-
await sleep(1500);
|
|
171
|
-
}
|
|
101
|
+
const outcome = await waitForOperation({
|
|
102
|
+
stackId,
|
|
103
|
+
operationId: stack.operationId,
|
|
104
|
+
auth,
|
|
105
|
+
log,
|
|
106
|
+
bin,
|
|
107
|
+
verbose,
|
|
108
|
+
progressNoun: 'deployment',
|
|
109
|
+
});
|
|
110
|
+
if (outcome.type === 'completed') {
|
|
111
|
+
log(styleText(['bold', 'green'], 'Stack deployment completed!'));
|
|
112
|
+
const legacyWarning = await legacyPermissionsNoticePromise;
|
|
113
|
+
return {
|
|
114
|
+
success: true,
|
|
115
|
+
json: { stackId, resources },
|
|
116
|
+
data: { resources },
|
|
117
|
+
warnings: legacyWarning ? [legacyWarning] : undefined,
|
|
118
|
+
};
|
|
172
119
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
120
|
+
if (outcome.type === 'unconfirmed') {
|
|
121
|
+
return {
|
|
122
|
+
success: false,
|
|
123
|
+
error: `Stack deployment was accepted but completion could not be confirmed${outcome.error ? ` (${outcome.error})` : ''}.`,
|
|
124
|
+
code: CODE_OPERATION_UNCONFIRMED,
|
|
125
|
+
exitCode: EXIT_OPERATION_UNCONFIRMED,
|
|
126
|
+
suggestions: [
|
|
127
|
+
'The deployment may or may not have finished on Sanity servers.',
|
|
128
|
+
`Run \`npx ${bin} blueprints info\` to check status.`,
|
|
129
|
+
`Run \`npx ${bin} blueprints logs --watch\` to keep streaming logs.`,
|
|
130
|
+
],
|
|
131
|
+
};
|
|
177
132
|
}
|
|
133
|
+
return {
|
|
134
|
+
success: false,
|
|
135
|
+
error: 'Stack deployment failed',
|
|
136
|
+
suggestions: [
|
|
137
|
+
...outcome.logHints,
|
|
138
|
+
'Review the deployment output above for error details.',
|
|
139
|
+
`Run \`npx ${bin} blueprints logs --verbose\` for more context.`,
|
|
140
|
+
`Run \`npx ${bin} blueprints plan\` to identify issues with your Blueprint.`,
|
|
141
|
+
],
|
|
142
|
+
};
|
|
178
143
|
}
|
|
179
144
|
catch (error) {
|
|
180
145
|
const errorMessage = error instanceof Error ? error.message : String(error);
|