1import * as AWS from "@/AWS";
2import { Host } from "@/AWS/CodeConnections/Host.ts";
3import * as Provider from "@/Provider";
4import * as Test from "@/Test/Alchemy";
5import * as codeconnections from "@distilled.cloud/aws/codeconnections";
6import { expect } from "alchemy-test";
7import * as Effect from "effect/Effect";
8
9const { test } = Test.make({ providers: AWS.providers() });
10
11// Host names are capped at 64 chars.
12const hostName = "alchemy-test-host";
13
14test.provider(
15 "lifecycle: create GHES host (PENDING), update endpoint, destroy",
16 (stack) =>
17 Effect.gen(function* () {
18 yield* stack.destroy();
19
20 // Create — the host is created in PENDING; completing the setup is a
21 // manual console step with no API, so PENDING is the only state we can
22 // assert without human interaction. The endpoint is not probed at
23 // creation time.
24 const deployed = yield* stack.deploy(
25 Effect.gen(function* () {
26 return yield* Host("GHEHost", {
27 name: hostName,
28 providerType: "GitHubEnterpriseServer",
29 providerEndpoint: "https://ghe.example.com",
30 });
31 }),
32 );
33 expect(deployed.hostArn).toContain(":host/");
34 expect(deployed.hostStatus).toBe("PENDING");
35 expect(deployed.providerType).toBe("GitHubEnterpriseServer");
36 expect(deployed.providerEndpoint).toBe("https://ghe.example.com");
37
38 // Out-of-band verification via distilled.
39 const created = yield* codeconnections.getHost({
40 HostArn: deployed.hostArn,
41 });
42 expect(created.Name).toBe(hostName);
43 expect(created.ProviderEndpoint).toBe("https://ghe.example.com");
44
45 // Update — the provider endpoint is mutable via UpdateHost.
46 const updated = yield* stack.deploy(
47 Effect.gen(function* () {
48 return yield* Host("GHEHost", {
49 name: hostName,
50 providerType: "GitHubEnterpriseServer",
51 providerEndpoint: "https://ghe2.example.com",
52 });
53 }),
54 );
55 // Same host (update, not replace)…
56 expect(updated.hostArn).toBe(deployed.hostArn);
57 // …with the new endpoint observed out-of-band.
58 const afterUpdate = yield* codeconnections.getHost({
59 HostArn: deployed.hostArn,
60 });
61 expect(afterUpdate.ProviderEndpoint).toBe("https://ghe2.example.com");
62
63 // Canonical list() coverage.
64 const provider = yield* Provider.findProvider(Host);
65 const all = yield* provider.list();
66 expect(all.some((h) => h.hostArn === deployed.hostArn)).toBe(true);
67
68 // Destroy — host is deleted; verify it is gone out-of-band.
69 yield* stack.destroy();
70 const after = yield* codeconnections
71 .getHost({ HostArn: deployed.hostArn })
72 .pipe(
73 Effect.map((res) => res.Name),
74 Effect.catchTag("ResourceNotFoundException", () =>
75 Effect.succeed(undefined),
76 ),
77 );
78 expect(after).toBeUndefined();
79 }),
80 {
81 tags: ["provider:aws", "provider:aws:codeconnections", "live"],
82 timeout: 120_000,
83 },
84);