1import * as GCP from "@/GCP";
2import { GcpEnvironment } from "@/GCP/Environment";
3import * as Test from "@/Test/Alchemy";
4import * as eventarc from "@distilled.cloud/gcp/eventarc_v1";
5import { expect } from "alchemy-test";
6import * as Effect from "effect/Effect";
7import { MinimumLogLevel } from "effect/References";
8import * as Schedule from "effect/Schedule";
9
10const { test } = Test.make({ providers: GCP.providers() });
11
12const logLevel = Effect.provideService(
13 MinimumLogLevel,
14 process.env.DEBUG ? "Debug" : "Info",
15);
16
17// Pipeline create/update/delete LROs take ~14 minutes end to end.
18const runLifecycle = !!process.env.GCP_TEST_SLOW && !process.env.FAST;
19const LOCATION = "europe-west3";
20
21const waitUntilGone = (name: string) =>
22 eventarc.getProjectsLocationsPipelines({ name }).pipe(
23 Effect.as("found" as const),
24 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
25 Effect.repeat({
26 schedule: Schedule.spaced("2 seconds"),
27 until: (status) => status === "gone",
28 times: 10,
29 }),
30 );
31
32test.provider(
33 "getProjectsLocationsPipelines on a missing pipeline fails with a typed tag",
34 (stack) =>
35 Effect.gen(function* () {
36 const { project } = yield* GcpEnvironment.current;
37 yield* stack.destroy();
38
39 const error = yield* Effect.flip(
40 eventarc.getProjectsLocationsPipelines({
41 name: `projects/${project}/locations/${LOCATION}/pipelines/alchemy-missing-pipeline`,
42 }),
43 );
44 expect(error._tag).toEqual("NotFound");
45
46 yield* stack.destroy();
47 }).pipe(logLevel),
48 { tags: ["provider:gcp", "provider:gcp:eventarc", "live"], timeout: 90_000 },
49);
50
51test.provider.skipIf(!runLifecycle)(
52 "create, update, and delete an Eventarc pipeline",
53 (stack) =>
54 Effect.gen(function* () {
55 yield* stack.destroy();
56
57 const created = yield* stack.deploy(
58 Effect.gen(function* () {
59 const bus = yield* GCP.Eventarc.MessageBus("Events", {
60 location: LOCATION,
61 labels: { env: "test" },
62 });
63 const pipeline = yield* GCP.Eventarc.Pipeline("Forward", {
64 location: LOCATION,
65 destinations: [{ messageBus: bus.name }],
66 displayName: "forward",
67 labels: { env: "test" },
68 });
69 return { bus, pipeline };
70 }),
71 );
72
73 expect(created.pipeline.name).toContain("/pipelines/");
74 expect(created.pipeline.pipelineId).toEqual(expect.any(String));
75 expect(created.pipeline.location).toEqual(LOCATION);
76 expect(created.pipeline.labels).toMatchObject({ env: "test" });
77 expect(created.pipeline.destinations[0]?.messageBus).toEqual(
78 created.bus.name,
79 );
80
81 const fetched = yield* eventarc.getProjectsLocationsPipelines({
82 name: created.pipeline.name,
83 });
84 expect(fetched.name).toEqual(created.pipeline.name);
85 expect(fetched.labels?.env).toEqual("test");
86 expect(fetched.destinations?.[0]?.messageBus).toEqual(created.bus.name);
87
88 const updated = yield* stack.deploy(
89 Effect.gen(function* () {
90 const bus = yield* GCP.Eventarc.MessageBus("Events", {
91 messageBusId: created.bus.messageBusId,
92 location: LOCATION,
93 labels: { env: "test" },
94 });
95 return yield* GCP.Eventarc.Pipeline("Forward", {
96 pipelineId: created.pipeline.pipelineId,
97 location: LOCATION,
98 destinations: [{ messageBus: bus.name }],
99 displayName: "forward-v2",
100 retryPolicy: { maxAttempts: 8 },
101 labels: { env: "prod", role: "pipeline" },
102 });
103 }),
104 );
105
106 expect(updated.name).toEqual(created.pipeline.name);
107 expect(updated.pipelineId).toEqual(created.pipeline.pipelineId);
108 expect(updated.displayName).toEqual("forward-v2");
109 expect(updated.labels).toMatchObject({ env: "prod", role: "pipeline" });
110 expect(updated.retryPolicy?.maxAttempts).toEqual(8);
111
112 const refetched = yield* eventarc.getProjectsLocationsPipelines({
113 name: created.pipeline.name,
114 });
115 expect(refetched.labels?.env).toEqual("prod");
116 expect(refetched.labels?.role).toEqual("pipeline");
117 expect(refetched.displayName).toEqual("forward-v2");
118
119 yield* stack.destroy();
120
121 const gone = yield* waitUntilGone(created.pipeline.name);
122 expect(gone).toEqual("gone");
123 }).pipe(logLevel),
124 {
125 tags: ["provider:gcp", "provider:gcp:eventarc", "live"],
126 timeout: 2_400_000,
127 },
128);