Skip to content

Commit 7d8d4a6

Browse files
authored
[Wrangler] Add Workflows sendEvent wrangler command (#11590)
* [Wrangler] Add Workflows sendEvent wrangler command * Apply comment suggestions * Apply review suggestions * Refactor some repeated code and remove localeCompare * Revert removal of localeCompare
1 parent 6b28de1 commit 7d8d4a6

File tree

11 files changed

+225
-167
lines changed

11 files changed

+225
-167
lines changed

.changeset/rude-carrots-exist.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"wrangler": minor
3+
---
4+
5+
Add Workflows send-event to wrangler commands.

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

Lines changed: 75 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ describe("wrangler workflows", () => {
4444
);
4545
};
4646

47-
const mockPatchRequest = async (expectedInstance: string) => {
47+
const mockChangeStatusRequest = async (expectedInstance: string) => {
4848
msw.use(
4949
http.patch(
5050
`*/accounts/:accountId/workflows/some-workflow/instances/:instanceId/status`,
@@ -62,6 +62,28 @@ describe("wrangler workflows", () => {
6262
);
6363
};
6464

65+
const mockSendEventRequest = async (
66+
expectedInstance: string,
67+
event: string
68+
) => {
69+
msw.use(
70+
http.post(
71+
`*/accounts/:accountId/workflows/some-workflow/instances/:instanceId/events/:event`,
72+
async ({ params }) => {
73+
expect(params.instanceId).toEqual(expectedInstance);
74+
expect(params.event).toEqual(event);
75+
return HttpResponse.json({
76+
success: true,
77+
errors: [],
78+
messages: [],
79+
result: {},
80+
});
81+
},
82+
{ once: true }
83+
)
84+
);
85+
};
86+
6587
const mockDeleteWorkflowRequest = async (workflowName: string) => {
6688
msw.use(
6789
http.delete(
@@ -145,19 +167,19 @@ describe("wrangler workflows", () => {
145167
await runWrangler(`workflows instances`);
146168
await endEventLoop();
147169

148-
expect(std.out).toMatchInlineSnapshot(
149-
`
170+
expect(std.out).toMatchInlineSnapshot(`
150171
"wrangler workflows instances
151172
152173
Manage Workflow instances
153174
154175
COMMANDS
155-
wrangler workflows instances list <name> Instance related commands (list, describe, terminate, pause, resume)
156-
wrangler workflows instances describe <name> [id] Describe a workflow instance - see its logs, retries and errors
157-
wrangler workflows instances terminate <name> <id> Terminate a workflow instance
158-
wrangler workflows instances restart <name> <id> Restart a workflow instance
159-
wrangler workflows instances pause <name> <id> Pause a workflow instance
160-
wrangler workflows instances resume <name> <id> Resume a workflow instance
176+
wrangler workflows instances list <name> Instance related commands (list, describe, terminate, pause, resume)
177+
wrangler workflows instances describe <name> [id] Describe a workflow instance - see its logs, retries and errors
178+
wrangler workflows instances send-event <name> <id> Send an event to a workflow instance
179+
wrangler workflows instances terminate <name> <id> Terminate a workflow instance
180+
wrangler workflows instances restart <name> <id> Restart a workflow instance
181+
wrangler workflows instances pause <name> <id> Pause a workflow instance
182+
wrangler workflows instances resume <name> <id> Resume a workflow instance
161183
162184
GLOBAL FLAGS
163185
-c, --config Path to Wrangler configuration file [string]
@@ -166,8 +188,7 @@ describe("wrangler workflows", () => {
166188
--env-file Path to an .env file to load - can be specified multiple times - values from earlier files are overridden by values in later files [array]
167189
-h, --help Show help [boolean]
168190
-v, --version Show version number [boolean]"
169-
`
170-
);
191+
`);
171192
});
172193
});
173194

@@ -480,6 +501,45 @@ describe("wrangler workflows", () => {
480501
});
481502
});
482503

504+
describe("instances send-event", () => {
505+
const mockInstances: Instance[] = [
506+
{
507+
id: "foo",
508+
created_on: mockCreateDate.toISOString(),
509+
modified_on: mockModifiedDate.toISOString(),
510+
workflow_id: "b",
511+
version_id: "c",
512+
status: "running",
513+
},
514+
];
515+
516+
it("should send an event without payload to the bar instance given a name", async () => {
517+
writeWranglerConfig();
518+
await mockGetInstances(mockInstances);
519+
await mockSendEventRequest("bar", "my-event");
520+
521+
await runWrangler(
522+
"workflows instances send-event some-workflow bar --type my-event"
523+
);
524+
expect(std.info).toMatchInlineSnapshot(
525+
`"📤 The event with type \\"my-event\\" was sent to the instance \\"bar\\" from some-workflow"`
526+
);
527+
});
528+
529+
it("should send an event with payload to the bar instance given a name", async () => {
530+
writeWranglerConfig();
531+
await mockGetInstances(mockInstances);
532+
await mockSendEventRequest("bar", "my-event");
533+
534+
await runWrangler(
535+
`workflows instances send-event some-workflow bar --type my-event --payload '{"key": "value"}'`
536+
);
537+
expect(std.info).toMatchInlineSnapshot(
538+
`"📤 The event with type \\"my-event\\" and payload \\"{\\"key\\": \\"value\\"}\\" was sent to the instance \\"bar\\" from some-workflow"`
539+
);
540+
});
541+
});
542+
483543
describe("instances pause", () => {
484544
const mockInstances: Instance[] = [
485545
{
@@ -503,7 +563,7 @@ describe("wrangler workflows", () => {
503563
it("should get and pause the bar instance given a name", async () => {
504564
writeWranglerConfig();
505565
await mockGetInstances(mockInstances);
506-
await mockPatchRequest("bar");
566+
await mockChangeStatusRequest("bar");
507567

508568
await runWrangler(`workflows instances pause some-workflow bar`);
509569
expect(std.info).toMatchInlineSnapshot(
@@ -535,7 +595,7 @@ describe("wrangler workflows", () => {
535595
it("should get and resume the bar instance given a name", async () => {
536596
writeWranglerConfig();
537597
await mockGetInstances(mockInstances);
538-
await mockPatchRequest("bar");
598+
await mockChangeStatusRequest("bar");
539599

540600
await runWrangler(`workflows instances resume some-workflow bar`);
541601
expect(std.info).toMatchInlineSnapshot(
@@ -567,7 +627,7 @@ describe("wrangler workflows", () => {
567627
it("should get and terminate the bar instance given a name", async () => {
568628
writeWranglerConfig();
569629
await mockGetInstances(mockInstances);
570-
await mockPatchRequest("bar");
630+
await mockChangeStatusRequest("bar");
571631

572632
await runWrangler(`workflows instances terminate some-workflow bar`);
573633
expect(std.info).toMatchInlineSnapshot(
@@ -599,7 +659,7 @@ describe("wrangler workflows", () => {
599659
it("should get and restart the bar instance given a name", async () => {
600660
writeWranglerConfig();
601661
await mockGetInstances(mockInstances);
602-
await mockPatchRequest("bar");
662+
await mockChangeStatusRequest("bar");
603663

604664
await runWrangler(`workflows instances restart some-workflow bar`);
605665
expect(std.info).toMatchInlineSnapshot(

packages/wrangler/src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ import { workflowsInstancesListCommand } from "./workflows/commands/instances/li
329329
import { workflowsInstancesPauseCommand } from "./workflows/commands/instances/pause";
330330
import { workflowsInstancesRestartCommand } from "./workflows/commands/instances/restart";
331331
import { workflowsInstancesResumeCommand } from "./workflows/commands/instances/resume";
332+
import { workflowsInstancesSendEventCommand } from "./workflows/commands/instances/send-event";
332333
import { workflowsInstancesTerminateCommand } from "./workflows/commands/instances/terminate";
333334
import { workflowsInstancesTerminateAllCommand } from "./workflows/commands/instances/terminate-all";
334335
import { workflowsListCommand } from "./workflows/commands/list";
@@ -1375,6 +1376,10 @@ export function createCLIParser(argv: string[]) {
13751376
command: "wrangler workflows instances describe",
13761377
definition: workflowsInstancesDescribeCommand,
13771378
},
1379+
{
1380+
command: "wrangler workflows instances send-event",
1381+
definition: workflowsInstancesSendEventCommand,
1382+
},
13781383
{
13791384
command: "wrangler workflows instances terminate",
13801385
definition: workflowsInstancesTerminateCommand,

packages/wrangler/src/workflows/commands/instances/describe.ts

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ import {
1515
emojifyInstanceStatus,
1616
emojifyInstanceTriggerName,
1717
emojifyStepType,
18+
getInstanceIdFromArgs,
1819
} from "../../utils";
1920
import type {
20-
Instance,
2121
InstanceSleepLog,
2222
InstanceStatusAndLogs,
2323
InstanceStepLog,
@@ -63,26 +63,7 @@ export const workflowsInstancesDescribeCommand = createCommand({
6363
async handler(args, { config }) {
6464
const accountId = await requireAuth(config);
6565

66-
let id = args.id;
67-
68-
if (id == "latest") {
69-
const instances = (
70-
await fetchResult<Instance[]>(
71-
config,
72-
`/accounts/${accountId}/workflows/${args.name}/instances`
73-
)
74-
).sort((a, b) => b.created_on.localeCompare(a.created_on));
75-
76-
if (instances.length == 0) {
77-
logger.error(
78-
`There are no deployed instances in workflow "${args.name}"`
79-
);
80-
return;
81-
}
82-
83-
logRaw("Describing latest instance:");
84-
id = instances[0].id;
85-
}
66+
const id = await getInstanceIdFromArgs(accountId, args, config);
8667

8768
const instance = await fetchResult<InstanceStatusAndLogs>(
8869
config,
@@ -136,6 +117,7 @@ export const workflowsInstancesDescribeCommand = createCommand({
136117
);
137118
}
138119

120+
logRaw("Describing latest instance:");
139121
logRaw(formatLabelledValues(formattedInstance));
140122
logRaw(white("Steps:"));
141123

packages/wrangler/src/workflows/commands/instances/pause.ts

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import { fetchResult } from "../../../cfetch";
21
import { createCommand } from "../../../core/create-command";
32
import { logger } from "../../../logger";
43
import { requireAuth } from "../../../user";
5-
import type { Instance } from "../../types";
4+
import { getInstanceIdFromArgs, updateInstanceStatus } from "../../utils";
65

76
export const workflowsInstancesPauseCommand = createCommand({
87
metadata: {
@@ -29,37 +28,9 @@ export const workflowsInstancesPauseCommand = createCommand({
2928
async handler(args, { config }) {
3029
const accountId = await requireAuth(config);
3130

32-
let id = args.id;
31+
const id = await getInstanceIdFromArgs(accountId, args, config);
3332

34-
if (id == "latest") {
35-
const instances = (
36-
await fetchResult<Instance[]>(
37-
config,
38-
`/accounts/${accountId}/workflows/${args.name}/instances`
39-
)
40-
).sort((a, b) => b.created_on.localeCompare(a.created_on));
41-
42-
if (instances.length == 0) {
43-
logger.error(
44-
`There are no deployed instances in workflow "${args.name}"`
45-
);
46-
return;
47-
}
48-
49-
id = instances[0].id;
50-
}
51-
52-
await fetchResult(
53-
config,
54-
`/accounts/${accountId}/workflows/${args.name}/instances/${id}/status`,
55-
{
56-
method: "PATCH",
57-
headers: {
58-
"Content-Type": "application/json",
59-
},
60-
body: JSON.stringify({ status: "pause" }),
61-
}
62-
);
33+
await updateInstanceStatus(config, accountId, args.name, id, "pause");
6334

6435
logger.info(
6536
`⏸️ The instance "${id}" from ${args.name} was paused successfully`

packages/wrangler/src/workflows/commands/instances/restart.ts

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import { fetchResult } from "../../../cfetch";
21
import { createCommand } from "../../../core/create-command";
32
import { logger } from "../../../logger";
43
import { requireAuth } from "../../../user";
5-
import type { Instance } from "../../types";
4+
import { getInstanceIdFromArgs, updateInstanceStatus } from "../../utils";
65

76
export const workflowsInstancesRestartCommand = createCommand({
87
metadata: {
@@ -29,37 +28,9 @@ export const workflowsInstancesRestartCommand = createCommand({
2928
async handler(args, { config }) {
3029
const accountId = await requireAuth(config);
3130

32-
let id = args.id;
31+
const id = await getInstanceIdFromArgs(accountId, args, config);
3332

34-
if (id == "latest") {
35-
const instances = (
36-
await fetchResult<Instance[]>(
37-
config,
38-
`/accounts/${accountId}/workflows/${args.name}/instances`
39-
)
40-
).sort((a, b) => b.created_on.localeCompare(a.created_on));
41-
42-
if (instances.length == 0) {
43-
logger.error(
44-
`There are no deployed instances in workflow "${args.name}"`
45-
);
46-
return;
47-
}
48-
49-
id = instances[0].id;
50-
}
51-
52-
await fetchResult(
53-
config,
54-
`/accounts/${accountId}/workflows/${args.name}/instances/${id}/status`,
55-
{
56-
method: "PATCH",
57-
headers: {
58-
"Content-Type": "application/json",
59-
},
60-
body: JSON.stringify({ status: "restart" }),
61-
}
62-
);
33+
await updateInstanceStatus(config, accountId, args.name, id, "restart");
6334

6435
logger.info(
6536
`🥷 The instance "${id}" from ${args.name} was restarted successfully`

packages/wrangler/src/workflows/commands/instances/resume.ts

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import { fetchResult } from "../../../cfetch";
21
import { createCommand } from "../../../core/create-command";
32
import { logger } from "../../../logger";
43
import { requireAuth } from "../../../user";
5-
import type { Instance } from "../../types";
4+
import { getInstanceIdFromArgs, updateInstanceStatus } from "../../utils";
65

76
export const workflowsInstancesResumeCommand = createCommand({
87
metadata: {
@@ -29,37 +28,9 @@ export const workflowsInstancesResumeCommand = createCommand({
2928
async handler(args, { config }) {
3029
const accountId = await requireAuth(config);
3130

32-
let id = args.id;
31+
const id = await getInstanceIdFromArgs(accountId, args, config);
3332

34-
if (id == "latest") {
35-
const instances = (
36-
await fetchResult<Instance[]>(
37-
config,
38-
`/accounts/${accountId}/workflows/${args.name}/instances`
39-
)
40-
).sort((a, b) => b.created_on.localeCompare(a.created_on));
41-
42-
if (instances.length == 0) {
43-
logger.error(
44-
`There are no deployed instances in workflow "${args.name}"`
45-
);
46-
return;
47-
}
48-
49-
id = instances[0].id;
50-
}
51-
52-
await fetchResult(
53-
config,
54-
`/accounts/${accountId}/workflows/${args.name}/instances/${id}/status`,
55-
{
56-
method: "PATCH",
57-
headers: {
58-
"Content-Type": "application/json",
59-
},
60-
body: JSON.stringify({ status: "resume" }),
61-
}
62-
);
33+
await updateInstanceStatus(config, accountId, args.name, id, "resume");
6334

6435
logger.info(
6536
`🔄 The instance "${id}" from ${args.name} was resumed successfully`

0 commit comments

Comments
 (0)