@supacloud/cli 0.78.0 → 0.80.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/dist/index.js +447 -36
- package/dist/shared/tools/app-tools.d.ts +9 -2
- package/dist/shared/tools/application-activation-http-status.test.d.ts +1 -0
- package/dist/shared/tools/application-deploy-http-status.test.d.ts +1 -0
- package/dist/shared/tools/application-history.test.d.ts +1 -0
- package/dist/shared/tools/application-schemas.d.ts +17 -0
- package/dist/shared/tools/application-tools.d.ts +2 -2
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -179093,11 +179093,13 @@ function resolveSupaCloudContext(env = process.env, cwd = process.cwd(), selecti
|
|
|
179093
179093
|
var ACTION_POLICY = {
|
|
179094
179094
|
deploy: { write: ["deploy"] },
|
|
179095
179095
|
applications: {
|
|
179096
|
-
read: ["list_releases", "get_release", "get_runtime", "get_deployment_evidence", "get_configuration", "logs", "get_preview_plan"],
|
|
179096
|
+
read: ["list_releases", "get_release", "get_runtime", "get_deployment_evidence", "get_configuration", "get_rollback_snapshot", "get_history", "get_deploy_plan", "logs", "get_preview_plan"],
|
|
179097
179097
|
write: [
|
|
179098
179098
|
"upload_release",
|
|
179099
179099
|
"put_configuration",
|
|
179100
179100
|
"activate_release",
|
|
179101
|
+
"deploy_release",
|
|
179102
|
+
"rollback_release",
|
|
179101
179103
|
"reconcile_activation",
|
|
179102
179104
|
"retire_activation",
|
|
179103
179105
|
"create_preview",
|
|
@@ -179199,7 +179201,7 @@ var ACTION_POLICY = {
|
|
|
179199
179201
|
ai: { local: ["show_skill", "install_skill"] },
|
|
179200
179202
|
app: {
|
|
179201
179203
|
local: ["init", "generate", "dev", "watch", "verify-plan", "compile", "check", "graph", "explain", "export-tools", "context", "doctor", "fix", "plan", "build"],
|
|
179202
|
-
read: ["status", "logs", "preview-plan"],
|
|
179204
|
+
read: ["status", "logs", "rollback-plan", "history", "deploy-plan", "diff", "preview-plan"],
|
|
179203
179205
|
write: ["upload", "configure", "deploy", "rollback", "reconcile", "retire", "preview", "previews", "preview-status", "preview-cleanup"]
|
|
179204
179206
|
},
|
|
179205
179207
|
db: {
|
|
@@ -180280,6 +180282,143 @@ var ApplicationActivationRetirementResultSchema = _Object_({
|
|
|
180280
180282
|
activation_id: ApplicationActivationIdSchema,
|
|
180281
180283
|
retired_at: String2()
|
|
180282
180284
|
}, { additionalProperties: false });
|
|
180285
|
+
var RollbackActivationSchema = _Object_({
|
|
180286
|
+
release_id: ApplicationReleaseIdSchema,
|
|
180287
|
+
configuration_id: ApplicationConfigurationIdSchema,
|
|
180288
|
+
activation_id: ApplicationActivationIdSchema
|
|
180289
|
+
}, { additionalProperties: false });
|
|
180290
|
+
var ApplicationRollbackSnapshotSchema = _Object_({
|
|
180291
|
+
schema: Literal("supacloud.application-rollback-snapshot.v1"),
|
|
180292
|
+
project_ref: String2({ pattern: "^[a-z0-9-]{1,20}$" }),
|
|
180293
|
+
application_id: ApplicationIdSchema,
|
|
180294
|
+
environment_id: ApplicationIdSchema,
|
|
180295
|
+
active: Union([RollbackActivationSchema, Null()]),
|
|
180296
|
+
previous: Union([RollbackActivationSchema, Null()])
|
|
180297
|
+
}, { additionalProperties: false });
|
|
180298
|
+
// node_modules/@supacloud/delivery/src/application-deploy-plan.ts
|
|
180299
|
+
var CandidateSchema = _Object_({
|
|
180300
|
+
release_id: ApplicationReleaseIdSchema,
|
|
180301
|
+
configuration_id: ApplicationConfigurationIdSchema
|
|
180302
|
+
}, { additionalProperties: false });
|
|
180303
|
+
var ApplicationDeployPlanSchema = _Object_({
|
|
180304
|
+
schema: Literal("supacloud.application-deploy-plan.v1"),
|
|
180305
|
+
project_ref: String2({ pattern: "^[a-z0-9-]{1,20}$" }),
|
|
180306
|
+
application_id: ApplicationIdSchema,
|
|
180307
|
+
environment_id: ApplicationIdSchema,
|
|
180308
|
+
candidate: CandidateSchema,
|
|
180309
|
+
current: Union([_Object_({
|
|
180310
|
+
...CandidateSchema.properties,
|
|
180311
|
+
activation_id: ApplicationActivationIdSchema
|
|
180312
|
+
}, { additionalProperties: false }), Null()]),
|
|
180313
|
+
expected_activation_id: Union([ApplicationActivationIdSchema, Null()]),
|
|
180314
|
+
action: Union([Literal("activate"), Literal("no-op")]),
|
|
180315
|
+
changes: _Object_({
|
|
180316
|
+
release: Boolean2(),
|
|
180317
|
+
configuration: Boolean2(),
|
|
180318
|
+
targets: _Object_({
|
|
180319
|
+
added: _Array_(String2()),
|
|
180320
|
+
removed: _Array_(String2()),
|
|
180321
|
+
changed: _Array_(String2())
|
|
180322
|
+
}, { additionalProperties: false })
|
|
180323
|
+
}, { additionalProperties: false }),
|
|
180324
|
+
migrations: _Object_({
|
|
180325
|
+
ledger_digest: ApplicationReleaseIdSchema,
|
|
180326
|
+
ledger_compatible: Boolean2(),
|
|
180327
|
+
project_migrations_applied: Boolean2(),
|
|
180328
|
+
operator_provisioning: Union([
|
|
180329
|
+
Literal("separate-verification-required"),
|
|
180330
|
+
Literal("not-declared")
|
|
180331
|
+
])
|
|
180332
|
+
}, { additionalProperties: false }),
|
|
180333
|
+
compatibility: Literal("not-proven"),
|
|
180334
|
+
execution_performed: Literal(false)
|
|
180335
|
+
}, { additionalProperties: false });
|
|
180336
|
+
function parseApplicationDeployPlan(value) {
|
|
180337
|
+
if (!Check2(ApplicationDeployPlanSchema, value) || value.expected_activation_id !== (value.current?.activation_id ?? null) || value.changes.release !== (value.current?.release_id !== value.candidate.release_id) || value.changes.configuration !== (value.current?.configuration_id !== value.candidate.configuration_id) || value.migrations.project_migrations_applied && !value.migrations.ledger_compatible) {
|
|
180338
|
+
throw new Error("Invalid application deploy plan");
|
|
180339
|
+
}
|
|
180340
|
+
const noOp = value.current !== null && !value.changes.release && !value.changes.configuration && Object.values(value.changes.targets).every((names) => names.length === 0) && value.migrations.ledger_compatible && value.migrations.project_migrations_applied && value.migrations.operator_provisioning === "not-declared";
|
|
180341
|
+
if (value.action === "no-op" !== noOp)
|
|
180342
|
+
throw new Error("Invalid application deploy plan action");
|
|
180343
|
+
return value;
|
|
180344
|
+
}
|
|
180345
|
+
// node_modules/@supacloud/delivery/src/application-history.ts
|
|
180346
|
+
var scope = {
|
|
180347
|
+
project_ref: String2({ pattern: "^[a-z0-9-]{1,20}$" }),
|
|
180348
|
+
application_id: ApplicationIdSchema,
|
|
180349
|
+
environment_id: ApplicationIdSchema
|
|
180350
|
+
};
|
|
180351
|
+
var timestamp = String2({ pattern: "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{6}Z$" });
|
|
180352
|
+
var ApplicationActivationHistoryPositionSchema = _Object_({
|
|
180353
|
+
completed_at: timestamp,
|
|
180354
|
+
activation_id: ApplicationActivationIdSchema
|
|
180355
|
+
}, { additionalProperties: false });
|
|
180356
|
+
var cursorSchema = _Object_({
|
|
180357
|
+
...scope,
|
|
180358
|
+
...ApplicationActivationHistoryPositionSchema.properties
|
|
180359
|
+
}, { additionalProperties: false });
|
|
180360
|
+
var ApplicationActivationHistoryCursorSchema = String2({
|
|
180361
|
+
pattern: "^[A-Za-z0-9_-]+$",
|
|
180362
|
+
maxLength: 1024,
|
|
180363
|
+
minLength: 1
|
|
180364
|
+
});
|
|
180365
|
+
var entrySchema = _Object_({
|
|
180366
|
+
...ApplicationActivationHistoryPositionSchema.properties,
|
|
180367
|
+
release_id: ApplicationReleaseIdSchema,
|
|
180368
|
+
configuration_id: Union([ApplicationConfigurationIdSchema, Null()]),
|
|
180369
|
+
previous_activation_id: Union([ApplicationActivationIdSchema, Null()]),
|
|
180370
|
+
is_active: Boolean2()
|
|
180371
|
+
}, { additionalProperties: false });
|
|
180372
|
+
var ApplicationActivationHistorySchema = _Object_({
|
|
180373
|
+
schema: Literal("supacloud.application-activation-history.v1"),
|
|
180374
|
+
...scope,
|
|
180375
|
+
active_activation_id: Union([ApplicationActivationIdSchema, Null()]),
|
|
180376
|
+
activations: _Array_(entrySchema, { maxItems: 100 }),
|
|
180377
|
+
next_cursor: Union([ApplicationActivationHistoryCursorSchema, Null()])
|
|
180378
|
+
}, { additionalProperties: false });
|
|
180379
|
+
function applicationHistoryTimestampMilliseconds(value) {
|
|
180380
|
+
const milliseconds = `${value.slice(0, 23)}Z`;
|
|
180381
|
+
if (!Check2(timestamp, value) || !Number.isFinite(Date.parse(milliseconds)) || new Date(milliseconds).toISOString() !== milliseconds)
|
|
180382
|
+
throw new Error("Invalid application history timestamp");
|
|
180383
|
+
return milliseconds;
|
|
180384
|
+
}
|
|
180385
|
+
function parseApplicationHistoryCursor(value, scope) {
|
|
180386
|
+
if (!Check2(ApplicationActivationHistoryCursorSchema, value))
|
|
180387
|
+
throw new Error("Invalid application history cursor");
|
|
180388
|
+
const bytes = Buffer.from(value, "base64url");
|
|
180389
|
+
if (bytes.toString("base64url") !== value)
|
|
180390
|
+
throw new Error("Invalid application history cursor");
|
|
180391
|
+
const cursor = JSON.parse(bytes.toString("utf8"));
|
|
180392
|
+
if (!Check2(cursorSchema, cursor) || cursor.project_ref !== scope.project_ref || cursor.application_id !== scope.application_id || cursor.environment_id !== scope.environment_id) {
|
|
180393
|
+
throw new Error("Invalid application history cursor");
|
|
180394
|
+
}
|
|
180395
|
+
applicationHistoryTimestampMilliseconds(cursor.completed_at);
|
|
180396
|
+
return { completed_at: cursor.completed_at, activation_id: cursor.activation_id };
|
|
180397
|
+
}
|
|
180398
|
+
function applicationHistoryPositionBefore(left, right) {
|
|
180399
|
+
return left.completed_at < right.completed_at || left.completed_at === right.completed_at && left.activation_id < right.activation_id;
|
|
180400
|
+
}
|
|
180401
|
+
function parseApplicationActivationHistory(value) {
|
|
180402
|
+
if (!Check2(ApplicationActivationHistorySchema, value))
|
|
180403
|
+
throw new Error("Invalid application activation history");
|
|
180404
|
+
const seen = new Set;
|
|
180405
|
+
let previous;
|
|
180406
|
+
for (const entry of value.activations) {
|
|
180407
|
+
applicationHistoryTimestampMilliseconds(entry.completed_at);
|
|
180408
|
+
if (seen.has(entry.activation_id) || previous && !applicationHistoryPositionBefore(entry, previous) || entry.previous_activation_id === entry.activation_id || entry.is_active !== (entry.activation_id === value.active_activation_id)) {
|
|
180409
|
+
throw new Error("Invalid application activation history");
|
|
180410
|
+
}
|
|
180411
|
+
seen.add(entry.activation_id);
|
|
180412
|
+
previous = entry;
|
|
180413
|
+
}
|
|
180414
|
+
if (value.next_cursor !== null) {
|
|
180415
|
+
const cursor = parseApplicationHistoryCursor(value.next_cursor, value);
|
|
180416
|
+
if (!previous || cursor.activation_id !== previous.activation_id || cursor.completed_at !== previous.completed_at) {
|
|
180417
|
+
throw new Error("Invalid application activation history");
|
|
180418
|
+
}
|
|
180419
|
+
}
|
|
180420
|
+
return structuredClone(value);
|
|
180421
|
+
}
|
|
180283
180422
|
// node_modules/@supacloud/delivery/src/deployment-evidence.ts
|
|
180284
180423
|
var closed3 = { additionalProperties: false };
|
|
180285
180424
|
var sha256 = String2({ pattern: "^[a-f0-9]{64}$" });
|
|
@@ -180451,7 +180590,7 @@ function parseApplicationReadinessReport(value) {
|
|
|
180451
180590
|
return value;
|
|
180452
180591
|
}
|
|
180453
180592
|
// node_modules/@supacloud/delivery/src/delivery-migration-archive.ts
|
|
180454
|
-
var
|
|
180593
|
+
var entrySchema2 = _Object_({
|
|
180455
180594
|
version: String2({ pattern: "^[1-9][0-9]{0,18}$" }),
|
|
180456
180595
|
name: String2({ pattern: "^[A-Za-z][A-Za-z0-9_-]{0,127}$" }),
|
|
180457
180596
|
executor: Union([Literal("project-migration"), Literal("operator-provisioning")]),
|
|
@@ -180465,7 +180604,7 @@ var archiveSchema = _Object_({
|
|
|
180465
180604
|
compatibility: Literal("not-proven"),
|
|
180466
180605
|
executionPerformed: Literal(false),
|
|
180467
180606
|
dataRecovery: Literal("separate-required"),
|
|
180468
|
-
migrations: _Array_(
|
|
180607
|
+
migrations: _Array_(entrySchema2, { minItems: 1, maxItems: 128 })
|
|
180469
180608
|
}, { additionalProperties: false });
|
|
180470
180609
|
async function readDeliveryMigrationArchive(manifestPath, target) {
|
|
180471
180610
|
try {
|
|
@@ -187252,6 +187391,8 @@ var ApplicationActivationIdSchema2 = ApplicationActivationIdSchema;
|
|
|
187252
187391
|
var ApplicationActivationWriteSchema2 = ApplicationActivationWriteSchema;
|
|
187253
187392
|
var ApplicationActivationResultSchema2 = ApplicationActivationResultSchema;
|
|
187254
187393
|
var ApplicationActivationRetirementResultSchema2 = ApplicationActivationRetirementResultSchema;
|
|
187394
|
+
var ApplicationRollbackSnapshotSchema2 = ApplicationRollbackSnapshotSchema;
|
|
187395
|
+
var ApplicationActivationHistoryCursorSchema2 = ApplicationActivationHistoryCursorSchema;
|
|
187255
187396
|
|
|
187256
187397
|
// src/shared/tools/application-preview-tools.ts
|
|
187257
187398
|
var APPLICATION_PREVIEW_ACTIONS = [
|
|
@@ -187338,14 +187479,14 @@ var actionFields = {
|
|
|
187338
187479
|
get_preview: ["preview_id", "wait", "timeout_seconds"],
|
|
187339
187480
|
cleanup_preview: ["preview_id"]
|
|
187340
187481
|
};
|
|
187341
|
-
function
|
|
187482
|
+
function timestamp2(value) {
|
|
187342
187483
|
return Number.isFinite(Date.parse(value)) && new Date(value).toISOString() === value;
|
|
187343
187484
|
}
|
|
187344
187485
|
function receipt(value, identity) {
|
|
187345
187486
|
if (!Check2(receiptSchema, value) || value.project_ref !== identity.ref || value.application_id !== identity.id || value.environment_id !== identity.environment || identity.previewId && value.preview_id !== identity.previewId || value.resources.build_artifact.release_id !== value.release_id || value.resources.storage_namespace.namespace !== value.resources.database_branch.branch_ref) {
|
|
187346
187487
|
throw new Error("Invalid preview receipt");
|
|
187347
187488
|
}
|
|
187348
|
-
if (value.expires_at !== null && !
|
|
187489
|
+
if (value.expires_at !== null && !timestamp2(value.expires_at) || value.created_at !== undefined && !timestamp2(value.created_at) || value.updated_at !== undefined && !timestamp2(value.updated_at) || value.expires_at !== null && value.created_at !== undefined && !Check2(ttlSecondsSchema, (Date.parse(value.expires_at) - Date.parse(value.created_at)) / 1000)) {
|
|
187349
187490
|
throw new Error("Invalid preview expiry");
|
|
187350
187491
|
}
|
|
187351
187492
|
if (value.status === "ready") {
|
|
@@ -187589,7 +187730,12 @@ var APPLICATION_TOOL_SCHEMA = {
|
|
|
187589
187730
|
"get_deployment_evidence",
|
|
187590
187731
|
"get_configuration",
|
|
187591
187732
|
"put_configuration",
|
|
187733
|
+
"get_deploy_plan",
|
|
187734
|
+
"deploy_release",
|
|
187592
187735
|
"activate_release",
|
|
187736
|
+
"rollback_release",
|
|
187737
|
+
"get_rollback_snapshot",
|
|
187738
|
+
"get_history",
|
|
187593
187739
|
"reconcile_activation",
|
|
187594
187740
|
"retire_activation",
|
|
187595
187741
|
...APPLICATION_PREVIEW_ACTIONS,
|
|
@@ -187597,15 +187743,15 @@ var APPLICATION_TOOL_SCHEMA = {
|
|
|
187597
187743
|
]), "Action"),
|
|
187598
187744
|
ref: withDescription(String2(), "Project ref"),
|
|
187599
187745
|
id: withDescription(ApplicationIdSchema2, "Application ID"),
|
|
187600
|
-
environment_id: optional(withDescription(ApplicationIdSchema2, "[get_runtime/get_configuration/put_configuration] Environment ID")),
|
|
187601
|
-
configuration_id: optional(ApplicationConfigurationIdSchema2, "[get_configuration/activate_release] Immutable revision; required for
|
|
187602
|
-
activation_id: optional(ApplicationActivationIdSchema2, "[activate_release/reconcile_activation/retire_activation]
|
|
187603
|
-
expected_activation_id: optional(Union([ApplicationActivationIdSchema2, Null(), Literal("absent")]), "[activate_release] Current activation ID, or absent for first activation"),
|
|
187746
|
+
environment_id: optional(withDescription(ApplicationIdSchema2, "[get_runtime/get_configuration/put_configuration/get_deploy_plan/deploy_release/get_rollback_snapshot/rollback_release/get_history] Environment ID")),
|
|
187747
|
+
configuration_id: optional(ApplicationConfigurationIdSchema2, "[get_configuration/get_deploy_plan/deploy_release/activate_release/rollback_release/get_history] Immutable revision; required for deployment"),
|
|
187748
|
+
activation_id: optional(ApplicationActivationIdSchema2, "[deploy_release/activate_release/reconcile_activation/retire_activation/rollback_release/get_history] Stable activation ID; generated for automatic deployment/rollback if omitted"),
|
|
187749
|
+
expected_activation_id: optional(Union([ApplicationActivationIdSchema2, Null(), Literal("absent")]), "[deploy_release/activate_release/rollback_release] Current activation ID, or absent for first activation; selected from verified plan for automatic deployment"),
|
|
187604
187750
|
configuration_path: optional(String2(), "[put_configuration] Local configuration write JSON including revision and expected revision"),
|
|
187605
187751
|
manifest_path: optional(String2(), "[upload_release] Local delivery.manifest.json"),
|
|
187606
|
-
release_id: optional(ApplicationReleaseIdSchema2, "[get_release/activate_release/reconcile_activation] Immutable application release ID"),
|
|
187607
|
-
cursor: optional(ApplicationReleaseIdSchema2, "[list_releases]
|
|
187608
|
-
limit: optional(Integer({ minimum: 1, maximum: 100 }), "[list_releases] Page size, default 50"),
|
|
187752
|
+
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"),
|
|
187753
|
+
cursor: optional(Union([ApplicationReleaseIdSchema2, ApplicationActivationHistoryCursorSchema2]), "[list_releases/get_history] Returned page cursor"),
|
|
187754
|
+
limit: optional(Integer({ minimum: 1, maximum: 100 }), "[list_releases/get_history] Page size, default 50/20"),
|
|
187609
187755
|
offset: optional(Integer({ minimum: 0, maximum: 1e6 }), "[logs] Result offset"),
|
|
187610
187756
|
service: optional(String2(), "[logs] Application target/service filter"),
|
|
187611
187757
|
search: optional(String2(), "[logs] Full-text log filter"),
|
|
@@ -187636,6 +187782,84 @@ function boundRelease(value, ref, id) {
|
|
|
187636
187782
|
throw new Error("Unbound application release");
|
|
187637
187783
|
return release;
|
|
187638
187784
|
}
|
|
187785
|
+
async function readDeployPlan(http, args, project) {
|
|
187786
|
+
const ref = text(args, "ref"), id = text(args, "id"), environmentId = text(args, "environment_id");
|
|
187787
|
+
const releaseId = text(args, "release_id"), configurationId = text(args, "configuration_id");
|
|
187788
|
+
if (!Check2(ApplicationIdSchema2, environmentId) || !Check2(ApplicationReleaseIdSchema2, releaseId) || !Check2(ApplicationConfigurationIdSchema2, configurationId))
|
|
187789
|
+
throw new Error("Invalid deployment plan identity");
|
|
187790
|
+
const identity = {
|
|
187791
|
+
project_ref: ref,
|
|
187792
|
+
application_id: id,
|
|
187793
|
+
environment_id: environmentId,
|
|
187794
|
+
release_id: releaseId,
|
|
187795
|
+
configuration_id: configurationId
|
|
187796
|
+
};
|
|
187797
|
+
const query = new URLSearchParams({ release_id: releaseId, configuration_id: configurationId });
|
|
187798
|
+
const response = await http.get(`/v1/projects/${project}/applications/${encodeURIComponent(id)}/environments/${encodeURIComponent(environmentId)}/deploy-plan?${query}`, { maxJsonBytes: 65536, responseTimeoutMs: 30000 });
|
|
187799
|
+
const operation = `applications.${text(args, "action")}`;
|
|
187800
|
+
if (!response.ok)
|
|
187801
|
+
return { failure: releaseControlFailure(operation, "HTTP_ERROR", response.transportError ? null : response.status, identity) };
|
|
187802
|
+
let plan;
|
|
187803
|
+
try {
|
|
187804
|
+
if (response.status !== 200)
|
|
187805
|
+
throw new Error("Incomplete deployment plan response");
|
|
187806
|
+
plan = parseApplicationDeployPlan(response.data);
|
|
187807
|
+
if (plan.project_ref !== ref || plan.application_id !== id || plan.environment_id !== environmentId || plan.candidate.release_id !== releaseId || plan.candidate.configuration_id !== configurationId)
|
|
187808
|
+
throw new Error;
|
|
187809
|
+
} catch {
|
|
187810
|
+
return { failure: releaseControlFailure(operation, "INVALID_RESPONSE", response.status, identity) };
|
|
187811
|
+
}
|
|
187812
|
+
return { plan, identity };
|
|
187813
|
+
}
|
|
187814
|
+
async function deployAction(http, args, project) {
|
|
187815
|
+
const activationId = args["activation_id"], expected = args["expected_activation_id"];
|
|
187816
|
+
if (activationId !== undefined && !Check2(ApplicationActivationIdSchema2, activationId)) {
|
|
187817
|
+
throw new Error("Invalid application activation ID");
|
|
187818
|
+
}
|
|
187819
|
+
if (expected !== undefined && expected !== null && expected !== "absent" && !Check2(ApplicationActivationIdSchema2, expected))
|
|
187820
|
+
throw new Error("Invalid expected activation ID");
|
|
187821
|
+
if (activationId !== undefined && expected !== undefined) {
|
|
187822
|
+
return activationAction(http, { ...args, action: "activate_release" }, project, {
|
|
187823
|
+
operation: "applications.deploy_release",
|
|
187824
|
+
configuration_id: args["configuration_id"],
|
|
187825
|
+
expected_activation_id: expected === "absent" ? null : expected
|
|
187826
|
+
});
|
|
187827
|
+
}
|
|
187828
|
+
const observed = await readDeployPlan(http, args, project);
|
|
187829
|
+
if (observed.failure)
|
|
187830
|
+
return observed.failure;
|
|
187831
|
+
const { plan, identity } = observed;
|
|
187832
|
+
if (expected !== undefined && (expected === "absent" ? null : expected) !== plan.expected_activation_id) {
|
|
187833
|
+
return releaseControlFailure("applications.deploy_release", "HTTP_ERROR", 409, {
|
|
187834
|
+
...identity,
|
|
187835
|
+
reason: "EXPECTED_ACTIVATION_CONFLICT",
|
|
187836
|
+
expected_activation_id: plan.expected_activation_id
|
|
187837
|
+
});
|
|
187838
|
+
}
|
|
187839
|
+
if (plan.action === "no-op")
|
|
187840
|
+
return releaseControlSuccess("applications.deploy_release", {
|
|
187841
|
+
...identity,
|
|
187842
|
+
no_op: true,
|
|
187843
|
+
execution_performed: false,
|
|
187844
|
+
activation_id: plan.current.activation_id,
|
|
187845
|
+
expected_activation_id: plan.expected_activation_id,
|
|
187846
|
+
plan,
|
|
187847
|
+
...activationId === undefined ? {} : { requested_activation_id: activationId }
|
|
187848
|
+
});
|
|
187849
|
+
const selectedId = activationId ?? crypto.randomUUID();
|
|
187850
|
+
if (selectedId === plan.expected_activation_id)
|
|
187851
|
+
throw new Error("Deployment requires a new activation ID");
|
|
187852
|
+
return activationAction(http, {
|
|
187853
|
+
...args,
|
|
187854
|
+
action: "activate_release",
|
|
187855
|
+
activation_id: selectedId,
|
|
187856
|
+
expected_activation_id: plan.expected_activation_id
|
|
187857
|
+
}, project, {
|
|
187858
|
+
operation: "applications.deploy_release",
|
|
187859
|
+
configuration_id: args["configuration_id"],
|
|
187860
|
+
expected_activation_id: plan.expected_activation_id
|
|
187861
|
+
});
|
|
187862
|
+
}
|
|
187639
187863
|
async function configurationAction(http, args, project) {
|
|
187640
187864
|
const action = text(args, "action"), ref = text(args, "ref"), id = text(args, "id");
|
|
187641
187865
|
const environmentId = text(args, "environment_id"), operation = `applications.${action}`;
|
|
@@ -187682,7 +187906,7 @@ async function configurationAction(http, args, project) {
|
|
|
187682
187906
|
return releaseControlFailure(operation, action === "put_configuration" ? "OUTCOME_UNKNOWN" : "INVALID_RESPONSE", result.status, identity);
|
|
187683
187907
|
}
|
|
187684
187908
|
}
|
|
187685
|
-
async function activationAction(http, args, project) {
|
|
187909
|
+
async function activationAction(http, args, project, selection) {
|
|
187686
187910
|
const action = text(args, "action"), ref = text(args, "ref"), id = text(args, "id");
|
|
187687
187911
|
const environmentId = text(args, "environment_id"), activationId = text(args, "activation_id");
|
|
187688
187912
|
const releaseId = args["release_id"] === undefined ? undefined : text(args, "release_id");
|
|
@@ -187692,7 +187916,7 @@ async function activationAction(http, args, project) {
|
|
|
187692
187916
|
if (!Check2(ApplicationIdSchema2, environmentId) || !Check2(ApplicationActivationIdSchema2, activationId) || action !== "retire_activation" && !Check2(ApplicationReleaseIdSchema2, releaseId)) {
|
|
187693
187917
|
throw new Error("Invalid application activation identity");
|
|
187694
187918
|
}
|
|
187695
|
-
const operation = `applications.${action}`;
|
|
187919
|
+
const operation = selection?.operation ?? `applications.${action}`;
|
|
187696
187920
|
const path = `/v1/projects/${project}/applications/${encodeURIComponent(id)}/environments/${encodeURIComponent(environmentId)}/activations`;
|
|
187697
187921
|
const identity = {
|
|
187698
187922
|
project_ref: ref,
|
|
@@ -187701,6 +187925,11 @@ async function activationAction(http, args, project) {
|
|
|
187701
187925
|
activation_id: activationId,
|
|
187702
187926
|
...releaseId ? { release_id: releaseId } : {}
|
|
187703
187927
|
};
|
|
187928
|
+
const selectedState = selection ? {
|
|
187929
|
+
configuration_id: selection.configuration_id,
|
|
187930
|
+
expected_activation_id: selection.expected_activation_id
|
|
187931
|
+
} : {};
|
|
187932
|
+
const safeState = { ...identity, ...selectedState };
|
|
187704
187933
|
let body = {};
|
|
187705
187934
|
if (action === "activate_release") {
|
|
187706
187935
|
body = {
|
|
@@ -187715,7 +187944,9 @@ async function activationAction(http, args, project) {
|
|
|
187715
187944
|
const endpoint = action === "activate_release" ? path : `${path}/${activationId}/${action === "retire_activation" ? "retire" : "reconcile"}`;
|
|
187716
187945
|
const result = await http.post(endpoint, body, { timeoutMs: 120000, maxJsonBytes: 65536, responseTimeoutMs: 30000 });
|
|
187717
187946
|
if (!result.ok)
|
|
187718
|
-
return releaseControlMutationFailure(operation, result,
|
|
187947
|
+
return releaseControlMutationFailure(operation, result, safeState);
|
|
187948
|
+
if (result.status !== 200)
|
|
187949
|
+
return releaseControlFailure(operation, "OUTCOME_UNKNOWN", result.status, safeState);
|
|
187719
187950
|
if (action === "retire_activation") {
|
|
187720
187951
|
if (!Check2(ApplicationActivationRetirementResultSchema2, result.data) || Object.entries(identity).some(([key, value]) => Reflect.get(result.data, key) !== value)) {
|
|
187721
187952
|
return releaseControlFailure(operation, "OUTCOME_UNKNOWN", result.status, identity);
|
|
@@ -187723,9 +187954,88 @@ async function activationAction(http, args, project) {
|
|
|
187723
187954
|
return releaseControlSuccess(operation, result.data);
|
|
187724
187955
|
}
|
|
187725
187956
|
if (!Check2(ApplicationActivationResultSchema2, result.data) || Object.entries(identity).some(([key, value]) => Reflect.get(result.data, key) !== value) || action === "reconcile_activation" && !result.data.replayed) {
|
|
187726
|
-
return releaseControlFailure(operation, "OUTCOME_UNKNOWN", result.status,
|
|
187957
|
+
return releaseControlFailure(operation, "OUTCOME_UNKNOWN", result.status, safeState);
|
|
187958
|
+
}
|
|
187959
|
+
return releaseControlSuccess(operation, { ...result.data, ...selectedState });
|
|
187960
|
+
}
|
|
187961
|
+
async function rollbackAction(http, args, project) {
|
|
187962
|
+
const ref = text(args, "ref"), id = text(args, "id"), environmentId = text(args, "environment_id");
|
|
187963
|
+
if (!Check2(ApplicationIdSchema2, environmentId))
|
|
187964
|
+
throw new Error("Invalid environment ID");
|
|
187965
|
+
const operation = `applications.${text(args, "action")}`;
|
|
187966
|
+
const identity = { project_ref: ref, application_id: id, environment_id: environmentId };
|
|
187967
|
+
let activationId = args["activation_id"];
|
|
187968
|
+
if (activationId !== undefined && !Check2(ApplicationActivationIdSchema2, activationId)) {
|
|
187969
|
+
throw new Error("Invalid application activation ID");
|
|
187970
|
+
}
|
|
187971
|
+
let releaseId = args["release_id"], configurationId = args["configuration_id"];
|
|
187972
|
+
let expectedActivationId = args["expected_activation_id"];
|
|
187973
|
+
if (releaseId === undefined || args["action"] === "get_rollback_snapshot") {
|
|
187974
|
+
if (releaseId !== undefined || configurationId !== undefined || expectedActivationId !== undefined) {
|
|
187975
|
+
throw new Error("Default rollback selection cannot mix explicit release/configuration/CAS flags");
|
|
187976
|
+
}
|
|
187977
|
+
const response = await http.get(`/v1/projects/${project}/applications/${encodeURIComponent(id)}/environments/${encodeURIComponent(environmentId)}/rollback-snapshot`, { maxJsonBytes: 65536, responseTimeoutMs: 30000 });
|
|
187978
|
+
if (!response.ok)
|
|
187979
|
+
return releaseControlFailure(operation, "HTTP_ERROR", response.transportError ? null : response.status, identity);
|
|
187980
|
+
const snapshot = response.data;
|
|
187981
|
+
if (response.status !== 200 || !Check2(ApplicationRollbackSnapshotSchema2, snapshot) || snapshot.project_ref !== ref || snapshot.application_id !== id || snapshot.environment_id !== environmentId || snapshot.previous !== null && (snapshot.active === null || snapshot.previous.activation_id === snapshot.active.activation_id)) {
|
|
187982
|
+
return releaseControlFailure(operation, "INVALID_RESPONSE", response.status, identity);
|
|
187983
|
+
}
|
|
187984
|
+
if (args["action"] === "get_rollback_snapshot")
|
|
187985
|
+
return releaseControlSuccess(operation, { ...identity, snapshot });
|
|
187986
|
+
if (!snapshot.active || !snapshot.previous) {
|
|
187987
|
+
return releaseControlFailure(operation, "MUTATION_NOT_SUCCEEDED", response.status, {
|
|
187988
|
+
...identity,
|
|
187989
|
+
reason: "NO_PREVIOUS_ACTIVATION"
|
|
187990
|
+
});
|
|
187991
|
+
}
|
|
187992
|
+
if (activationId === snapshot.active.activation_id || activationId === snapshot.previous.activation_id) {
|
|
187993
|
+
throw new Error("Rollback requires a new activation ID");
|
|
187994
|
+
}
|
|
187995
|
+
releaseId = snapshot.previous.release_id;
|
|
187996
|
+
configurationId = snapshot.previous.configuration_id;
|
|
187997
|
+
expectedActivationId = snapshot.active.activation_id;
|
|
187998
|
+
}
|
|
187999
|
+
activationId ??= crypto.randomUUID();
|
|
188000
|
+
return activationAction(http, {
|
|
188001
|
+
...args,
|
|
188002
|
+
action: "activate_release",
|
|
188003
|
+
activation_id: activationId,
|
|
188004
|
+
release_id: releaseId,
|
|
188005
|
+
configuration_id: configurationId,
|
|
188006
|
+
expected_activation_id: expectedActivationId
|
|
188007
|
+
}, project, {
|
|
188008
|
+
operation: "applications.rollback_release",
|
|
188009
|
+
configuration_id: configurationId,
|
|
188010
|
+
expected_activation_id: expectedActivationId === "absent" ? null : expectedActivationId
|
|
188011
|
+
});
|
|
188012
|
+
}
|
|
188013
|
+
async function historyAction(http, args, project) {
|
|
188014
|
+
const ref = text(args, "ref"), id = text(args, "id"), environmentId = text(args, "environment_id");
|
|
188015
|
+
if (!Check2(ApplicationIdSchema2, environmentId))
|
|
188016
|
+
throw new Error("Invalid environment ID");
|
|
188017
|
+
const limit = args["limit"] ?? 20, cursor = args["cursor"];
|
|
188018
|
+
if (typeof limit !== "number" || !Number.isInteger(limit) || limit < 1 || limit > 100 || cursor !== undefined && typeof cursor !== "string")
|
|
188019
|
+
throw new Error("Invalid history page");
|
|
188020
|
+
const query = new URLSearchParams({ limit: String(limit) });
|
|
188021
|
+
const scope = { project_ref: ref, application_id: id, environment_id: environmentId };
|
|
188022
|
+
const before = typeof cursor === "string" ? parseApplicationHistoryCursor(cursor, scope) : null;
|
|
188023
|
+
if (typeof cursor === "string")
|
|
188024
|
+
query.set("cursor", cursor);
|
|
188025
|
+
const operation = "applications.get_history";
|
|
188026
|
+
const response = await http.get(`/v1/projects/${project}/applications/${encodeURIComponent(id)}/environments/${encodeURIComponent(environmentId)}/history?${query}`, { maxJsonBytes: 262144, responseTimeoutMs: 30000 });
|
|
188027
|
+
if (!response.ok)
|
|
188028
|
+
return releaseControlFailure(operation, "HTTP_ERROR", response.transportError ? null : response.status, scope);
|
|
188029
|
+
try {
|
|
188030
|
+
if (response.status !== 200)
|
|
188031
|
+
throw new Error;
|
|
188032
|
+
const history = parseApplicationActivationHistory(response.data);
|
|
188033
|
+
if (history.project_ref !== ref || history.application_id !== id || history.environment_id !== environmentId || history.activations.length > limit || history.next_cursor !== null && history.activations.length !== limit || before && history.activations.some((entry) => !applicationHistoryPositionBefore(entry, before)))
|
|
188034
|
+
throw new Error;
|
|
188035
|
+
return releaseControlSuccess(operation, { project_ref: ref, application_id: id, environment_id: environmentId, history });
|
|
188036
|
+
} catch {
|
|
188037
|
+
return releaseControlFailure(operation, "INVALID_RESPONSE", response.status, scope);
|
|
187727
188038
|
}
|
|
187728
|
-
return releaseControlSuccess(operation, result.data);
|
|
187729
188039
|
}
|
|
187730
188040
|
function registerApplicationTools(server2, http) {
|
|
187731
188041
|
registerTool(server2, "applications", "Store, inspect and explicitly activate immutable HTTP/Worker application releases. Upload does not activate a release.", APPLICATION_TOOL_SCHEMA, async (args) => {
|
|
@@ -187735,6 +188045,17 @@ function registerApplicationTools(server2, http) {
|
|
|
187735
188045
|
throw new Error("Invalid application ID");
|
|
187736
188046
|
const path = `/v1/projects/${project}/applications/${encodeURIComponent(id)}/releases`;
|
|
187737
188047
|
const operation = `applications.${action}`;
|
|
188048
|
+
if (action === "get_deploy_plan") {
|
|
188049
|
+
const observed = await readDeployPlan(http, args, project);
|
|
188050
|
+
return observed.failure ?? releaseControlSuccess(operation, { ...observed.identity, plan: observed.plan });
|
|
188051
|
+
}
|
|
188052
|
+
if (action === "deploy_release")
|
|
188053
|
+
return deployAction(http, args, project);
|
|
188054
|
+
if (action === "rollback_release" || action === "get_rollback_snapshot") {
|
|
188055
|
+
return rollbackAction(http, args, project);
|
|
188056
|
+
}
|
|
188057
|
+
if (action === "get_history")
|
|
188058
|
+
return historyAction(http, args, project);
|
|
187738
188059
|
if (APPLICATION_PREVIEW_ACTIONS.some((value) => value === action)) {
|
|
187739
188060
|
return applicationPreviewAction(http, args, project);
|
|
187740
188061
|
}
|
|
@@ -193979,9 +194300,13 @@ async function applyScaffoldWrites(plan) {
|
|
|
193979
194300
|
var REMOTE_APP_ACTIONS = {
|
|
193980
194301
|
upload: "upload_release",
|
|
193981
194302
|
configure: "put_configuration",
|
|
193982
|
-
deploy: "
|
|
194303
|
+
deploy: "deploy_release",
|
|
194304
|
+
"deploy-plan": "get_deploy_plan",
|
|
194305
|
+
diff: "get_deploy_plan",
|
|
193983
194306
|
status: "get_runtime",
|
|
193984
|
-
rollback: "
|
|
194307
|
+
rollback: "rollback_release",
|
|
194308
|
+
"rollback-plan": "get_rollback_snapshot",
|
|
194309
|
+
history: "get_history",
|
|
193985
194310
|
reconcile: "reconcile_activation",
|
|
193986
194311
|
retire: "retire_activation",
|
|
193987
194312
|
logs: "logs",
|
|
@@ -193992,22 +194317,24 @@ var REMOTE_APP_ACTIONS = {
|
|
|
193992
194317
|
"preview-cleanup": "cleanup_preview"
|
|
193993
194318
|
};
|
|
193994
194319
|
var REMOTE_APP_DESCRIPTIONS = {
|
|
193995
|
-
ref: "[upload/configure/deploy/status/rollback/reconcile/retire/preview-plan/preview/previews/preview-status/preview-cleanup] Project ref (defaults to context)",
|
|
193996
|
-
id: "[upload/configure/deploy/status/rollback/reconcile/retire/preview-plan/preview/previews/preview-status/preview-cleanup] Application ID",
|
|
193997
|
-
environment_id: "[configure/deploy/status/rollback/reconcile/retire/preview-plan/preview/previews/preview-status/preview-cleanup] Environment ID",
|
|
193998
|
-
configuration_id: "[deploy/rollback/preview] Required
|
|
193999
|
-
activation_id: "[deploy/rollback/reconcile/retire]
|
|
194000
|
-
expected_activation_id: "[deploy/rollback]
|
|
194320
|
+
ref: "[upload/configure/deploy/deploy-plan/diff/status/rollback/rollback-plan/history/reconcile/retire/preview-plan/preview/previews/preview-status/preview-cleanup] Project ref (defaults to context)",
|
|
194321
|
+
id: "[upload/configure/deploy/deploy-plan/diff/status/rollback/rollback-plan/history/reconcile/retire/preview-plan/preview/previews/preview-status/preview-cleanup] Application ID",
|
|
194322
|
+
environment_id: "[configure/deploy/deploy-plan/diff/status/rollback/rollback-plan/history/reconcile/retire/preview-plan/preview/previews/preview-status/preview-cleanup] Environment ID",
|
|
194323
|
+
configuration_id: "[deploy/deploy-plan/diff/rollback/preview] Required for deployment/preview; platform selects for default rollback",
|
|
194324
|
+
activation_id: "[deploy/rollback/reconcile/retire] Stable activation ID; auto-generated for deploy/rollback if omitted",
|
|
194325
|
+
expected_activation_id: "[deploy/rollback] Auto-selected from verified state; supply with activation_id for an exact retry",
|
|
194001
194326
|
configuration_path: "[configure] Configuration write JSON including revision and expected revision",
|
|
194002
194327
|
manifest_path: "[upload] Local delivery.manifest.json",
|
|
194003
|
-
release_id: "[deploy/rollback/reconcile/preview-plan/preview] Required
|
|
194328
|
+
release_id: "[deploy/deploy-plan/diff/rollback/reconcile/preview-plan/preview] Required for deployment/preview; defaults to journal-selected previous for rollback",
|
|
194004
194329
|
preview_id: "[preview-status/preview-cleanup] Preview receipt ID",
|
|
194005
194330
|
branch_ref: "[preview-plan] Proposed branch ref; preview assigns its own",
|
|
194006
194331
|
branch_name: "[preview] Branch display name",
|
|
194007
194332
|
data_mode: "[preview-plan/preview] Default schema_only; full_clone copies rows",
|
|
194008
194333
|
ttl_seconds: "[preview-plan/preview] Lifetime from 300 to 604800 seconds; creation defaults to the platform TTL",
|
|
194009
194334
|
wait: "[preview/preview-status] Wait for verified readiness of the selected preview",
|
|
194010
|
-
timeout_seconds: "[preview/preview-status] Observation budget with --wait, from 1 to 3600 seconds (default 300)"
|
|
194335
|
+
timeout_seconds: "[preview/preview-status] Observation budget with --wait, from 1 to 3600 seconds (default 300)",
|
|
194336
|
+
cursor: "[history] Returned page cursor",
|
|
194337
|
+
limit: "[history] Page size, default 20 (1-100)"
|
|
194011
194338
|
};
|
|
194012
194339
|
var { action: _remoteAction, ...remoteFields } = APPLICATION_TOOL_SCHEMA;
|
|
194013
194340
|
var REMOTE_APP_SCHEMA = Partial(_Object_(remoteFields)).properties;
|
|
@@ -194906,6 +195233,75 @@ async function runDelivery(args) {
|
|
|
194906
195233
|
const result = await buildDeliveryProject(options, loaded.delivery);
|
|
194907
195234
|
return textResult(JSON.stringify(result, null, 2), !result.ok);
|
|
194908
195235
|
}
|
|
195236
|
+
var historyReceiptSchema = _Object_({
|
|
195237
|
+
schema: Literal(RELEASE_CONTROL_RESPONSE_SCHEMA),
|
|
195238
|
+
ok: Literal(true),
|
|
195239
|
+
operation: Literal("applications.get_history"),
|
|
195240
|
+
project_ref: String2(),
|
|
195241
|
+
application_id: String2(),
|
|
195242
|
+
environment_id: String2(),
|
|
195243
|
+
history: ApplicationActivationHistorySchema
|
|
195244
|
+
}, { additionalProperties: false });
|
|
195245
|
+
function historyText(result, request, projectRef) {
|
|
195246
|
+
if (result.isError)
|
|
195247
|
+
return result;
|
|
195248
|
+
try {
|
|
195249
|
+
if (result.content.length !== 1 || result.content[0].text.length > 262144)
|
|
195250
|
+
throw new Error;
|
|
195251
|
+
const receipt = JSON.parse(result.content[0].text);
|
|
195252
|
+
if (!Check2(historyReceiptSchema, receipt))
|
|
195253
|
+
throw new Error;
|
|
195254
|
+
const history = parseApplicationActivationHistory(receipt.history);
|
|
195255
|
+
if (history.project_ref !== projectRef || history.application_id !== request.id || history.environment_id !== request.environment_id || receipt.project_ref !== history.project_ref || receipt.application_id !== history.application_id || receipt.environment_id !== history.environment_id)
|
|
195256
|
+
throw new Error;
|
|
195257
|
+
const lines = [
|
|
195258
|
+
`Activation History: ${history.project_ref}/${history.application_id}/${history.environment_id}`,
|
|
195259
|
+
`Active activation: ${history.active_activation_id ?? "none"}`,
|
|
195260
|
+
""
|
|
195261
|
+
];
|
|
195262
|
+
if (history.activations.length === 0)
|
|
195263
|
+
lines.push("No successful activations on this page.");
|
|
195264
|
+
else {
|
|
195265
|
+
lines.push(`${"Completed (UTC)".padEnd(29)} ${"State".padEnd(7)} ${"Activation ID".padEnd(36)} Release (12)`);
|
|
195266
|
+
for (const entry of history.activations)
|
|
195267
|
+
lines.push(`${entry.completed_at.padEnd(29)} ${(entry.is_active ? "current" : "-").padEnd(7)} ${entry.activation_id} ${entry.release_id.slice(0, 12)}`);
|
|
195268
|
+
}
|
|
195269
|
+
if (history.next_cursor)
|
|
195270
|
+
lines.push("", `Next cursor: ${history.next_cursor}`);
|
|
195271
|
+
return textResult(lines.join(`
|
|
195272
|
+
`));
|
|
195273
|
+
} catch {
|
|
195274
|
+
return releaseControlFailure("applications.get_history", "INVALID_RESPONSE", null);
|
|
195275
|
+
}
|
|
195276
|
+
}
|
|
195277
|
+
function formatRemoteDeployPlan(result) {
|
|
195278
|
+
if (result.isError)
|
|
195279
|
+
return result;
|
|
195280
|
+
try {
|
|
195281
|
+
const payload = JSON.parse(result.content[0]?.text ?? "");
|
|
195282
|
+
if (!payload || typeof payload !== "object" || !("ok" in payload) || payload.ok !== true || !("plan" in payload))
|
|
195283
|
+
return result;
|
|
195284
|
+
const plan = parseApplicationDeployPlan(payload.plan);
|
|
195285
|
+
const names = (values, prefix) => values.map((name) => `${prefix}${name}`);
|
|
195286
|
+
const targets = [
|
|
195287
|
+
...names(plan.changes.targets.added, "+"),
|
|
195288
|
+
...names(plan.changes.targets.removed, "-"),
|
|
195289
|
+
...names(plan.changes.targets.changed, "~")
|
|
195290
|
+
];
|
|
195291
|
+
return textResult([
|
|
195292
|
+
`${plan.project_ref}/${plan.application_id} [${plan.environment_id}]: ${plan.action === "no-op" ? "No changes" : "Activation required"}`,
|
|
195293
|
+
`Release: ${plan.candidate.release_id} (${plan.changes.release ? "changed" : "unchanged"})`,
|
|
195294
|
+
`Configuration: ${plan.candidate.configuration_id} (${plan.changes.configuration ? "changed" : "unchanged"})`,
|
|
195295
|
+
`Targets: ${targets.length ? targets.join(", ") : "unchanged"}`,
|
|
195296
|
+
`Migrations: ${!plan.migrations.ledger_compatible ? "ledger conflict" : plan.migrations.project_migrations_applied ? "applied" : "pending"}`,
|
|
195297
|
+
`Provisioning: ${plan.migrations.operator_provisioning}`,
|
|
195298
|
+
`Expected activation: ${plan.expected_activation_id ?? "absent"}`
|
|
195299
|
+
].join(`
|
|
195300
|
+
`));
|
|
195301
|
+
} catch {
|
|
195302
|
+
return result;
|
|
195303
|
+
}
|
|
195304
|
+
}
|
|
194909
195305
|
async function runAppTool(request, options = {}) {
|
|
194910
195306
|
if (request.dry_run !== undefined && request["dry-run"] !== undefined || request.register_in !== undefined && request["register-in"] !== undefined || request.database_url !== undefined && request["database-url"] !== undefined) {
|
|
194911
195307
|
throw new ScaffoldError("SCAFFOLD_OPTION_INVALID", "Do not combine hyphenated and underscored aliases of the same flag");
|
|
@@ -194922,18 +195318,26 @@ async function runAppTool(request, options = {}) {
|
|
|
194922
195318
|
if (request.database_url !== undefined && request.action !== "dev" && request.action !== "watch") {
|
|
194923
195319
|
throw new ScaffoldError("SCAFFOLD_OPTION_INVALID", "--database-url applies only to app dev --profile integration");
|
|
194924
195320
|
}
|
|
195321
|
+
if (request.json !== undefined && (request.action !== "history" || request.json !== true || request.format === "text")) {
|
|
195322
|
+
throw new Error("--json applies only to app history and cannot be combined with --format text");
|
|
195323
|
+
}
|
|
194925
195324
|
if (Object.hasOwn(REMOTE_APP_ACTIONS, request.action)) {
|
|
194926
195325
|
const delegate = options.getApplications?.();
|
|
194927
195326
|
if (!delegate)
|
|
194928
195327
|
return textResult("App remote actions require a Management API context.", true);
|
|
194929
195328
|
const action = REMOTE_APP_ACTIONS[request.action];
|
|
195329
|
+
const { format, json, ...remoteRequest } = request;
|
|
194930
195330
|
const args = {
|
|
194931
|
-
...
|
|
195331
|
+
...remoteRequest,
|
|
194932
195332
|
action,
|
|
194933
195333
|
ref: request.ref ?? options.projectRef
|
|
194934
195334
|
};
|
|
194935
195335
|
validateToolArguments(APPLICATION_TOOL_SCHEMA, args);
|
|
194936
|
-
|
|
195336
|
+
const result = await delegate(args);
|
|
195337
|
+
if (request.action === "history" && format !== "json" && json !== true) {
|
|
195338
|
+
return historyText(result, request, args.ref);
|
|
195339
|
+
}
|
|
195340
|
+
return (request.action === "deploy-plan" || request.action === "diff") && format !== "json" ? formatRemoteDeployPlan(result) : result;
|
|
194937
195341
|
}
|
|
194938
195342
|
switch (request.action) {
|
|
194939
195343
|
case "verify-plan": {
|
|
@@ -195008,8 +195412,12 @@ function registerAppTools(server2, options = {}) {
|
|
|
195008
195412
|
"upload",
|
|
195009
195413
|
"configure",
|
|
195010
195414
|
"deploy",
|
|
195415
|
+
"deploy-plan",
|
|
195416
|
+
"diff",
|
|
195011
195417
|
"status",
|
|
195012
195418
|
"rollback",
|
|
195419
|
+
"rollback-plan",
|
|
195420
|
+
"history",
|
|
195013
195421
|
"reconcile",
|
|
195014
195422
|
"retire",
|
|
195015
195423
|
"logs",
|
|
@@ -195018,7 +195426,7 @@ function registerAppTools(server2, options = {}) {
|
|
|
195018
195426
|
"previews",
|
|
195019
195427
|
"preview-status",
|
|
195020
195428
|
"preview-cleanup"
|
|
195021
|
-
]), "App action;
|
|
195429
|
+
]), "App action; local plan is topology-only, deploy-plan/diff observe remote state, deploy skips verified no-op, rollback never downgrades schema"),
|
|
195022
195430
|
kind: optional(stringEnum(["module", "command", "query", "controller", "job", "contract", "resource"]), "[generate] Scaffold kind"),
|
|
195023
195431
|
template: optional(stringEnum(["minimal", "http", "command", "edge"]), "[init] Minimal application by default; explicit http/command/edge recipes"),
|
|
195024
195432
|
name: optional(String2(), "[init/generate] Project or object name"),
|
|
@@ -195033,7 +195441,8 @@ function registerAppTools(server2, options = {}) {
|
|
|
195033
195441
|
include: optional(String2(), "[dev/compile/check] Comma-separated glob patterns for source files"),
|
|
195034
195442
|
out_dir: optional(String2(), "[dev/compile/plan/build/export-tools] Output directory (default: configured outDir)"),
|
|
195035
195443
|
strict: optional(Boolean2(), "[dev/compile/check] Promote warnings to errors"),
|
|
195036
|
-
format: optional(stringEnum(["text", "json"]), "[dev/generate/compile/check/plan/graph/export-tools] Output format (default: text)"),
|
|
195444
|
+
format: optional(stringEnum(["text", "json"]), "[dev/generate/compile/check/plan/deploy-plan/diff/history/graph/export-tools] Output format (default: text)"),
|
|
195445
|
+
json: optional(Literal(true), "[history] Return the validated JSON receipt"),
|
|
195037
195446
|
profile: optional(stringEnum(["fast", "integration"]), "[dev] Run dev or dev:integration; integration verifies an explicit loopback database"),
|
|
195038
195447
|
once: optional(Boolean2(), "[dev] Validate and report once without watching"),
|
|
195039
195448
|
watch: optional(Boolean2(), "[dev] Watch for changes (default: true; --once disables)"),
|
|
@@ -198585,7 +198994,7 @@ function registerRemoteDevTools(server2, options = {}) {
|
|
|
198585
198994
|
// package.json
|
|
198586
198995
|
var package_default = {
|
|
198587
198996
|
name: "@supacloud/cli",
|
|
198588
|
-
version: "0.
|
|
198997
|
+
version: "0.80.0",
|
|
198589
198998
|
description: "Project-scoped CLI for SupaCloud users",
|
|
198590
198999
|
type: "module",
|
|
198591
199000
|
main: "./dist/index.js",
|
|
@@ -198637,14 +199046,14 @@ var package_default = {
|
|
|
198637
199046
|
},
|
|
198638
199047
|
dependencies: {
|
|
198639
199048
|
"@supacloud/compiler": "^0.43.0",
|
|
198640
|
-
"@supacloud/delivery": "0.
|
|
199049
|
+
"@supacloud/delivery": "0.10.0",
|
|
198641
199050
|
"@supacloud/db": "0.16.0",
|
|
198642
199051
|
fflate: "^0.8.3",
|
|
198643
199052
|
typebox: "1.3.34"
|
|
198644
199053
|
},
|
|
198645
199054
|
overrides: {
|
|
198646
199055
|
"@supacloud/contracts": "0.8.0",
|
|
198647
|
-
"@supacloud/delivery": "0.
|
|
199056
|
+
"@supacloud/delivery": "0.10.0",
|
|
198648
199057
|
"@graphql-tools/utils": "^12.0.3"
|
|
198649
199058
|
},
|
|
198650
199059
|
devDependencies: {
|
|
@@ -198905,7 +199314,9 @@ EXAMPLES
|
|
|
198905
199314
|
${preferredCommand} app build --root .
|
|
198906
199315
|
${preferredCommand} app upload --ref abc123 --id orders --manifest_path generated/delivery/delivery.manifest.json
|
|
198907
199316
|
${preferredCommand} app configure --ref abc123 --id orders --environment_id test --configuration_path configuration.json
|
|
198908
|
-
${preferredCommand} app deploy --ref abc123 --id orders --environment_id test --release_id <sha256> --configuration_id <uuid>
|
|
199317
|
+
${preferredCommand} app deploy-plan --ref abc123 --id orders --environment_id test --release_id <sha256> --configuration_id <uuid>
|
|
199318
|
+
${preferredCommand} app diff --ref abc123 --id orders --environment_id test --release_id <sha256> --configuration_id <uuid>
|
|
199319
|
+
${preferredCommand} app deploy --ref abc123 --id orders --environment_id test --release_id <sha256> --configuration_id <uuid>
|
|
198909
199320
|
${preferredCommand} app status --ref abc123 --id orders --environment_id test
|
|
198910
199321
|
${preferredCommand} app preview-plan --ref abc123 --id orders --environment_id test --release_id <sha256> --branch_ref preview-orders
|
|
198911
199322
|
${preferredCommand} app preview --ref abc123 --id orders --environment_id test --release_id <sha256> --configuration_id <uuid> --ttl_seconds 3600 --wait
|
|
@@ -3,9 +3,13 @@ import { type AppManifest } from "./app-tool-export";
|
|
|
3
3
|
declare const REMOTE_APP_ACTIONS: {
|
|
4
4
|
readonly upload: "upload_release";
|
|
5
5
|
readonly configure: "put_configuration";
|
|
6
|
-
readonly deploy: "
|
|
6
|
+
readonly deploy: "deploy_release";
|
|
7
|
+
readonly "deploy-plan": "get_deploy_plan";
|
|
8
|
+
readonly diff: "get_deploy_plan";
|
|
7
9
|
readonly status: "get_runtime";
|
|
8
|
-
readonly rollback: "
|
|
10
|
+
readonly rollback: "rollback_release";
|
|
11
|
+
readonly "rollback-plan": "get_rollback_snapshot";
|
|
12
|
+
readonly history: "get_history";
|
|
9
13
|
readonly reconcile: "reconcile_activation";
|
|
10
14
|
readonly retire: "retire_activation";
|
|
11
15
|
readonly logs: "logs";
|
|
@@ -34,6 +38,8 @@ export interface AppToolArguments {
|
|
|
34
38
|
configuration_path?: string;
|
|
35
39
|
manifest_path?: string;
|
|
36
40
|
release_id?: string;
|
|
41
|
+
cursor?: string;
|
|
42
|
+
limit?: number;
|
|
37
43
|
preview_id?: string;
|
|
38
44
|
branch_ref?: string;
|
|
39
45
|
branch_name?: string;
|
|
@@ -56,6 +62,7 @@ export interface AppToolArguments {
|
|
|
56
62
|
out_dir?: string;
|
|
57
63
|
strict?: boolean;
|
|
58
64
|
format?: "text" | "json";
|
|
65
|
+
json?: true;
|
|
59
66
|
target?: string;
|
|
60
67
|
fix?: string;
|
|
61
68
|
write?: boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -73,3 +73,20 @@ export declare const ApplicationActivationRetirementResultSchema: import("typebo
|
|
|
73
73
|
activation_id: import("typebox").TString;
|
|
74
74
|
retired_at: import("typebox").TString;
|
|
75
75
|
}>;
|
|
76
|
+
export declare const ApplicationRollbackSnapshotSchema: import("typebox").TObject<{
|
|
77
|
+
schema: import("typebox").TLiteral<"supacloud.application-rollback-snapshot.v1">;
|
|
78
|
+
project_ref: import("typebox").TString;
|
|
79
|
+
application_id: import("typebox").TString;
|
|
80
|
+
environment_id: import("typebox").TString;
|
|
81
|
+
active: import("typebox").TUnion<[import("typebox").TObject<{
|
|
82
|
+
release_id: import("typebox").TString;
|
|
83
|
+
configuration_id: import("typebox").TString;
|
|
84
|
+
activation_id: import("typebox").TString;
|
|
85
|
+
}>, import("typebox").TNull]>;
|
|
86
|
+
previous: import("typebox").TUnion<[import("typebox").TObject<{
|
|
87
|
+
release_id: import("typebox").TString;
|
|
88
|
+
configuration_id: import("typebox").TString;
|
|
89
|
+
activation_id: import("typebox").TString;
|
|
90
|
+
}>, import("typebox").TNull]>;
|
|
91
|
+
}>;
|
|
92
|
+
export declare const ApplicationActivationHistoryCursorSchema: import("typebox").TString;
|
|
@@ -9,7 +9,7 @@ export declare const APPLICATION_TOOL_SCHEMA: {
|
|
|
9
9
|
ttl_seconds: Type.TOptional<Type.TInteger>;
|
|
10
10
|
wait: Type.TOptional<Type.TBoolean>;
|
|
11
11
|
timeout_seconds: Type.TOptional<Type.TInteger>;
|
|
12
|
-
action: Type.TEnum<("list_releases" | "get_release" | "upload_release" | "activate_release" | "logs" | "get_runtime" | "get_deployment_evidence" | "get_configuration" | "get_preview_plan" | "put_configuration" | "reconcile_activation" | "retire_activation" | "create_preview" | "list_previews" | "get_preview" | "cleanup_preview")[]>;
|
|
12
|
+
action: Type.TEnum<("list_releases" | "get_release" | "upload_release" | "activate_release" | "logs" | "get_runtime" | "get_deployment_evidence" | "get_configuration" | "get_rollback_snapshot" | "get_history" | "get_deploy_plan" | "get_preview_plan" | "put_configuration" | "deploy_release" | "rollback_release" | "reconcile_activation" | "retire_activation" | "create_preview" | "list_previews" | "get_preview" | "cleanup_preview")[]>;
|
|
13
13
|
ref: Type.TString;
|
|
14
14
|
id: Type.TString;
|
|
15
15
|
environment_id: Type.TOptional<Type.TString>;
|
|
@@ -19,7 +19,7 @@ export declare const APPLICATION_TOOL_SCHEMA: {
|
|
|
19
19
|
configuration_path: Type.TOptional<Type.TString>;
|
|
20
20
|
manifest_path: Type.TOptional<Type.TString>;
|
|
21
21
|
release_id: Type.TOptional<Type.TString>;
|
|
22
|
-
cursor: Type.TOptional<Type.TString
|
|
22
|
+
cursor: Type.TOptional<Type.TUnion<[Type.TString, Type.TString]>>;
|
|
23
23
|
limit: Type.TOptional<Type.TInteger>;
|
|
24
24
|
offset: Type.TOptional<Type.TInteger>;
|
|
25
25
|
service: Type.TOptional<Type.TString>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@supacloud/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.80.0",
|
|
4
4
|
"description": "Project-scoped CLI for SupaCloud users",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -52,14 +52,14 @@
|
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@supacloud/compiler": "^0.43.0",
|
|
55
|
-
"@supacloud/delivery": "0.
|
|
55
|
+
"@supacloud/delivery": "0.10.0",
|
|
56
56
|
"@supacloud/db": "0.16.0",
|
|
57
57
|
"fflate": "^0.8.3",
|
|
58
58
|
"typebox": "1.3.34"
|
|
59
59
|
},
|
|
60
60
|
"overrides": {
|
|
61
61
|
"@supacloud/contracts": "0.8.0",
|
|
62
|
-
"@supacloud/delivery": "0.
|
|
62
|
+
"@supacloud/delivery": "0.10.0",
|
|
63
63
|
"@graphql-tools/utils": "^12.0.3"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|