1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as storage from "@distilled.cloud/gcp/storage_v1";
4import { expect } from "alchemy-test";
5import * as Effect from "effect/Effect";
6import { MinimumLogLevel } from "effect/References";
7import * as Schedule from "effect/Schedule";
8
9const { test } = Test.make({ providers: GCP.providers() });
10
11const logLevel = Effect.provideService(
12 MinimumLogLevel,
13 process.env.DEBUG ? "Debug" : "Info",
14);
15
16const waitUntilGone = (bucketName: string, managedFolderName: string) =>
17 storage
18 .getManagedFolders({
19 bucket: bucketName,
20 managedFolder: managedFolderName,
21 })
22 .pipe(
23 Effect.as("found" as const),
24 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
25 Effect.repeat({
26 schedule: Schedule.spaced("1 second"),
27 until: (status) => status === "gone",
28 times: 10,
29 }),
30 );
31
32test.provider(
33 "create, replace, and delete a managed folder",
34 (stack) =>
35 Effect.gen(function* () {
36 yield* stack.destroy();
37
38 const created = yield* stack.deploy(
39 Effect.gen(function* () {
40 const bucket = yield* GCP.Storage.Bucket("Assets", {
41 location: "US-CENTRAL1",
42 uniformBucketLevelAccess: true,
43 forceDestroy: true,
44 });
45 const folder = yield* GCP.Storage.Managed("Team", {
46 bucketName: bucket.bucketName,
47 managedFolderName: "teams/",
48 });
49 return { bucket, folder };
50 }),
51 );
52
53 expect(created.folder.bucketName).toEqual(created.bucket.bucketName);
54 expect(created.folder.managedFolderName).toEqual("teams/");
55 expect(created.bucket.uniformBucketLevelAccess).toEqual(true);
56
57 const fetched = yield* storage.getManagedFolders({
58 bucket: created.folder.bucketName,
59 managedFolder: created.folder.managedFolderName,
60 });
61 expect(fetched.name).toEqual("teams/");
62
63 const updated = yield* stack.deploy(
64 Effect.gen(function* () {
65 const bucket = yield* GCP.Storage.Bucket("Assets", {
66 bucketName: created.bucket.bucketName,
67 location: "US-CENTRAL1",
68 uniformBucketLevelAccess: true,
69 forceDestroy: true,
70 });
71 const folder = yield* GCP.Storage.Managed("Team", {
72 bucketName: bucket.bucketName,
73 managedFolderName: "payments/",
74 });
75 return { bucket, folder };
76 }),
77 );
78
79 expect(updated.folder.bucketName).toEqual(created.bucket.bucketName);
80 expect(updated.folder.managedFolderName).toEqual("payments/");
81 expect(updated.folder.managedFolderName).not.toEqual(
82 created.folder.managedFolderName,
83 );
84
85 const refetched = yield* storage.getManagedFolders({
86 bucket: updated.folder.bucketName,
87 managedFolder: updated.folder.managedFolderName,
88 });
89 expect(refetched.name).toEqual("payments/");
90
91 const previousGone = yield* waitUntilGone(
92 created.folder.bucketName,
93 created.folder.managedFolderName,
94 );
95 expect(previousGone).toEqual("gone");
96
97 yield* stack.destroy();
98
99 const gone = yield* waitUntilGone(
100 updated.folder.bucketName,
101 updated.folder.managedFolderName,
102 );
103 expect(gone).toEqual("gone");
104 }).pipe(logLevel),
105 { tags: ["provider:gcp", "provider:gcp:storage", "live"], timeout: 90_000 },
106);