From bf9cb3d32d4710dbefd7d3c412aefe1558ecd57e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Duarte?= Date: Tue, 3 Mar 2026 20:47:05 +0000 Subject: [PATCH 1/2] feat: add configurable step limits for Workflows (#12622) Co-authored-by: emily-shen <69125074+emily-shen@users.noreply.github.com> --- .changeset/workflow-step-limits.md | 27 +++ .../miniflare/src/plugins/workflows/index.ts | 9 + .../workers-utils/src/config/environment.ts | 5 + .../workers-utils/src/config/validation.ts | 42 ++++ packages/workers-utils/src/worker.ts | 3 + packages/workflows-shared/src/context.ts | 10 + packages/workflows-shared/src/engine.ts | 9 + .../workflows-shared/tests/engine.test.ts | 116 ++++++++- .../src/__tests__/deploy/workflows.test.ts | 229 ++++++++++++++++++ .../wrangler/src/__tests__/workflows.test.ts | 229 ++++++++++++++++++ packages/wrangler/src/dev/miniflare/index.ts | 27 ++- packages/wrangler/src/triggers/deploy.ts | 7 + 12 files changed, 708 insertions(+), 5 deletions(-) create mode 100644 .changeset/workflow-step-limits.md diff --git a/.changeset/workflow-step-limits.md b/.changeset/workflow-step-limits.md new file mode 100644 index 000000000000..e44c431cf6d6 --- /dev/null +++ b/.changeset/workflow-step-limits.md @@ -0,0 +1,27 @@ +--- +"wrangler": minor +"miniflare": minor +"@cloudflare/workflows-shared": minor +--- + +Add configurable step limits for Workflows + +You can now set a maximum number of steps for a Workflow instance via the `limits.steps` configuration in your Wrangler config. When a Workflow instance exceeds this limit, it will fail with an error indicating the limit was reached. + +```jsonc +// wrangler.jsonc +{ + "workflows": [ + { + "binding": "MY_WORKFLOW", + "name": "my-workflow", + "class_name": "MyWorkflow", + "limits": { + "steps": 5000, + }, + }, + ], +} +``` + +The `steps` value must be an integer between 1 and 25,000. If not specified, the default limit of 10,000 steps is used. Step limits are also enforced in local development via `wrangler dev`. diff --git a/packages/miniflare/src/plugins/workflows/index.ts b/packages/miniflare/src/plugins/workflows/index.ts index b3170744fb1a..4d9cc10e617c 100644 --- a/packages/miniflare/src/plugins/workflows/index.ts +++ b/packages/miniflare/src/plugins/workflows/index.ts @@ -23,6 +23,7 @@ export const WorkflowsOptionsSchema = z.object({ remoteProxyConnectionString: z .custom() .optional(), + stepLimit: z.number().int().min(1).optional(), }) ) .optional(), @@ -151,6 +152,14 @@ export const WORKFLOWS_PLUGIN: Plugin< name: "BINDING_NAME", json: JSON.stringify(bindingName), }, + ...(workflow.stepLimit !== undefined + ? [ + { + name: "STEP_LIMIT", + json: JSON.stringify(workflow.stepLimit), + }, + ] + : []), ], }, }; diff --git a/packages/workers-utils/src/config/environment.ts b/packages/workers-utils/src/config/environment.ts index da77d98b3c7f..26bd4e48aba1 100644 --- a/packages/workers-utils/src/config/environment.ts +++ b/packages/workers-utils/src/config/environment.ts @@ -675,6 +675,11 @@ export type WorkflowBinding = { script_name?: string; /** Whether the Workflow should be remote or not in local development */ remote?: boolean; + /** Optional limits for the Workflow */ + limits?: { + /** Maximum number of steps a Workflow instance can execute */ + steps?: number; + }; }; /** diff --git a/packages/workers-utils/src/config/validation.ts b/packages/workers-utils/src/config/validation.ts index f791c7ef5394..0dff9e292b86 100644 --- a/packages/workers-utils/src/config/validation.ts +++ b/packages/workers-utils/src/config/validation.ts @@ -2584,12 +2584,54 @@ const validateWorkflowBinding: ValidatorFn = (diagnostics, field, value) => { isValid = false; } + if (hasProperty(value, "limits") && value.limits !== undefined) { + if ( + typeof value.limits !== "object" || + value.limits === null || + Array.isArray(value.limits) + ) { + diagnostics.errors.push( + `"${field}" bindings should, optionally, have an object "limits" field but got ${JSON.stringify( + value + )}.` + ); + isValid = false; + } else { + const limits = value.limits as Record; + if (limits.steps !== undefined) { + if ( + typeof limits.steps !== "number" || + !Number.isInteger(limits.steps) || + limits.steps < 1 + ) { + diagnostics.errors.push( + `"${field}" bindings "limits.steps" field must be a positive integer but got ${JSON.stringify( + limits.steps + )}.` + ); + isValid = false; + } else if (limits.steps > 25_000) { + diagnostics.warnings.push( + `"${field}" has a step limit of ${limits.steps}, which exceeds the production maximum of 25,000. This configuration may not work when deployed.` + ); + } + } + validateAdditionalProperties( + diagnostics, + `${field}.limits`, + Object.keys(limits), + ["steps"] + ); + } + } + validateAdditionalProperties(diagnostics, field, Object.keys(value), [ "binding", "name", "class_name", "script_name", "remote", + "limits", ]); return isValid; diff --git a/packages/workers-utils/src/worker.ts b/packages/workers-utils/src/worker.ts index f0f6cf5caae9..6b044866df9c 100644 --- a/packages/workers-utils/src/worker.ts +++ b/packages/workers-utils/src/worker.ts @@ -181,6 +181,9 @@ export interface CfWorkflow { script_name?: string; remote?: boolean; raw?: boolean; + limits?: { + steps?: number; + }; } export interface CfQueue { diff --git a/packages/workflows-shared/src/context.ts b/packages/workflows-shared/src/context.ts index b63448b3a7cd..71a2460ac422 100644 --- a/packages/workflows-shared/src/context.ts +++ b/packages/workflows-shared/src/context.ts @@ -47,6 +47,7 @@ export class Context extends RpcTarget { #state: DurableObjectState; #counters: Map = new Map(); + #lifetimeStepCounter: number = 0; constructor(engine: Engine, state: DurableObjectState) { super(); @@ -85,6 +86,15 @@ export class Context extends RpcTarget { stepConfig = {}; } + this.#lifetimeStepCounter++; + + const stepLimit = this.#engine.stepLimit; + if (this.#lifetimeStepCounter > stepLimit) { + throw new WorkflowFatalError( + `The limit of ${stepLimit} steps has been reached. This limit can be changed in your worker configuration.` + ); + } + if (!isValidStepName(name)) { // NOTE(lduarte): marking errors as user error allows the observability layer to avoid leaking // user errors to sentry while making everything more observable. `isUserError` is not serialized diff --git a/packages/workflows-shared/src/engine.ts b/packages/workflows-shared/src/engine.ts index 6b84402a402a..6413eee84fd8 100644 --- a/packages/workflows-shared/src/engine.ts +++ b/packages/workflows-shared/src/engine.ts @@ -23,6 +23,7 @@ import type { WorkflowEntrypoint, WorkflowEvent } from "cloudflare:workers"; interface Env { USER_WORKFLOW: WorkflowEntrypoint; + STEP_LIMIT?: string; // JSON-encoded number from miniflare binding } export type DatabaseWorkflow = { @@ -74,6 +75,8 @@ const ENGINE_STATUS_KEY = "ENGINE_STATUS"; const EVENT_MAP_PREFIX = "EVENT_MAP"; +export const DEFAULT_STEP_LIMIT = 10_000; + export class Engine extends DurableObject { logs: Array = []; @@ -83,6 +86,7 @@ export class Engine extends DurableObject { workflowName: string | undefined; timeoutHandler: GracePeriodSemaphore; priorityQueue: TimePriorityQueue | undefined; + stepLimit: number; waiters: Map) => void>> = new Map(); @@ -90,6 +94,11 @@ export class Engine extends DurableObject { constructor(state: DurableObjectState, env: Env) { super(state, env); + + this.stepLimit = env.STEP_LIMIT + ? JSON.parse(env.STEP_LIMIT) + : DEFAULT_STEP_LIMIT; + void this.ctx.blockConcurrencyWhile(async () => { this.ctx.storage.transactionSync(() => { try { diff --git a/packages/workflows-shared/tests/engine.test.ts b/packages/workflows-shared/tests/engine.test.ts index f00b5c4c6905..ef93206ff449 100644 --- a/packages/workflows-shared/tests/engine.test.ts +++ b/packages/workflows-shared/tests/engine.test.ts @@ -5,7 +5,7 @@ import { } from "cloudflare:test"; import { NonRetryableError } from "cloudflare:workflows"; import { describe, it, vi } from "vitest"; -import { InstanceEvent, InstanceStatus } from "../src"; +import { DEFAULT_STEP_LIMIT, InstanceEvent, InstanceStatus } from "../src"; import type { DatabaseInstance, DatabaseVersion, @@ -271,4 +271,118 @@ describe("Engine", () => { logs.logs.some((log) => log.event === InstanceEvent.WORKFLOW_START) ).toBe(true); }); + + describe("step limits", () => { + it("should enforce step limit when exceeded", async ({ expect }) => { + const stepLimit = 3; + + const engineStub = await runWorkflow( + "STEP-LIMIT-EXCEEDED", + async (_event, step) => { + // Try to run more steps than the limit + for (let i = 0; i < stepLimit + 1; i++) { + await step.do(`step-${i}`, async () => `result-${i}`); + } + } + ); + + // Set the step limit on the engine + await runInDurableObject(engineStub, (engine) => { + engine.stepLimit = stepLimit; + }); + + // Re-init to run with the new limit + await setWorkflowEntrypoint(engineStub, async (_event, step) => { + for (let i = 0; i < stepLimit + 1; i++) { + await step.do(`step-${i}`, async () => `result-${i}`); + } + }); + + const engineId = env.ENGINE.idFromName("STEP-LIMIT-EXCEEDED-2"); + const freshStub = env.ENGINE.get(engineId); + + await runInDurableObject(freshStub, (engine) => { + engine.stepLimit = stepLimit; + }); + + await setWorkflowEntrypoint(freshStub, async (_event, step) => { + for (let i = 0; i < stepLimit + 1; i++) { + await step.do(`step-${i}`, async () => `result-${i}`); + } + }); + + await freshStub.init( + 12346, + {} as DatabaseWorkflow, + {} as DatabaseVersion, + { id: "STEP-LIMIT-EXCEEDED-2" } as DatabaseInstance, + { + payload: {}, + timestamp: new Date(), + instanceId: "STEP-LIMIT-EXCEEDED-2", + } + ); + + const logs = (await freshStub.readLogs()) as EngineLogs; + + expect( + logs.logs.some((val) => val.event === InstanceEvent.WORKFLOW_FAILURE) + ).toBe(true); + }); + + it("should succeed when steps are exactly at the limit", async ({ + expect, + }) => { + const stepLimit = 3; + + const engineId = env.ENGINE.idFromName("STEP-LIMIT-AT-LIMIT"); + const freshStub = env.ENGINE.get(engineId); + + await runInDurableObject(freshStub, (engine) => { + engine.stepLimit = stepLimit; + }); + + await setWorkflowEntrypoint(freshStub, async (_event, step) => { + for (let i = 0; i < stepLimit; i++) { + await step.do(`step-${i}`, async () => `result-${i}`); + } + return "done"; + }); + + await freshStub.init( + 12346, + {} as DatabaseWorkflow, + {} as DatabaseVersion, + { id: "STEP-LIMIT-AT-LIMIT" } as DatabaseInstance, + { + payload: {}, + timestamp: new Date(), + instanceId: "STEP-LIMIT-AT-LIMIT", + } + ); + + const logs = (await freshStub.readLogs()) as EngineLogs; + + expect( + logs.logs.some((val) => val.event === InstanceEvent.WORKFLOW_SUCCESS) + ).toBe(true); + expect( + logs.logs.some((val) => val.event === InstanceEvent.WORKFLOW_FAILURE) + ).toBe(false); + }); + + it("should use DEFAULT_STEP_LIMIT when no limit is configured", async ({ + expect, + }) => { + const engineId = env.ENGINE.idFromName("STEP-LIMIT-DEFAULT"); + const freshStub = env.ENGINE.get(engineId); + + const stepLimit = await runInDurableObject( + freshStub, + (engine) => engine.stepLimit + ); + + expect(stepLimit).toBe(DEFAULT_STEP_LIMIT); + }); + }); }); diff --git a/packages/wrangler/src/__tests__/deploy/workflows.test.ts b/packages/wrangler/src/__tests__/deploy/workflows.test.ts index b65be0af63b0..68f400afe36b 100644 --- a/packages/wrangler/src/__tests__/deploy/workflows.test.ts +++ b/packages/wrangler/src/__tests__/deploy/workflows.test.ts @@ -173,6 +173,61 @@ describe("deploy", () => { `); }); + it("should deploy a workflow with limits", async () => { + writeWranglerConfig({ + main: "index.js", + workflows: [ + { + binding: "WORKFLOW", + name: "my-workflow", + class_name: "MyWorkflow", + limits: { steps: 5000 }, + }, + ], + }); + await fs.promises.writeFile( + "index.js", + ` + import { WorkflowEntrypoint } from 'cloudflare:workers'; + export default {}; + export class MyWorkflow extends WorkflowEntrypoint {}; + ` + ); + + const handler = http.put( + "*/accounts/:accountId/workflows/:workflowName", + async ({ params, request }) => { + expect(params.workflowName).toBe("my-workflow"); + const body = (await request.json()) as Record; + expect(body).toEqual({ + script_name: "test-name", + class_name: "MyWorkflow", + limits: { steps: 5000 }, + }); + return HttpResponse.json( + createFetchResult({ id: "mock-new-workflow-id" }) + ); + } + ); + msw.use(handler); + mockSubDomainRequest(); + mockUploadWorkerRequest({ + expectedBindings: [ + { + type: "workflow", + name: "WORKFLOW", + workflow_name: "my-workflow", + class_name: "MyWorkflow", + }, + ], + }); + + await runWrangler("deploy"); + + expect(std.warn).toMatchInlineSnapshot(`""`); + expect(std.out).toContain("workflow: my-workflow"); + }); + it("should not call Workflow's API if the workflow binds to another script", async () => { writeWranglerConfig({ main: "index.js", @@ -237,6 +292,180 @@ describe("deploy", () => { `); }); + it("should error when deploying a workflow with limits that references an external script", async () => { + writeWranglerConfig({ + main: "index.js", + name: "this-script", + workflows: [ + { + binding: "WORKFLOW", + name: "my-workflow", + class_name: "MyWorkflow", + script_name: "another-script", + limits: { steps: 5000 }, + }, + ], + }); + + mockSubDomainRequest(); + mockUploadWorkerRequest({ + expectedScriptName: "this-script", + expectedBindings: [ + { + type: "workflow", + name: "WORKFLOW", + workflow_name: "my-workflow", + class_name: "MyWorkflow", + script_name: "another-script", + }, + ], + }); + await fs.promises.writeFile( + "index.js", + ` + export default {}; + ` + ); + + await expect(runWrangler("deploy")).rejects.toThrow( + 'Workflow "my-workflow" has "limits" configured but references external script "another-script"' + ); + }); + + describe("workflow script_name validation with environments", () => { + it("should error when script_name matches top-level name but not env-suffixed name and limits are set", async () => { + writeWranglerConfig({ + main: "index.js", + name: "my-app", + env: { + staging: { + workflows: [ + { + binding: "WORKFLOW", + name: "my-workflow", + class_name: "MyWorkflow", + script_name: "my-app", + limits: { steps: 5000 }, + }, + ], + }, + }, + }); + await fs.promises.writeFile("index.js", `export default {};`); + + mockSubDomainRequest(); + mockUploadWorkerRequest({ + expectedScriptName: "my-app-staging", + }); + + await expect(runWrangler("deploy --env staging")).rejects.toThrow( + 'Workflow "my-workflow" has "limits" configured but references external script "my-app"' + ); + }); + + it("should allow limits when script_name matches the env-suffixed name", async () => { + writeWranglerConfig({ + main: "index.js", + name: "my-app", + env: { + staging: { + workflows: [ + { + binding: "WORKFLOW", + name: "my-workflow", + class_name: "MyWorkflow", + script_name: "my-app-staging", + limits: { steps: 5000 }, + }, + ], + }, + }, + }); + await fs.promises.writeFile( + "index.js", + ` + import { WorkflowEntrypoint } from 'cloudflare:workers'; + export default {}; + export class MyWorkflow extends WorkflowEntrypoint {}; + ` + ); + + const handler = http.put( + "*/accounts/:accountId/workflows/:workflowName", + async ({ params, request }) => { + expect(params.workflowName).toBe("my-workflow"); + const body = (await request.json()) as Record; + expect(body).toEqual({ + script_name: "my-app-staging", + class_name: "MyWorkflow", + limits: { steps: 5000 }, + }); + return HttpResponse.json( + createFetchResult({ id: "mock-new-workflow-id" }) + ); + } + ); + msw.use(handler); + mockSubDomainRequest(); + mockUploadWorkerRequest({ + expectedScriptName: "my-app-staging", + }); + + await runWrangler("deploy --env staging"); + + expect(std.warn).toMatchInlineSnapshot(`""`); + expect(std.out).toContain("workflow: my-workflow"); + }); + + it("should deploy external script_name under env without limits", async () => { + writeWranglerConfig({ + main: "index.js", + name: "my-app", + env: { + staging: { + workflows: [ + { + binding: "WORKFLOW", + name: "my-workflow", + class_name: "MyWorkflow", + script_name: "another-script", + }, + ], + }, + }, + }); + await fs.promises.writeFile("index.js", `export default {};`); + + const handler = http.put( + "*/accounts/:accountId/workflows/:workflowName", + () => { + expect( + false, + "Workflows API should not be called for external bindings." + ); + } + ); + msw.use(handler); + mockSubDomainRequest(); + mockUploadWorkerRequest({ + expectedScriptName: "my-app-staging", + expectedBindings: [ + { + type: "workflow", + name: "WORKFLOW", + workflow_name: "my-workflow", + class_name: "MyWorkflow", + script_name: "another-script", + }, + ], + }); + + await runWrangler("deploy --env staging"); + + expect(std.out).toContain("Uploaded my-app-staging"); + }); + }); + describe("workflow conflict detection", () => { function mockGetWorkflow( workflowsByName: Record< diff --git a/packages/wrangler/src/__tests__/workflows.test.ts b/packages/wrangler/src/__tests__/workflows.test.ts index 33ebd1f20d1a..1ba3ffbcc6f6 100644 --- a/packages/wrangler/src/__tests__/workflows.test.ts +++ b/packages/wrangler/src/__tests__/workflows.test.ts @@ -1,3 +1,4 @@ +import fs from "node:fs"; import { mockCreateDate, mockEndDate, @@ -929,6 +930,234 @@ describe("wrangler workflows", () => { expect(std.err).toContain('"workflows" bindings should be objects'); }); + it("should accept workflow binding with valid limits", async () => { + fs.writeFileSync( + "index.js", + "import { WorkflowEntrypoint } from 'cloudflare:workers';\nexport default {};\nexport class MyWorkflow extends WorkflowEntrypoint {};" + ); + writeWranglerConfig({ + main: "index.js", + workflows: [ + { + binding: "MY_WORKFLOW", + name: "my-workflow", + class_name: "MyWorkflow", + limits: { steps: 5000 }, + }, + ], + }); + + await runWrangler("deploy --dry-run"); + expect(std.err).toBe(""); + }); + + it("should accept workflow binding with empty limits object", async () => { + fs.writeFileSync( + "index.js", + "import { WorkflowEntrypoint } from 'cloudflare:workers';\nexport default {};\nexport class MyWorkflow extends WorkflowEntrypoint {};" + ); + writeWranglerConfig({ + main: "index.js", + workflows: [ + { + binding: "MY_WORKFLOW", + name: "my-workflow", + class_name: "MyWorkflow", + limits: {}, + }, + ], + }); + + await runWrangler("deploy --dry-run"); + expect(std.err).toBe(""); + }); + + it("should accept workflow binding with limits.steps at boundary value 1", async () => { + fs.writeFileSync( + "index.js", + "import { WorkflowEntrypoint } from 'cloudflare:workers';\nexport default {};\nexport class MyWorkflow extends WorkflowEntrypoint {};" + ); + writeWranglerConfig({ + main: "index.js", + workflows: [ + { + binding: "MY_WORKFLOW", + name: "my-workflow", + class_name: "MyWorkflow", + limits: { steps: 1 }, + }, + ], + }); + + await runWrangler("deploy --dry-run"); + expect(std.err).toBe(""); + }); + + it("should reject workflow binding with limits.steps of 0", async () => { + writeWranglerConfig({ + workflows: [ + { + binding: "MY_WORKFLOW", + name: "my-workflow", + class_name: "MyWorkflow", + limits: { steps: 0 }, + } as any, // eslint-disable-line @typescript-eslint/no-explicit-any + ], + }); + + await expect(runWrangler("deploy --dry-run")).rejects.toThrow(); + expect(std.err).toContain( + '"limits.steps" field must be a positive integer' + ); + }); + + it("should reject workflow binding with non-integer limits.steps", async () => { + writeWranglerConfig({ + workflows: [ + { + binding: "MY_WORKFLOW", + name: "my-workflow", + class_name: "MyWorkflow", + limits: { steps: 1.5 }, + } as any, // eslint-disable-line @typescript-eslint/no-explicit-any + ], + }); + + await expect(runWrangler("deploy --dry-run")).rejects.toThrow(); + expect(std.err).toContain( + '"limits.steps" field must be a positive integer' + ); + }); + + it("should reject workflow binding with negative limits.steps", async () => { + writeWranglerConfig({ + workflows: [ + { + binding: "MY_WORKFLOW", + name: "my-workflow", + class_name: "MyWorkflow", + limits: { steps: -1 }, + } as any, // eslint-disable-line @typescript-eslint/no-explicit-any + ], + }); + + await expect(runWrangler("deploy --dry-run")).rejects.toThrow(); + expect(std.err).toContain( + '"limits.steps" field must be a positive integer' + ); + }); + + it("should reject workflow binding with non-object limits", async () => { + writeWranglerConfig({ + workflows: [ + { + binding: "MY_WORKFLOW", + name: "my-workflow", + class_name: "MyWorkflow", + limits: "invalid", + } as any, // eslint-disable-line @typescript-eslint/no-explicit-any + ], + }); + + await expect(runWrangler("deploy --dry-run")).rejects.toThrow(); + expect(std.err).toContain( + 'should, optionally, have an object "limits" field' + ); + }); + + it("should reject workflow binding with array limits", async () => { + writeWranglerConfig({ + workflows: [ + { + binding: "MY_WORKFLOW", + name: "my-workflow", + class_name: "MyWorkflow", + limits: [1, 2, 3], + } as any, // eslint-disable-line @typescript-eslint/no-explicit-any + ], + }); + + await expect(runWrangler("deploy --dry-run")).rejects.toThrow(); + expect(std.err).toContain( + 'should, optionally, have an object "limits" field' + ); + }); + + it("should warn on unexpected fields in workflow binding limits", async () => { + writeWorkerSource({ format: "ts" }); + writeWranglerConfig({ + main: "index.ts", + workflows: [ + { + binding: "MY_WORKFLOW", + name: "my-workflow", + class_name: "MyWorkflow", + script_name: "external-script", + limits: { + steps: 10, + // @ts-expect-error Testing unexpected fields in limits + unknownProp: "foo", + }, + }, + ], + }); + + await runWrangler("deploy --dry-run"); + expect(std.warn).toContain( + 'Unexpected fields found in workflows[0].limits field: "unknownProp"' + ); + }); + + it("should warn when step limit exceeds production maximum", async () => { + fs.writeFileSync( + "index.js", + "import { WorkflowEntrypoint } from 'cloudflare:workers';\nexport default {};\nexport class MyWorkflow extends WorkflowEntrypoint {};" + ); + writeWranglerConfig( + { + main: "index.js", + workflows: [ + { + binding: "MY_WORKFLOW", + name: "my-workflow", + class_name: "MyWorkflow", + limits: { steps: 30_000 }, + }, + ], + }, + "./wrangler.json" + ); + + await runWrangler("deploy --dry-run --config wrangler.json"); + expect(std.warn).toContain( + "has a step limit of 30000, which exceeds the production maximum of 25,000" + ); + }); + + it("should not warn when step limit is within production maximum", async () => { + fs.writeFileSync( + "index.js", + "import { WorkflowEntrypoint } from 'cloudflare:workers';\nexport default {};\nexport class MyWorkflow extends WorkflowEntrypoint {};" + ); + writeWranglerConfig( + { + main: "index.js", + workflows: [ + { + binding: "MY_WORKFLOW", + name: "my-workflow", + class_name: "MyWorkflow", + limits: { steps: 25_000 }, + }, + ], + }, + "./wrangler.json" + ); + + await runWrangler("deploy --dry-run --config wrangler.json"); + expect(std.warn).not.toContain("step limit"); + }); + it("should reject workflows binding with same name", async () => { writeWorkerSource({ format: "ts" }); writeWranglerConfig({ diff --git a/packages/wrangler/src/dev/miniflare/index.ts b/packages/wrangler/src/dev/miniflare/index.ts index baf18c8351a7..27dd72075554 100644 --- a/packages/wrangler/src/dev/miniflare/index.ts +++ b/packages/wrangler/src/dev/miniflare/index.ts @@ -1,7 +1,10 @@ import assert from "node:assert"; import path from "node:path"; import { getDevContainerImageName } from "@cloudflare/containers-shared"; -import { getLocalExplorerEnabledFromEnv } from "@cloudflare/workers-utils"; +import { + getLocalExplorerEnabledFromEnv, + UserError, +} from "@cloudflare/workers-utils"; import { Log, LogLevel } from "miniflare"; import { extractBindingsOfType, @@ -301,6 +304,7 @@ function workflowEntry( class_name: className, script_name: scriptName, remote, + limits, }: CfWorkflow, remoteProxyConnectionString?: RemoteProxyConnectionString ): [ @@ -310,8 +314,11 @@ function workflowEntry( className: string; scriptName?: string; remoteProxyConnectionString?: RemoteProxyConnectionString; + stepLimit?: number; }, ] { + const stepLimit = limits?.steps; + if (!remoteProxyConnectionString || !remote) { return [ binding, @@ -319,6 +326,7 @@ function workflowEntry( name, className, scriptName, + ...(stepLimit !== undefined && { stepLimit }), }, ]; } @@ -330,6 +338,7 @@ function workflowEntry( className, scriptName, remoteProxyConnectionString, + ...(stepLimit !== undefined && { stepLimit }), }, ]; } @@ -714,9 +723,19 @@ export function buildMiniflareBindingOptions( ]) ), workflows: Object.fromEntries( - workflows.map((workflow) => - workflowEntry(workflow, remoteProxyConnectionString) - ) + workflows.map((workflow) => { + if ( + workflow.script_name !== undefined && + workflow.script_name !== config.name && + workflow.limits + ) { + throw new UserError( + `Workflow "${workflow.name}" has "limits" configured but references external script "${workflow.script_name}". ` + + `Configure limits on the worker that defines the workflow.` + ); + } + return workflowEntry(workflow, remoteProxyConnectionString); + }) ), secretsStoreSecrets: Object.fromEntries( secretsStoreSecrets.map((binding) => [binding.binding, binding]) diff --git a/packages/wrangler/src/triggers/deploy.ts b/packages/wrangler/src/triggers/deploy.ts index 01612e218a06..d13a5938916c 100644 --- a/packages/wrangler/src/triggers/deploy.ts +++ b/packages/wrangler/src/triggers/deploy.ts @@ -259,6 +259,12 @@ export default async function triggersDeploy( workflow.script_name !== undefined && workflow.script_name !== scriptName ) { + if (workflow.limits) { + throw new UserError( + `Workflow "${workflow.name}" has "limits" configured but references external script "${workflow.script_name}". ` + + `Configure limits on the worker that defines the workflow.` + ); + } continue; } @@ -271,6 +277,7 @@ export default async function triggersDeploy( body: JSON.stringify({ script_name: scriptName, class_name: workflow.class_name, + ...(workflow.limits && { limits: workflow.limits }), }), headers: { "Content-Type": "application/json", From ea57dfd56f2e82079927ce0b6fe690713e794a78 Mon Sep 17 00:00:00 2001 From: ANT Bot <116369605+workers-devprod@users.noreply.github.com> Date: Tue, 3 Mar 2026 21:46:42 +0000 Subject: [PATCH 2/2] Version Packages (#12702) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .changeset/breezy-groups-warn.md | 21 ---- .changeset/c3-frameworks-update-12713.md | 11 -- .changeset/c3-frameworks-update-12715.md | 11 -- .changeset/c3-frameworks-update-12716.md | 11 -- .changeset/c3-frameworks-update-12717.md | 11 -- .changeset/c3-frameworks-update-12718.md | 11 -- .changeset/c3-frameworks-update-12719.md | 11 -- .changeset/c3-frameworks-update-12720.md | 11 -- .changeset/dry-shoes-cheat.md | 7 -- .changeset/empty-radios-happen.md | 10 -- .changeset/images-binding-crud-operations.md | 7 -- .changeset/pin-workerd-latest.md | 13 -- .changeset/polite-schools-buy.md | 7 -- .changeset/quiet-queens-build.md | 21 ---- .changeset/remove-ai-search-workaround.md | 6 - .changeset/remove-chalk-create-cloudflare.md | 5 - .changeset/rude-ends-battle.md | 5 - .changeset/sharp-sheep-buy.md | 22 ---- .changeset/tricky-frogs-fry.md | 21 ---- .changeset/wicked-wombats-decide.md | 5 - .changeset/workflow-step-limits.md | 27 ---- packages/containers-shared/CHANGELOG.md | 27 ++++ packages/containers-shared/package.json | 2 +- packages/create-cloudflare/CHANGELOG.md | 66 ++++++++++ packages/create-cloudflare/package.json | 2 +- packages/miniflare/CHANGELOG.md | 47 +++++++ packages/miniflare/package.json | 2 +- packages/pages-shared/CHANGELOG.md | 7 ++ packages/pages-shared/package.json | 2 +- packages/vite-plugin-cloudflare/CHANGELOG.md | 31 +++++ packages/vite-plugin-cloudflare/package.json | 2 +- packages/vitest-pool-workers/CHANGELOG.md | 10 ++ packages/vitest-pool-workers/package.json | 2 +- packages/workflows-shared/CHANGELOG.md | 26 ++++ packages/workflows-shared/package.json | 2 +- packages/wrangler/CHANGELOG.md | 123 +++++++++++++++++++ packages/wrangler/package.json | 2 +- 37 files changed, 345 insertions(+), 262 deletions(-) delete mode 100644 .changeset/breezy-groups-warn.md delete mode 100644 .changeset/c3-frameworks-update-12713.md delete mode 100644 .changeset/c3-frameworks-update-12715.md delete mode 100644 .changeset/c3-frameworks-update-12716.md delete mode 100644 .changeset/c3-frameworks-update-12717.md delete mode 100644 .changeset/c3-frameworks-update-12718.md delete mode 100644 .changeset/c3-frameworks-update-12719.md delete mode 100644 .changeset/c3-frameworks-update-12720.md delete mode 100644 .changeset/dry-shoes-cheat.md delete mode 100644 .changeset/empty-radios-happen.md delete mode 100644 .changeset/images-binding-crud-operations.md delete mode 100644 .changeset/pin-workerd-latest.md delete mode 100644 .changeset/polite-schools-buy.md delete mode 100644 .changeset/quiet-queens-build.md delete mode 100644 .changeset/remove-ai-search-workaround.md delete mode 100644 .changeset/remove-chalk-create-cloudflare.md delete mode 100644 .changeset/rude-ends-battle.md delete mode 100644 .changeset/sharp-sheep-buy.md delete mode 100644 .changeset/tricky-frogs-fry.md delete mode 100644 .changeset/wicked-wombats-decide.md delete mode 100644 .changeset/workflow-step-limits.md diff --git a/.changeset/breezy-groups-warn.md b/.changeset/breezy-groups-warn.md deleted file mode 100644 index b342a063f48a..000000000000 --- a/.changeset/breezy-groups-warn.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -"@cloudflare/containers-shared": patch -"wrangler": minor ---- - -Users are now able to configure DockerHub credentials and have containers reference images stored there. - -DockerHub can be configured as follows: - -```sh -echo $PAT_TOKEN | npx wrangler@latest containers registries configure docker.io --dockerhub-username=user --secret-name=DockerHub_PAT_Token -``` - -Containers can then specify an image from DockerHub in their `wrangler.jsonc` as follows: - -```jsonc -"containers": { - "image": "docker.io/namespace/image:tag", - ... -} -``` diff --git a/.changeset/c3-frameworks-update-12713.md b/.changeset/c3-frameworks-update-12713.md deleted file mode 100644 index f17bc0bb4c45..000000000000 --- a/.changeset/c3-frameworks-update-12713.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"create-cloudflare": patch ---- - -Update dependencies of "create-cloudflare" - -The following dependency versions have been updated: - -| Dependency | From | To | -| --------------- | ------ | ------ | -| @angular/create | 21.1.4 | 21.2.0 | diff --git a/.changeset/c3-frameworks-update-12715.md b/.changeset/c3-frameworks-update-12715.md deleted file mode 100644 index 15d96bffe004..000000000000 --- a/.changeset/c3-frameworks-update-12715.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"create-cloudflare": patch ---- - -Update dependencies of "create-cloudflare" - -The following dependency versions have been updated: - -| Dependency | From | To | -| ---------- | ------ | ------ | -| create-vue | 3.21.1 | 3.22.0 | diff --git a/.changeset/c3-frameworks-update-12716.md b/.changeset/c3-frameworks-update-12716.md deleted file mode 100644 index ecad27d67736..000000000000 --- a/.changeset/c3-frameworks-update-12716.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"create-cloudflare": patch ---- - -Update dependencies of "create-cloudflare" - -The following dependency versions have been updated: - -| Dependency | From | To | -| ------------------- | ------ | ------ | -| create-react-router | 7.13.0 | 7.13.1 | diff --git a/.changeset/c3-frameworks-update-12717.md b/.changeset/c3-frameworks-update-12717.md deleted file mode 100644 index a2b988fd0713..000000000000 --- a/.changeset/c3-frameworks-update-12717.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"create-cloudflare": patch ---- - -Update dependencies of "create-cloudflare" - -The following dependency versions have been updated: - -| Dependency | From | To | -| ------------- | ----- | ----- | -| create-analog | 2.2.3 | 2.3.1 | diff --git a/.changeset/c3-frameworks-update-12718.md b/.changeset/c3-frameworks-update-12718.md deleted file mode 100644 index ac9aa501f835..000000000000 --- a/.changeset/c3-frameworks-update-12718.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"create-cloudflare": patch ---- - -Update dependencies of "create-cloudflare" - -The following dependency versions have been updated: - -| Dependency | From | To | -| ---------- | ------ | ------ | -| sv | 0.12.2 | 0.12.4 | diff --git a/.changeset/c3-frameworks-update-12719.md b/.changeset/c3-frameworks-update-12719.md deleted file mode 100644 index 39d006f8bfb7..000000000000 --- a/.changeset/c3-frameworks-update-12719.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"create-cloudflare": patch ---- - -Update dependencies of "create-cloudflare" - -The following dependency versions have been updated: - -| Dependency | From | To | -| ----------- | ------- | ------- | -| create-vike | 0.0.581 | 0.0.591 | diff --git a/.changeset/c3-frameworks-update-12720.md b/.changeset/c3-frameworks-update-12720.md deleted file mode 100644 index a5227fc9e029..000000000000 --- a/.changeset/c3-frameworks-update-12720.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"create-cloudflare": patch ---- - -Update dependencies of "create-cloudflare" - -The following dependency versions have been updated: - -| Dependency | From | To | -| ----------- | ---------------------- | ---------------------- | -| create-waku | 0.12.5-1.0.0-alpha.4-0 | 0.12.5-1.0.0-alpha.5-0 | diff --git a/.changeset/dry-shoes-cheat.md b/.changeset/dry-shoes-cheat.md deleted file mode 100644 index 8067f5a7b901..000000000000 --- a/.changeset/dry-shoes-cheat.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"wrangler": patch ---- - -Fix SolidStart autoconfig for projects using version 2.0.0-alpha or later - -SolidStart v2.0.0-alpha introduced a breaking change where configuration moved from `app.config.(js|ts)` to `vite.config.(js|ts)`. Wrangler's autoconfig now detects the installed SolidStart version and based on it updates the appropriate configuration file diff --git a/.changeset/empty-radios-happen.md b/.changeset/empty-radios-happen.md deleted file mode 100644 index 33c0f9c52b56..000000000000 --- a/.changeset/empty-radios-happen.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -"@cloudflare/vite-plugin": minor -"@cloudflare/containers-shared": minor -"miniflare": minor -"wrangler": minor ---- - -Add experimental support for containers to workers communication with interceptOutboundHttp - -This feature is experimental and requires adding the "experimental" compatibility flag to your Wrangler configuration. diff --git a/.changeset/images-binding-crud-operations.md b/.changeset/images-binding-crud-operations.md deleted file mode 100644 index 9488dcf061c4..000000000000 --- a/.changeset/images-binding-crud-operations.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"miniflare": minor ---- - -Add Hosted Images CRUD operations to Images binding. - -This is an experimental API that only works locally for the moment. diff --git a/.changeset/pin-workerd-latest.md b/.changeset/pin-workerd-latest.md deleted file mode 100644 index 0db069c7162c..000000000000 --- a/.changeset/pin-workerd-latest.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -"miniflare": patch -"wrangler": patch ---- - -Update dependencies of "miniflare", "wrangler" - -The following dependency versions have been updated: - -| Dependency | From | To | -| ------------------------- | ------------ | ------------ | -| workerd | 1.20260305.0 | 1.20260226.1 | -| @cloudflare/workers-types | 4.20260305.0 | 4.20260226.1 | diff --git a/.changeset/polite-schools-buy.md b/.changeset/polite-schools-buy.md deleted file mode 100644 index e81f0f465d7e..000000000000 --- a/.changeset/polite-schools-buy.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"create-cloudflare": patch ---- - -Update SolidStart template for compatibility with v2. - -SolidStart v2 uses the `nitro` Vite plugin so we now update the Nitro config in `vite.config.ts` rather than `app.config.ts`. diff --git a/.changeset/quiet-queens-build.md b/.changeset/quiet-queens-build.md deleted file mode 100644 index c4dcf8de35cc..000000000000 --- a/.changeset/quiet-queens-build.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -"@cloudflare/vite-plugin": minor -"wrangler": minor ---- - -Add local dev validation for the experimental `secrets` configuration property - -When the new `secrets` property is defined, `wrangler dev` and `vite dev` now validate secrets declared in `secrets.required`. When required secrets are missing from `.dev.vars` or `.env`/`process.env`, a warning is logged listing the missing secret names. - -When `secrets` is defined, only the keys listed in `secrets.required` are loaded. Additional keys in `.dev.vars` or `.env` are excluded. If you are not using `.dev.vars`, keys listed in `secrets.required` are loaded from `process.env` as well as `.env`. The `CLOUDFLARE_INCLUDE_PROCESS_ENV` environment variable is therefore not needed when using this feature. - -When `secrets` is not defined, the existing behavior is unchanged. - -```jsonc -// wrangler.jsonc -{ - "secrets": { - "required": ["API_KEY", "DB_PASSWORD"], - }, -} -``` diff --git a/.changeset/remove-ai-search-workaround.md b/.changeset/remove-ai-search-workaround.md deleted file mode 100644 index 5ca198f5f29c..000000000000 --- a/.changeset/remove-ai-search-workaround.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"miniflare": patch -"wrangler": patch ---- - -Remove temporary AI Search RPC workaround (no user-facing changes) diff --git a/.changeset/remove-chalk-create-cloudflare.md b/.changeset/remove-chalk-create-cloudflare.md deleted file mode 100644 index 78bfbef17e4b..000000000000 --- a/.changeset/remove-chalk-create-cloudflare.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"create-cloudflare": patch ---- - -Remove unused `chalk` dependency from create-cloudflare. diff --git a/.changeset/rude-ends-battle.md b/.changeset/rude-ends-battle.md deleted file mode 100644 index d0f88d689951..000000000000 --- a/.changeset/rude-ends-battle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"wrangler": patch ---- - -Fix `wrangler pipelines setup` failing for Data Catalog sinks on new buckets by using the correct R2 Catalog API error code (`40401`). diff --git a/.changeset/sharp-sheep-buy.md b/.changeset/sharp-sheep-buy.md deleted file mode 100644 index 020beebdd386..000000000000 --- a/.changeset/sharp-sheep-buy.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -"wrangler": minor ---- - -Add type generation for the experimental `secrets` configuration property - -When the new `secrets` property is defined, `wrangler types` now generates typed bindings from the names listed in `secrets.required`. - -When `secrets` is defined at any config level, type generation uses it exclusively and no longer infers secret names from `.dev.vars` or `.env` files. This enables running type generation in environments where these files are not present. - -Per-environment secrets are supported. Each named environment produces its own interface, and the aggregated `Env` marks secrets that only appear in some environments as optional. - -When `secrets` is not defined, the existing behavior is unchanged. - -```jsonc -// wrangler.jsonc -{ - "secrets": { - "required": ["API_KEY", "DB_PASSWORD"], - }, -} -``` diff --git a/.changeset/tricky-frogs-fry.md b/.changeset/tricky-frogs-fry.md deleted file mode 100644 index 6e051f8ac203..000000000000 --- a/.changeset/tricky-frogs-fry.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -"wrangler": minor ---- - -Add `wrangler containers registries credentials` command for generating temporary push/pull credentials - -This command generates short-lived credentials for authenticating with the Cloudflare managed registry (`registry.cloudflare.com`). Useful for CI/CD pipelines or local Docker authentication. - -```bash -# Generate push credentials (for uploading images) -wrangler containers registries credentials registry.cloudflare.com --push - -# Generate pull credentials (for downloading images) -wrangler containers registries credentials registry.cloudflare.com --pull - -# Generate credentials with both permissions -wrangler containers registries credentials registry.cloudflare.com --push --pull - -# Custom expiration (default 15) -wrangler containers registries credentials registry.cloudflare.com --push --expiration-minutes=30 -``` diff --git a/.changeset/wicked-wombats-decide.md b/.changeset/wicked-wombats-decide.md deleted file mode 100644 index 64ae580ef618..000000000000 --- a/.changeset/wicked-wombats-decide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@cloudflare/vitest-pool-workers": patch ---- - -Fix resource leak where remote proxy sessions were not disposed during pool shutdown, causing vitest processes to hang. diff --git a/.changeset/workflow-step-limits.md b/.changeset/workflow-step-limits.md deleted file mode 100644 index e44c431cf6d6..000000000000 --- a/.changeset/workflow-step-limits.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -"wrangler": minor -"miniflare": minor -"@cloudflare/workflows-shared": minor ---- - -Add configurable step limits for Workflows - -You can now set a maximum number of steps for a Workflow instance via the `limits.steps` configuration in your Wrangler config. When a Workflow instance exceeds this limit, it will fail with an error indicating the limit was reached. - -```jsonc -// wrangler.jsonc -{ - "workflows": [ - { - "binding": "MY_WORKFLOW", - "name": "my-workflow", - "class_name": "MyWorkflow", - "limits": { - "steps": 5000, - }, - }, - ], -} -``` - -The `steps` value must be an integer between 1 and 25,000. If not specified, the default limit of 10,000 steps is used. Step limits are also enforced in local development via `wrangler dev`. diff --git a/packages/containers-shared/CHANGELOG.md b/packages/containers-shared/CHANGELOG.md index 1bd70d3fab10..2b6861b2ed20 100644 --- a/packages/containers-shared/CHANGELOG.md +++ b/packages/containers-shared/CHANGELOG.md @@ -1,5 +1,32 @@ # @cloudflare/containers-shared +## 0.10.0 + +### Minor Changes + +- [#12649](https://github.com/cloudflare/workers-sdk/pull/12649) [`35b2c56`](https://github.com/cloudflare/workers-sdk/commit/35b2c56cdef6f4e7d33a885959f4ce8fc01201d0) Thanks [@gabivlj](https://github.com/gabivlj)! - Add experimental support for containers to workers communication with interceptOutboundHttp + + This feature is experimental and requires adding the "experimental" compatibility flag to your Wrangler configuration. + +### Patch Changes + +- [#11332](https://github.com/cloudflare/workers-sdk/pull/11332) [`6a8aa5f`](https://github.com/cloudflare/workers-sdk/commit/6a8aa5f28fdf8e8392b1e279a8f679e9698c4671) Thanks [@nikitassharma](https://github.com/nikitassharma)! - Users are now able to configure DockerHub credentials and have containers reference images stored there. + + DockerHub can be configured as follows: + + ```sh + echo $PAT_TOKEN | npx wrangler@latest containers registries configure docker.io --dockerhub-username=user --secret-name=DockerHub_PAT_Token + ``` + + Containers can then specify an image from DockerHub in their `wrangler.jsonc` as follows: + + ```jsonc + "containers": { + "image": "docker.io/namespace/image:tag", + ... + } + ``` + ## 0.9.0 ### Minor Changes diff --git a/packages/containers-shared/package.json b/packages/containers-shared/package.json index b3f3289432b2..cd55dba2fcec 100644 --- a/packages/containers-shared/package.json +++ b/packages/containers-shared/package.json @@ -1,6 +1,6 @@ { "name": "@cloudflare/containers-shared", - "version": "0.9.0", + "version": "0.10.0", "private": true, "description": "Package that contains shared container functionality for Cloudflare Workers SDK.", "homepage": "https://github.com/cloudflare/workers-sdk/tree/main/packages/containers-shared#readme", diff --git a/packages/create-cloudflare/CHANGELOG.md b/packages/create-cloudflare/CHANGELOG.md index c7a392277987..7f448dfcf08e 100644 --- a/packages/create-cloudflare/CHANGELOG.md +++ b/packages/create-cloudflare/CHANGELOG.md @@ -1,5 +1,71 @@ # create-cloudflare +## 2.64.5 + +### Patch Changes + +- [#12713](https://github.com/cloudflare/workers-sdk/pull/12713) [`f498237`](https://github.com/cloudflare/workers-sdk/commit/f498237074b00d97874cb145b4daf5e5556bbdae) Thanks [@dependabot](https://github.com/apps/dependabot)! - Update dependencies of "create-cloudflare" + + The following dependency versions have been updated: + + | Dependency | From | To | + | --------------- | ------ | ------ | + | @angular/create | 21.1.4 | 21.2.0 | + +- [#12715](https://github.com/cloudflare/workers-sdk/pull/12715) [`8d0c835`](https://github.com/cloudflare/workers-sdk/commit/8d0c8350f49638413d1a2359c07fef9b4745619d) Thanks [@dependabot](https://github.com/apps/dependabot)! - Update dependencies of "create-cloudflare" + + The following dependency versions have been updated: + + | Dependency | From | To | + | ---------- | ------ | ------ | + | create-vue | 3.21.1 | 3.22.0 | + +- [#12716](https://github.com/cloudflare/workers-sdk/pull/12716) [`1c2d93d`](https://github.com/cloudflare/workers-sdk/commit/1c2d93d28d0e9dac9d98442387686e37b7505b94) Thanks [@dependabot](https://github.com/apps/dependabot)! - Update dependencies of "create-cloudflare" + + The following dependency versions have been updated: + + | Dependency | From | To | + | ------------------- | ------ | ------ | + | create-react-router | 7.13.0 | 7.13.1 | + +- [#12717](https://github.com/cloudflare/workers-sdk/pull/12717) [`8e738f8`](https://github.com/cloudflare/workers-sdk/commit/8e738f82f4e16f29eb08854f9576ee3132933e00) Thanks [@dependabot](https://github.com/apps/dependabot)! - Update dependencies of "create-cloudflare" + + The following dependency versions have been updated: + + | Dependency | From | To | + | ------------- | ----- | ----- | + | create-analog | 2.2.3 | 2.3.1 | + +- [#12718](https://github.com/cloudflare/workers-sdk/pull/12718) [`62e20c1`](https://github.com/cloudflare/workers-sdk/commit/62e20c19abcb32c6affb8c840a325fbbc2391c71) Thanks [@dependabot](https://github.com/apps/dependabot)! - Update dependencies of "create-cloudflare" + + The following dependency versions have been updated: + + | Dependency | From | To | + | ---------- | ------ | ------ | + | sv | 0.12.2 | 0.12.4 | + +- [#12719](https://github.com/cloudflare/workers-sdk/pull/12719) [`554c5f3`](https://github.com/cloudflare/workers-sdk/commit/554c5f3e68170a86a4b77da875b2c33be4151822) Thanks [@dependabot](https://github.com/apps/dependabot)! - Update dependencies of "create-cloudflare" + + The following dependency versions have been updated: + + | Dependency | From | To | + | ----------- | ------- | ------- | + | create-vike | 0.0.581 | 0.0.591 | + +- [#12720](https://github.com/cloudflare/workers-sdk/pull/12720) [`a3ff7d4`](https://github.com/cloudflare/workers-sdk/commit/a3ff7d48b186a15915859f2069372e96a5cf8707) Thanks [@dependabot](https://github.com/apps/dependabot)! - Update dependencies of "create-cloudflare" + + The following dependency versions have been updated: + + | Dependency | From | To | + | ----------- | ---------------------- | ---------------------- | + | create-waku | 0.12.5-1.0.0-alpha.4-0 | 0.12.5-1.0.0-alpha.5-0 | + +- [#12728](https://github.com/cloudflare/workers-sdk/pull/12728) [`bbe09b6`](https://github.com/cloudflare/workers-sdk/commit/bbe09b619f9509fb9d392b6984dd066f93217b2f) Thanks [@jamesopstad](https://github.com/jamesopstad)! - Update SolidStart template for compatibility with v2. + + SolidStart v2 uses the `nitro` Vite plugin so we now update the Nitro config in `vite.config.ts` rather than `app.config.ts`. + +- [#12692](https://github.com/cloudflare/workers-sdk/pull/12692) [`f671934`](https://github.com/cloudflare/workers-sdk/commit/f671934de19985285453af15f396b228b4a0858b) Thanks [@roli-lpci](https://github.com/roli-lpci)! - Remove unused `chalk` dependency from create-cloudflare. + ## 2.64.4 ### Patch Changes diff --git a/packages/create-cloudflare/package.json b/packages/create-cloudflare/package.json index b95775d1159e..4e81708da68c 100644 --- a/packages/create-cloudflare/package.json +++ b/packages/create-cloudflare/package.json @@ -1,6 +1,6 @@ { "name": "create-cloudflare", - "version": "2.64.4", + "version": "2.64.5", "description": "A CLI for creating and deploying new applications to Cloudflare.", "keywords": [ "cloudflare", diff --git a/packages/miniflare/CHANGELOG.md b/packages/miniflare/CHANGELOG.md index 5d29fd1574a6..99c19cb922b8 100644 --- a/packages/miniflare/CHANGELOG.md +++ b/packages/miniflare/CHANGELOG.md @@ -1,5 +1,52 @@ # miniflare +## 4.20260301.1 + +### Minor Changes + +- [#12649](https://github.com/cloudflare/workers-sdk/pull/12649) [`35b2c56`](https://github.com/cloudflare/workers-sdk/commit/35b2c56cdef6f4e7d33a885959f4ce8fc01201d0) Thanks [@gabivlj](https://github.com/gabivlj)! - Add experimental support for containers to workers communication with interceptOutboundHttp + + This feature is experimental and requires adding the "experimental" compatibility flag to your Wrangler configuration. + +- [#10153](https://github.com/cloudflare/workers-sdk/pull/10153) [`5f7aaf2`](https://github.com/cloudflare/workers-sdk/commit/5f7aaf2a94fe99ec95d318b15ff864a9b07eccd6) Thanks [@mglewis](https://github.com/mglewis)! - Add Hosted Images CRUD operations to Images binding. + + This is an experimental API that only works locally for the moment. + +- [#12622](https://github.com/cloudflare/workers-sdk/pull/12622) [`bf9cb3d`](https://github.com/cloudflare/workers-sdk/commit/bf9cb3d32d4710dbefd7d3c412aefe1558ecd57e) Thanks [@LuisDuarte1](https://github.com/LuisDuarte1)! - Add configurable step limits for Workflows + + You can now set a maximum number of steps for a Workflow instance via the `limits.steps` configuration in your Wrangler config. When a Workflow instance exceeds this limit, it will fail with an error indicating the limit was reached. + + ```jsonc + // wrangler.jsonc + { + "workflows": [ + { + "binding": "MY_WORKFLOW", + "name": "my-workflow", + "class_name": "MyWorkflow", + "limits": { + "steps": 5000, + }, + }, + ], + } + ``` + + The `steps` value must be an integer between 1 and 25,000. If not specified, the default limit of 10,000 steps is used. Step limits are also enforced in local development via `wrangler dev`. + +### Patch Changes + +- [#12698](https://github.com/cloudflare/workers-sdk/pull/12698) [`209b396`](https://github.com/cloudflare/workers-sdk/commit/209b3963ccecbe7c9f96f1c4cc30e4682730f257) Thanks [@penalosa](https://github.com/penalosa)! - Update dependencies of "miniflare", "wrangler" + + The following dependency versions have been updated: + + | Dependency | From | To | + | ------------------------- | ------------ | ------------ | + | workerd | 1.20260305.0 | 1.20260226.1 | + | @cloudflare/workers-types | 4.20260305.0 | 4.20260226.1 | + +- [#12691](https://github.com/cloudflare/workers-sdk/pull/12691) [`596b8a0`](https://github.com/cloudflare/workers-sdk/commit/596b8a0cb2cb2cb5b9f7fefbe1e7fc638c7e934f) Thanks [@penalosa](https://github.com/penalosa)! - Remove temporary AI Search RPC workaround (no user-facing changes) + ## 4.20260305.0 ### Patch Changes diff --git a/packages/miniflare/package.json b/packages/miniflare/package.json index 5b87cb4044b4..cbf77d04f6a8 100644 --- a/packages/miniflare/package.json +++ b/packages/miniflare/package.json @@ -1,6 +1,6 @@ { "name": "miniflare", - "version": "4.20260305.0", + "version": "4.20260301.1", "description": "Fun, full-featured, fully-local simulator for Cloudflare Workers", "keywords": [ "cloudflare", diff --git a/packages/pages-shared/CHANGELOG.md b/packages/pages-shared/CHANGELOG.md index 78c39e805cdc..c6c22fb53b36 100644 --- a/packages/pages-shared/CHANGELOG.md +++ b/packages/pages-shared/CHANGELOG.md @@ -1,5 +1,12 @@ # @cloudflare/pages-shared +## 0.13.112 + +### Patch Changes + +- Updated dependencies [[`35b2c56`](https://github.com/cloudflare/workers-sdk/commit/35b2c56cdef6f4e7d33a885959f4ce8fc01201d0), [`5f7aaf2`](https://github.com/cloudflare/workers-sdk/commit/5f7aaf2a94fe99ec95d318b15ff864a9b07eccd6), [`209b396`](https://github.com/cloudflare/workers-sdk/commit/209b3963ccecbe7c9f96f1c4cc30e4682730f257), [`596b8a0`](https://github.com/cloudflare/workers-sdk/commit/596b8a0cb2cb2cb5b9f7fefbe1e7fc638c7e934f), [`bf9cb3d`](https://github.com/cloudflare/workers-sdk/commit/bf9cb3d32d4710dbefd7d3c412aefe1558ecd57e)]: + - miniflare@4.20260301.1 + ## 0.13.111 ### Patch Changes diff --git a/packages/pages-shared/package.json b/packages/pages-shared/package.json index 531edccb2479..c4ee4ade5b86 100644 --- a/packages/pages-shared/package.json +++ b/packages/pages-shared/package.json @@ -1,6 +1,6 @@ { "name": "@cloudflare/pages-shared", - "version": "0.13.111", + "version": "0.13.112", "repository": { "type": "git", "url": "https://github.com/cloudflare/workers-sdk.git", diff --git a/packages/vite-plugin-cloudflare/CHANGELOG.md b/packages/vite-plugin-cloudflare/CHANGELOG.md index e1bc64722e02..9b3bb5174987 100644 --- a/packages/vite-plugin-cloudflare/CHANGELOG.md +++ b/packages/vite-plugin-cloudflare/CHANGELOG.md @@ -1,5 +1,36 @@ # @cloudflare/vite-plugin +## 1.26.0 + +### Minor Changes + +- [#12649](https://github.com/cloudflare/workers-sdk/pull/12649) [`35b2c56`](https://github.com/cloudflare/workers-sdk/commit/35b2c56cdef6f4e7d33a885959f4ce8fc01201d0) Thanks [@gabivlj](https://github.com/gabivlj)! - Add experimental support for containers to workers communication with interceptOutboundHttp + + This feature is experimental and requires adding the "experimental" compatibility flag to your Wrangler configuration. + +- [#12701](https://github.com/cloudflare/workers-sdk/pull/12701) [`23a365a`](https://github.com/cloudflare/workers-sdk/commit/23a365a7e578ecb6735c1f05a204f5bf236b24f6) Thanks [@jamesopstad](https://github.com/jamesopstad)! - Add local dev validation for the experimental `secrets` configuration property + + When the new `secrets` property is defined, `wrangler dev` and `vite dev` now validate secrets declared in `secrets.required`. When required secrets are missing from `.dev.vars` or `.env`/`process.env`, a warning is logged listing the missing secret names. + + When `secrets` is defined, only the keys listed in `secrets.required` are loaded. Additional keys in `.dev.vars` or `.env` are excluded. If you are not using `.dev.vars`, keys listed in `secrets.required` are loaded from `process.env` as well as `.env`. The `CLOUDFLARE_INCLUDE_PROCESS_ENV` environment variable is therefore not needed when using this feature. + + When `secrets` is not defined, the existing behavior is unchanged. + + ```jsonc + // wrangler.jsonc + { + "secrets": { + "required": ["API_KEY", "DB_PASSWORD"], + }, + } + ``` + +### Patch Changes + +- Updated dependencies [[`6a8aa5f`](https://github.com/cloudflare/workers-sdk/commit/6a8aa5f28fdf8e8392b1e279a8f679e9698c4671), [`d672e2e`](https://github.com/cloudflare/workers-sdk/commit/d672e2ec47f87ed3403aa291fbb9f671970afbfe), [`35b2c56`](https://github.com/cloudflare/workers-sdk/commit/35b2c56cdef6f4e7d33a885959f4ce8fc01201d0), [`5f7aaf2`](https://github.com/cloudflare/workers-sdk/commit/5f7aaf2a94fe99ec95d318b15ff864a9b07eccd6), [`209b396`](https://github.com/cloudflare/workers-sdk/commit/209b3963ccecbe7c9f96f1c4cc30e4682730f257), [`23a365a`](https://github.com/cloudflare/workers-sdk/commit/23a365a7e578ecb6735c1f05a204f5bf236b24f6), [`596b8a0`](https://github.com/cloudflare/workers-sdk/commit/596b8a0cb2cb2cb5b9f7fefbe1e7fc638c7e934f), [`00e729e`](https://github.com/cloudflare/workers-sdk/commit/00e729eaa986b19f5573ed6fd52a3e8d33868378), [`0769056`](https://github.com/cloudflare/workers-sdk/commit/0769056523c43902b14bdd32330deda01acd65c4), [`150ef7b`](https://github.com/cloudflare/workers-sdk/commit/150ef7bcaa9ad2d2de661200ef87ea8f15c62a36), [`bf9cb3d`](https://github.com/cloudflare/workers-sdk/commit/bf9cb3d32d4710dbefd7d3c412aefe1558ecd57e)]: + - wrangler@4.70.0 + - miniflare@4.20260301.1 + ## 1.25.6 ### Patch Changes diff --git a/packages/vite-plugin-cloudflare/package.json b/packages/vite-plugin-cloudflare/package.json index aa2527114a23..8f1658d43511 100644 --- a/packages/vite-plugin-cloudflare/package.json +++ b/packages/vite-plugin-cloudflare/package.json @@ -1,6 +1,6 @@ { "name": "@cloudflare/vite-plugin", - "version": "1.25.6", + "version": "1.26.0", "description": "Cloudflare plugin for Vite", "keywords": [ "cloudflare", diff --git a/packages/vitest-pool-workers/CHANGELOG.md b/packages/vitest-pool-workers/CHANGELOG.md index 92cf88b0369f..39da5705c7c9 100644 --- a/packages/vitest-pool-workers/CHANGELOG.md +++ b/packages/vitest-pool-workers/CHANGELOG.md @@ -1,5 +1,15 @@ # @cloudflare/vitest-pool-workers +## 0.12.19 + +### Patch Changes + +- [#12682](https://github.com/cloudflare/workers-sdk/pull/12682) [`b5b91c9`](https://github.com/cloudflare/workers-sdk/commit/b5b91c970554ed8a8cc1648ebdc06107c1aa87b5) Thanks [@hiendv](https://github.com/hiendv)! - Fix resource leak where remote proxy sessions were not disposed during pool shutdown, causing vitest processes to hang. + +- Updated dependencies [[`6a8aa5f`](https://github.com/cloudflare/workers-sdk/commit/6a8aa5f28fdf8e8392b1e279a8f679e9698c4671), [`d672e2e`](https://github.com/cloudflare/workers-sdk/commit/d672e2ec47f87ed3403aa291fbb9f671970afbfe), [`35b2c56`](https://github.com/cloudflare/workers-sdk/commit/35b2c56cdef6f4e7d33a885959f4ce8fc01201d0), [`5f7aaf2`](https://github.com/cloudflare/workers-sdk/commit/5f7aaf2a94fe99ec95d318b15ff864a9b07eccd6), [`209b396`](https://github.com/cloudflare/workers-sdk/commit/209b3963ccecbe7c9f96f1c4cc30e4682730f257), [`23a365a`](https://github.com/cloudflare/workers-sdk/commit/23a365a7e578ecb6735c1f05a204f5bf236b24f6), [`596b8a0`](https://github.com/cloudflare/workers-sdk/commit/596b8a0cb2cb2cb5b9f7fefbe1e7fc638c7e934f), [`00e729e`](https://github.com/cloudflare/workers-sdk/commit/00e729eaa986b19f5573ed6fd52a3e8d33868378), [`0769056`](https://github.com/cloudflare/workers-sdk/commit/0769056523c43902b14bdd32330deda01acd65c4), [`150ef7b`](https://github.com/cloudflare/workers-sdk/commit/150ef7bcaa9ad2d2de661200ef87ea8f15c62a36), [`bf9cb3d`](https://github.com/cloudflare/workers-sdk/commit/bf9cb3d32d4710dbefd7d3c412aefe1558ecd57e)]: + - wrangler@4.70.0 + - miniflare@4.20260301.1 + ## 0.12.18 ### Patch Changes diff --git a/packages/vitest-pool-workers/package.json b/packages/vitest-pool-workers/package.json index 1ad76e4b01ac..84ba7d03c9c9 100644 --- a/packages/vitest-pool-workers/package.json +++ b/packages/vitest-pool-workers/package.json @@ -1,6 +1,6 @@ { "name": "@cloudflare/vitest-pool-workers", - "version": "0.12.18", + "version": "0.12.19", "description": "Workers Vitest integration for writing Vitest unit and integration tests that run inside the Workers runtime", "keywords": [ "cloudflare", diff --git a/packages/workflows-shared/CHANGELOG.md b/packages/workflows-shared/CHANGELOG.md index c1e888fa1cb6..7fe86fa1b74b 100644 --- a/packages/workflows-shared/CHANGELOG.md +++ b/packages/workflows-shared/CHANGELOG.md @@ -1,5 +1,31 @@ # @cloudflare/workflows-shared +## 0.5.0 + +### Minor Changes + +- [#12622](https://github.com/cloudflare/workers-sdk/pull/12622) [`bf9cb3d`](https://github.com/cloudflare/workers-sdk/commit/bf9cb3d32d4710dbefd7d3c412aefe1558ecd57e) Thanks [@LuisDuarte1](https://github.com/LuisDuarte1)! - Add configurable step limits for Workflows + + You can now set a maximum number of steps for a Workflow instance via the `limits.steps` configuration in your Wrangler config. When a Workflow instance exceeds this limit, it will fail with an error indicating the limit was reached. + + ```jsonc + // wrangler.jsonc + { + "workflows": [ + { + "binding": "MY_WORKFLOW", + "name": "my-workflow", + "class_name": "MyWorkflow", + "limits": { + "steps": 5000, + }, + }, + ], + } + ``` + + The `steps` value must be an integer between 1 and 25,000. If not specified, the default limit of 10,000 steps is used. Step limits are also enforced in local development via `wrangler dev`. + ## 0.4.0 ### Minor Changes diff --git a/packages/workflows-shared/package.json b/packages/workflows-shared/package.json index 2b972fc90b3c..3f0264321961 100644 --- a/packages/workflows-shared/package.json +++ b/packages/workflows-shared/package.json @@ -1,6 +1,6 @@ { "name": "@cloudflare/workflows-shared", - "version": "0.4.0", + "version": "0.5.0", "private": true, "description": "Package that is used at Cloudflare to power some internal features of Cloudflare Workflows.", "keywords": [ diff --git a/packages/wrangler/CHANGELOG.md b/packages/wrangler/CHANGELOG.md index 3bb1647dbc23..2440736f0cfd 100644 --- a/packages/wrangler/CHANGELOG.md +++ b/packages/wrangler/CHANGELOG.md @@ -1,5 +1,128 @@ # wrangler +## 4.70.0 + +### Minor Changes + +- [#11332](https://github.com/cloudflare/workers-sdk/pull/11332) [`6a8aa5f`](https://github.com/cloudflare/workers-sdk/commit/6a8aa5f28fdf8e8392b1e279a8f679e9698c4671) Thanks [@nikitassharma](https://github.com/nikitassharma)! - Users are now able to configure DockerHub credentials and have containers reference images stored there. + + DockerHub can be configured as follows: + + ```sh + echo $PAT_TOKEN | npx wrangler@latest containers registries configure docker.io --dockerhub-username=user --secret-name=DockerHub_PAT_Token + ``` + + Containers can then specify an image from DockerHub in their `wrangler.jsonc` as follows: + + ```jsonc + "containers": { + "image": "docker.io/namespace/image:tag", + ... + } + ``` + +- [#12649](https://github.com/cloudflare/workers-sdk/pull/12649) [`35b2c56`](https://github.com/cloudflare/workers-sdk/commit/35b2c56cdef6f4e7d33a885959f4ce8fc01201d0) Thanks [@gabivlj](https://github.com/gabivlj)! - Add experimental support for containers to workers communication with interceptOutboundHttp + + This feature is experimental and requires adding the "experimental" compatibility flag to your Wrangler configuration. + +- [#12701](https://github.com/cloudflare/workers-sdk/pull/12701) [`23a365a`](https://github.com/cloudflare/workers-sdk/commit/23a365a7e578ecb6735c1f05a204f5bf236b24f6) Thanks [@jamesopstad](https://github.com/jamesopstad)! - Add local dev validation for the experimental `secrets` configuration property + + When the new `secrets` property is defined, `wrangler dev` and `vite dev` now validate secrets declared in `secrets.required`. When required secrets are missing from `.dev.vars` or `.env`/`process.env`, a warning is logged listing the missing secret names. + + When `secrets` is defined, only the keys listed in `secrets.required` are loaded. Additional keys in `.dev.vars` or `.env` are excluded. If you are not using `.dev.vars`, keys listed in `secrets.required` are loaded from `process.env` as well as `.env`. The `CLOUDFLARE_INCLUDE_PROCESS_ENV` environment variable is therefore not needed when using this feature. + + When `secrets` is not defined, the existing behavior is unchanged. + + ```jsonc + // wrangler.jsonc + { + "secrets": { + "required": ["API_KEY", "DB_PASSWORD"], + }, + } + ``` + +- [#12695](https://github.com/cloudflare/workers-sdk/pull/12695) [`0769056`](https://github.com/cloudflare/workers-sdk/commit/0769056523c43902b14bdd32330deda01acd65c4) Thanks [@jamesopstad](https://github.com/jamesopstad)! - Add type generation for the experimental `secrets` configuration property + + When the new `secrets` property is defined, `wrangler types` now generates typed bindings from the names listed in `secrets.required`. + + When `secrets` is defined at any config level, type generation uses it exclusively and no longer infers secret names from `.dev.vars` or `.env` files. This enables running type generation in environments where these files are not present. + + Per-environment secrets are supported. Each named environment produces its own interface, and the aggregated `Env` marks secrets that only appear in some environments as optional. + + When `secrets` is not defined, the existing behavior is unchanged. + + ```jsonc + // wrangler.jsonc + { + "secrets": { + "required": ["API_KEY", "DB_PASSWORD"], + }, + } + ``` + +- [#12693](https://github.com/cloudflare/workers-sdk/pull/12693) [`150ef7b`](https://github.com/cloudflare/workers-sdk/commit/150ef7bcaa9ad2d2de661200ef87ea8f15c62a36) Thanks [@martinezjandrew](https://github.com/martinezjandrew)! - Add `wrangler containers registries credentials` command for generating temporary push/pull credentials + + This command generates short-lived credentials for authenticating with the Cloudflare managed registry (`registry.cloudflare.com`). Useful for CI/CD pipelines or local Docker authentication. + + ```bash + # Generate push credentials (for uploading images) + wrangler containers registries credentials registry.cloudflare.com --push + + # Generate pull credentials (for downloading images) + wrangler containers registries credentials registry.cloudflare.com --pull + + # Generate credentials with both permissions + wrangler containers registries credentials registry.cloudflare.com --push --pull + + # Custom expiration (default 15) + wrangler containers registries credentials registry.cloudflare.com --push --expiration-minutes=30 + ``` + +- [#12622](https://github.com/cloudflare/workers-sdk/pull/12622) [`bf9cb3d`](https://github.com/cloudflare/workers-sdk/commit/bf9cb3d32d4710dbefd7d3c412aefe1558ecd57e) Thanks [@LuisDuarte1](https://github.com/LuisDuarte1)! - Add configurable step limits for Workflows + + You can now set a maximum number of steps for a Workflow instance via the `limits.steps` configuration in your Wrangler config. When a Workflow instance exceeds this limit, it will fail with an error indicating the limit was reached. + + ```jsonc + // wrangler.jsonc + { + "workflows": [ + { + "binding": "MY_WORKFLOW", + "name": "my-workflow", + "class_name": "MyWorkflow", + "limits": { + "steps": 5000, + }, + }, + ], + } + ``` + + The `steps` value must be an integer between 1 and 25,000. If not specified, the default limit of 10,000 steps is used. Step limits are also enforced in local development via `wrangler dev`. + +### Patch Changes + +- [#12733](https://github.com/cloudflare/workers-sdk/pull/12733) [`d672e2e`](https://github.com/cloudflare/workers-sdk/commit/d672e2ec47f87ed3403aa291fbb9f671970afbfe) Thanks [@dario-piotrowicz](https://github.com/dario-piotrowicz)! - Fix SolidStart autoconfig for projects using version 2.0.0-alpha or later + + SolidStart v2.0.0-alpha introduced a breaking change where configuration moved from `app.config.(js|ts)` to `vite.config.(js|ts)`. Wrangler's autoconfig now detects the installed SolidStart version and based on it updates the appropriate configuration file + +- [#12698](https://github.com/cloudflare/workers-sdk/pull/12698) [`209b396`](https://github.com/cloudflare/workers-sdk/commit/209b3963ccecbe7c9f96f1c4cc30e4682730f257) Thanks [@penalosa](https://github.com/penalosa)! - Update dependencies of "miniflare", "wrangler" + + The following dependency versions have been updated: + + | Dependency | From | To | + | ------------------------- | ------------ | ------------ | + | workerd | 1.20260305.0 | 1.20260226.1 | + | @cloudflare/workers-types | 4.20260305.0 | 4.20260226.1 | + +- [#12691](https://github.com/cloudflare/workers-sdk/pull/12691) [`596b8a0`](https://github.com/cloudflare/workers-sdk/commit/596b8a0cb2cb2cb5b9f7fefbe1e7fc638c7e934f) Thanks [@penalosa](https://github.com/penalosa)! - Remove temporary AI Search RPC workaround (no user-facing changes) + +- [#12694](https://github.com/cloudflare/workers-sdk/pull/12694) [`00e729e`](https://github.com/cloudflare/workers-sdk/commit/00e729eaa986b19f5573ed6fd52a3e8d33868378) Thanks [@garvit-gupta](https://github.com/garvit-gupta)! - Fix `wrangler pipelines setup` failing for Data Catalog sinks on new buckets by using the correct R2 Catalog API error code (`40401`). + +- Updated dependencies [[`35b2c56`](https://github.com/cloudflare/workers-sdk/commit/35b2c56cdef6f4e7d33a885959f4ce8fc01201d0), [`5f7aaf2`](https://github.com/cloudflare/workers-sdk/commit/5f7aaf2a94fe99ec95d318b15ff864a9b07eccd6), [`209b396`](https://github.com/cloudflare/workers-sdk/commit/209b3963ccecbe7c9f96f1c4cc30e4682730f257), [`596b8a0`](https://github.com/cloudflare/workers-sdk/commit/596b8a0cb2cb2cb5b9f7fefbe1e7fc638c7e934f), [`bf9cb3d`](https://github.com/cloudflare/workers-sdk/commit/bf9cb3d32d4710dbefd7d3c412aefe1558ecd57e)]: + - miniflare@4.20260301.1 + ## 4.69.0 ### Minor Changes diff --git a/packages/wrangler/package.json b/packages/wrangler/package.json index 728e1c7256a2..9625683fbd7c 100644 --- a/packages/wrangler/package.json +++ b/packages/wrangler/package.json @@ -1,6 +1,6 @@ { "name": "wrangler", - "version": "4.69.0", + "version": "4.70.0", "description": "Command-line interface for all things Cloudflare Workers", "keywords": [ "wrangler",