@supacloud/cli 0.92.0 → 0.94.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/README.md +23 -32
- package/dist/index.js +234 -559
- package/dist/shared/deployment-upgrade.d.ts +2 -0
- package/dist/shared/tools/app-tools.d.ts +1 -1
- package/dist/shared/tools/application-schemas.d.ts +2 -8
- package/dist/shared/tools/application-tools.d.ts +2 -5
- package/dist/shared/tools/deploy-tools.d.ts +0 -8
- package/dist/shared/tools/developer-experience-tools.d.ts +1 -1
- package/dist/shared/tools/frontend-release-control.d.ts +1 -0
- package/dist/shared/tools/project-deployment.d.ts +1 -0
- package/dist/shared/tools/remote-dev-tools.d.ts +1 -1
- package/dist/tool-runtime.js +25 -0
- package/package.json +4 -4
- package/skills/supacloud/SKILL.md +9 -0
- package/skills/supacloud/references/command-map.md +3 -5
package/dist/index.js
CHANGED
|
@@ -8766,6 +8766,28 @@ function outcomeUnknownGuidance(text) {
|
|
|
8766
8766
|
保持原 --env/--env-file 选择,先查询:${command}` : "");
|
|
8767
8767
|
}
|
|
8768
8768
|
|
|
8769
|
+
// src/shared/deployment-upgrade.ts
|
|
8770
|
+
var DEPLOYMENT_UPGRADE = "DEPLOYMENT_UPGRADE_REQUIRED: Legacy deployment is no longer supported. Upgrade with `npm install -g @supacloud/cli@latest`, bind application.id and application.environmentId in supacloud.json (or SUPACLOUD_APPLICATION_ID and SUPACLOUD_ENV), then run `supacloud deploy`. SupaCloud owns deployment planning and activation; do not retry with legacy commands.";
|
|
8771
|
+
var removedFrontendActions = new Set([
|
|
8772
|
+
"deploy_git",
|
|
8773
|
+
"deploy_upload",
|
|
8774
|
+
"redeploy",
|
|
8775
|
+
"upload_release",
|
|
8776
|
+
"activate_release"
|
|
8777
|
+
]);
|
|
8778
|
+
var removedDeployFlags = ["target", "id", "build_command", "output_dir", "plan", "diff", "dry_run"];
|
|
8779
|
+
function assertCurrentDeploymentInput(tool, input) {
|
|
8780
|
+
if (!input || typeof input !== "object" || Array.isArray(input))
|
|
8781
|
+
return;
|
|
8782
|
+
const args = input;
|
|
8783
|
+
if (tool === "frontend" && typeof args["action"] === "string" && removedFrontendActions.has(args["action"])) {
|
|
8784
|
+
throw new Error(DEPLOYMENT_UPGRADE);
|
|
8785
|
+
}
|
|
8786
|
+
if (tool === "deploy" && removedDeployFlags.some((flag) => Object.hasOwn(args, flag))) {
|
|
8787
|
+
throw new Error(`${DEPLOYMENT_UPGRADE} Put build settings in the frontend configuration. For read-only review use \`supacloud app deploy-plan\`.`);
|
|
8788
|
+
}
|
|
8789
|
+
}
|
|
8790
|
+
|
|
8769
8791
|
// src/shared/cli.ts
|
|
8770
8792
|
function cliToolResultIsError(toolResult) {
|
|
8771
8793
|
if (toolResult.isError === true)
|
|
@@ -8889,6 +8911,7 @@ async function runCli(cliTools, args, options = {}) {
|
|
|
8889
8911
|
const parsedArgs = parseCliFlags(args, startIdx, tool.schema);
|
|
8890
8912
|
if (startIdx === 2)
|
|
8891
8913
|
parsedArgs.action = args[1];
|
|
8914
|
+
assertCurrentDeploymentInput(args[0], parsedArgs);
|
|
8892
8915
|
validateToolArguments(tool.schema, parsedArgs);
|
|
8893
8916
|
const result = await tool.callback(parsedArgs);
|
|
8894
8917
|
if (result && result.content && Array.isArray(result.content)) {
|
|
@@ -10499,12 +10522,9 @@ function parseApplicationDeployPlan(value) {
|
|
|
10499
10522
|
var closed3 = { additionalProperties: false };
|
|
10500
10523
|
var sha256 = ApplicationReleaseIdSchema;
|
|
10501
10524
|
var nullableActivation = Union([ApplicationActivationIdSchema, Null()]);
|
|
10502
|
-
var
|
|
10525
|
+
var ApplicationDeployWebReleaseSchema = _Object_({
|
|
10503
10526
|
deployment_id: String2({ pattern: "^[A-Za-z0-9_-]{1,128}$" }),
|
|
10504
|
-
release_id: sha256
|
|
10505
|
-
expected_active_release_id: String2({ minLength: 1 }),
|
|
10506
|
-
expected_activation_id: String2({ minLength: 1 }),
|
|
10507
|
-
mutation_id: ApplicationActivationIdSchema
|
|
10527
|
+
release_id: sha256
|
|
10508
10528
|
}, closed3);
|
|
10509
10529
|
var ApplicationDeployRequestSchema = _Object_({
|
|
10510
10530
|
mutation_id: ApplicationActivationIdSchema,
|
|
@@ -10513,7 +10533,7 @@ var ApplicationDeployRequestSchema = _Object_({
|
|
|
10513
10533
|
configuration_write: Optional(ApplicationConfigurationWriteSchema),
|
|
10514
10534
|
expected_plan_sha256: Optional(sha256),
|
|
10515
10535
|
approved_migration_digest: Optional(sha256),
|
|
10516
|
-
|
|
10536
|
+
web_release: Optional(ApplicationDeployWebReleaseSchema)
|
|
10517
10537
|
}, closed3);
|
|
10518
10538
|
var ApplicationBackendReceiptSchema = _Object_({
|
|
10519
10539
|
schema: Literal("supacloud.application-backend-receipt.v1"),
|
|
@@ -10572,7 +10592,7 @@ function parseApplicationDeployResult(value, expected) {
|
|
|
10572
10592
|
if (expected) {
|
|
10573
10593
|
const { request } = expected;
|
|
10574
10594
|
const configurationId = request.configuration_id ?? request.configuration_write?.configuration_id;
|
|
10575
|
-
if (value.project_ref !== expected.project_ref || value.application_id !== expected.application_id || value.environment_id !== expected.environment_id || value.release_id !== request.release_id || value.mutation_id !== request.mutation_id || configurationId !== undefined && value.configuration_id !== configurationId || request.configuration_write !== undefined && value.configuration_id !== request.configuration_write.configuration_id || request.expected_plan_sha256 !== undefined && value.plan_sha256 !== request.expected_plan_sha256 || Boolean(value.web) !== Boolean(request.
|
|
10595
|
+
if (value.project_ref !== expected.project_ref || value.application_id !== expected.application_id || value.environment_id !== expected.environment_id || value.release_id !== request.release_id || value.mutation_id !== request.mutation_id || configurationId !== undefined && value.configuration_id !== configurationId || request.configuration_write !== undefined && value.configuration_id !== request.configuration_write.configuration_id || request.expected_plan_sha256 !== undefined && value.plan_sha256 !== request.expected_plan_sha256 || Boolean(value.web) !== Boolean(request.web_release) || request.web_release !== undefined && (value.web?.deployment_id !== request.web_release.deployment_id || value.web.release_id !== request.web_release.release_id)) {
|
|
10576
10596
|
throw new Error("Application deploy receipt does not match request");
|
|
10577
10597
|
}
|
|
10578
10598
|
}
|
|
@@ -11191,6 +11211,7 @@ var resultSchema = _Object_({
|
|
|
11191
11211
|
});
|
|
11192
11212
|
function registerTool(server, name, description, schema, callback) {
|
|
11193
11213
|
server.tool(name, description, schema, async (input) => {
|
|
11214
|
+
assertCurrentDeploymentInput(name, input);
|
|
11194
11215
|
const args = parseToolArguments(schema, input);
|
|
11195
11216
|
const result = await callback(args);
|
|
11196
11217
|
if (!Check2(resultSchema, result))
|
|
@@ -16322,42 +16343,21 @@ async function getFrontendRelease(http, projectRef, deploymentId, releaseId) {
|
|
|
16322
16343
|
}
|
|
16323
16344
|
return toolResponse({ project_ref: projectRef, deployment_id: deploymentId, release });
|
|
16324
16345
|
}
|
|
16325
|
-
async function
|
|
16326
|
-
const endpoint =
|
|
16346
|
+
async function uploadProjectWebRelease(http, projectRef, environmentId, deploymentId, archivePath) {
|
|
16347
|
+
const endpoint = `/v1/projects/${encodeURIComponent(projectRef)}/environments/${encodeURIComponent(environmentId)}/deployments/web-release?deployment_id=${encodeURIComponent(deploymentId)}`;
|
|
16327
16348
|
const archive = await verifiedArchive(archivePath);
|
|
16328
|
-
|
|
16329
|
-
|
|
16330
|
-
|
|
16331
|
-
|
|
16332
|
-
|
|
16333
|
-
|
|
16334
|
-
|
|
16335
|
-
|
|
16336
|
-
|
|
16337
|
-
|
|
16338
|
-
timeoutMs: UPLOAD_REQUEST_TIMEOUT_MS,
|
|
16339
|
-
responseTimeoutMs: MUTATION_RESPONSE_TIMEOUT_MS
|
|
16349
|
+
const successPayload = (value) => {
|
|
16350
|
+
const release = value ? releaseRecord(value.release) : null;
|
|
16351
|
+
if (!value || value.ok !== true || value.project_ref !== projectRef || value.environment_id !== environmentId || value.deployment_id !== deploymentId || value.release_id !== archive.sha256 || release?.release_id !== archive.sha256 || release.tree_sha256.length !== 64)
|
|
16352
|
+
return null;
|
|
16353
|
+
return toolResponse({
|
|
16354
|
+
project_ref: projectRef,
|
|
16355
|
+
environment_id: environmentId,
|
|
16356
|
+
deployment_id: deploymentId,
|
|
16357
|
+
release_id: archive.sha256,
|
|
16358
|
+
release
|
|
16340
16359
|
});
|
|
16341
|
-
}
|
|
16342
|
-
await archive.handle.close();
|
|
16343
|
-
}
|
|
16344
|
-
const release = response.ok ? releaseEnvelope(response.data, { projectRef, deploymentId, releaseId: archive.sha256 }) : null;
|
|
16345
|
-
if (!release) {
|
|
16346
|
-
if (response.status >= 400 && response.status < 500 && response.status !== 408 && !response.transportError) {
|
|
16347
|
-
return releaseFailure("frontend.upload_release", "HTTP_ERROR", response.status);
|
|
16348
|
-
}
|
|
16349
|
-
return uploadReadback(http, projectRef, deploymentId, archive.sha256, response.status);
|
|
16350
|
-
}
|
|
16351
|
-
const readback = await http.get(`${endpoint}/${release.release_id}`, { maxJsonBytes: RESPONSE_MAX_BYTES });
|
|
16352
|
-
const verified = readback.ok ? releaseEnvelope(readback.data, { projectRef, deploymentId, releaseId: release.release_id }) : null;
|
|
16353
|
-
if (!verified || verified.tree_sha256 !== release.tree_sha256) {
|
|
16354
|
-
return releaseFailure("frontend.upload_release", "OUTCOME_UNKNOWN", readback.status);
|
|
16355
|
-
}
|
|
16356
|
-
return toolResponse({ project_ref: projectRef, deployment_id: deploymentId, release: verified });
|
|
16357
|
-
}
|
|
16358
|
-
async function uploadFrontendSource(http, projectRef, deploymentId, archivePath) {
|
|
16359
|
-
const endpoint = `${deploymentEndpoint(projectRef, deploymentId)}/deploy/upload`;
|
|
16360
|
-
const archive = await verifiedArchive(archivePath);
|
|
16360
|
+
};
|
|
16361
16361
|
try {
|
|
16362
16362
|
const response = await http.postBinary(endpoint, {
|
|
16363
16363
|
stream: archiveStream(archive),
|
|
@@ -16367,29 +16367,36 @@ async function uploadFrontendSource(http, projectRef, deploymentId, archivePath)
|
|
|
16367
16367
|
contentLength: archive.sizeBytes,
|
|
16368
16368
|
contentSha256: archive.sha256,
|
|
16369
16369
|
maxJsonBytes: RESPONSE_MAX_BYTES,
|
|
16370
|
-
timeoutMs: UPLOAD_REQUEST_TIMEOUT_MS
|
|
16370
|
+
timeoutMs: UPLOAD_REQUEST_TIMEOUT_MS,
|
|
16371
|
+
responseTimeoutMs: MUTATION_RESPONSE_TIMEOUT_MS
|
|
16371
16372
|
});
|
|
16372
|
-
|
|
16373
|
-
|
|
16374
|
-
|
|
16375
|
-
|
|
16376
|
-
|
|
16373
|
+
const value = response.data && typeof response.data === "object" && !Array.isArray(response.data) ? response.data : null;
|
|
16374
|
+
if (response.ok && response.status === 201) {
|
|
16375
|
+
const success = successPayload(value);
|
|
16376
|
+
if (success)
|
|
16377
|
+
return success;
|
|
16378
|
+
}
|
|
16379
|
+
if (response.transportError || response.responseReadError || response.status >= 500 || response.status === 202) {
|
|
16380
|
+
const readback = await getFrontendRelease(http, projectRef, deploymentId, archive.sha256);
|
|
16381
|
+
if (!readback.isError) {
|
|
16382
|
+
const readbackValue = JSON.parse(readback.content[0]?.text ?? "{}");
|
|
16383
|
+
const release = readbackValue.release;
|
|
16384
|
+
if (release && typeof release === "object" && !Array.isArray(release) && release.release_id === archive.sha256) {
|
|
16385
|
+
return toolResponse({
|
|
16386
|
+
project_ref: projectRef,
|
|
16387
|
+
environment_id: environmentId,
|
|
16388
|
+
deployment_id: deploymentId,
|
|
16389
|
+
release_id: archive.sha256,
|
|
16390
|
+
release
|
|
16391
|
+
});
|
|
16392
|
+
}
|
|
16393
|
+
}
|
|
16377
16394
|
}
|
|
16378
|
-
return
|
|
16395
|
+
return releaseFailure("frontend.upload_project_web_release", response.status >= 400 && response.status < 500 && !response.transportError ? "HTTP_ERROR" : "OUTCOME_UNKNOWN", response.status);
|
|
16379
16396
|
} finally {
|
|
16380
16397
|
await archive.handle.close();
|
|
16381
16398
|
}
|
|
16382
16399
|
}
|
|
16383
|
-
async function uploadReadback(http, projectRef, deploymentId, releaseId, uploadStatus) {
|
|
16384
|
-
const response = await http.get(releasePath(projectRef, deploymentId, releaseId), {
|
|
16385
|
-
maxJsonBytes: RESPONSE_MAX_BYTES
|
|
16386
|
-
});
|
|
16387
|
-
const release = response.ok ? releaseEnvelope(response.data, { projectRef, deploymentId, releaseId }) : null;
|
|
16388
|
-
if (!release) {
|
|
16389
|
-
return releaseFailure("frontend.upload_release", "OUTCOME_UNKNOWN", uploadStatus);
|
|
16390
|
-
}
|
|
16391
|
-
return toolResponse({ project_ref: projectRef, deployment_id: deploymentId, release });
|
|
16392
|
-
}
|
|
16393
16400
|
function stableJson(candidate) {
|
|
16394
16401
|
if (candidate === null || typeof candidate !== "object")
|
|
16395
16402
|
return JSON.stringify(candidate);
|
|
@@ -16467,9 +16474,6 @@ async function activeReleaseReadback(http, identity) {
|
|
|
16467
16474
|
if (inventory.active_release_id !== identity.releaseId || inventory.active_activation_id !== identity.mutationId) {
|
|
16468
16475
|
return { release: null, status: 200 };
|
|
16469
16476
|
}
|
|
16470
|
-
if (snapshot.exactReadback) {
|
|
16471
|
-
return { release: inventory.releases[0] ?? null, status: 200 };
|
|
16472
|
-
}
|
|
16473
16477
|
const releaseRead = await http.get(releasePath(identity.projectRef, identity.deploymentId, identity.releaseId), { maxJsonBytes: RESPONSE_MAX_BYTES });
|
|
16474
16478
|
const release = releaseRead.ok ? releaseEnvelope(releaseRead.data, {
|
|
16475
16479
|
projectRef: identity.projectRef,
|
|
@@ -16487,43 +16491,31 @@ async function readActiveFrontendRelease(http, projectRef, deploymentId) {
|
|
|
16487
16491
|
if (inventory.next_cursor !== null || inventory.releases.length !== (inventory.active_release_id === null ? 0 : 1) || inventory.releases[0] && inventory.releases[0].release_id !== inventory.active_release_id) {
|
|
16488
16492
|
return { failure: releaseReadFailure("frontend.get_active_release", response), status: response.status };
|
|
16489
16493
|
}
|
|
16490
|
-
return { inventory
|
|
16491
|
-
}
|
|
16492
|
-
if (response.ok || response.status !== 404) {
|
|
16493
|
-
return { failure: releaseReadFailure("frontend.get_active_release", response), status: response.status };
|
|
16494
|
-
}
|
|
16495
|
-
const historyResponse = await http.get(`${releaseEndpoint(projectRef, deploymentId)}?limit=1`, {
|
|
16496
|
-
maxJsonBytes: RESPONSE_MAX_BYTES
|
|
16497
|
-
});
|
|
16498
|
-
const history = historyResponse.ok && historyResponse.status === 200 ? releaseInventory(historyResponse.data, { projectRef, deploymentId }) : null;
|
|
16499
|
-
if (!history || history.releases.length > 1) {
|
|
16500
|
-
return {
|
|
16501
|
-
failure: releaseReadFailure("frontend.get_active_release", historyResponse),
|
|
16502
|
-
status: historyResponse.status
|
|
16503
|
-
};
|
|
16494
|
+
return { inventory };
|
|
16504
16495
|
}
|
|
16505
|
-
if (
|
|
16506
|
-
return { inventory: { ...history, releases: [], next_cursor: null }, exactReadback: false };
|
|
16507
|
-
}
|
|
16508
|
-
const exactResponse = await http.get(releasePath(projectRef, deploymentId, history.active_release_id), {
|
|
16509
|
-
maxJsonBytes: RESPONSE_MAX_BYTES
|
|
16510
|
-
});
|
|
16511
|
-
const release = exactResponse.ok && exactResponse.status === 200 ? releaseEnvelope(exactResponse.data, { projectRef, deploymentId, releaseId: history.active_release_id }) : null;
|
|
16512
|
-
if (!release) {
|
|
16496
|
+
if (response.status === 404) {
|
|
16513
16497
|
return {
|
|
16514
|
-
failure:
|
|
16515
|
-
|
|
16498
|
+
failure: {
|
|
16499
|
+
isError: true,
|
|
16500
|
+
content: [{ type: "text", text: JSON.stringify({
|
|
16501
|
+
ok: false,
|
|
16502
|
+
operation: "frontend.get_active_release",
|
|
16503
|
+
error: {
|
|
16504
|
+
code: "DEPLOYMENT_UPGRADE_REQUIRED",
|
|
16505
|
+
http_status: 404,
|
|
16506
|
+
message: `${DEPLOYMENT_UPGRADE} Check that the deployment exists and upgrade the server if this endpoint is unavailable.`
|
|
16507
|
+
}
|
|
16508
|
+
}) }]
|
|
16509
|
+
},
|
|
16510
|
+
status: response.status
|
|
16516
16511
|
};
|
|
16517
16512
|
}
|
|
16518
|
-
return {
|
|
16513
|
+
return { failure: releaseReadFailure("frontend.get_active_release", response), status: response.status };
|
|
16519
16514
|
}
|
|
16520
16515
|
async function getActiveFrontendRelease(http, projectRef, deploymentId) {
|
|
16521
16516
|
const snapshot = await readActiveFrontendRelease(http, projectRef, deploymentId);
|
|
16522
16517
|
return "failure" in snapshot ? snapshot.failure : toolResponse(snapshot.inventory);
|
|
16523
16518
|
}
|
|
16524
|
-
async function readFrontendReleaseAuthority(http, projectRef, deploymentId) {
|
|
16525
|
-
return getActiveFrontendRelease(http, projectRef, deploymentId);
|
|
16526
|
-
}
|
|
16527
16519
|
async function rollbackFrontendRelease(http, projectRef, deploymentId, releaseId) {
|
|
16528
16520
|
if (releaseId !== undefined && !RELEASE_ID_PATTERN.test(releaseId)) {
|
|
16529
16521
|
throw new Error("'release_id' must be a SHA-256 digest");
|
|
@@ -16619,7 +16611,6 @@ async function readPreviousFrontendRelease(http, projectRef, deploymentId) {
|
|
|
16619
16611
|
releases: [],
|
|
16620
16612
|
next_cursor: null
|
|
16621
16613
|
},
|
|
16622
|
-
exactReadback: false,
|
|
16623
16614
|
...previous ? { previousRelease: previous } : {}
|
|
16624
16615
|
};
|
|
16625
16616
|
}
|
|
@@ -16689,16 +16680,13 @@ async function activationReadback(http, input, mutationId, activationStatus) {
|
|
|
16689
16680
|
// src/shared/tools/frontend-tools.ts
|
|
16690
16681
|
function registerFrontendTools(server, http) {
|
|
16691
16682
|
registerTool(server, "frontend", `Frontend hosting and immutable prebuilt releases. Supports: static, react, vue, svelte, sveltekit, sveltekit-static, nextjs, nuxt, astro.
|
|
16692
|
-
Actions: list, get, create, update, delete,
|
|
16683
|
+
Actions: list, get, create, update, delete, build_logs, add_domain, remove_domain, set_env, list_frameworks, list_records, list_releases, get_active_release, get_release, rollback. Publish with supacloud deploy.`, {
|
|
16693
16684
|
action: withDescription(stringEnum([
|
|
16694
16685
|
"list",
|
|
16695
16686
|
"get",
|
|
16696
16687
|
"create",
|
|
16697
16688
|
"update",
|
|
16698
16689
|
"delete",
|
|
16699
|
-
"deploy_git",
|
|
16700
|
-
"deploy_upload",
|
|
16701
|
-
"redeploy",
|
|
16702
16690
|
"build_logs",
|
|
16703
16691
|
"add_domain",
|
|
16704
16692
|
"remove_domain",
|
|
@@ -16708,8 +16696,6 @@ Actions: list, get, create, update, delete, deploy_git, deploy_upload, redeploy,
|
|
|
16708
16696
|
"list_releases",
|
|
16709
16697
|
"get_active_release",
|
|
16710
16698
|
"get_release",
|
|
16711
|
-
"upload_release",
|
|
16712
|
-
"activate_release",
|
|
16713
16699
|
"rollback"
|
|
16714
16700
|
]), "Action"),
|
|
16715
16701
|
ref: optional(String2(), "Project ref"),
|
|
@@ -16723,13 +16709,7 @@ Actions: list, get, create, update, delete, deploy_git, deploy_upload, redeploy,
|
|
|
16723
16709
|
node_version: optional(String2(), "[create/update] Node.js version"),
|
|
16724
16710
|
health_check_path: optional(String2(), "[create/update] SSR readiness path (default: /)"),
|
|
16725
16711
|
env_vars: optional(Record(String2(), String2()), "[create/update/set_env] Environment variables"),
|
|
16726
|
-
|
|
16727
|
-
branch: optional(String2(), "[deploy_git] Branch (default: main)"),
|
|
16728
|
-
archive_path: optional(String2(), "[deploy_upload/upload_release] Local tar.zst file path"),
|
|
16729
|
-
release_id: optional(String2(), "[get_release/activate_release] SHA-256 release ID; [rollback] optional, defaults to journal-verified previous release"),
|
|
16730
|
-
expected_active_release_id: optional(String2(), "[activate_release] Current release SHA-256 or absent"),
|
|
16731
|
-
expected_activation_id: optional(String2(), "[activate_release] Current activation UUIDv4 or absent"),
|
|
16732
|
-
mutation_id: optional(String2(), "[activate_release] Required retry-stable UUIDv4"),
|
|
16712
|
+
release_id: optional(String2(), "[get_release] SHA-256 release ID; [rollback] optional, defaults to journal-verified previous release"),
|
|
16733
16713
|
cursor: optional(String2(), "[list_releases] Last release SHA-256 cursor"),
|
|
16734
16714
|
limit: optional(Number2(), "[list_releases] Page size, 1-100 (default 50)")
|
|
16735
16715
|
}, async (args) => {
|
|
@@ -16746,13 +16726,7 @@ Actions: list, get, create, update, delete, deploy_git, deploy_upload, redeploy,
|
|
|
16746
16726
|
node_version,
|
|
16747
16727
|
health_check_path,
|
|
16748
16728
|
env_vars,
|
|
16749
|
-
git_url,
|
|
16750
|
-
branch,
|
|
16751
|
-
archive_path,
|
|
16752
16729
|
release_id,
|
|
16753
|
-
expected_active_release_id,
|
|
16754
|
-
expected_activation_id,
|
|
16755
|
-
mutation_id,
|
|
16756
16730
|
cursor,
|
|
16757
16731
|
limit
|
|
16758
16732
|
} = args;
|
|
@@ -16807,22 +16781,6 @@ Actions: list, get, create, update, delete, deploy_git, deploy_upload, redeploy,
|
|
|
16807
16781
|
need("id", id);
|
|
16808
16782
|
text = (await http.delete(`/v1/projects/${ref}/frontend/deployments/${id}`)).ok ? `✅ Deleted` : `❌ Failed`;
|
|
16809
16783
|
break;
|
|
16810
|
-
case "deploy_git":
|
|
16811
|
-
need("ref", ref);
|
|
16812
|
-
need("id", id);
|
|
16813
|
-
need("git_url", git_url);
|
|
16814
|
-
text = ok(await http.post(`/v1/projects/${ref}/frontend/deployments/${id}/deploy/git`, { git_url, branch }));
|
|
16815
|
-
break;
|
|
16816
|
-
case "deploy_upload":
|
|
16817
|
-
need("ref", ref);
|
|
16818
|
-
need("id", id);
|
|
16819
|
-
need("archive_path", archive_path);
|
|
16820
|
-
return uploadFrontendSource(http, ref, id, archive_path);
|
|
16821
|
-
case "redeploy":
|
|
16822
|
-
need("ref", ref);
|
|
16823
|
-
need("id", id);
|
|
16824
|
-
text = ok(await http.post(`/v1/projects/${ref}/frontend/deployments/${id}/redeploy`));
|
|
16825
|
-
break;
|
|
16826
16784
|
case "build_logs":
|
|
16827
16785
|
need("ref", ref);
|
|
16828
16786
|
need("id", id);
|
|
@@ -16868,26 +16826,6 @@ Actions: list, get, create, update, delete, deploy_git, deploy_upload, redeploy,
|
|
|
16868
16826
|
need("ref", ref);
|
|
16869
16827
|
need("id", id);
|
|
16870
16828
|
return getActiveFrontendRelease(http, ref, id);
|
|
16871
|
-
case "upload_release":
|
|
16872
|
-
need("ref", ref);
|
|
16873
|
-
need("id", id);
|
|
16874
|
-
need("archive_path", archive_path);
|
|
16875
|
-
return uploadFrontendRelease(http, ref, id, archive_path);
|
|
16876
|
-
case "activate_release":
|
|
16877
|
-
need("ref", ref);
|
|
16878
|
-
need("id", id);
|
|
16879
|
-
need("release_id", release_id);
|
|
16880
|
-
need("expected_active_release_id", expected_active_release_id);
|
|
16881
|
-
need("expected_activation_id", expected_activation_id);
|
|
16882
|
-
need("mutation_id", mutation_id);
|
|
16883
|
-
return activateFrontendRelease(http, {
|
|
16884
|
-
projectRef: ref,
|
|
16885
|
-
deploymentId: id,
|
|
16886
|
-
releaseId: release_id,
|
|
16887
|
-
expectedActiveReleaseId: expected_active_release_id,
|
|
16888
|
-
expectedActivationId: expected_activation_id,
|
|
16889
|
-
mutationId: mutation_id
|
|
16890
|
-
});
|
|
16891
16829
|
case "rollback":
|
|
16892
16830
|
need("ref", ref);
|
|
16893
16831
|
need("id", id);
|
|
@@ -16912,7 +16850,7 @@ var ApplicationRollbackSnapshotSchema2 = ApplicationRollbackSnapshotSchema;
|
|
|
16912
16850
|
var ApplicationActivationHistoryCursorSchema2 = ApplicationActivationHistoryCursorSchema;
|
|
16913
16851
|
var ApplicationPromotionPlanSchema2 = ApplicationPromotionPlanSchema;
|
|
16914
16852
|
var ApplicationDeployRequestSchema2 = ApplicationDeployRequestSchema;
|
|
16915
|
-
var
|
|
16853
|
+
var ApplicationDeployWebReleaseSchema2 = ApplicationDeployWebReleaseSchema;
|
|
16916
16854
|
|
|
16917
16855
|
// src/shared/mutation-protocol.ts
|
|
16918
16856
|
import { createHash as createHash6 } from "node:crypto";
|
|
@@ -17730,7 +17668,7 @@ var APPLICATION_TOOL_SCHEMA = {
|
|
|
17730
17668
|
configuration_path: optional(String2(), "[put_configuration] Local configuration write JSON including revision and expected revision"),
|
|
17731
17669
|
configuration_write: optional(Unknown(), "[deploy_application] Parsed immutable configuration write"),
|
|
17732
17670
|
manifest_path: optional(String2(), "[upload_release] Local delivery.manifest.json"),
|
|
17733
|
-
|
|
17671
|
+
web_release: optional(ApplicationDeployWebReleaseSchema2, "[deploy_application] Immutable staged Web release uploaded by the deploy profile"),
|
|
17734
17672
|
release_id: optional(ApplicationReleaseIdSchema2, "[get_release/get_deploy_plan/deploy_release/activate_release/reconcile_activation/rollback_release] Immutable application release ID; platform selects previous for default rollback"),
|
|
17735
17673
|
source_ref: optional(String2({ pattern: "^[A-Za-z0-9_-]{1,20}$" }), "[get_release_transfer_plan/transfer_release] Source project ref"),
|
|
17736
17674
|
source_release_id: optional(ApplicationReleaseIdSchema2, "[get_release_transfer_plan/transfer_release] Source immutable release ID"),
|
|
@@ -18109,7 +18047,7 @@ function registerApplicationTools(server, http) {
|
|
|
18109
18047
|
...configurationId === undefined ? {} : { configuration_id: configurationId },
|
|
18110
18048
|
...configurationWrite === undefined ? {} : { configuration_write: configurationWrite },
|
|
18111
18049
|
...typeof args["approved_migration_digest"] === "string" ? { approved_migration_digest: args["approved_migration_digest"] } : {},
|
|
18112
|
-
...args["
|
|
18050
|
+
...args["web_release"] === undefined ? {} : { web_release: args["web_release"] }
|
|
18113
18051
|
};
|
|
18114
18052
|
if (!Check2(ApplicationDeployRequestSchema2, body)) {
|
|
18115
18053
|
throw new Error("Invalid application deploy request");
|
|
@@ -21179,7 +21117,7 @@ var starter_metadata_default = {
|
|
|
21179
21117
|
version: "0.8.1"
|
|
21180
21118
|
},
|
|
21181
21119
|
db: {
|
|
21182
|
-
version: "0.16.
|
|
21120
|
+
version: "0.16.2",
|
|
21183
21121
|
peerDependencies: {
|
|
21184
21122
|
"drizzle-orm": "1.0.0-rc.5-169397b"
|
|
21185
21123
|
},
|
|
@@ -24587,7 +24525,7 @@ var REMOTE_APP_DESCRIPTIONS = {
|
|
|
24587
24525
|
source_environment_id: "[promote-plan/diff/promote] Source environment ID",
|
|
24588
24526
|
mutation_id: "[promote-status/promote-reconcile] Stable promotion mutation ID",
|
|
24589
24527
|
approved_migration_digest: "[promote] Exact reviewed migration execution-plan digest",
|
|
24590
|
-
|
|
24528
|
+
web_release: "[release] Immutable staged Web release uploaded by the deploy profile",
|
|
24591
24529
|
branch_ref: "[preview-plan] Preview branch identity",
|
|
24592
24530
|
branch_name: "[preview/preview-create] Human-readable preview branch name",
|
|
24593
24531
|
data_mode: "[preview-plan/preview/preview-create] schema_only or full_clone",
|
|
@@ -25630,10 +25568,13 @@ async function runAppRelease(request, options, delegate) {
|
|
|
25630
25568
|
mutation_id: activationId,
|
|
25631
25569
|
...configurationId === undefined ? {} : { configuration_id: configurationId },
|
|
25632
25570
|
...configurationWrite === undefined ? {} : { configuration_write: configurationWrite },
|
|
25633
|
-
...request.
|
|
25571
|
+
...request.web_release === undefined ? {} : { web_release: request.web_release }
|
|
25634
25572
|
};
|
|
25635
25573
|
validateToolArguments(APPLICATION_TOOL_SCHEMA, deployArgs);
|
|
25636
|
-
|
|
25574
|
+
if (!options.projectDeployment) {
|
|
25575
|
+
throw new Error("Application release requires the unified project deployment handler");
|
|
25576
|
+
}
|
|
25577
|
+
const deployed = await options.projectDeployment(deployArgs);
|
|
25637
25578
|
const deployReceipt = resultObject(deployed);
|
|
25638
25579
|
const resolvedConfigurationId = typeof deployReceipt?.configuration_id === "string" ? deployReceipt.configuration_id : undefined;
|
|
25639
25580
|
if (resolvedConfigurationId !== undefined) {
|
|
@@ -28054,6 +27995,117 @@ import { spawn as spawn2 } from "node:child_process";
|
|
|
28054
27995
|
import { createHash as createHash9 } from "node:crypto";
|
|
28055
27996
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
28056
27997
|
import { basename as basename8, dirname as dirname11, join as join17, relative as relative10, resolve as resolve22, sep as sep5 } from "node:path";
|
|
27998
|
+
|
|
27999
|
+
// src/shared/tools/project-deployment.ts
|
|
28000
|
+
async function requireProjectDeploymentProtocol(http, projectRef, environmentId) {
|
|
28001
|
+
const response = await http.get(`/v1/projects/${encodeURIComponent(projectRef)}/environments/${encodeURIComponent(environmentId)}/deployments/protocol`, { retry: false, totalTimeoutMs: 5000, maxJsonBytes: 4096 });
|
|
28002
|
+
if (response.transportError || response.responseReadError || response.status >= 500 || response.status === 401 || response.status === 403 || response.status === 429) {
|
|
28003
|
+
throw new Error(`DEPLOYMENT_PROTOCOL_UNAVAILABLE: Cannot verify the selected server (HTTP ${response.status}). Check connectivity, credentials and server health; no upload or deployment was attempted.`);
|
|
28004
|
+
}
|
|
28005
|
+
const data = response.data;
|
|
28006
|
+
if (response.status !== 200 || !response.ok || !data || typeof data !== "object" || !("protocol" in data) || data.protocol !== "supacloud.project-deployment.v1" || !("project_ref" in data) || data.project_ref !== projectRef || !("environment_id" in data) || data.environment_id !== environmentId) {
|
|
28007
|
+
throw new Error("DEPLOYMENT_PROTOCOL_MISMATCH: Upgrade the SupaCloud server and CLI together (`npm install -g @supacloud/cli@latest`), then retry `supacloud deploy`. No upload or deployment was attempted; legacy endpoints will not be used.");
|
|
28008
|
+
}
|
|
28009
|
+
}
|
|
28010
|
+
var operation = "applications.project_deploy";
|
|
28011
|
+
var scopeSchema = _Object_({
|
|
28012
|
+
project_ref: String2({ pattern: "^[a-z0-9-]{1,20}$" }),
|
|
28013
|
+
application_id: ApplicationIdSchema,
|
|
28014
|
+
environment_id: ApplicationIdSchema
|
|
28015
|
+
});
|
|
28016
|
+
var statusSchema = _Object_({
|
|
28017
|
+
schema: Literal("supacloud.project-deployment-status.v1"),
|
|
28018
|
+
deployment_id: ApplicationDeployRequestSchema.properties.mutation_id,
|
|
28019
|
+
status: Union([
|
|
28020
|
+
Literal("pending"),
|
|
28021
|
+
Literal("running"),
|
|
28022
|
+
Literal("succeeded"),
|
|
28023
|
+
Literal("failed_retryable"),
|
|
28024
|
+
Literal("failed_terminal"),
|
|
28025
|
+
Literal("outcome_unknown")
|
|
28026
|
+
]),
|
|
28027
|
+
phase: Union([
|
|
28028
|
+
Literal("queued"),
|
|
28029
|
+
Literal("prepared"),
|
|
28030
|
+
Literal("migrating"),
|
|
28031
|
+
Literal("activating"),
|
|
28032
|
+
Literal("binding-web"),
|
|
28033
|
+
Literal("verifying")
|
|
28034
|
+
]),
|
|
28035
|
+
operation: Literal("application.release.deploy"),
|
|
28036
|
+
...scopeSchema.properties,
|
|
28037
|
+
receipt: Optional(Unknown()),
|
|
28038
|
+
failure_code: Optional(String2({ pattern: "^[A-Z][A-Z0-9_]{0,63}$" }))
|
|
28039
|
+
}, { additionalProperties: false });
|
|
28040
|
+
function responseReceipt(data, expected) {
|
|
28041
|
+
if (!data || typeof data !== "object" || Array.isArray(data) || !("ok" in data) || data.ok !== true) {
|
|
28042
|
+
throw new Error("Invalid project deployment response");
|
|
28043
|
+
}
|
|
28044
|
+
const { ok: _ok, ...receipt } = data;
|
|
28045
|
+
return parseApplicationDeployResult(receipt, expected);
|
|
28046
|
+
}
|
|
28047
|
+
async function runProjectDeployment(http, args) {
|
|
28048
|
+
const scope = { project_ref: args.ref, application_id: args.id, environment_id: args.environment_id };
|
|
28049
|
+
const request = {
|
|
28050
|
+
mutation_id: args.mutation_id,
|
|
28051
|
+
release_id: args.release_id,
|
|
28052
|
+
...args.configuration_id === undefined ? {} : { configuration_id: args.configuration_id },
|
|
28053
|
+
...args.configuration_write === undefined ? {} : { configuration_write: args.configuration_write },
|
|
28054
|
+
...args.expected_plan_sha256 === undefined ? {} : { expected_plan_sha256: args.expected_plan_sha256 },
|
|
28055
|
+
...args.approved_migration_digest === undefined ? {} : { approved_migration_digest: args.approved_migration_digest },
|
|
28056
|
+
...args.web_release === undefined ? {} : { web_release: args.web_release }
|
|
28057
|
+
};
|
|
28058
|
+
if (!Check2(scopeSchema, scope) || !Check2(ApplicationDeployRequestSchema, request) || request.configuration_id !== undefined && request.configuration_write !== undefined && request.configuration_id !== request.configuration_write.configuration_id) {
|
|
28059
|
+
return releaseControlFailure(operation, "INVALID_RESPONSE", null);
|
|
28060
|
+
}
|
|
28061
|
+
const expected = { ...scope, request };
|
|
28062
|
+
const identity = {
|
|
28063
|
+
...scope,
|
|
28064
|
+
deployment_id: request.mutation_id,
|
|
28065
|
+
mutation_id: request.mutation_id,
|
|
28066
|
+
release_id: request.release_id
|
|
28067
|
+
};
|
|
28068
|
+
const endpoint = `/v1/projects/${encodeURIComponent(scope.project_ref)}/environments/${encodeURIComponent(scope.environment_id)}/deployments`;
|
|
28069
|
+
const { mutation_id, ...candidate } = request;
|
|
28070
|
+
const result = await http.post(endpoint, {
|
|
28071
|
+
...candidate,
|
|
28072
|
+
deployment_id: mutation_id,
|
|
28073
|
+
application_id: scope.application_id
|
|
28074
|
+
}, { timeoutMs: 120000, maxJsonBytes: 131072, responseTimeoutMs: 30000 });
|
|
28075
|
+
if (result.ok && result.status === 200) {
|
|
28076
|
+
try {
|
|
28077
|
+
return releaseControlSuccess(operation, {
|
|
28078
|
+
...responseReceipt(result.data, expected),
|
|
28079
|
+
deployment_id: mutation_id
|
|
28080
|
+
});
|
|
28081
|
+
} catch {}
|
|
28082
|
+
} else if (!result.ok && !result.transportError && !result.responseReadError && result.status < 500 && result.status !== 408) {
|
|
28083
|
+
return releaseControlMutationFailure(operation, result, identity);
|
|
28084
|
+
}
|
|
28085
|
+
const observed = await http.get(`${endpoint}/${encodeURIComponent(mutation_id)}`, {
|
|
28086
|
+
retry: false,
|
|
28087
|
+
totalTimeoutMs: 30000,
|
|
28088
|
+
maxJsonBytes: 131072
|
|
28089
|
+
});
|
|
28090
|
+
try {
|
|
28091
|
+
if (!observed.ok || observed.status !== 200 || !Check2(statusSchema, observed.data))
|
|
28092
|
+
throw new Error;
|
|
28093
|
+
const state = observed.data;
|
|
28094
|
+
if (state.deployment_id !== mutation_id || state.project_ref !== scope.project_ref || state.application_id !== scope.application_id || state.environment_id !== scope.environment_id || state.status !== "succeeded" || state.phase !== "verifying")
|
|
28095
|
+
throw new Error;
|
|
28096
|
+
const receipt = parseApplicationDeployResult(state.receipt, expected);
|
|
28097
|
+
return releaseControlSuccess(operation, {
|
|
28098
|
+
...receipt,
|
|
28099
|
+
deployment_id: mutation_id,
|
|
28100
|
+
replayed: true,
|
|
28101
|
+
execution_performed: false
|
|
28102
|
+
});
|
|
28103
|
+
} catch {
|
|
28104
|
+
return releaseControlFailure(operation, "OUTCOME_UNKNOWN", result.transportError ? null : result.status, identity);
|
|
28105
|
+
}
|
|
28106
|
+
}
|
|
28107
|
+
|
|
28108
|
+
// src/shared/tools/deploy-tools.ts
|
|
28057
28109
|
var MAX_SOURCE_BYTES = 256 * 1024 * 1024;
|
|
28058
28110
|
var PUBLIC_BUILD_ENV_PREFIXES = ["PUBLIC_", "VITE_", "NEXT_PUBLIC_", "NUXT_PUBLIC_", "ASTRO_PUBLIC_"];
|
|
28059
28111
|
var SENSITIVE_BUILD_ENV = /(?:^|_)(?:PASSWORD|PASS|SECRET|TOKEN|KEY|CREDENTIAL|AUTHORIZATION|COOKIE|SESSION)(?:_|$)|(?:DATABASE_URL|DATABASE_URI|CONNECTION_STRING|DSN|PRIVATE_KEY)/i;
|
|
@@ -28065,15 +28117,8 @@ function isProtectedBuildEnv(name) {
|
|
|
28065
28117
|
}
|
|
28066
28118
|
var deployToolSchema = {
|
|
28067
28119
|
ref: optional(String2(), "Project ref (defaults to the linked project)"),
|
|
28068
|
-
target: optional(String2(), "Named deploy target from supacloud.json"),
|
|
28069
|
-
id: optional(String2(), "Frontend deployment ID (auto-selected when unambiguous)"),
|
|
28070
28120
|
cwd: optional(String2(), "Project directory (default: current directory)"),
|
|
28071
|
-
build_command: optional(String2(), "Build command override"),
|
|
28072
|
-
output_dir: optional(String2(), "Build output directory override"),
|
|
28073
28121
|
skip_build: optional(Boolean2(), "Use an existing output directory without building"),
|
|
28074
|
-
dry_run: optional(Boolean2(), "Resolve and validate the deployment without building or publishing"),
|
|
28075
|
-
plan: optional(Boolean2(), "Build and compare the release with current authority without publishing"),
|
|
28076
|
-
diff: optional(Boolean2(), "Build and report the immutable release-level diff without publishing"),
|
|
28077
28122
|
json: optional(Boolean2(), "Print only the final JSON result")
|
|
28078
28123
|
};
|
|
28079
28124
|
function record4(candidate) {
|
|
@@ -28332,40 +28377,6 @@ function targetRoot(configRoot, target, name) {
|
|
|
28332
28377
|
}
|
|
28333
28378
|
return root;
|
|
28334
28379
|
}
|
|
28335
|
-
function selectTarget(configRoot, invocationDirectory, config, requestedName) {
|
|
28336
|
-
const targets = config.targets ? Object.entries(config.targets) : [["frontend", {
|
|
28337
|
-
type: "frontend",
|
|
28338
|
-
root: config.frontend?.root,
|
|
28339
|
-
id: config.frontend?.id,
|
|
28340
|
-
buildCommand: config.frontend?.buildCommand,
|
|
28341
|
-
outputDirectory: config.frontend?.outputDirectory,
|
|
28342
|
-
buildEnv: config.frontend?.buildEnv
|
|
28343
|
-
}]];
|
|
28344
|
-
if (targets.length === 0)
|
|
28345
|
-
throw new Error("supacloud.json defines no deploy targets");
|
|
28346
|
-
if (requestedName) {
|
|
28347
|
-
const selected = targets.find(([name]) => name === requestedName);
|
|
28348
|
-
if (!selected)
|
|
28349
|
-
throw new Error(`Deploy target '${requestedName}' was not found in supacloud.json`);
|
|
28350
|
-
return { name: selected[0], config: selected[1], root: targetRoot(configRoot, selected[1], selected[0]) };
|
|
28351
|
-
}
|
|
28352
|
-
const containing = targets.map(([name, target]) => ({ name, target, root: targetRoot(configRoot, target, name) })).filter((candidate) => invocationDirectory === candidate.root || invocationDirectory.startsWith(`${candidate.root}${sep5}`)).sort((left, right) => right.root.length - left.root.length);
|
|
28353
|
-
if (containing.length === 1 || containing.length > 1 && containing[0].root !== containing[1].root) {
|
|
28354
|
-
const selected = containing[0];
|
|
28355
|
-
return { name: selected.name, config: selected.target, root: selected.root };
|
|
28356
|
-
}
|
|
28357
|
-
if (config.defaultTarget) {
|
|
28358
|
-
const selected = targets.find(([name]) => name === config.defaultTarget);
|
|
28359
|
-
if (!selected)
|
|
28360
|
-
throw new Error(`supacloud.json defaultTarget '${config.defaultTarget}' was not found`);
|
|
28361
|
-
return { name: selected[0], config: selected[1], root: targetRoot(configRoot, selected[1], selected[0]) };
|
|
28362
|
-
}
|
|
28363
|
-
if (targets.length === 1) {
|
|
28364
|
-
const selected = targets[0];
|
|
28365
|
-
return { name: selected[0], config: selected[1], root: targetRoot(configRoot, selected[1], selected[0]) };
|
|
28366
|
-
}
|
|
28367
|
-
throw new Error(`Multiple deploy targets found (${targets.map(([name]) => name).sort().join(", ")}). Pass --target`);
|
|
28368
|
-
}
|
|
28369
28380
|
function defaultOutputDirectory(framework) {
|
|
28370
28381
|
switch (framework) {
|
|
28371
28382
|
case "sveltekit-static":
|
|
@@ -28502,7 +28513,7 @@ function payload(response) {
|
|
|
28502
28513
|
throw new Error("Deployment operation returned an invalid response");
|
|
28503
28514
|
return parsed;
|
|
28504
28515
|
}
|
|
28505
|
-
async function stageApplicationWebRelease(http, projectRef, configRoot, skipBuild, json, environmentVariables) {
|
|
28516
|
+
async function stageApplicationWebRelease(http, projectRef, environmentId, configRoot, skipBuild, json, environmentVariables) {
|
|
28506
28517
|
const target = selectFrontendTarget(configRoot, await readDeployConfig(configRoot));
|
|
28507
28518
|
if (!target)
|
|
28508
28519
|
return null;
|
|
@@ -28528,17 +28539,7 @@ async function stageApplicationWebRelease(http, projectRef, configRoot, skipBuil
|
|
|
28528
28539
|
}
|
|
28529
28540
|
const archive = await createFrontendArchive(outputDirectory);
|
|
28530
28541
|
try {
|
|
28531
|
-
const
|
|
28532
|
-
const activeReleaseId = typeof authority.active_release_id === "string" ? authority.active_release_id : null;
|
|
28533
|
-
const activeActivationId = typeof authority.active_activation_id === "string" ? authority.active_activation_id : null;
|
|
28534
|
-
const current = Array.isArray(authority.releases) ? record4(authority.releases[0]) : null;
|
|
28535
|
-
if (archive.sha256 === activeReleaseId && archive.treeSha256 !== current?.tree_sha256) {
|
|
28536
|
-
throw new Error("Active Web release tree does not match the local archive");
|
|
28537
|
-
}
|
|
28538
|
-
if (archive.treeSha256 === current?.tree_sha256) {
|
|
28539
|
-
return {};
|
|
28540
|
-
}
|
|
28541
|
-
const uploaded = payload(await uploadFrontendRelease(http, projectRef, selected.id, archive.archivePath));
|
|
28542
|
+
const uploaded = payload(await uploadProjectWebRelease(http, projectRef, environmentId, selected.id, archive.archivePath));
|
|
28542
28543
|
const release = record4(uploaded.release);
|
|
28543
28544
|
const releaseId = requiredString(release?.release_id, "release.release_id");
|
|
28544
28545
|
if (releaseId !== archive.sha256)
|
|
@@ -28548,34 +28549,15 @@ async function stageApplicationWebRelease(http, projectRef, configRoot, skipBuil
|
|
|
28548
28549
|
return {
|
|
28549
28550
|
request: {
|
|
28550
28551
|
deployment_id: selected.id,
|
|
28551
|
-
release_id: releaseId
|
|
28552
|
-
expected_active_release_id: activeReleaseId ?? "absent",
|
|
28553
|
-
expected_activation_id: activeActivationId ?? "absent",
|
|
28554
|
-
mutation_id: crypto.randomUUID()
|
|
28552
|
+
release_id: releaseId
|
|
28555
28553
|
}
|
|
28556
28554
|
};
|
|
28557
28555
|
} finally {
|
|
28558
28556
|
await archive.cleanup();
|
|
28559
28557
|
}
|
|
28560
28558
|
}
|
|
28561
|
-
function deployResponse(result, json) {
|
|
28562
|
-
if (json)
|
|
28563
|
-
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
28564
|
-
const lines = [
|
|
28565
|
-
result.unchanged === true ? "Already up to date." : `Deployed ${String(result.target || result.deployment_id || result.slug)}.`,
|
|
28566
|
-
result.url ? `URL: ${String(result.url)}` : null,
|
|
28567
|
-
result.release_id ? `Release: ${String(result.release_id)}` : null,
|
|
28568
|
-
result.active_version ? `Active version: ${String(result.active_version)}` : null,
|
|
28569
|
-
result.file_count ? `Files: ${String(result.file_count)}` : null
|
|
28570
|
-
].filter((line) => Boolean(line));
|
|
28571
|
-
return { content: [{ type: "text", text: lines.join(`
|
|
28572
|
-
`) }] };
|
|
28573
|
-
}
|
|
28574
28559
|
function registerDeployTools(server, http, options = {}) {
|
|
28575
28560
|
registerTool(server, "deploy", "Build and publish the linked project with one command", deployToolSchema, async (args) => {
|
|
28576
|
-
if (args.dry_run === true && (args.plan === true || args.diff === true)) {
|
|
28577
|
-
throw new Error("Use dry_run for resolution only, or plan/diff for a built release comparison, not both");
|
|
28578
|
-
}
|
|
28579
28561
|
const invocationDirectory = resolve22(String(args.cwd || options.cwd || process.cwd()));
|
|
28580
28562
|
const projectRef = String(args.ref || options.projectRef || "").trim();
|
|
28581
28563
|
if (!projectRef)
|
|
@@ -28586,8 +28568,8 @@ function registerDeployTools(server, http, options = {}) {
|
|
|
28586
28568
|
...config.application,
|
|
28587
28569
|
environmentId: options.environment || config.application.environmentId
|
|
28588
28570
|
} : undefined;
|
|
28589
|
-
if (
|
|
28590
|
-
throw new Error(
|
|
28571
|
+
if (await hasProjectReleaseManifest(configRoot)) {
|
|
28572
|
+
throw new Error(`${DEPLOYMENT_UPGRADE} Replace deploy-manifest.json with the current application delivery configuration; no remote mutation was performed.`);
|
|
28591
28573
|
}
|
|
28592
28574
|
if (application?.id) {
|
|
28593
28575
|
if (Object.values(config.targets ?? {}).some((target) => target.type === "edge_function")) {
|
|
@@ -28596,12 +28578,6 @@ function registerDeployTools(server, http, options = {}) {
|
|
|
28596
28578
|
if (!options.applicationRelease) {
|
|
28597
28579
|
throw new Error("Application release support is unavailable in this CLI context");
|
|
28598
28580
|
}
|
|
28599
|
-
if (args.target || args.build_command || args.output_dir) {
|
|
28600
|
-
throw new Error("Application profile deploy does not accept frontend target, build command, or output directory flags");
|
|
28601
|
-
}
|
|
28602
|
-
if (args.dry_run === true || args.plan === true || args.diff === true) {
|
|
28603
|
-
throw new Error("Application profile deploy does not support dry_run, plan, or diff; use app deploy-plan for a read-only plan");
|
|
28604
|
-
}
|
|
28605
28581
|
const environmentId = application.environmentId?.trim();
|
|
28606
28582
|
if (!environmentId || !Check2(ApplicationIdSchema, environmentId) || !Check2(ApplicationIdSchema, application.id)) {
|
|
28607
28583
|
throw new Error("Application profile requires SUPACLOUD_APPLICATION_ENVIRONMENT_ID or SUPACLOUD_ENV");
|
|
@@ -28611,7 +28587,8 @@ function registerDeployTools(server, http, options = {}) {
|
|
|
28611
28587
|
if (configurationPath && configurationId) {
|
|
28612
28588
|
throw new Error("Application profile must set only one of SUPACLOUD_APPLICATION_CONFIGURATION_PATH or SUPACLOUD_APPLICATION_CONFIGURATION_ID");
|
|
28613
28589
|
}
|
|
28614
|
-
|
|
28590
|
+
await requireProjectDeploymentProtocol(http, projectRef, environmentId);
|
|
28591
|
+
const stagedWeb = await stageApplicationWebRelease(http, projectRef, environmentId, configRoot, args.skip_build === true, args.json === true, options.environmentVariables);
|
|
28615
28592
|
const result = await options.applicationRelease({
|
|
28616
28593
|
action: "release",
|
|
28617
28594
|
ref: projectRef,
|
|
@@ -28622,220 +28599,12 @@ function registerDeployTools(server, http, options = {}) {
|
|
|
28622
28599
|
...configurationId ? { configuration_id: configurationId } : {},
|
|
28623
28600
|
...application.manifestPath ? { manifest_path: application.manifestPath } : {},
|
|
28624
28601
|
...args.skip_build === true ? { skip_build: true } : {},
|
|
28625
|
-
...stagedWeb?.request === undefined ? {} : {
|
|
28602
|
+
...stagedWeb?.request === undefined ? {} : { web_release: stagedWeb.request },
|
|
28626
28603
|
...args.json === true ? { format: "json", json: true } : {}
|
|
28627
28604
|
});
|
|
28628
28605
|
return result;
|
|
28629
28606
|
}
|
|
28630
|
-
|
|
28631
|
-
if (!args.target && target.config.type === "frontend" && (Object.values(config.targets ?? {}).some((candidate) => candidate.type === "edge_function") || await pathExists(join17(configRoot, "supacloud.config.ts")) || await pathExists(join17(configRoot, "supabase", "migrations")) || await pathExists(join17(configRoot, "supabase", "functions")))) {
|
|
28632
|
-
throw new Error("PROJECT_DEPLOYMENT_UNSUPPORTED: Backend declarations were detected but are not covered by this deployment. No Web-only fallback or remote mutation was performed.");
|
|
28633
|
-
}
|
|
28634
|
-
const projectDirectory = target.root;
|
|
28635
|
-
const targetState = await lstat5(projectDirectory).catch(() => null);
|
|
28636
|
-
if (!targetState?.isDirectory() || targetState.isSymbolicLink()) {
|
|
28637
|
-
throw new Error(`Deploy target '${target.name}' root is not a regular directory: ${projectDirectory}`);
|
|
28638
|
-
}
|
|
28639
|
-
const requestedId = String(args.id || target.config.id || "").trim() || undefined;
|
|
28640
|
-
const build = createBuildEnvironment(target.config.buildEnv, options.environmentVariables);
|
|
28641
|
-
if (target.config.type === "edge_function") {
|
|
28642
|
-
if (args.diff === true)
|
|
28643
|
-
throw new Error("Function release diffs require an immutable function release manifest");
|
|
28644
|
-
if (!options.edgeFunctionDeploy)
|
|
28645
|
-
throw new Error("Edge Function deploy support is unavailable in this CLI context");
|
|
28646
|
-
const slug = target.config.slug || requestedId || target.name;
|
|
28647
|
-
const functionListResponse = await options.edgeFunctionDeploy({
|
|
28648
|
-
action: "list",
|
|
28649
|
-
ref: projectRef
|
|
28650
|
-
});
|
|
28651
|
-
if (functionListResponse.isError) {
|
|
28652
|
-
throw new Error(`Unable to read the current identity for Edge Function '${slug}'`);
|
|
28653
|
-
}
|
|
28654
|
-
const functionListText = functionListResponse.content.find((chunk) => chunk.type === "text")?.text;
|
|
28655
|
-
if (!functionListText)
|
|
28656
|
-
throw new Error(`Unable to read the current identity for Edge Function '${slug}'`);
|
|
28657
|
-
const functions = projectedFunctionList(JSON.parse(functionListText));
|
|
28658
|
-
if (!functions)
|
|
28659
|
-
throw new Error(`Invalid current identity for Edge Function '${slug}'`);
|
|
28660
|
-
const current = functions?.find((candidate) => candidate.slug === slug);
|
|
28661
|
-
const activeVersion = current && typeof current.version === "number" ? String(current.version) : "absent";
|
|
28662
|
-
const activationId = current && typeof current.activation_id === "string" ? current.activation_id : "legacy";
|
|
28663
|
-
if (!activeVersion || !activationId)
|
|
28664
|
-
throw new Error(`Edge Function '${slug}' has an invalid active identity`);
|
|
28665
|
-
const buildCommand = String(args.build_command || target.config.buildCommand || "").trim() || (args.skip_build === true ? "" : await defaultBuildCommand(projectDirectory, configRoot));
|
|
28666
|
-
const bundleDirectory = resolveInsideProject(projectDirectory, String(args.output_dir || target.config.bundleDirectory || target.config.outputDirectory || "dist"), true);
|
|
28667
|
-
if (args.dry_run === true || args.plan === true) {
|
|
28668
|
-
return { content: [{ type: "text", text: JSON.stringify({
|
|
28669
|
-
ok: true,
|
|
28670
|
-
dry_run: true,
|
|
28671
|
-
type: target.config.type,
|
|
28672
|
-
target: target.name,
|
|
28673
|
-
project_ref: projectRef,
|
|
28674
|
-
slug,
|
|
28675
|
-
build_command: args.skip_build === true ? null : buildCommand,
|
|
28676
|
-
build_env: build.names,
|
|
28677
|
-
missing_build_env: build.missing,
|
|
28678
|
-
bundle_directory: bundleDirectory,
|
|
28679
|
-
expected_active_version: activeVersion,
|
|
28680
|
-
expected_activation_id: activationId
|
|
28681
|
-
}, null, 2) }] };
|
|
28682
|
-
}
|
|
28683
|
-
assertBuildEnvironment(build, args.skip_build === true);
|
|
28684
|
-
if (args.skip_build !== true) {
|
|
28685
|
-
await runBuild(buildCommand, projectDirectory, build.env, args.json === true);
|
|
28686
|
-
}
|
|
28687
|
-
const deployed = await options.edgeFunctionDeploy({
|
|
28688
|
-
action: "deploy_bundle",
|
|
28689
|
-
ref: projectRef,
|
|
28690
|
-
slug,
|
|
28691
|
-
"bundle-dir": bundleDirectory,
|
|
28692
|
-
entrypoint: target.config.entrypoint || "index.ts",
|
|
28693
|
-
minify: target.config.minify,
|
|
28694
|
-
verify_jwt: target.config.verifyJwt,
|
|
28695
|
-
framework: target.config.framework,
|
|
28696
|
-
"expected-active-version": activeVersion,
|
|
28697
|
-
"expected-activation-id": activationId
|
|
28698
|
-
});
|
|
28699
|
-
if (deployed.isError)
|
|
28700
|
-
return deployed;
|
|
28701
|
-
const deployedText = deployed.content.find((chunk) => chunk.type === "text")?.text;
|
|
28702
|
-
const deployedPayload = deployedText ? record4(JSON.parse(deployedText)) : null;
|
|
28703
|
-
return deployResponse({
|
|
28704
|
-
ok: true,
|
|
28705
|
-
unchanged: false,
|
|
28706
|
-
type: target.config.type,
|
|
28707
|
-
target: target.name,
|
|
28708
|
-
project_ref: projectRef,
|
|
28709
|
-
slug,
|
|
28710
|
-
active_version: deployedPayload?.active_version,
|
|
28711
|
-
activation_id: deployedPayload?.activation_id
|
|
28712
|
-
}, args.json === true);
|
|
28713
|
-
}
|
|
28714
|
-
const listResponse = await http.get(`/v1/projects/${encodeURIComponent(projectRef)}/frontend/deployments`);
|
|
28715
|
-
if (!listResponse.ok)
|
|
28716
|
-
throw new Error(`Failed to list frontend deployments (HTTP ${listResponse.status})`);
|
|
28717
|
-
const selected = selectDeployment(deploymentList(listResponse.data), requestedId, await packageName(projectDirectory));
|
|
28718
|
-
const configuredBuildCommand = String(args.build_command || target.config.buildCommand || selected.buildCommand || "").trim();
|
|
28719
|
-
const buildCommand = configuredBuildCommand || (args.skip_build === true ? "" : await defaultBuildCommand(projectDirectory, configRoot));
|
|
28720
|
-
const configuredOutput = String(args.output_dir || target.config.outputDirectory || "").trim();
|
|
28721
|
-
const remoteOutput = selected.outputDirectory && selected.outputDirectory !== "." ? selected.outputDirectory : "";
|
|
28722
|
-
const outputDirectory = resolveInsideProject(projectDirectory, configuredOutput || remoteOutput || defaultOutputDirectory(selected.framework));
|
|
28723
|
-
if (args.dry_run === true) {
|
|
28724
|
-
return { content: [{ type: "text", text: JSON.stringify({
|
|
28725
|
-
ok: true,
|
|
28726
|
-
dry_run: true,
|
|
28727
|
-
project_ref: projectRef,
|
|
28728
|
-
deployment_id: selected.id,
|
|
28729
|
-
build_command: args.skip_build === true ? null : buildCommand,
|
|
28730
|
-
build_env: build.names,
|
|
28731
|
-
missing_build_env: build.missing,
|
|
28732
|
-
output_directory: outputDirectory
|
|
28733
|
-
}, null, 2) }] };
|
|
28734
|
-
}
|
|
28735
|
-
assertBuildEnvironment(build, args.skip_build === true);
|
|
28736
|
-
if (args.skip_build !== true) {
|
|
28737
|
-
await runBuild(buildCommand, projectDirectory, build.env, args.json === true);
|
|
28738
|
-
}
|
|
28739
|
-
const archive = await createFrontendArchive(outputDirectory);
|
|
28740
|
-
try {
|
|
28741
|
-
const inventory = payload(await readFrontendReleaseAuthority(http, projectRef, selected.id));
|
|
28742
|
-
const activeReleaseId = typeof inventory.active_release_id === "string" ? inventory.active_release_id : null;
|
|
28743
|
-
const activeActivationId = typeof inventory.active_activation_id === "string" ? inventory.active_activation_id : null;
|
|
28744
|
-
const current = Array.isArray(inventory.releases) ? record4(inventory.releases[0]) : null;
|
|
28745
|
-
if (archive.sha256 === activeReleaseId && archive.treeSha256 !== current?.tree_sha256) {
|
|
28746
|
-
throw new Error("Active release tree does not match the local archive");
|
|
28747
|
-
}
|
|
28748
|
-
const unchanged = archive.treeSha256 === current?.tree_sha256;
|
|
28749
|
-
if (args.plan === true || args.diff === true) {
|
|
28750
|
-
return { content: [{ type: "text", text: JSON.stringify({
|
|
28751
|
-
schema: "supacloud.frontend-deploy-plan.v1",
|
|
28752
|
-
ok: true,
|
|
28753
|
-
planned: true,
|
|
28754
|
-
published: false,
|
|
28755
|
-
unchanged,
|
|
28756
|
-
environment: options.environment ?? null,
|
|
28757
|
-
type: "frontend",
|
|
28758
|
-
target: target.name,
|
|
28759
|
-
project_ref: projectRef,
|
|
28760
|
-
deployment_id: selected.id,
|
|
28761
|
-
comparison: "immutable_release",
|
|
28762
|
-
archive_format: FRONTEND_ARCHIVE_FORMAT,
|
|
28763
|
-
release_id: archive.sha256,
|
|
28764
|
-
tree_sha256: archive.treeSha256,
|
|
28765
|
-
active_release_id: activeReleaseId,
|
|
28766
|
-
active_tree_sha256: current?.tree_sha256 ?? null,
|
|
28767
|
-
expected_active_release_id: activeReleaseId ?? "absent",
|
|
28768
|
-
expected_activation_id: activeActivationId ?? "absent",
|
|
28769
|
-
actions: unchanged ? [] : ["upload_release", "activate_release"],
|
|
28770
|
-
file_count: archive.fileCount,
|
|
28771
|
-
source_bytes: archive.sourceBytes,
|
|
28772
|
-
archive_bytes: archive.archiveBytes
|
|
28773
|
-
}, null, 2) }] };
|
|
28774
|
-
}
|
|
28775
|
-
if (unchanged) {
|
|
28776
|
-
return deployResponse({
|
|
28777
|
-
ok: true,
|
|
28778
|
-
unchanged: true,
|
|
28779
|
-
project_ref: projectRef,
|
|
28780
|
-
deployment_id: selected.id,
|
|
28781
|
-
release_id: activeReleaseId,
|
|
28782
|
-
tree_sha256: archive.treeSha256,
|
|
28783
|
-
url: selected.deploymentUrl,
|
|
28784
|
-
file_count: archive.fileCount,
|
|
28785
|
-
source_bytes: archive.sourceBytes
|
|
28786
|
-
}, args.json === true);
|
|
28787
|
-
}
|
|
28788
|
-
const uploaded = payload(await uploadFrontendRelease(http, projectRef, selected.id, archive.archivePath));
|
|
28789
|
-
const release = record4(uploaded.release);
|
|
28790
|
-
const releaseId = requiredString(release?.release_id, "release.release_id");
|
|
28791
|
-
if (releaseId !== archive.sha256)
|
|
28792
|
-
throw new Error("Uploaded release identity does not match the local archive");
|
|
28793
|
-
if (release?.tree_sha256 !== archive.treeSha256)
|
|
28794
|
-
throw new Error("Uploaded release tree does not match the local build");
|
|
28795
|
-
const mutationId = crypto.randomUUID();
|
|
28796
|
-
const activationResponse = await activateFrontendRelease(http, {
|
|
28797
|
-
projectRef,
|
|
28798
|
-
deploymentId: selected.id,
|
|
28799
|
-
releaseId,
|
|
28800
|
-
expectedActiveReleaseId: activeReleaseId || "absent",
|
|
28801
|
-
expectedActivationId: activeActivationId || "absent",
|
|
28802
|
-
mutationId
|
|
28803
|
-
});
|
|
28804
|
-
if (activationResponse.isError) {
|
|
28805
|
-
const failure = record4(JSON.parse(activationResponse.content[0]?.text ?? "{}"));
|
|
28806
|
-
return {
|
|
28807
|
-
isError: true,
|
|
28808
|
-
content: [{ type: "text", text: JSON.stringify({
|
|
28809
|
-
...failure,
|
|
28810
|
-
operation: "deploy",
|
|
28811
|
-
project_ref: projectRef,
|
|
28812
|
-
deployment_id: selected.id,
|
|
28813
|
-
mutation_id: mutationId,
|
|
28814
|
-
target_release_id: releaseId,
|
|
28815
|
-
expected_active_release_id: activeReleaseId ?? "absent",
|
|
28816
|
-
expected_activation_id: activeActivationId ?? "absent"
|
|
28817
|
-
}) }]
|
|
28818
|
-
};
|
|
28819
|
-
}
|
|
28820
|
-
const activated = payload(activationResponse);
|
|
28821
|
-
const finalResponse = await http.get(`/v1/projects/${encodeURIComponent(projectRef)}/frontend/deployments/${encodeURIComponent(selected.id)}`);
|
|
28822
|
-
const finalDeployment = finalResponse.ok ? frontendDeployment(finalResponse.data) : selected;
|
|
28823
|
-
return deployResponse({
|
|
28824
|
-
ok: true,
|
|
28825
|
-
unchanged: false,
|
|
28826
|
-
project_ref: projectRef,
|
|
28827
|
-
deployment_id: selected.id,
|
|
28828
|
-
release_id: activated.active_release_id,
|
|
28829
|
-
activation_id: activated.activation_id,
|
|
28830
|
-
previous_release_id: activeReleaseId,
|
|
28831
|
-
previous_activation_id: activeActivationId,
|
|
28832
|
-
url: finalDeployment.deploymentUrl,
|
|
28833
|
-
file_count: archive.fileCount,
|
|
28834
|
-
source_bytes: archive.sourceBytes
|
|
28835
|
-
}, args.json === true);
|
|
28836
|
-
} finally {
|
|
28837
|
-
await archive.cleanup();
|
|
28838
|
-
}
|
|
28607
|
+
throw new Error(DEPLOYMENT_UPGRADE);
|
|
28839
28608
|
});
|
|
28840
28609
|
}
|
|
28841
28610
|
|
|
@@ -29127,6 +28896,7 @@ var TEST_PROFILE = [
|
|
|
29127
28896
|
"SUPACLOUD_API_URL=https://management.test.example.com",
|
|
29128
28897
|
"SUPACLOUD_API_TOKEN=<test-management-api-token>",
|
|
29129
28898
|
"SUPACLOUD_PROJECT_REF=<test-project-ref>",
|
|
28899
|
+
"SUPACLOUD_APPLICATION_ID=<application-id>",
|
|
29130
28900
|
""
|
|
29131
28901
|
].join(`
|
|
29132
28902
|
`);
|
|
@@ -29135,6 +28905,7 @@ var PRODUCTION_PROFILE = [
|
|
|
29135
28905
|
"SUPACLOUD_API_URL=https://management.example.com",
|
|
29136
28906
|
"SUPACLOUD_API_TOKEN=<production-management-api-token>",
|
|
29137
28907
|
"SUPACLOUD_PROJECT_REF=<production-project-ref>",
|
|
28908
|
+
"SUPACLOUD_APPLICATION_ID=<application-id>",
|
|
29138
28909
|
""
|
|
29139
28910
|
].join(`
|
|
29140
28911
|
`);
|
|
@@ -29258,6 +29029,7 @@ async function initializeProject(request, options) {
|
|
|
29258
29029
|
},
|
|
29259
29030
|
next: [
|
|
29260
29031
|
"cp .env.supacloud.test.example .env.supacloud.test",
|
|
29032
|
+
"Set SUPACLOUD_APPLICATION_ID to the application's ID and configure its current SupaCloud delivery build.",
|
|
29261
29033
|
"supacloud env check",
|
|
29262
29034
|
"supacloud --env test deploy"
|
|
29263
29035
|
]
|
|
@@ -29305,17 +29077,16 @@ function statusMissing(context) {
|
|
|
29305
29077
|
}
|
|
29306
29078
|
return ["SUPACLOUD_API_URL", "SUPACLOUD_API_TOKEN", "SUPACLOUD_PROJECT_REF"];
|
|
29307
29079
|
}
|
|
29308
|
-
function deployMissing(context) {
|
|
29080
|
+
function deployMissing(context, application) {
|
|
29309
29081
|
const missing = statusMissing(context);
|
|
29310
29082
|
if (context.credentialScope !== "management") {
|
|
29311
29083
|
return [...missing, "Management API context"];
|
|
29312
29084
|
}
|
|
29313
|
-
if (context.applicationId) {
|
|
29314
|
-
|
|
29315
|
-
|
|
29316
|
-
|
|
29317
|
-
|
|
29318
|
-
}
|
|
29085
|
+
if (!Check2(ApplicationIdSchema, context.applicationId || application?.id)) {
|
|
29086
|
+
missing.push("valid SUPACLOUD_APPLICATION_ID or supacloud.json application.id");
|
|
29087
|
+
}
|
|
29088
|
+
if (!Check2(ApplicationIdSchema, context.applicationEnvironmentId || application?.environmentId)) {
|
|
29089
|
+
missing.push("valid SUPACLOUD_APPLICATION_ENVIRONMENT_ID or SUPACLOUD_ENV");
|
|
29319
29090
|
}
|
|
29320
29091
|
return missing;
|
|
29321
29092
|
}
|
|
@@ -29325,7 +29096,13 @@ async function inspectProfile(profile) {
|
|
|
29325
29096
|
environmentName: profile.name
|
|
29326
29097
|
});
|
|
29327
29098
|
const status = statusMissing(context);
|
|
29328
|
-
const
|
|
29099
|
+
const configText = await readFile8(join19(dirname12(profile.path), "supacloud.json"), "utf8").catch((error) => {
|
|
29100
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
29101
|
+
return "{}";
|
|
29102
|
+
throw error;
|
|
29103
|
+
});
|
|
29104
|
+
const config = record5(JSON.parse(configText));
|
|
29105
|
+
const deploy = deployMissing(context, record5(config?.application));
|
|
29329
29106
|
return {
|
|
29330
29107
|
name: profile.name,
|
|
29331
29108
|
path: profile.path,
|
|
@@ -29418,109 +29195,10 @@ function registerDeveloperExperienceTools(server, options = {}) {
|
|
|
29418
29195
|
registerTool(server, "init", "Create SupaCloud deployment configuration and non-secret environment examples without overwriting project files.", initToolSchema, (request) => initializeProject(request, options));
|
|
29419
29196
|
registerTool(server, "env", "List or locally validate named SupaCloud environment profiles without contacting the platform or printing secrets.", environmentToolSchema, (request) => inspectEnvironment(request, options));
|
|
29420
29197
|
}
|
|
29421
|
-
|
|
29422
|
-
// src/shared/tools/project-deployment.ts
|
|
29423
|
-
var operation = "applications.project_deploy";
|
|
29424
|
-
var scopeSchema = _Object_({
|
|
29425
|
-
project_ref: String2({ pattern: "^[a-z0-9-]{1,20}$" }),
|
|
29426
|
-
application_id: ApplicationIdSchema,
|
|
29427
|
-
environment_id: ApplicationIdSchema
|
|
29428
|
-
});
|
|
29429
|
-
var statusSchema = _Object_({
|
|
29430
|
-
schema: Literal("supacloud.project-deployment-status.v1"),
|
|
29431
|
-
deployment_id: ApplicationDeployRequestSchema.properties.mutation_id,
|
|
29432
|
-
status: Union([
|
|
29433
|
-
Literal("pending"),
|
|
29434
|
-
Literal("running"),
|
|
29435
|
-
Literal("succeeded"),
|
|
29436
|
-
Literal("failed_retryable"),
|
|
29437
|
-
Literal("failed_terminal"),
|
|
29438
|
-
Literal("outcome_unknown")
|
|
29439
|
-
]),
|
|
29440
|
-
phase: Union([
|
|
29441
|
-
Literal("queued"),
|
|
29442
|
-
Literal("prepared"),
|
|
29443
|
-
Literal("migrating"),
|
|
29444
|
-
Literal("activating"),
|
|
29445
|
-
Literal("binding-web"),
|
|
29446
|
-
Literal("verifying")
|
|
29447
|
-
]),
|
|
29448
|
-
operation: Literal("application.release.deploy"),
|
|
29449
|
-
...scopeSchema.properties,
|
|
29450
|
-
receipt: Optional(Unknown()),
|
|
29451
|
-
failure_code: Optional(String2({ pattern: "^[A-Z][A-Z0-9_]{0,63}$" }))
|
|
29452
|
-
}, { additionalProperties: false });
|
|
29453
|
-
function responseReceipt(data, expected) {
|
|
29454
|
-
if (!data || typeof data !== "object" || Array.isArray(data) || !("ok" in data) || data.ok !== true) {
|
|
29455
|
-
throw new Error("Invalid project deployment response");
|
|
29456
|
-
}
|
|
29457
|
-
const { ok: _ok, ...receipt } = data;
|
|
29458
|
-
return parseApplicationDeployResult(receipt, expected);
|
|
29459
|
-
}
|
|
29460
|
-
async function runProjectDeployment(http, args) {
|
|
29461
|
-
const scope = { project_ref: args.ref, application_id: args.id, environment_id: args.environment_id };
|
|
29462
|
-
const request = {
|
|
29463
|
-
mutation_id: args.mutation_id,
|
|
29464
|
-
release_id: args.release_id,
|
|
29465
|
-
...args.configuration_id === undefined ? {} : { configuration_id: args.configuration_id },
|
|
29466
|
-
...args.configuration_write === undefined ? {} : { configuration_write: args.configuration_write },
|
|
29467
|
-
...args.expected_plan_sha256 === undefined ? {} : { expected_plan_sha256: args.expected_plan_sha256 },
|
|
29468
|
-
...args.approved_migration_digest === undefined ? {} : { approved_migration_digest: args.approved_migration_digest },
|
|
29469
|
-
...args.web === undefined ? {} : { web: args.web }
|
|
29470
|
-
};
|
|
29471
|
-
if (!Check2(scopeSchema, scope) || !Check2(ApplicationDeployRequestSchema, request) || request.configuration_id !== undefined && request.configuration_write !== undefined && request.configuration_id !== request.configuration_write.configuration_id) {
|
|
29472
|
-
return releaseControlFailure(operation, "INVALID_RESPONSE", null);
|
|
29473
|
-
}
|
|
29474
|
-
const expected = { ...scope, request };
|
|
29475
|
-
const identity = {
|
|
29476
|
-
...scope,
|
|
29477
|
-
deployment_id: request.mutation_id,
|
|
29478
|
-
mutation_id: request.mutation_id,
|
|
29479
|
-
release_id: request.release_id
|
|
29480
|
-
};
|
|
29481
|
-
const endpoint = `/v1/projects/${encodeURIComponent(scope.project_ref)}/environments/${encodeURIComponent(scope.environment_id)}/deployments`;
|
|
29482
|
-
const { mutation_id, ...candidate } = request;
|
|
29483
|
-
const result = await http.post(endpoint, {
|
|
29484
|
-
...candidate,
|
|
29485
|
-
deployment_id: mutation_id,
|
|
29486
|
-
application_id: scope.application_id
|
|
29487
|
-
}, { timeoutMs: 120000, maxJsonBytes: 131072, responseTimeoutMs: 30000 });
|
|
29488
|
-
if (result.ok && result.status === 200) {
|
|
29489
|
-
try {
|
|
29490
|
-
return releaseControlSuccess(operation, {
|
|
29491
|
-
...responseReceipt(result.data, expected),
|
|
29492
|
-
deployment_id: mutation_id
|
|
29493
|
-
});
|
|
29494
|
-
} catch {}
|
|
29495
|
-
} else if (!result.ok && !result.transportError && !result.responseReadError && result.status < 500 && result.status !== 408) {
|
|
29496
|
-
return releaseControlMutationFailure(operation, result, identity);
|
|
29497
|
-
}
|
|
29498
|
-
const observed = await http.get(`${endpoint}/${encodeURIComponent(mutation_id)}`, {
|
|
29499
|
-
retry: false,
|
|
29500
|
-
totalTimeoutMs: 30000,
|
|
29501
|
-
maxJsonBytes: 131072
|
|
29502
|
-
});
|
|
29503
|
-
try {
|
|
29504
|
-
if (!observed.ok || observed.status !== 200 || !Check2(statusSchema, observed.data))
|
|
29505
|
-
throw new Error;
|
|
29506
|
-
const state = observed.data;
|
|
29507
|
-
if (state.deployment_id !== mutation_id || state.project_ref !== scope.project_ref || state.application_id !== scope.application_id || state.environment_id !== scope.environment_id || state.status !== "succeeded" || state.phase !== "verifying")
|
|
29508
|
-
throw new Error;
|
|
29509
|
-
const receipt = parseApplicationDeployResult(state.receipt, expected);
|
|
29510
|
-
return releaseControlSuccess(operation, {
|
|
29511
|
-
...receipt,
|
|
29512
|
-
deployment_id: mutation_id,
|
|
29513
|
-
replayed: true,
|
|
29514
|
-
execution_performed: false
|
|
29515
|
-
});
|
|
29516
|
-
} catch {
|
|
29517
|
-
return releaseControlFailure(operation, "OUTCOME_UNKNOWN", result.transportError ? null : result.status, identity);
|
|
29518
|
-
}
|
|
29519
|
-
}
|
|
29520
29198
|
// package.json
|
|
29521
29199
|
var package_default = {
|
|
29522
29200
|
name: "@supacloud/cli",
|
|
29523
|
-
version: "0.
|
|
29201
|
+
version: "0.94.0",
|
|
29524
29202
|
description: "Project-scoped CLI for SupaCloud users",
|
|
29525
29203
|
type: "module",
|
|
29526
29204
|
main: "./dist/index.js",
|
|
@@ -29573,13 +29251,13 @@ var package_default = {
|
|
|
29573
29251
|
},
|
|
29574
29252
|
dependencies: {
|
|
29575
29253
|
"@supacloud/compiler": "^0.44.1",
|
|
29576
|
-
"@supacloud/delivery": "0.
|
|
29577
|
-
"@supacloud/db": "0.16.
|
|
29254
|
+
"@supacloud/delivery": "0.16.0",
|
|
29255
|
+
"@supacloud/db": "0.16.2",
|
|
29578
29256
|
typebox: "1.3.36"
|
|
29579
29257
|
},
|
|
29580
29258
|
overrides: {
|
|
29581
29259
|
"@supacloud/contracts": "0.8.1",
|
|
29582
|
-
"@supacloud/delivery": "0.
|
|
29260
|
+
"@supacloud/delivery": "0.16.0",
|
|
29583
29261
|
"@graphql-tools/utils": "^12.0.3"
|
|
29584
29262
|
},
|
|
29585
29263
|
devDependencies: {
|
|
@@ -29796,8 +29474,6 @@ EXAMPLES
|
|
|
29796
29474
|
${preferredCommand} deploy
|
|
29797
29475
|
${preferredCommand} --env test deploy
|
|
29798
29476
|
${preferredCommand} --env production deploy --confirm-production <project-ref>
|
|
29799
|
-
${preferredCommand} deploy --target web
|
|
29800
|
-
${preferredCommand} deploy --target api
|
|
29801
29477
|
${preferredCommand} dev sync --env test --target functions --function api
|
|
29802
29478
|
${preferredCommand} dev status --env test
|
|
29803
29479
|
${preferredCommand} dev watch --env test --target project
|
|
@@ -30153,8 +29829,7 @@ function createCliTools(context, confirmProduction) {
|
|
|
30153
29829
|
applicationRelease: (args) => tools.app ? tools.app.callback(args) : Promise.resolve({
|
|
30154
29830
|
isError: true,
|
|
30155
29831
|
content: [{ type: "text", text: "Application release support is unavailable in this CLI context" }]
|
|
30156
|
-
})
|
|
30157
|
-
edgeFunctionDeploy: advancedTools.edge_functions?.callback
|
|
29832
|
+
})
|
|
30158
29833
|
})));
|
|
30159
29834
|
assign(captureTools((server) => registerGatewayTools(server, http, {
|
|
30160
29835
|
projectRef: context.projectRef || undefined
|