1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as artifactregistry from "@distilled.cloud/gcp/artifactregistry_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 = (name: string) =>
17 artifactregistry.getProjectsLocationsRepositoriesRules({ name }).pipe(
18 Effect.as("found" as const),
19 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
20 Effect.repeat({
21 schedule: Schedule.spaced("1 second"),
22 until: (status) => status === "gone",
23 times: 10,
24 }),
25 );
26
27test.provider(
28 "create, update, and delete a repository download rule",
29 (stack) =>
30 Effect.gen(function* () {
31 yield* stack.destroy();
32
33 const created = yield* stack.deploy(
34 Effect.gen(function* () {
35 const images = yield* GCP.ArtifactRegistry.Repository("Images", {
36 location: "us-central1",
37 format: "DOCKER",
38 description: "rule parent",
39 });
40 const rule = yield* GCP.ArtifactRegistry.RepositoriesRule("Deny", {
41 repository: images.name,
42 location: "us-central1",
43 action: "ALLOW",
44 });
45 return { images, rule };
46 }),
47 );
48
49 expect(created.rule.name).toContain("/rules/");
50 expect(created.rule.repository).toEqual(created.images.name);
51 expect(created.rule.action).toEqual("ALLOW");
52 expect(created.rule.operation).toEqual("DOWNLOAD");
53 expect(created.rule.location).toEqual("us-central1");
54
55 const fetched =
56 yield* artifactregistry.getProjectsLocationsRepositoriesRules({
57 name: created.rule.name,
58 });
59 expect(fetched.name).toEqual(created.rule.name);
60 expect(fetched.action).toEqual("ALLOW");
61 expect(fetched.condition?.title).toContain("[alchemy ");
62
63 const updated = yield* stack.deploy(
64 Effect.gen(function* () {
65 const images = yield* GCP.ArtifactRegistry.Repository("Images", {
66 repositoryId: created.images.repositoryId,
67 location: "us-central1",
68 format: "DOCKER",
69 description: "rule parent",
70 });
71 const rule = yield* GCP.ArtifactRegistry.RepositoriesRule("Deny", {
72 repository: images.name,
73 ruleId: created.rule.ruleId,
74 location: "us-central1",
75 action: "DENY",
76 condition: { expression: "pkg.version.id != '9.9.9'" },
77 });
78 return { images, rule };
79 }),
80 );
81
82 expect(updated.rule.name).toEqual(created.rule.name);
83 expect(updated.rule.action).toEqual("DENY");
84 expect(updated.rule.condition?.expression).toEqual(
85 "pkg.version.id != '9.9.9'",
86 );
87
88 const refetched =
89 yield* artifactregistry.getProjectsLocationsRepositoriesRules({
90 name: created.rule.name,
91 });
92 expect(refetched.action).toEqual("DENY");
93 expect(refetched.condition?.expression).toEqual(
94 "pkg.version.id != '9.9.9'",
95 );
96
97 yield* stack.destroy();
98
99 const gone = yield* waitUntilGone(created.rule.name);
100 expect(gone).toEqual("gone");
101 }).pipe(logLevel),
102 {
103 tags: ["provider:gcp", "provider:gcp:artifactregistry", "live"],
104 timeout: 90_000,
105 },
106);