@sanity/runtime-cli 17.12.0 → 17.13.0-next.g06897b0
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 +21 -21
- package/dist/actions/blueprints/assets.d.ts +23 -20
- package/dist/actions/blueprints/assets.js +18 -87
- package/dist/actions/blueprints/logs-polling.d.ts +3 -5
- package/dist/actions/blueprints/logs-polling.js +4 -9
- package/dist/actions/blueprints/logs.d.ts +1 -2
- package/dist/actions/blueprints/logs.js +1 -3
- package/dist/actions/blueprints/operations-state.d.ts +10 -0
- package/dist/actions/blueprints/operations-state.js +42 -0
- package/dist/actions/blueprints/operations.d.ts +2 -9
- package/dist/actions/blueprints/operations.js +1 -15
- package/dist/actions/blueprints/pre-deploy.d.ts +19 -11
- package/dist/actions/blueprints/pre-deploy.js +95 -27
- package/dist/actions/blueprints/process-assets.d.ts +13 -11
- package/dist/actions/blueprints/process-assets.js +9 -7
- package/dist/actions/blueprints/stacks.d.ts +4 -4
- package/dist/actions/blueprints/stacks.js +2 -4
- package/dist/actions/blueprints/wait-for-operation.d.ts +1 -10
- package/dist/actions/blueprints/wait-for-operation.js +56 -101
- package/dist/baseCommands.js +6 -1
- package/dist/commands/blueprints/deploy.js +2 -0
- package/dist/commands/functions/dev.js +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.js +6 -0
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +1 -0
- package/dist/cores/blueprints/config.js +1 -1
- package/dist/cores/blueprints/deploy.d.ts +2 -0
- package/dist/cores/blueprints/deploy.js +38 -7
- package/dist/cores/blueprints/destroy.js +4 -2
- package/dist/cores/blueprints/doctor.js +2 -2
- package/dist/cores/blueprints/init.js +3 -1
- package/dist/cores/blueprints/logs.js +11 -5
- package/dist/cores/blueprints/mint-deploy-token.js +2 -1
- package/dist/cores/functions/build.js +4 -5
- package/dist/cores/functions/test.js +3 -1
- package/dist/cores/index.js +3 -1
- package/dist/server/app.d.ts +2 -1
- package/dist/server/app.js +4 -1
- package/dist/server/handlers/invoke.js +1 -1
- package/dist/server/static/vendor/vendor.bundle.js +21791 -25197
- package/dist/server/static/web-socket.js +4 -2
- package/dist/utils/blueprints/deploy-metadata.d.ts +10 -0
- package/dist/utils/blueprints/deploy-metadata.js +17 -0
- package/dist/utils/blueprints/resolve-deployed-resources.d.ts +2 -3
- package/dist/utils/blueprints/resolve-deployed-resources.js +2 -2
- package/dist/utils/blueprints/wait-for.d.ts +60 -0
- package/dist/utils/blueprints/wait-for.js +115 -0
- package/dist/utils/display/blueprints-formatting.d.ts +1 -0
- package/dist/utils/display/blueprints-formatting.js +17 -3
- package/dist/utils/display/dates.d.ts +0 -2
- package/dist/utils/display/dates.js +0 -25
- package/dist/utils/display/functions-formatting.js +1 -1
- package/dist/utils/display/prompt.js +5 -2
- package/dist/utils/display/resources-formatting.d.ts +6 -0
- package/dist/utils/display/resources-formatting.js +17 -0
- package/dist/utils/functions/child-runtime/durable.js +2 -2
- package/dist/utils/functions/dependency-info.d.ts +30 -0
- package/dist/utils/functions/dependency-info.js +57 -0
- package/dist/utils/functions/invoke/assert-console.d.ts +5 -0
- package/dist/utils/functions/invoke/assert-console.js +60 -0
- package/dist/utils/functions/invoke/local.js +9 -0
- package/dist/utils/functions/is-folder-larger-than.d.ts +5 -0
- package/dist/utils/functions/is-folder-larger-than.js +38 -0
- package/dist/utils/functions/prepare-asset.d.ts +2 -0
- package/dist/utils/functions/prepare-asset.js +59 -23
- package/dist/utils/studios/prepare-asset.js +36 -9
- package/dist/utils/types.d.ts +35 -4
- package/dist/utils/types.js +0 -3
- package/oclif.manifest.json +2 -2
- package/package.json +17 -19
- package/skills/functions-dev.md +1 -1
- package/dist/utils/functions/get-folder-size.d.ts +0 -5
- package/dist/utils/functions/get-folder-size.js +0 -24
|
@@ -1,15 +1,52 @@
|
|
|
1
|
+
import { SANITY_FUNCTION_PREFIX } from '../../constants.js';
|
|
1
2
|
import { resolveDeployedResources } from '../../utils/blueprints/resolve-deployed-resources.js';
|
|
2
3
|
import { CODE_OPERATION_UNCONFIRMED, EXIT_OPERATION_UNCONFIRMED } from '../../utils/exit-codes.js';
|
|
4
|
+
import { prepareAsset as prepareFunctionAsset } from '../../utils/functions/prepare-asset.js';
|
|
3
5
|
import { runCommand } from '../../utils/package-manager.js';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
+
import { prepareStudioAsset } from '../../utils/studios/prepare-asset.js';
|
|
7
|
+
import { setupLogPolling } from './logs-polling.js';
|
|
8
|
+
import { getOperationStateInfo } from './operations-state.js';
|
|
6
9
|
import { processAssets } from './process-assets.js';
|
|
7
10
|
import { updateStack } from './stacks.js';
|
|
8
|
-
|
|
11
|
+
/**
|
|
12
|
+
* A list of configurations for pre-deployment of resources. The first resourceType to match in the list will take precedence.
|
|
13
|
+
*/
|
|
14
|
+
const preDeployConfigs = [
|
|
15
|
+
{
|
|
16
|
+
resourceType: 'sanity.studio',
|
|
17
|
+
async prepareAsset(options) {
|
|
18
|
+
return prepareStudioAsset({
|
|
19
|
+
resource: options.resource,
|
|
20
|
+
blueprintFileDir: options.blueprintFileDir,
|
|
21
|
+
});
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
resourceType: (type) => type.startsWith(SANITY_FUNCTION_PREFIX),
|
|
26
|
+
async prepareAsset(options) {
|
|
27
|
+
return prepareFunctionAsset({
|
|
28
|
+
resource: options.resource,
|
|
29
|
+
blueprintFileDir: options.blueprintFileDir,
|
|
30
|
+
installer: options.installer,
|
|
31
|
+
});
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
function hasPreDeployResources(resources) {
|
|
36
|
+
return resources.some((r) => {
|
|
37
|
+
return !!getPredeployConfig(r);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function getPredeployConfig(r) {
|
|
41
|
+
return preDeployConfigs.find((c) => {
|
|
42
|
+
return ((typeof c.resourceType === 'function' && c.resourceType(r.type)) ||
|
|
43
|
+
(typeof c.resourceType !== 'function' && c.resourceType === r.type));
|
|
44
|
+
});
|
|
45
|
+
}
|
|
9
46
|
export async function preDeploy(options) {
|
|
10
|
-
const { resources, stackId, auth, blueprintFileDir, installer,
|
|
11
|
-
const
|
|
12
|
-
if (
|
|
47
|
+
const { resources, stackId, auth, blueprintFileDir, installer, fetchFn } = options;
|
|
48
|
+
const resourceMetadata = [];
|
|
49
|
+
if (hasPreDeployResources(resources)) {
|
|
13
50
|
const preDeployStackResult = await preDeployStack(options);
|
|
14
51
|
if (!preDeployStackResult.success) {
|
|
15
52
|
return preDeployStackResult;
|
|
@@ -19,17 +56,23 @@ export async function preDeploy(options) {
|
|
|
19
56
|
resources,
|
|
20
57
|
stackId,
|
|
21
58
|
auth,
|
|
22
|
-
|
|
59
|
+
fetchFn,
|
|
23
60
|
});
|
|
24
|
-
const assetResources =
|
|
25
|
-
|
|
61
|
+
const assetResources = [];
|
|
62
|
+
for (const r of resolvedResources) {
|
|
63
|
+
const config = getPredeployConfig(r);
|
|
64
|
+
if (typeof config !== 'undefined' && typeof config.prepareAsset === 'function') {
|
|
65
|
+
assetResources.push({ resource: r, prepareAsset: config.prepareAsset });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
let processedAssets = [];
|
|
26
69
|
try {
|
|
27
70
|
processedAssets = await processAssets({
|
|
28
71
|
assetResources,
|
|
29
72
|
auth,
|
|
30
73
|
blueprintFileDir,
|
|
31
74
|
installer,
|
|
32
|
-
|
|
75
|
+
fetchFn,
|
|
33
76
|
onProgress: (progress) => options.onAssetEvent?.({ type: 'progress', progress }),
|
|
34
77
|
onResult: (result) => options.onAssetEvent?.({ type: 'result', result }),
|
|
35
78
|
});
|
|
@@ -47,13 +90,23 @@ export async function preDeploy(options) {
|
|
|
47
90
|
if (idx === -1)
|
|
48
91
|
throw new Error('Unable to update resource asset');
|
|
49
92
|
resources[idx] = asset.resource;
|
|
93
|
+
if (asset.success) {
|
|
94
|
+
const { name, type } = asset.resource;
|
|
95
|
+
resourceMetadata.push({
|
|
96
|
+
name,
|
|
97
|
+
type,
|
|
98
|
+
assetHash: asset.hash,
|
|
99
|
+
assetReused: asset.exists,
|
|
100
|
+
...asset.metadata,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
50
103
|
}
|
|
51
104
|
}
|
|
52
|
-
return { success: true };
|
|
105
|
+
return { success: true, resourceMetadata };
|
|
53
106
|
}
|
|
54
107
|
async function preDeployStack(options) {
|
|
55
|
-
const { scopeType, scopeId, stackId, stackName, resources, auth,
|
|
56
|
-
|
|
108
|
+
const { scopeType, scopeId, stackId, stackName, resources, auth, bin, fetchFn, waitForFn } = options;
|
|
109
|
+
options.onPreDeployStackStart?.();
|
|
57
110
|
const stackMutation = {
|
|
58
111
|
scopeType,
|
|
59
112
|
scopeId,
|
|
@@ -61,9 +114,9 @@ async function preDeployStack(options) {
|
|
|
61
114
|
preDeploy: true,
|
|
62
115
|
document: { resources },
|
|
63
116
|
};
|
|
64
|
-
const { ok: deployOk, stack, error: deployError, } = await updateStack({ stackId, stackMutation, auth,
|
|
117
|
+
const { ok: deployOk, stack, error: deployError, } = await updateStack({ stackId, stackMutation, auth, fetchFn });
|
|
65
118
|
if (!deployOk) {
|
|
66
|
-
|
|
119
|
+
options.onPreDeployStackFail?.();
|
|
67
120
|
return {
|
|
68
121
|
success: false,
|
|
69
122
|
error: deployError || 'Failed to complete Stack pre-deployment',
|
|
@@ -73,22 +126,37 @@ async function preDeployStack(options) {
|
|
|
73
126
|
],
|
|
74
127
|
};
|
|
75
128
|
}
|
|
76
|
-
|
|
129
|
+
options.onPreDeployStackDone?.();
|
|
77
130
|
if (stack.changeCount === 0)
|
|
78
131
|
return { success: true };
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
132
|
+
options.onPreDeployOperationStart?.();
|
|
133
|
+
const outcome = await waitForFn({
|
|
134
|
+
getIdleMessage() {
|
|
135
|
+
return `The pre-deployment is still running on Sanity servers.`;
|
|
136
|
+
},
|
|
137
|
+
async onRequestLatestState() {
|
|
138
|
+
return await getOperationStateInfo({
|
|
139
|
+
stackId,
|
|
140
|
+
operationId: stack.operationId,
|
|
141
|
+
auth,
|
|
142
|
+
fetchFn,
|
|
143
|
+
includeDestroyed: false,
|
|
144
|
+
progressNoun: 'pre-deployment',
|
|
145
|
+
});
|
|
146
|
+
},
|
|
147
|
+
onStartLogPolling(options) {
|
|
148
|
+
return setupLogPolling({
|
|
149
|
+
auth,
|
|
150
|
+
fetchFn,
|
|
151
|
+
operationId: stack.operationId,
|
|
152
|
+
stackId,
|
|
153
|
+
onActivity: options.onActivity,
|
|
154
|
+
onLogEntry: options.onLogEntry,
|
|
155
|
+
});
|
|
156
|
+
},
|
|
89
157
|
});
|
|
90
158
|
if (outcome.type === 'completed') {
|
|
91
|
-
|
|
159
|
+
options.onPreDeployOperationDone?.();
|
|
92
160
|
}
|
|
93
161
|
else if (outcome.type === 'unconfirmed') {
|
|
94
162
|
return {
|
|
@@ -1,29 +1,31 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BlueprintResource } from '@sanity/blueprints';
|
|
2
2
|
import type { AssetResource, AuthParams, InstallerType } from '../../utils/types.js';
|
|
3
|
-
type ProcessAssetsOptions = {
|
|
4
|
-
assetResources: AssetResource[];
|
|
3
|
+
type ProcessAssetsOptions<R extends BlueprintResource> = {
|
|
4
|
+
assetResources: AssetResource<R>[];
|
|
5
5
|
auth: AuthParams;
|
|
6
6
|
blueprintFileDir: string;
|
|
7
7
|
installer: InstallerType;
|
|
8
|
-
|
|
8
|
+
fetchFn: typeof fetch;
|
|
9
9
|
onProgress?: (progress: ProcessAssetsProgress) => void;
|
|
10
|
-
onResult?: (result: ProcessedAsset) => void;
|
|
10
|
+
onResult?: (result: ProcessedAsset<R>) => void;
|
|
11
11
|
};
|
|
12
12
|
export type ProcessAssetsProgress = {
|
|
13
13
|
completed: number;
|
|
14
14
|
total: number;
|
|
15
15
|
slow: boolean;
|
|
16
16
|
};
|
|
17
|
-
export type ProcessedAsset = {
|
|
17
|
+
export type ProcessedAsset<R extends BlueprintResource> = {
|
|
18
18
|
success: false;
|
|
19
|
-
resource:
|
|
19
|
+
resource: R;
|
|
20
20
|
error: string;
|
|
21
21
|
failureKind: 'processing' | 'upload';
|
|
22
22
|
} | {
|
|
23
23
|
success: true;
|
|
24
|
-
resource:
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
resource: R;
|
|
25
|
+
assetParameter: string;
|
|
26
|
+
hash: string;
|
|
27
|
+
exists: boolean;
|
|
28
|
+
metadata?: Record<string, unknown>;
|
|
27
29
|
};
|
|
28
|
-
export declare function processAssets(options: ProcessAssetsOptions): Promise<ProcessedAsset[]>;
|
|
30
|
+
export declare function processAssets<R extends BlueprintResource>(options: ProcessAssetsOptions<R>): Promise<ProcessedAsset<R>[]>;
|
|
29
31
|
export {};
|
|
@@ -21,8 +21,8 @@ export async function processAssets(options) {
|
|
|
21
21
|
try {
|
|
22
22
|
for (let start = 0; start < total; start += concurrency) {
|
|
23
23
|
const batch = assetResources.slice(start, start + concurrency);
|
|
24
|
-
const batchResults = await Promise.all(batch.map(async (
|
|
25
|
-
const result = await processAsset(resource, options);
|
|
24
|
+
const batchResults = await Promise.all(batch.map(async (assetResource) => {
|
|
25
|
+
const result = await processAsset(assetResource.resource, assetResource.prepareAsset, options);
|
|
26
26
|
completed += 1;
|
|
27
27
|
reportProgress();
|
|
28
28
|
onResult?.(result);
|
|
@@ -42,13 +42,13 @@ function getAssetConcurrency() {
|
|
|
42
42
|
const configured = Number(env.SANITY_ASSET_CONCURRENCY);
|
|
43
43
|
return Number.isSafeInteger(configured) && configured > 0 ? configured : DEFAULT_ASSET_CONCURRENCY;
|
|
44
44
|
}
|
|
45
|
-
async function processAsset(resource, options) {
|
|
46
|
-
const { auth, blueprintFileDir, installer,
|
|
45
|
+
async function processAsset(resource, prepAsset, options) {
|
|
46
|
+
const { auth, blueprintFileDir, installer, fetchFn } = options;
|
|
47
47
|
let assetTimeoutTimer;
|
|
48
48
|
let result;
|
|
49
49
|
try {
|
|
50
50
|
result = await Promise.race([
|
|
51
|
-
stashAsset({ resource, blueprintFileDir, auth,
|
|
51
|
+
stashAsset({ resource, prepAsset, blueprintFileDir, auth, fetchFn, installer }),
|
|
52
52
|
new Promise((_, reject) => {
|
|
53
53
|
assetTimeoutTimer = setTimeout(() => {
|
|
54
54
|
reject(new Error(`Processing ${resource.name} timed out after ${assetTimeoutS}s`));
|
|
@@ -66,15 +66,17 @@ async function processAsset(resource, options) {
|
|
|
66
66
|
if (result.success && result.assetId) {
|
|
67
67
|
return {
|
|
68
68
|
success: true,
|
|
69
|
-
resource: { ...resource,
|
|
69
|
+
resource: { ...resource, [result.assetParameter]: result.assetId },
|
|
70
|
+
assetParameter: result.assetParameter,
|
|
70
71
|
hash: result.hash,
|
|
71
72
|
exists: result.exists,
|
|
73
|
+
metadata: result.metadata,
|
|
72
74
|
};
|
|
73
75
|
}
|
|
74
76
|
return {
|
|
75
77
|
success: false,
|
|
76
78
|
resource,
|
|
77
|
-
error: result.error || 'Failed to process asset',
|
|
79
|
+
error: ('error' in result && result.error) || 'Failed to process asset',
|
|
78
80
|
failureKind: 'upload',
|
|
79
81
|
};
|
|
80
82
|
}
|
|
@@ -25,10 +25,10 @@ type GetStackResponse = {
|
|
|
25
25
|
stack?: unknown;
|
|
26
26
|
response?: Response;
|
|
27
27
|
};
|
|
28
|
-
export declare function getStack({ stackId, auth,
|
|
28
|
+
export declare function getStack({ stackId, auth, fetchFn, }: {
|
|
29
29
|
stackId: string;
|
|
30
30
|
auth: AuthParams;
|
|
31
|
-
|
|
31
|
+
fetchFn: typeof fetch;
|
|
32
32
|
}): Promise<GetStackResponse>;
|
|
33
33
|
type CreateStackResponse = GetStackResponse;
|
|
34
34
|
export declare function createStack({ stackMutation, auth, logger, }: {
|
|
@@ -55,11 +55,11 @@ type UpdateStackResponse = {
|
|
|
55
55
|
error: string;
|
|
56
56
|
stack?: unknown;
|
|
57
57
|
};
|
|
58
|
-
export declare function updateStack({ stackId, stackMutation, auth,
|
|
58
|
+
export declare function updateStack({ stackId, stackMutation, auth, fetchFn, }: {
|
|
59
59
|
stackId: string;
|
|
60
60
|
stackMutation: StackMutation;
|
|
61
61
|
auth: AuthParams;
|
|
62
|
-
|
|
62
|
+
fetchFn: typeof fetch;
|
|
63
63
|
}): Promise<UpdateStackResponse>;
|
|
64
64
|
interface PlanResourceSnapshot {
|
|
65
65
|
name: string;
|
|
@@ -24,8 +24,7 @@ export async function listStacks(auth, logger) {
|
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
-
export async function getStack({ stackId, auth,
|
|
28
|
-
const fetchFn = createTracedFetch(logger);
|
|
27
|
+
export async function getStack({ stackId, auth, fetchFn, }) {
|
|
29
28
|
try {
|
|
30
29
|
const response = await fetchFn(`${stacksUrl}/${stackId}`, {
|
|
31
30
|
method: 'GET',
|
|
@@ -92,8 +91,7 @@ export async function createEmptyStack({ token, scopeType, scopeId, name, logger
|
|
|
92
91
|
}
|
|
93
92
|
return response.stack;
|
|
94
93
|
}
|
|
95
|
-
export async function updateStack({ stackId, stackMutation, auth,
|
|
96
|
-
const fetchFn = createTracedFetch(logger);
|
|
94
|
+
export async function updateStack({ stackId, stackMutation, auth, fetchFn, }) {
|
|
97
95
|
try {
|
|
98
96
|
const response = await fetchFn(`${stacksUrl}/${stackId}`, {
|
|
99
97
|
method: 'PUT',
|
|
@@ -1,15 +1,6 @@
|
|
|
1
|
+
import { type OperationOutcome } from '../../utils/blueprints/wait-for.js';
|
|
1
2
|
import type { Logger } from '../../utils/logger.js';
|
|
2
3
|
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
4
|
export interface WaitForOperationOptions {
|
|
14
5
|
stackId: string;
|
|
15
6
|
operationId: string;
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { runCommand } from '../../utils/package-manager.js';
|
|
1
|
+
import { createWaitFor } from '../../utils/blueprints/wait-for.js';
|
|
2
|
+
import { createTracedFetch } from '../../utils/traced-fetch.js';
|
|
4
3
|
import { setupLogPolling } from './logs-polling.js';
|
|
5
|
-
import { classifyOperationPoll, getOperation
|
|
6
|
-
const IDLE_SPINNER_DELAY_MS = 30_000;
|
|
7
|
-
const IDLE_SPINNER_UPDATE_INTERVAL_MS = 15_000;
|
|
4
|
+
import { classifyOperationPoll, getOperation } from './operations.js';
|
|
8
5
|
/**
|
|
9
6
|
* Stream logs and poll an operation until it settles.
|
|
10
7
|
* handles log-stream lifecycle, retry budget, and idle messaging;
|
|
@@ -12,107 +9,65 @@ const IDLE_SPINNER_UPDATE_INTERVAL_MS = 15_000;
|
|
|
12
9
|
*/
|
|
13
10
|
export async function waitForOperation(options) {
|
|
14
11
|
const { stackId, operationId, auth, log, bin, verbose = false, includeDestroyed, progressNoun, } = options;
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
log.showProgress();
|
|
25
|
-
};
|
|
26
|
-
try {
|
|
27
|
-
log.showProgress();
|
|
28
|
-
let lastLogAt = Date.now();
|
|
29
|
-
let nextIdleSpinnerUpdateAt = IDLE_SPINNER_DELAY_MS;
|
|
30
|
-
let consecutiveErrors = 0;
|
|
31
|
-
let lastStatus;
|
|
32
|
-
logStreamCleanup = setupLogPolling({
|
|
33
|
-
stackId,
|
|
34
|
-
operationId,
|
|
35
|
-
auth,
|
|
36
|
-
log,
|
|
37
|
-
verbose,
|
|
38
|
-
onActivity: () => {
|
|
39
|
-
lastLogAt = Date.now();
|
|
40
|
-
nextIdleSpinnerUpdateAt = IDLE_SPINNER_DELAY_MS;
|
|
41
|
-
stopIdleSpinner(true);
|
|
42
|
-
},
|
|
43
|
-
onLogEntry: (logEntry) => logHints.inspectLog(logEntry),
|
|
44
|
-
});
|
|
45
|
-
// balk in case read replica lags
|
|
46
|
-
await sleep(OPERATION_POLL_INITIAL_DELAY_MS);
|
|
47
|
-
while (true) {
|
|
48
|
-
const { ok, error: pollError, operation, response, } = await getOperation({
|
|
12
|
+
const fetchFn = createTracedFetch(log);
|
|
13
|
+
const waitFor = createWaitFor({
|
|
14
|
+
bin,
|
|
15
|
+
log,
|
|
16
|
+
verbose,
|
|
17
|
+
});
|
|
18
|
+
return await waitFor({
|
|
19
|
+
async onRequestLatestState() {
|
|
20
|
+
const { ok, error, operation, response } = await getOperation({
|
|
49
21
|
stackId,
|
|
50
22
|
operationId,
|
|
51
23
|
auth,
|
|
52
|
-
|
|
24
|
+
fetchFn,
|
|
53
25
|
includeDestroyed,
|
|
54
26
|
});
|
|
55
27
|
const httpStatus = response?.status;
|
|
56
28
|
const state = classifyOperationPoll({ ok, httpStatus, operation });
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
29
|
+
switch (state) {
|
|
30
|
+
case 'completed':
|
|
31
|
+
case 'failed':
|
|
32
|
+
return {
|
|
33
|
+
state,
|
|
34
|
+
};
|
|
35
|
+
case 'error':
|
|
36
|
+
return {
|
|
37
|
+
state,
|
|
38
|
+
error,
|
|
39
|
+
verboseError: `Could not read ${progressNoun} status (HTTP ${httpStatus ?? 'unknown'}${error ? `: ${error}` : ''})`,
|
|
40
|
+
};
|
|
41
|
+
case 'pending':
|
|
42
|
+
if (httpStatus === 404 || !operation) {
|
|
43
|
+
return {
|
|
44
|
+
state: 'not_found',
|
|
45
|
+
verboseError: `Waiting for ${progressNoun} status (HTTP 404); retrying.`,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
return {
|
|
50
|
+
state,
|
|
51
|
+
latestStatus: operation.status,
|
|
52
|
+
verboseMessage: `${progressNoun} operation status: ${operation.status}.`,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
default:
|
|
56
|
+
throw new Error(`Unexpected poll state: ${state}`);
|
|
63
57
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
log('');
|
|
80
|
-
return { type: 'unconfirmed', error: pollError ?? undefined };
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
else {
|
|
84
|
-
consecutiveErrors = 0;
|
|
85
|
-
if (httpStatus === 404) {
|
|
86
|
-
log.verbose(`Waiting for ${progressNoun} status (HTTP 404); retrying.`);
|
|
87
|
-
}
|
|
88
|
-
else if (operation && operation.status !== lastStatus) {
|
|
89
|
-
log.verbose(`${progressNoun} operation status: ${operation.status}.`);
|
|
90
|
-
lastStatus = operation.status;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
const idleFor = Date.now() - lastLogAt;
|
|
94
|
-
if (idleFor >= nextIdleSpinnerUpdateAt) {
|
|
95
|
-
const elapsedIdleMs = IDLE_SPINNER_DELAY_MS +
|
|
96
|
-
Math.floor((idleFor - IDLE_SPINNER_DELAY_MS) / IDLE_SPINNER_UPDATE_INTERVAL_MS) *
|
|
97
|
-
IDLE_SPINNER_UPDATE_INTERVAL_MS;
|
|
98
|
-
const elapsedIdleSeconds = elapsedIdleMs / 1000;
|
|
99
|
-
const text = `No new activity for ${elapsedIdleSeconds} seconds. The ${progressNoun} is still running on Sanity servers. You can safely exit and check status later with \`${runCommand(bin)} blueprints info\`.`;
|
|
100
|
-
if (idleSpinner)
|
|
101
|
-
idleSpinner.start(text);
|
|
102
|
-
else
|
|
103
|
-
idleSpinner = log.ora(text).start();
|
|
104
|
-
nextIdleSpinnerUpdateAt = elapsedIdleMs + IDLE_SPINNER_UPDATE_INTERVAL_MS;
|
|
105
|
-
}
|
|
106
|
-
await sleep(OPERATION_POLL_INTERVAL_MS);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
catch (error) {
|
|
110
|
-
if (logStreamCleanup)
|
|
111
|
-
logStreamCleanup();
|
|
112
|
-
throw error;
|
|
113
|
-
}
|
|
114
|
-
finally {
|
|
115
|
-
stopIdleSpinner();
|
|
116
|
-
log.clearProgress();
|
|
117
|
-
}
|
|
58
|
+
},
|
|
59
|
+
onStartLogPolling(options) {
|
|
60
|
+
return setupLogPolling({
|
|
61
|
+
stackId,
|
|
62
|
+
operationId,
|
|
63
|
+
auth,
|
|
64
|
+
fetchFn,
|
|
65
|
+
onActivity: options.onActivity,
|
|
66
|
+
onLogEntry: options.onLogEntry,
|
|
67
|
+
});
|
|
68
|
+
},
|
|
69
|
+
getIdleMessage() {
|
|
70
|
+
return `The ${progressNoun} is still running on Sanity servers.`;
|
|
71
|
+
},
|
|
72
|
+
});
|
|
118
73
|
}
|
package/dist/baseCommands.js
CHANGED
|
@@ -9,6 +9,7 @@ import { CI_SETUP_DOCS_URL } from './constants.js';
|
|
|
9
9
|
import { presentBlueprintParserErrors } from './utils/display/errors.js';
|
|
10
10
|
import { Logger } from './utils/logger.js';
|
|
11
11
|
import { styleText } from './utils/style-text.js';
|
|
12
|
+
import { createTracedFetch } from './utils/traced-fetch.js';
|
|
12
13
|
import { validTokenOrErrorMessage } from './utils/validated-token.js';
|
|
13
14
|
/**
|
|
14
15
|
* Fallback error-to-hint patterns for RuntimeCommand.catch().
|
|
@@ -378,7 +379,11 @@ export class ResolvedCommand extends RuntimeCommand {
|
|
|
378
379
|
// 8. Deployed Stack
|
|
379
380
|
if (needsDeployedStack) {
|
|
380
381
|
const spinner = log.ora('Loading Stack deployment...').start();
|
|
381
|
-
const response = await getStack({
|
|
382
|
+
const response = await getStack({
|
|
383
|
+
stackId: this.stackId,
|
|
384
|
+
auth: this.auth,
|
|
385
|
+
fetchFn: createTracedFetch(log),
|
|
386
|
+
});
|
|
382
387
|
if (!response.ok) {
|
|
383
388
|
spinner.fail('Could not load Stack deployment');
|
|
384
389
|
this.error('Missing Stack deployment', {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Flags } from '@oclif/core';
|
|
2
2
|
import { organizationIdFlagConfig, projectIdFlagConfig, ResolvedCommand, stackFlagConfig, } from '../../baseCommands.js';
|
|
3
|
+
import { RUNTIME_CLI_NAME } from '../../config.js';
|
|
3
4
|
import { blueprintDeployCore } from '../../cores/blueprints/deploy.js';
|
|
4
5
|
import { Logger } from '../../utils/logger.js';
|
|
5
6
|
import { INSTALLER_OPTIONS } from '../../utils/types.js';
|
|
@@ -79,6 +80,7 @@ Exit codes: 0 deployed, 2 deployment failed, 75 deployment accepted but completi
|
|
|
79
80
|
scopeId: this.scopeId,
|
|
80
81
|
deployedStack: this.deployedStack,
|
|
81
82
|
blueprint: this.blueprint,
|
|
83
|
+
cliVersion: this.config.name === RUNTIME_CLI_NAME ? undefined : this.config.version,
|
|
82
84
|
validateResources: this.flags['validate-resources'],
|
|
83
85
|
flags: this.flags,
|
|
84
86
|
});
|
|
@@ -9,7 +9,7 @@ export default class DevCommand extends ResolvedCommand {
|
|
|
9
9
|
|
|
10
10
|
Open the emulator in your browser to interactively test your functions with the payload editor.
|
|
11
11
|
|
|
12
|
-
Optionally, set the host and port with the --host and --port flags.
|
|
12
|
+
Optionally, set the host and port with the --host and --port flags. The live-reload WebSocket server shares this host and port. Function timeout can be configured with the --timeout flag.
|
|
13
13
|
|
|
14
14
|
To invoke a function with the CLI, use 'functions test'.`;
|
|
15
15
|
static examples = [
|
package/dist/config.d.ts
CHANGED
package/dist/config.js
CHANGED
|
@@ -40,6 +40,11 @@ const apiUrls = {
|
|
|
40
40
|
default: 'http://api.sanity/',
|
|
41
41
|
};
|
|
42
42
|
const apiUrl = sanityEnv ? (apiUrls[sanityEnv] ?? sanityEnv) : apiUrls.default;
|
|
43
|
+
const studioDomains = {
|
|
44
|
+
production: 'sanity.studio',
|
|
45
|
+
staging: 'studio.sanity.work',
|
|
46
|
+
};
|
|
47
|
+
const studioDomain = studioDomains[sanityEnv] ?? studioDomains.production;
|
|
43
48
|
// allow override of populus URL
|
|
44
49
|
const populusApiUrl = env.POPULUS_API_URL ?? apiUrl;
|
|
45
50
|
/**
|
|
@@ -78,6 +83,7 @@ export default {
|
|
|
78
83
|
isLive,
|
|
79
84
|
apiUrl,
|
|
80
85
|
populusApiUrl,
|
|
86
|
+
studioDomain,
|
|
81
87
|
isCi,
|
|
82
88
|
get token() {
|
|
83
89
|
return _token === undefined ? loadToken() : _token;
|
package/dist/constants.d.ts
CHANGED
|
@@ -51,6 +51,7 @@ export declare const LABEL_PUBSUB = "PubSub";
|
|
|
51
51
|
export declare const LABEL_SCHEDULED = "Scheduled";
|
|
52
52
|
export declare const LABEL_SYNC_TAG_INVALIDATE = "Sync Tag Invalidate";
|
|
53
53
|
export declare const CI_SETUP_DOCS_URL = "https://www.sanity.io/docs/blueprints/deploy-blueprints-from-ci";
|
|
54
|
+
export declare const STACKS_DOCS_URL = "https://www.sanity.io/docs/blueprints/stacks-and-scope";
|
|
54
55
|
export declare const STEP_PHASE_GLYPH: Record<DurableStepPhase, string>;
|
|
55
56
|
/** Stands in for environment variable values, which are never echoed back to the user */
|
|
56
57
|
export declare const ENV_MASK = "********";
|
package/dist/constants.js
CHANGED
|
@@ -56,6 +56,7 @@ export const LABEL_PUBSUB = 'PubSub';
|
|
|
56
56
|
export const LABEL_SCHEDULED = 'Scheduled';
|
|
57
57
|
export const LABEL_SYNC_TAG_INVALIDATE = 'Sync Tag Invalidate';
|
|
58
58
|
export const CI_SETUP_DOCS_URL = 'https://www.sanity.io/docs/blueprints/deploy-blueprints-from-ci';
|
|
59
|
+
export const STACKS_DOCS_URL = 'https://www.sanity.io/docs/blueprints/stacks-and-scope';
|
|
59
60
|
export const STEP_PHASE_GLYPH = {
|
|
60
61
|
start: '▶',
|
|
61
62
|
complete: '✔',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { formatDateTime } from '@sanity/cli-core/dates';
|
|
1
2
|
import { patchConfigFile, writeConfigFile, } from '../../actions/blueprints/config.js';
|
|
2
3
|
import { resolveStackIdByNameOrId } from '../../actions/blueprints/stacks.js';
|
|
3
|
-
import { formatDateTime } from '../../utils/display/dates.js';
|
|
4
4
|
import { filePathRelativeToCwd, labeledId, warn } from '../../utils/display/presenters.js';
|
|
5
5
|
import { CancelledError, runScopeAndStackWizard } from '../../utils/display/prompt.js';
|
|
6
6
|
import { runCommand } from '../../utils/package-manager.js';
|
|
@@ -8,6 +8,8 @@ export interface BlueprintDeployOptions extends CoreConfig {
|
|
|
8
8
|
scopeId: string;
|
|
9
9
|
deployedStack: Stack;
|
|
10
10
|
blueprint: ReadBlueprintResult;
|
|
11
|
+
/** Version of the CLI that hosts this plugin. Absent when the runtime CLI runs on its own. */
|
|
12
|
+
cliVersion?: string;
|
|
11
13
|
flags: {
|
|
12
14
|
'fn-installer'?: string;
|
|
13
15
|
'no-wait'?: boolean;
|