Skip to content

Commit cd116a5

Browse files
committed
improve api schema and types
1 parent a687ab4 commit cd116a5

6 files changed

Lines changed: 48 additions & 39 deletions

File tree

apps/webapp/app/routes/api.v1.bulk-actions.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,7 @@ const { action } = createActionApiRoute(
4242
userId: authentication.actor?.sub ?? null,
4343
action: body.action,
4444
title: body.name,
45-
region: body.region,
46-
emailNotification: body.emailNotification,
45+
region: body.targetRegion,
4746
filters: body.runIds
4847
? { runId: body.runIds }
4948
: bulkActionFilterToRunListFilters(body.filter),

apps/webapp/app/v3/services/bulk/BulkActionV2.server.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export type ProcessToCompletionResult = {
5050

5151
export class BulkActionService extends BaseService {
5252
public async create(input: CreateBulkActionInput) {
53+
const { organizationId, projectId, environmentId, userId } = input;
5354
const filters = freezeRunListFilters(input.filters);
5455

5556
// Region is a replay-only override that re-routes the replayed runs. It's
@@ -61,7 +62,7 @@ export class BulkActionService extends BaseService {
6162
// region surfaces as a user-input (400) error rather than a 500.
6263
const [regionError] = await tryCatch(
6364
new WorkerGroupService({ prisma: this._prisma }).getDefaultWorkerGroupForProject({
64-
projectId: input.projectId,
65+
projectId,
6566
regionOverride: replayRegion,
6667
})
6768
);
@@ -78,17 +79,17 @@ export class BulkActionService extends BaseService {
7879

7980
// Count the runs that will be affected by the bulk action
8081
const clickhouse = await clickhouseFactory.getClickhouseForOrganization(
81-
input.organizationId,
82+
organizationId,
8283
"standard"
8384
);
8485
const runsRepository = new RunsRepository({
8586
clickhouse,
8687
prisma: this._replica as PrismaClient,
8788
});
8889
const count = await runsRepository.countRuns({
89-
organizationId: input.organizationId,
90-
projectId: input.projectId,
91-
environmentId: input.environmentId,
90+
organizationId,
91+
projectId,
92+
environmentId,
9293
...filters,
9394
});
9495

@@ -98,9 +99,9 @@ export class BulkActionService extends BaseService {
9899
data: {
99100
id,
100101
friendlyId,
101-
projectId: input.projectId,
102-
environmentId: input.environmentId,
103-
userId: input.userId,
102+
projectId,
103+
environmentId,
104+
userId,
104105
name: input.title,
105106
type: input.action === "cancel" ? BulkActionType.CANCEL : BulkActionType.REPLAY,
106107
params,

packages/core/src/v3/apiClient/bulkActions.test.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ describe("ApiClient bulk actions", () => {
6767
action: "replay",
6868
filter: { status: ["FAILED"], taskIdentifier: "my-task" },
6969
name: "Replay failures",
70-
region: "eu_1",
71-
emailNotification: true,
70+
targetRegion: "eu_1",
7271
});
7372

7473
expect(result).toEqual({ id: "bulk_created" });
@@ -80,8 +79,7 @@ describe("ApiClient bulk actions", () => {
8079
action: "replay",
8180
filter: { status: ["FAILED"], taskIdentifier: "my-task" },
8281
name: "Replay failures",
83-
region: "eu_1",
84-
emailNotification: true,
82+
targetRegion: "eu_1",
8583
});
8684
});
8785

packages/core/src/v3/apiClient/types.ts

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,32 +70,35 @@ export interface ListProjectRunsQueryParams extends CursorPageParams, ListRunsQu
7070
env?: Array<"dev" | "staging" | "prod"> | "dev" | "staging" | "prod";
7171
}
7272

73+
/** Same filters as runs.list(), excluding pagination. */
7374
export type BulkActionFilter = Omit<ListRunsQueryParams, keyof CursorPageParams>;
7475

7576
export type BulkActionSelection =
7677
| { filter: BulkActionFilter; runIds?: never }
7778
| { runIds: string[]; filter?: never };
7879

79-
export type CreateBulkActionOptions = BulkActionSelection & {
80-
action: "cancel" | "replay";
80+
type BaseBulkActionOptions = BulkActionSelection & {
8181
name?: string;
82-
/** Region identifier to replay runs in. When omitted, each replay keeps the original run's region. */
83-
region?: string;
84-
emailNotification?: boolean;
8582
};
8683

87-
export type CreateBulkCancelActionOptions = BulkActionSelection & {
88-
name?: string;
89-
emailNotification?: boolean;
84+
type TargetRegionOption = {
85+
/** Region identifier to replay runs in. When omitted, each replay keeps the original run's region. */
86+
targetRegion?: string;
9087
};
9188

92-
export type CreateBulkReplayActionOptions = BulkActionSelection & {
93-
name?: string;
94-
/** Region identifier to replay runs in. When omitted, each replay keeps the original run's region. */
95-
region?: string;
96-
emailNotification?: boolean;
89+
export type CreateBulkActionOptions =
90+
| (BaseBulkActionOptions & {
91+
action: "cancel";
92+
targetRegion?: never;
93+
})
94+
| (BaseBulkActionOptions & { action: "replay" } & TargetRegionOption);
95+
96+
export type CreateBulkCancelActionOptions = BaseBulkActionOptions & {
97+
targetRegion?: never;
9798
};
9899

100+
export type CreateBulkReplayActionOptions = BaseBulkActionOptions & TargetRegionOption;
101+
99102
export type ListBulkActionsQueryParams = CursorPageParams;
100103

101104
export interface SubscribeToRunsQueryParams {

packages/core/src/v3/schemas/api.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,15 +1246,25 @@ const BulkActionFilterRequestBody = z.object({
12461246
region: StringOrStringArray.optional(),
12471247
});
12481248

1249+
const BulkActionSelectionRequestBody = {
1250+
filter: BulkActionFilterRequestBody.optional(),
1251+
runIds: z.array(z.string()).min(1).optional(),
1252+
name: z.string().optional(),
1253+
};
1254+
12491255
export const CreateBulkActionRequestBody = z
1250-
.object({
1251-
action: z.enum(["cancel", "replay"]),
1252-
filter: BulkActionFilterRequestBody.optional(),
1253-
runIds: z.array(z.string()).min(1).optional(),
1254-
name: z.string().optional(),
1255-
region: z.string().optional(),
1256-
emailNotification: z.boolean().optional(),
1257-
})
1256+
.discriminatedUnion("action", [
1257+
z.object({
1258+
action: z.literal("cancel"),
1259+
targetRegion: z.never().optional(),
1260+
...BulkActionSelectionRequestBody,
1261+
}),
1262+
z.object({
1263+
action: z.literal("replay"),
1264+
targetRegion: z.string().optional(),
1265+
...BulkActionSelectionRequestBody,
1266+
}),
1267+
])
12581268
.refine((body) => (body.filter ? 1 : 0) + (body.runIds ? 1 : 0) === 1, {
12591269
message: "Exactly one of filter or runIds must be provided",
12601270
});

packages/trigger-sdk/src/v3/runs-bulk.test.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,7 @@ describe("runs.bulk", () => {
8585
runs.bulk.replay({
8686
filter: { status: "FAILED", taskIdentifier: ["task-a", "task-b"] },
8787
name: "Replay failed tasks",
88-
region: "eu_1",
89-
emailNotification: true,
88+
targetRegion: "eu_1",
9089
})
9190
);
9291

@@ -97,8 +96,7 @@ describe("runs.bulk", () => {
9796
action: "replay",
9897
filter: { status: "FAILED", taskIdentifier: ["task-a", "task-b"] },
9998
name: "Replay failed tasks",
100-
region: "eu_1",
101-
emailNotification: true,
99+
targetRegion: "eu_1",
102100
});
103101
});
104102

0 commit comments

Comments
 (0)