1import * as AWS from "@/AWS";
2import { ReportGroup } from "@/AWS/CodeBuild/ReportGroup.ts";
3import * as Provider from "@/Provider";
4import * as Test from "@/Test/Alchemy";
5import * as codebuild from "@distilled.cloud/aws/codebuild";
6import { expect } from "alchemy-test";
7import * as Effect from "effect/Effect";
8
9const { test } = Test.make({ providers: AWS.providers() });
10
11const reportGroupName = "alchemy-test-codebuild-report-group";
12
13/** Find the group's ARN by name (report groups are addressed by ARN). */
14const findReportGroupArn = codebuild
15 .listReportGroups({})
16 .pipe(
17 Effect.map((res) =>
18 res.reportGroups?.find((arn) =>
19 arn.endsWith(`report-group/${reportGroupName}`),
20 ),
21 ),
22 );
23
24const getReportGroup = Effect.gen(function* () {
25 const arn = yield* findReportGroupArn;
26 if (arn === undefined) return undefined;
27 const res = yield* codebuild.batchGetReportGroups({
28 reportGroupArns: [arn],
29 });
30 const group = res.reportGroups?.[0];
31 return group?.status === "DELETING" ? undefined : group;
32});
33
34test.provider(
35 "lifecycle: create TEST report group, update tags, destroy",
36 (stack) =>
37 Effect.gen(function* () {
38 yield* stack.destroy();
39
40 // Create — a TEST report group with the default NO_EXPORT config.
41 const deployed = yield* stack.deploy(
42 ReportGroup("LifecycleReportGroup", {
43 reportGroupName,
44 type: "TEST",
45 }),
46 );
47 expect(deployed.reportGroupArn).toContain(
48 `report-group/${reportGroupName}`,
49 );
50 expect(deployed.reportGroupName).toBe(reportGroupName);
51
52 // Out-of-band verification via distilled.
53 const created = yield* getReportGroup;
54 expect(created?.name).toBe(reportGroupName);
55 expect(created?.type).toBe("TEST");
56 expect(created?.exportConfig?.exportConfigType).toBe("NO_EXPORT");
57
58 // Canonical list() coverage.
59 const provider = yield* Provider.findProvider(ReportGroup);
60 const all = yield* provider.list();
61 expect(all.some((g) => g.reportGroupName === reportGroupName)).toBe(true);
62
63 // Update — add a user tag in place (no replacement).
64 yield* stack.deploy(
65 ReportGroup("LifecycleReportGroup", {
66 reportGroupName,
67 type: "TEST",
68 tags: { Purpose: "alchemy-test" },
69 }),
70 );
71 const updated = yield* getReportGroup;
72 expect(updated?.tags?.find((t) => t.key === "Purpose")?.value).toBe(
73 "alchemy-test",
74 );
75
76 // Re-deploy identical props — sync diff is a no-op that converges.
77 yield* stack.deploy(
78 ReportGroup("LifecycleReportGroup", {
79 reportGroupName,
80 type: "TEST",
81 tags: { Purpose: "alchemy-test" },
82 }),
83 );
84
85 // Destroy — the group is deleted; verify it is gone out-of-band.
86 yield* stack.destroy();
87 const after = yield* getReportGroup;
88 expect(after).toBeUndefined();
89 }),
90 {
91 tags: ["provider:aws", "provider:aws:codebuild", "live"],
92 timeout: 120_000,
93 },
94);