diff --git a/.github/workflows/ui-container-checks.yml b/.github/workflows/ui-container-checks.yml index d6ebaf46a3..010d57d147 100644 --- a/.github/workflows/ui-container-checks.yml +++ b/.github/workflows/ui-container-checks.yml @@ -80,6 +80,7 @@ jobs: registry-1.docker.io:443 auth.docker.io:443 production.cloudflare.docker.com:443 + production.cloudfront.docker.com:443 registry.npmjs.org:443 dl-cdn.alpinelinux.org:443 fonts.googleapis.com:443 diff --git a/ui/app/api/health/route.test.ts b/ui/app/api/health/route.test.ts index 4f893c2574..5fdf7f5886 100644 --- a/ui/app/api/health/route.test.ts +++ b/ui/app/api/health/route.test.ts @@ -3,8 +3,11 @@ import { afterEach, describe, expect, it, vi } from "vitest"; import { GET } from "./route"; interface HealthResponse { - status: "healthy"; - service: "prowler-ui"; + status: "pass"; + version: string; + releaseId: string; + serviceId: "prowler-ui"; + description: string; } const parseHealthResponse = async (response: Response) => @@ -16,12 +19,9 @@ describe("GET /api/health", () => { vi.unstubAllGlobals(); }); - it("should return a healthy response when the Next.js route handler responds", async () => { + it("should return an IETF-shaped healthy response when the Next.js route handler responds", async () => { // Given - const expectedBody: HealthResponse = { - status: "healthy", - service: "prowler-ui", - }; + vi.stubEnv("NEXT_PUBLIC_PROWLER_RELEASE_VERSION", "1.28.0"); // When const response = await GET(); @@ -29,8 +29,30 @@ describe("GET /api/health", () => { // Then expect(response.status).toBe(200); + expect(response.headers.get("Content-Type")).toBe( + "application/health+json", + ); expect(response.headers.get("Cache-Control")).toBe("no-store"); - expect(body).toEqual(expectedBody); + expect(body).toEqual({ + status: "pass", + version: "1", + releaseId: "1.28.0", + serviceId: "prowler-ui", + description: "Prowler UI", + }); + }); + + it("should fall back to 'unknown' when the release version env var is missing", async () => { + // Given + vi.stubEnv("NEXT_PUBLIC_PROWLER_RELEASE_VERSION", ""); + + // When + const response = await GET(); + const body = await parseHealthResponse(response); + + // Then + expect(response.status).toBe(200); + expect(body.releaseId).toBe("unknown"); }); it("should not call fetch while evaluating UI liveness", async () => { @@ -60,10 +82,8 @@ describe("GET /api/health", () => { // Then expect(response.status).toBe(200); - expect(body).toEqual({ - status: "healthy", - service: "prowler-ui", - }); + expect(body.status).toBe("pass"); + expect(body.serviceId).toBe("prowler-ui"); expect(fetchMock).not.toHaveBeenCalled(); }); }); diff --git a/ui/app/api/health/route.ts b/ui/app/api/health/route.ts index 0b6730dd1f..f352ffd6a1 100644 --- a/ui/app/api/health/route.ts +++ b/ui/app/api/health/route.ts @@ -1,13 +1,18 @@ -const healthResponse = { - status: "healthy", - service: "prowler-ui", -} as const; - export const dynamic = "force-dynamic"; export async function GET() { - return Response.json(healthResponse, { + const body = { + status: "pass", + version: "1", + releaseId: process.env.NEXT_PUBLIC_PROWLER_RELEASE_VERSION || "unknown", + serviceId: "prowler-ui", + description: "Prowler UI", + }; + + return new Response(JSON.stringify(body), { + status: 200, headers: { + "Content-Type": "application/health+json", "Cache-Control": "no-store", }, });