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
17const runLifecycle = !process.env.FAST;
18const LOCATION = "us-east4";
19
20const waitUntilGone = (name: string) =>
21 eventarc.getProjectsLocationsGoogleApiSources({ name }).pipe(
22 Effect.as("found" as const),
23 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
24 Effect.repeat({
25 schedule: Schedule.spaced("2 seconds"),
26 until: (status) => status === "gone",
27 times: 10,
28 }),
29 );
30
31test.provider(
32 "getProjectsLocationsGoogleApiSources on a missing source fails with a typed tag",
33 (stack) =>
34 Effect.gen(function* () {
35 const { project } = yield* GcpEnvironment.current;
36 yield* stack.destroy();
37
38 const error = yield* Effect.flip(
39 eventarc.getProjectsLocationsGoogleApiSources({
40 name: `projects/${project}/locations/${LOCATION}/googleApiSources/alchemy-missing-source`,
41 }),
42 );
43 expect(error._tag).toEqual("NotFound");
44
45 yield* stack.destroy();
46 }).pipe(logLevel),
47 { tags: ["provider:gcp", "provider:gcp:eventarc", "live"], timeout: 90_000 },
48);
49
50test.provider.skipIf(!runLifecycle)(
51 "create, update, and delete an Eventarc Google API source",
52 (stack) =>
53 Effect.gen(function* () {
54 yield* stack.destroy();
55
56 const created = yield* stack.deploy(
57 Effect.gen(function* () {
58 const bus = yield* GCP.Eventarc.MessageBus("Events", {
59 location: LOCATION,
60 labels: { env: "test" },
61 });
62 const source = yield* GCP.Eventarc.GoogleApiSource("GoogleEvents", {
63 location: LOCATION,
64 destination: bus.name,
65 displayName: "google events",
66 labels: { env: "test" },
67 });
68 return { bus, source };
69 }),
70 );
71
72 expect(created.source.name).toContain("/googleApiSources/");
73 expect(created.source.googleApiSourceId).toEqual(expect.any(String));
74 expect(created.source.location).toEqual(LOCATION);
75 expect(created.source.destination).toEqual(created.bus.name);
76 expect(created.source.labels).toMatchObject({ env: "test" });
77
78 const fetched = yield* eventarc.getProjectsLocationsGoogleApiSources({
79 name: created.source.name,
80 });
81 expect(fetched.name).toEqual(created.source.name);
82 expect(fetched.labels?.env).toEqual("test");
83 expect(fetched.destination).toEqual(created.bus.name);
84
85 const updated = yield* stack.deploy(
86 Effect.gen(function* () {
87 const bus = yield* GCP.Eventarc.MessageBus("Events", {
88 messageBusId: created.bus.messageBusId,
89 location: LOCATION,
90 labels: { env: "test" },
91 });
92 return yield* GCP.Eventarc.GoogleApiSource("GoogleEvents", {
93 googleApiSourceId: created.source.googleApiSourceId,
94 location: LOCATION,
95 destination: bus.name,
96 displayName: "google events v2",
97 loggingConfig: { logSeverity: "INFO" },
98 labels: { env: "prod", role: "source" },
99 });
100 }),
101 );
102
103 expect(updated.name).toEqual(created.source.name);
104 expect(updated.googleApiSourceId).toEqual(
105 created.source.googleApiSourceId,
106 );
107 expect(updated.displayName).toEqual("google events v2");
108 expect(updated.labels).toMatchObject({ env: "prod", role: "source" });
109
110 const refetched = yield* eventarc.getProjectsLocationsGoogleApiSources({
111 name: created.source.name,
112 });
113 expect(refetched.labels?.env).toEqual("prod");
114 expect(refetched.labels?.role).toEqual("source");
115 expect(refetched.displayName).toEqual("google events v2");
116
117 yield* stack.destroy();
118
119 const gone = yield* waitUntilGone(created.source.name);
120 expect(gone).toEqual("gone");
121 }).pipe(logLevel),
122 { tags: ["provider:gcp", "provider:gcp:eventarc", "live"], timeout: 180_000 },
123);