Skip to content

Commit 196ccbf

Browse files
authored
PIPE-391: Better error messages and client-side validation (#10833)
Some field validation has been moved to the client side for more immediate feedback. ``` ./bin/wrangler.js pipelines setup ⛅️ wrangler 4.40.3 ─────────────────── ▲ [WARNING] 🚧 `wrangler pipelines setup` is an open-beta command. Please report any issues to https://github.com/cloudflare/workers-sdk/issues/new/choose 🚀 Welcome to Cloudflare Pipelines Setup! This will guide you through creating a complete pipeline: stream → pipeline → sink ✔ What would you like to name your pipeline? … this-a-test ✘ [ERROR] Pipeline name must contain only letters, numbers, and underscores ```
1 parent 51f9dc1 commit 196ccbf

File tree

6 files changed

+52
-6
lines changed

6 files changed

+52
-6
lines changed

.changeset/some-spies-greet.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"wrangler": patch
3+
---
4+
5+
Validate Pipeline entity names in Wrangler config before sending to the API.

packages/wrangler/src/__tests__/pipelines.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,14 @@ describe("wrangler pipelines", () => {
11231123
);
11241124
});
11251125

1126+
it("should error when name contains invalid characters", async () => {
1127+
await expect(
1128+
runWrangler("pipelines streams create my-stream")
1129+
).rejects.toThrowErrorMatchingInlineSnapshot(
1130+
`[Error: stream name must contain only letters, numbers, and underscores]`
1131+
);
1132+
});
1133+
11261134
it("should create stream with default settings", async () => {
11271135
setIsTTY(true);
11281136
mockConfirm({
@@ -1564,6 +1572,16 @@ describe("wrangler pipelines", () => {
15641572
return requests;
15651573
}
15661574

1575+
it("should error when name contains invalid characters", async () => {
1576+
await expect(
1577+
runWrangler(
1578+
"pipelines sinks create my-sink --bucket my-bucket --type r2"
1579+
)
1580+
).rejects.toThrowErrorMatchingInlineSnapshot(
1581+
`[Error: sink name must contain only letters, numbers, and underscores]`
1582+
);
1583+
});
1584+
15671585
it("should error when type is missing", async () => {
15681586
await expect(
15691587
runWrangler("pipelines sinks create my_sink --bucket my-bucket")

packages/wrangler/src/pipelines/cli/setup.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
} from "../client";
1717
import { SINK_DEFAULTS } from "../defaults";
1818
import { authorizeR2Bucket } from "../index";
19+
import { validateEntityName } from "../validate";
1920
import {
2021
displayUsageExamples,
2122
formatSchemaFieldsForTable,
@@ -91,11 +92,7 @@ async function setupPipelineNaming(
9192
throw new UserError("Pipeline name is required");
9293
}
9394

94-
if (!/^[a-zA-Z0-9_-]+$/.test(pipelineName)) {
95-
throw new UserError(
96-
"Pipeline name must contain only letters, numbers, hyphens, and underscores"
97-
);
98-
}
95+
validateEntityName("pipeline", pipelineName);
9996

10097
const streamName = `${pipelineName}_stream`;
10198
const sinkName = `${pipelineName}_sink`;

packages/wrangler/src/pipelines/cli/sinks/create.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { requireAuth } from "../../../user";
66
import { createSink } from "../../client";
77
import { applyDefaultsToSink, SINK_DEFAULTS } from "../../defaults";
88
import { authorizeR2Bucket } from "../../index";
9+
import { validateEntityName } from "../../validate";
910
import { displaySinkConfiguration } from "./utils";
1011
import type { CreateSinkRequest, SinkFormat } from "../../types";
1112

@@ -102,6 +103,8 @@ export const pipelinesSinksCreateCommand = createCommand({
102103
},
103104
},
104105
validateArgs: (args) => {
106+
validateEntityName("sink", args.sink);
107+
105108
const sinkType = parseSinkType(args.type);
106109

107110
if (!isValidR2BucketName(args.bucket)) {

packages/wrangler/src/pipelines/cli/streams/create.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { logger } from "../../../logger";
66
import { parseJSON } from "../../../parse";
77
import { requireAuth } from "../../../user";
88
import { createStream } from "../../client";
9+
import { validateEntityName } from "../../validate";
910
import { displayStreamConfiguration } from "./utils";
1011
import type { CreateStreamRequest, SchemaField } from "../../types";
1112

@@ -42,6 +43,9 @@ export const pipelinesStreamsCreateCommand = createCommand({
4243
array: true,
4344
},
4445
},
46+
validateArgs: (args) => {
47+
validateEntityName("stream", args.stream);
48+
},
4549
async handler(args, { config }) {
4650
await requireAuth(config);
4751
const streamName = args.stream;

packages/wrangler/src/pipelines/validate.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
1-
import { UserError } from "../errors";
1+
import { CommandLineArgsError, UserError } from "../errors";
22

3+
/**
4+
* Validate entity name is used for Pipelines V1 API entities such as sources, sinks and pipelines.
5+
* @param label the name of the entity to validate
6+
* @param name the user provided name
7+
*/
8+
export function validateEntityName(label: string, name: string) {
9+
if (!name.match(/^[a-zA-Z0-9_]+$/)) {
10+
throw new CommandLineArgsError(
11+
`${label} name must contain only letters, numbers, and underscores`
12+
);
13+
}
14+
}
15+
16+
/**
17+
* Validate name is used for legacy Pipelines. This validation should not be used for Pipelines V1 entities.
18+
* @param label the name of the entity to validate
19+
* @param name the user provided name
20+
* @deprecated use validateEntityName instead
21+
*/
322
export function validateName(label: string, name: string) {
423
if (!name.match(/^[a-zA-Z0-9-]+$/)) {
524
throw new UserError(`Must provide a valid ${label}`);

0 commit comments

Comments
 (0)