@hs-x/cli 0.3.0 → 0.3.6

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.
@@ -1,85 +0,0 @@
1
- /**
2
- * Traffic-first rollback orchestration (ADR-021 R04).
3
- *
4
- * A rollback restores live Cloudflare traffic to a verified prior Worker
5
- * *version* BEFORE any control-plane record moves. Given a membership-gated
6
- * {@link DeployRollbackPlan} (which already resolved the target, confirmed it
7
- * carries a real Cloudflare version, enforced the force gate, and minted the
8
- * deterministic operation id), this drives the data-plane change through the
9
- * R01 Worker Versions/Deployments adapter and returns the verbatim
10
- * {@link RollbackOperation} outcome the CLI then commits to the control plane:
11
- *
12
- * 1. read the current active deployment (the restore point);
13
- * 2. create a 100% deployment of the target version (idempotent by
14
- * operation id — a retry reconciles instead of double-applying);
15
- * 3. health-probe the now-live deployment;
16
- * 4a. probe OK → status `applied` (or `ambiguous-reconciled` when the
17
- * create response was ambiguous and we reconciled to the applied
18
- * deployment). The commit advances the CP active pointer.
19
- * 4b. probe FAILS → restore traffic to the pre-rollback version and
20
- * report status `probe-failed-restored`. The CP pointer is NOT advanced.
21
- * 4c. no traffic ever changed (missing/incompatible target, create rejected,
22
- * or an ambiguous create that reconciled to nothing) → status `failed`.
23
- * The CP pointer is NOT advanced.
24
- *
25
- * This module never fabricates a version or deployment id — every id it records
26
- * came verbatim from Cloudflare (or the injected fake) through the adapter.
27
- */
28
- import type { DeployRollbackPlan, RollbackOperation } from '@hs-x/types';
29
- import { type CloudflareWorkerVersionsClient, type WorkerDeployment } from './cloudflare-worker-versions.js';
30
- export interface TrafficRollbackProbeInput {
31
- readonly client: CloudflareWorkerVersionsClient;
32
- /** The deployment the rollback just created (or reconciled to). */
33
- readonly deployment: WorkerDeployment;
34
- /** The target Cloudflare version id traffic should now serve. */
35
- readonly versionId: string;
36
- readonly scriptName: string;
37
- readonly cloudflareAccountId: string;
38
- }
39
- /** Health-probe the now-live deployment. `ok:false` triggers a restore. */
40
- export type TrafficRollbackProbe = (input: TrafficRollbackProbeInput) => Promise<{
41
- readonly ok: boolean;
42
- readonly detail?: string;
43
- }>;
44
- export interface TrafficRollbackDeps {
45
- /** Injection seam for tests / alternate transports (default: the R01 HTTP adapter). */
46
- readonly createClient?: (input: {
47
- readonly accountId: string;
48
- readonly scriptName: string;
49
- readonly apiToken: string;
50
- }) => CloudflareWorkerVersionsClient;
51
- /** Health probe (default: confirm the target version now serves 100% of traffic). */
52
- readonly probe?: TrafficRollbackProbe;
53
- readonly fetchImpl?: typeof fetch;
54
- /** Cloudflare API base URL for the default adapter (default: https://api.cloudflare.com). */
55
- readonly baseUrl?: string;
56
- /** ISO-8601 clock; defaults to `new Date().toISOString()`. */
57
- readonly now?: () => string;
58
- }
59
- export interface TrafficRollbackInput {
60
- readonly plan: DeployRollbackPlan;
61
- /** Cloudflare API token for the tenant account that owns the Worker. */
62
- readonly apiToken: string;
63
- /** Bypass the binding-compatibility gate and Cloudflare deploy safeguards. */
64
- readonly force: boolean;
65
- }
66
- export interface TrafficRollbackOutcome {
67
- readonly operation: RollbackOperation;
68
- /** True iff live traffic now serves the target version (`applied` | `ambiguous-reconciled`). */
69
- readonly ok: boolean;
70
- readonly liveVersionId?: string;
71
- readonly liveDeploymentId?: string;
72
- /** Version traffic was restored to after a failed probe (when a restore point existed). */
73
- readonly restoredVersionId?: string;
74
- /** True when the target deployment was found already-applied via reconcile (idempotent retry). */
75
- readonly alreadyApplied: boolean;
76
- }
77
- /**
78
- * Default health probe: confirm through Cloudflare that the created deployment
79
- * is the active one and the target version now serves 100% of traffic. This is
80
- * a real edge-state check (not a content probe); R05's live E2E layers an
81
- * authenticated HTTP request to the Worker on top via a custom `probe`.
82
- */
83
- export declare const defaultTrafficRollbackProbe: TrafficRollbackProbe;
84
- export declare function runTrafficRollback(deps: TrafficRollbackDeps, input: TrafficRollbackInput): Promise<TrafficRollbackOutcome>;
85
- //# sourceMappingURL=rollback-traffic.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rollback-traffic.d.ts","sourceRoot":"","sources":["../src/rollback-traffic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAEL,KAAK,8BAA8B,EAGnC,KAAK,gBAAgB,EAEtB,MAAM,iCAAiC,CAAC;AAEzC,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,MAAM,EAAE,8BAA8B,CAAC;IAChD,mEAAmE;IACnE,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC,iEAAiE;IACjE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;CACtC;AAED,2EAA2E;AAC3E,MAAM,MAAM,oBAAoB,GAAG,CACjC,KAAK,EAAE,yBAAyB,KAC7B,OAAO,CAAC;IAAE,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEjE,MAAM,WAAW,mBAAmB;IAClC,uFAAuF;IACvF,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE;QAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;KAC3B,KAAK,8BAA8B,CAAC;IACrC,qFAAqF;IACrF,QAAQ,CAAC,KAAK,CAAC,EAAE,oBAAoB,CAAC;IACtC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IAClC,6FAA6F;IAC7F,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,8DAA8D;IAC9D,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC;IACtC,gGAAgG;IAChG,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,2FAA2F;IAC3F,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,kGAAkG;IAClG,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CAClC;AAED;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,EAAE,oBAezC,CAAC;AAEF,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,mBAAmB,EACzB,KAAK,EAAE,oBAAoB,GAC1B,OAAO,CAAC,sBAAsB,CAAC,CA6JjC"}
@@ -1,204 +0,0 @@
1
- /**
2
- * Traffic-first rollback orchestration (ADR-021 R04).
3
- *
4
- * A rollback restores live Cloudflare traffic to a verified prior Worker
5
- * *version* BEFORE any control-plane record moves. Given a membership-gated
6
- * {@link DeployRollbackPlan} (which already resolved the target, confirmed it
7
- * carries a real Cloudflare version, enforced the force gate, and minted the
8
- * deterministic operation id), this drives the data-plane change through the
9
- * R01 Worker Versions/Deployments adapter and returns the verbatim
10
- * {@link RollbackOperation} outcome the CLI then commits to the control plane:
11
- *
12
- * 1. read the current active deployment (the restore point);
13
- * 2. create a 100% deployment of the target version (idempotent by
14
- * operation id — a retry reconciles instead of double-applying);
15
- * 3. health-probe the now-live deployment;
16
- * 4a. probe OK → status `applied` (or `ambiguous-reconciled` when the
17
- * create response was ambiguous and we reconciled to the applied
18
- * deployment). The commit advances the CP active pointer.
19
- * 4b. probe FAILS → restore traffic to the pre-rollback version and
20
- * report status `probe-failed-restored`. The CP pointer is NOT advanced.
21
- * 4c. no traffic ever changed (missing/incompatible target, create rejected,
22
- * or an ambiguous create that reconciled to nothing) → status `failed`.
23
- * The CP pointer is NOT advanced.
24
- *
25
- * This module never fabricates a version or deployment id — every id it records
26
- * came verbatim from Cloudflare (or the injected fake) through the adapter.
27
- */
28
- import { Schema, schemas } from '@hs-x/types';
29
- import { CloudflareDeploymentAmbiguousError, CloudflareWorkerVersionsError, createWorkerVersionsClient, } from './cloudflare-worker-versions.js';
30
- /**
31
- * Default health probe: confirm through Cloudflare that the created deployment
32
- * is the active one and the target version now serves 100% of traffic. This is
33
- * a real edge-state check (not a content probe); R05's live E2E layers an
34
- * authenticated HTTP request to the Worker on top via a custom `probe`.
35
- */
36
- export const defaultTrafficRollbackProbe = async ({ client, versionId }) => {
37
- try {
38
- const active = await client.getActiveDeployment();
39
- const serves = active?.versions.some((split) => split.versionId === versionId && split.percentage >= 100);
40
- return serves
41
- ? { ok: true }
42
- : {
43
- ok: false,
44
- detail: `Active Cloudflare deployment does not serve version ${versionId} at 100%.`,
45
- };
46
- }
47
- catch (error) {
48
- return { ok: false, detail: describeError(error) };
49
- }
50
- };
51
- export async function runTrafficRollback(deps, input) {
52
- const now = deps.now ?? (() => new Date().toISOString());
53
- const probe = deps.probe ?? defaultTrafficRollbackProbe;
54
- const { plan, force } = input;
55
- const revision = plan.revision;
56
- const client = (deps.createClient ??
57
- ((clientInput) => createWorkerVersionsClient({
58
- ...clientInput,
59
- ...(deps.baseUrl ? { baseUrl: deps.baseUrl } : {}),
60
- ...(deps.fetchImpl ? { fetchImpl: deps.fetchImpl } : {}),
61
- })))({
62
- accountId: revision.cloudflareAccountId,
63
- scriptName: revision.scriptName,
64
- apiToken: input.apiToken,
65
- });
66
- const base = {
67
- schemaVersion: 1,
68
- operationId: plan.operationId,
69
- accountId: plan.targetDeploy.accountId,
70
- projectId: plan.projectId,
71
- cloudflareAccountId: revision.cloudflareAccountId,
72
- scriptName: revision.scriptName,
73
- fromDeployId: plan.fromDeploy.deployId,
74
- toDeployId: plan.targetDeploy.deployId,
75
- targetVersionId: revision.versionId,
76
- };
77
- const failed = (detail) => ({
78
- operation: decodeOperation({ ...base, status: 'failed', detail, recordedAt: now() }),
79
- ok: false,
80
- alreadyApplied: false,
81
- });
82
- // Binding-compatibility gate: a target whose bindings differ from the current
83
- // deploy is not safe to serve blindly. Reject BEFORE touching Cloudflare (no
84
- // traffic change) unless the caller forced it. Prior active state is retained.
85
- const fromFingerprint = plan.fromDeploy.revision?.bindingFingerprint;
86
- if (!force && fromFingerprint && fromFingerprint !== revision.bindingFingerprint) {
87
- return failed(`Rollback target bindings (${revision.bindingFingerprint}) differ from the current deploy (${fromFingerprint}); re-run with --force after reviewing cross-deploy compatibility.`);
88
- }
89
- // Restore point: the version currently serving traffic, read before we change it.
90
- let previous;
91
- try {
92
- previous = await client.getActiveDeployment();
93
- }
94
- catch (error) {
95
- return failed(`Could not read the current active Cloudflare deployment: ${describeError(error)}`);
96
- }
97
- const previousVersionId = previous?.versions.find((split) => split.percentage > 0)?.versionId ??
98
- previous?.versions[0]?.versionId;
99
- // Point 100% of traffic at the target version (idempotent by operation id).
100
- let created;
101
- let viaAmbiguousReconcile = false;
102
- try {
103
- created = await client.createDeployment({
104
- versionId: revision.versionId,
105
- operationId: plan.operationId,
106
- triggeredBy: 'rollback',
107
- message: `HS-X rollback to deploy ${plan.targetDeploy.deployId}`,
108
- ...(force ? { force: true } : {}),
109
- });
110
- }
111
- catch (error) {
112
- if (error instanceof CloudflareDeploymentAmbiguousError) {
113
- // The create response was ambiguous (timeout/5xx after POST). Reconcile by
114
- // operation id to discover whether it actually applied — never blind-retry.
115
- const reconciled = await client.reconcileDeployment(plan.operationId).catch(() => undefined);
116
- if (!reconciled) {
117
- return failed(`Cloudflare returned an ambiguous response and no deployment for operation ${plan.operationId} was found; traffic is unchanged.`);
118
- }
119
- created = { deployment: reconciled, alreadyApplied: true };
120
- viaAmbiguousReconcile = true;
121
- }
122
- else {
123
- return failed(`Cloudflare deployment create failed: ${describeError(error)}`);
124
- }
125
- }
126
- const probeResult = await probe({
127
- client,
128
- deployment: created.deployment,
129
- versionId: revision.versionId,
130
- scriptName: revision.scriptName,
131
- cloudflareAccountId: revision.cloudflareAccountId,
132
- });
133
- if (probeResult.ok) {
134
- const status = viaAmbiguousReconcile ? 'ambiguous-reconciled' : 'applied';
135
- return {
136
- operation: decodeOperation({
137
- ...base,
138
- status,
139
- deploymentId: created.deployment.id,
140
- ...(created.deployment.createdOn
141
- ? { deploymentCreatedOn: created.deployment.createdOn }
142
- : {}),
143
- ...(probeResult.detail ? { detail: probeResult.detail } : {}),
144
- recordedAt: now(),
145
- }),
146
- ok: true,
147
- liveVersionId: revision.versionId,
148
- liveDeploymentId: created.deployment.id,
149
- alreadyApplied: created.alreadyApplied,
150
- };
151
- }
152
- // Probe failed: the target went live but is unhealthy. Restore traffic to the
153
- // pre-rollback version and report a failure — never leave a bad version live
154
- // while claiming the rollback did not happen.
155
- let restoredVersionId;
156
- let restoreDetail = '';
157
- if (previousVersionId && previousVersionId !== revision.versionId) {
158
- try {
159
- await client.createDeployment({
160
- versionId: previousVersionId,
161
- operationId: `${plan.operationId}.restore`,
162
- triggeredBy: 'rollback-restore',
163
- message: `HS-X restore to version ${previousVersionId} after a failed rollback health probe`,
164
- force: true,
165
- });
166
- restoredVersionId = previousVersionId;
167
- }
168
- catch (error) {
169
- restoreDetail = ` Restore of prior version ${previousVersionId} ALSO failed: ${describeError(error)}.`;
170
- }
171
- }
172
- else if (!previousVersionId) {
173
- restoreDetail = ' No prior active deployment existed to restore.';
174
- }
175
- else {
176
- // The pre-rollback version IS the target version — traffic never left it.
177
- restoredVersionId = previousVersionId;
178
- }
179
- return {
180
- operation: decodeOperation({
181
- ...base,
182
- status: 'probe-failed-restored',
183
- deploymentId: created.deployment.id,
184
- ...(created.deployment.createdOn
185
- ? { deploymentCreatedOn: created.deployment.createdOn }
186
- : {}),
187
- detail: `Health probe failed: ${probeResult.detail ?? 'unknown reason'}.${restoreDetail}`,
188
- recordedAt: now(),
189
- }),
190
- ok: false,
191
- ...(restoredVersionId ? { restoredVersionId } : {}),
192
- alreadyApplied: created.alreadyApplied,
193
- };
194
- }
195
- function decodeOperation(value) {
196
- return Schema.decodeUnknownSync(schemas.RollbackOperation)(value);
197
- }
198
- function describeError(error) {
199
- if (error instanceof CloudflareWorkerVersionsError) {
200
- return `${error.message} (${error.detail})`;
201
- }
202
- return error instanceof Error ? error.message : String(error);
203
- }
204
- //# sourceMappingURL=rollback-traffic.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rollback-traffic.js","sourceRoot":"","sources":["../src/rollback-traffic.ts"],"names":[],"mappings":"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"}