@void/deploy-cloudflare 1.2.0 → 1.3.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.d.mts +8 -0
- package/dist/index.mjs +52 -19
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -87,6 +87,7 @@ type CloudflareOperation = ({
|
|
|
87
87
|
percentage: number;
|
|
88
88
|
}>;
|
|
89
89
|
message?: string;
|
|
90
|
+
bypassDeploymentChecks?: boolean;
|
|
90
91
|
} & WorkerTarget) | ({
|
|
91
92
|
type: "versions.upload" | "worker.deploy";
|
|
92
93
|
message?: string;
|
|
@@ -345,6 +346,12 @@ type CloudflareVersionActivation = {
|
|
|
345
346
|
versionId?: string;
|
|
346
347
|
previousVersionId?: string | null;
|
|
347
348
|
rollback?: "not-needed" | "succeeded" | "failed" | "unavailable" | "unsafe";
|
|
349
|
+
/**
|
|
350
|
+
* Cloudflare refused to restore the previous version because a secret
|
|
351
|
+
* changed with this deploy, so Void forced it. The previous version runs
|
|
352
|
+
* with its earlier secret values.
|
|
353
|
+
*/
|
|
354
|
+
restoredOlderSecrets?: true;
|
|
348
355
|
/** Version that owned production after a concurrent operation superseded this command. */
|
|
349
356
|
activeVersionId?: string | null;
|
|
350
357
|
/** Whether Void restored the active version's immutable trigger snapshot. */
|
|
@@ -474,6 +481,7 @@ export declare function deployCloudflareVersionTraffic(options: {
|
|
|
474
481
|
workerName: string;
|
|
475
482
|
percentages: Array<string>;
|
|
476
483
|
message: string;
|
|
484
|
+
bypassDeploymentChecks?: boolean;
|
|
477
485
|
}): Promise<CloudflareCommandResult>;
|
|
478
486
|
/** Normalize an account workers.dev subdomain supplied by config or the environment. */
|
|
479
487
|
export declare function normalizeWorkersDevSubdomain(value: string | undefined): string | undefined;
|
package/dist/index.mjs
CHANGED
|
@@ -799,6 +799,7 @@ function cloudflareCommandDiagnostic(result) {
|
|
|
799
799
|
//#endregion
|
|
800
800
|
//#region src/version.ts
|
|
801
801
|
const DURABLE_MIGRATION_VERSION_ERROR = 10211;
|
|
802
|
+
const CLOUDFLARE_SECRET_CHANGED_ERROR = 10220;
|
|
802
803
|
/** Encode migration state into Cloudflare's version annotation for safe rollback diagnostics. */
|
|
803
804
|
function encodeCloudflareVersionMessage(migrations, triggerConfig, contentHash) {
|
|
804
805
|
const metadata = triggerConfig ? {
|
|
@@ -1526,14 +1527,14 @@ async function activateCloudflareVersionWithSecretsFile(options) {
|
|
|
1526
1527
|
reason: ready === "access-denied" ? "readiness-access-denied" : "readiness-failed",
|
|
1527
1528
|
versionId,
|
|
1528
1529
|
previousVersionId: previous.versionId,
|
|
1529
|
-
|
|
1530
|
+
...stagedVersionOverride ? await restorePreviousVersion(options, previous.versionId, "readiness failed", [stagedVersionPercentages(previous.versionId, versionId)]) : { rollback: "not-needed" }
|
|
1530
1531
|
};
|
|
1531
1532
|
if (!options.verifyUploader()) return {
|
|
1532
1533
|
ok: false,
|
|
1533
1534
|
reason: "uploader-changed",
|
|
1534
1535
|
versionId,
|
|
1535
1536
|
previousVersionId: previous.versionId,
|
|
1536
|
-
|
|
1537
|
+
...stagedVersionOverride ? await restorePreviousVersion(options, previous.versionId, "uploader verification failed", [stagedVersionPercentages(previous.versionId, versionId)]) : { rollback: "not-needed" }
|
|
1537
1538
|
};
|
|
1538
1539
|
const ownerBeforeActivation = await readCurrentProductionVersion(options);
|
|
1539
1540
|
if (ownerBeforeActivation.kind === "failed") return {
|
|
@@ -1570,10 +1571,10 @@ async function activateCloudflareVersionWithSecretsFile(options) {
|
|
|
1570
1571
|
status: activate.status,
|
|
1571
1572
|
versionId,
|
|
1572
1573
|
previousVersionId: previous.versionId,
|
|
1573
|
-
|
|
1574
|
+
...stagedVersionOverride ? await restorePreviousVersion(options, previous.versionId, "version activation failed", [stagedVersionPercentages(previous.versionId, versionId), [{
|
|
1574
1575
|
versionId,
|
|
1575
1576
|
percentage: 100
|
|
1576
|
-
}]]) : "not-needed"
|
|
1577
|
+
}]]) : { rollback: "not-needed" }
|
|
1577
1578
|
};
|
|
1578
1579
|
if (!options.verifyUploader()) return {
|
|
1579
1580
|
ok: false,
|
|
@@ -1666,14 +1667,14 @@ async function activateCloudflareVersionWithSecretsFile(options) {
|
|
|
1666
1667
|
triggerRepair: triggerRepairOutcome(repair)
|
|
1667
1668
|
};
|
|
1668
1669
|
}
|
|
1669
|
-
const
|
|
1670
|
+
const restore = await restorePreviousVersionAndTriggers(options, previous.versionId, "trigger activation failed", desiredTriggerConfig, versionId, versionedPreviousTriggerConfigWithTraffic);
|
|
1670
1671
|
return {
|
|
1671
1672
|
ok: false,
|
|
1672
1673
|
reason: "triggers-failed",
|
|
1673
1674
|
status: triggers.status,
|
|
1674
1675
|
versionId,
|
|
1675
1676
|
previousVersionId: previous.versionId,
|
|
1676
|
-
|
|
1677
|
+
...restore
|
|
1677
1678
|
};
|
|
1678
1679
|
}
|
|
1679
1680
|
if (!triggers.targetOwnsTraffic) return {
|
|
@@ -1704,16 +1705,28 @@ async function restorePreviousVersionAndTriggers(options, previousVersionId, cau
|
|
|
1704
1705
|
versionId: failedVersionId,
|
|
1705
1706
|
percentage: 100
|
|
1706
1707
|
}]]);
|
|
1707
|
-
if (traffic !== "succeeded" || !previousVersionId) return traffic;
|
|
1708
|
-
if (!options.verifyUploader()) return
|
|
1708
|
+
if (traffic.rollback !== "succeeded" || !previousVersionId) return traffic;
|
|
1709
|
+
if (!options.verifyUploader()) return {
|
|
1710
|
+
...traffic,
|
|
1711
|
+
rollback: "unsafe"
|
|
1712
|
+
};
|
|
1709
1713
|
let targetTriggerConfig = capturedTriggerConfig;
|
|
1710
1714
|
if (!targetTriggerConfig) {
|
|
1711
1715
|
const metadata = await readCloudflareVersionMetadata(options, previousVersionId);
|
|
1712
|
-
if (metadata?.schema !== 2) return
|
|
1716
|
+
if (metadata?.schema !== 2) return {
|
|
1717
|
+
...traffic,
|
|
1718
|
+
rollback: "unavailable"
|
|
1719
|
+
};
|
|
1713
1720
|
targetTriggerConfig = metadata.triggerConfig;
|
|
1714
1721
|
}
|
|
1715
|
-
if (targetTriggerConfig.preserve) return
|
|
1716
|
-
|
|
1722
|
+
if (targetTriggerConfig.preserve) return {
|
|
1723
|
+
...traffic,
|
|
1724
|
+
rollback: "unavailable"
|
|
1725
|
+
};
|
|
1726
|
+
if (!options.verifyUploader()) return {
|
|
1727
|
+
...traffic,
|
|
1728
|
+
rollback: "unsafe"
|
|
1729
|
+
};
|
|
1717
1730
|
const triggers = await stabilizeCloudflareVersionTriggers({
|
|
1718
1731
|
runWrangler: options.runWrangler,
|
|
1719
1732
|
workerName: options.workerName,
|
|
@@ -1725,7 +1738,10 @@ async function restorePreviousVersionAndTriggers(options, previousVersionId, cau
|
|
|
1725
1738
|
publishEmptyCustomDomains: options.publishEmptyCustomDomains,
|
|
1726
1739
|
publishEmptyCrons: options.publishEmptyCrons
|
|
1727
1740
|
});
|
|
1728
|
-
return
|
|
1741
|
+
return {
|
|
1742
|
+
...traffic,
|
|
1743
|
+
rollback: triggers.ok && triggers.targetOwnsTraffic ? "succeeded" : "failed"
|
|
1744
|
+
};
|
|
1729
1745
|
}
|
|
1730
1746
|
async function readCloudflareVersionMetadata(options, versionId) {
|
|
1731
1747
|
return (await readCloudflareVersionInspection(options, versionId))?.metadata ?? null;
|
|
@@ -2236,7 +2252,8 @@ async function deployVersionPercentages(options, percentages, message) {
|
|
|
2236
2252
|
versions: versionPercentages(percentages),
|
|
2237
2253
|
configPath: options.configPath,
|
|
2238
2254
|
workerName: options.workerName,
|
|
2239
|
-
message
|
|
2255
|
+
message,
|
|
2256
|
+
...options.bypassDeploymentChecks ? { bypassDeploymentChecks: true } : {}
|
|
2240
2257
|
}, { capture: false });
|
|
2241
2258
|
}
|
|
2242
2259
|
/** Change version traffic without synchronizing Worker settings from local config. */
|
|
@@ -2251,7 +2268,8 @@ async function deployCloudflareVersionTraffic(options) {
|
|
|
2251
2268
|
versions: versionPercentages(options.percentages),
|
|
2252
2269
|
configPath: path,
|
|
2253
2270
|
workerName: options.workerName,
|
|
2254
|
-
message: options.message
|
|
2271
|
+
message: options.message,
|
|
2272
|
+
...options.bypassDeploymentChecks ? { bypassDeploymentChecks: true } : {}
|
|
2255
2273
|
}, { capture: false });
|
|
2256
2274
|
} finally {
|
|
2257
2275
|
rmSync(directory, {
|
|
@@ -2261,11 +2279,26 @@ async function deployCloudflareVersionTraffic(options) {
|
|
|
2261
2279
|
}
|
|
2262
2280
|
}
|
|
2263
2281
|
async function restorePreviousVersion(options, previousVersionId, cause, expectedOwnedTraffic) {
|
|
2264
|
-
if (!previousVersionId) return "unavailable";
|
|
2265
|
-
if (!options.verifyUploader()) return "unsafe";
|
|
2266
|
-
const
|
|
2267
|
-
|
|
2268
|
-
|
|
2282
|
+
if (!previousVersionId) return { rollback: "unavailable" };
|
|
2283
|
+
if (!options.verifyUploader()) return { rollback: "unsafe" };
|
|
2284
|
+
const ownsExpectedTraffic = async () => {
|
|
2285
|
+
const owner = await readCurrentProductionVersion(options);
|
|
2286
|
+
return owner.kind === "ok" && expectedOwnedTraffic.some((expected) => productionVersionPercentagesEqual(owner.versions, expected));
|
|
2287
|
+
};
|
|
2288
|
+
if (!await ownsExpectedTraffic()) return { rollback: "unsafe" };
|
|
2289
|
+
const restore = (bypassDeploymentChecks) => deployVersionPercentages({
|
|
2290
|
+
...options,
|
|
2291
|
+
bypassDeploymentChecks
|
|
2292
|
+
}, [`${previousVersionId}@100`], `Void automatic rollback after ${cause}.`);
|
|
2293
|
+
const result = await restore(false);
|
|
2294
|
+
if (result.errorCode === CLOUDFLARE_SECRET_CHANGED_ERROR) {
|
|
2295
|
+
if (!await ownsExpectedTraffic()) return { rollback: "unsafe" };
|
|
2296
|
+
return isCleanCommandExit(await restore(true)) ? {
|
|
2297
|
+
rollback: "succeeded",
|
|
2298
|
+
restoredOlderSecrets: true
|
|
2299
|
+
} : { rollback: "failed" };
|
|
2300
|
+
}
|
|
2301
|
+
return { rollback: isCleanCommandExit(result) ? "succeeded" : "failed" };
|
|
2269
2302
|
}
|
|
2270
2303
|
function workersDevReadinessUrl(workerName, value) {
|
|
2271
2304
|
const subdomain = normalizeWorkersDevSubdomain(value);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@void/deploy-cloudflare",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Cloudflare deployment primitives for Void runtimes and deployment adapters.",
|
|
5
5
|
"homepage": "https://void.cloud",
|
|
6
6
|
"bugs": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"access": "public"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@void/deploy-core": "1.
|
|
29
|
+
"@void/deploy-core": "1.3.0",
|
|
30
30
|
"jsonc-parser": "^3.3.1"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|