diff --git a/packages/harness/src/extensions/posthog-provider/oauth.test.ts b/packages/harness/src/extensions/posthog-provider/oauth.test.ts index 2a99b3c2b8..a26080fbee 100644 --- a/packages/harness/src/extensions/posthog-provider/oauth.test.ts +++ b/packages/harness/src/extensions/posthog-provider/oauth.test.ts @@ -77,6 +77,26 @@ function hitCallbackBody(port: number, query: string): Promise { }); } +async function getAvailablePort(): Promise { + const server = http.createServer(); + + await new Promise((resolve, reject) => { + server.once("error", reject); + server.listen(0, "127.0.0.1", resolve); + }); + + const address = server.address(); + if (address === null || typeof address === "string") { + throw new Error("Failed to allocate an OAuth callback port"); + } + + await new Promise((resolve, reject) => { + server.close((error) => (error ? reject(error) : resolve())); + }); + + return address.port; +} + describe("buildAuthorizeUrl", () => { it("targets the same authorize endpoint and client as PostHog Code", () => { const url = buildAuthorizeUrl("us", "challenge123", getRedirectUri(8237)); @@ -151,8 +171,8 @@ describe("loginPosthog region selection", () => { let fetchSpy: MockInstance; let port: number; - beforeEach(() => { - port = 18500 + Math.floor(Math.random() * 500); + beforeEach(async () => { + port = await getAvailablePort(); process.env.HARNESS_OAUTH_PORT = String(port); fetchSpy = vi.spyOn(global, "fetch").mockResolvedValue({ ok: true, @@ -256,8 +276,8 @@ describe("loginPosthog", { timeout: 15_000 }, () => { let fetchSpy: MockInstance; let port: number; - beforeEach(() => { - port = 18000 + Math.floor(Math.random() * 1000); + beforeEach(async () => { + port = await getAvailablePort(); process.env.HARNESS_OAUTH_PORT = String(port); fetchSpy = vi.spyOn(global, "fetch"); }); @@ -466,8 +486,8 @@ describe("openBrowser (via loginPosthog)", () => { let fetchSpy: MockInstance; let port: number; - beforeEach(() => { - port = 19000 + Math.floor(Math.random() * 1000); + beforeEach(async () => { + port = await getAvailablePort(); process.env.HARNESS_OAUTH_PORT = String(port); fetchSpy = vi.spyOn(global, "fetch").mockResolvedValue({ ok: true, diff --git a/packages/ui/src/features/settings/sections/environments/useSandboxCustomImages.ts b/packages/ui/src/features/settings/sections/environments/useSandboxCustomImages.ts index d87a90f588..c780e55b8d 100644 --- a/packages/ui/src/features/settings/sections/environments/useSandboxCustomImages.ts +++ b/packages/ui/src/features/settings/sections/environments/useSandboxCustomImages.ts @@ -7,9 +7,12 @@ import { useQueryClient } from "@tanstack/react-query"; import { useAuthenticatedMutation } from "../../../../hooks/useAuthenticatedMutation"; import { useAuthenticatedQuery } from "../../../../hooks/useAuthenticatedQuery"; import { toast } from "../../../../primitives/toast"; +import { useFeatureFlag } from "../../../feature-flags/useFeatureFlag"; import { watchImageBuild } from "./imageBuildWatcher"; import { sandboxEnvKeys } from "./useSandboxEnvironments"; +const CUSTOM_IMAGES_FEATURE_FLAG = "tasks-modal-vm-sandbox"; + const sandboxCustomImageKeys = { list: ["sandbox-custom-images", "list"] as const, detail: (id: string) => ["sandbox-custom-images", "detail", id] as const, @@ -30,6 +33,7 @@ export function useSandboxCustomImageDetail(imageId: string) { export function useSandboxCustomImages() { const queryClient = useQueryClient(); + const customImagesFlagEnabled = useFeatureFlag(CUSTOM_IMAGES_FEATURE_FLAG); const { data: images, @@ -39,6 +43,7 @@ export function useSandboxCustomImages() { sandboxCustomImageKeys.list, (client) => client.listSandboxCustomImages(), { + enabled: customImagesFlagEnabled, retry: (failureCount, error) => !(error instanceof SandboxCustomImagesDisabledError) && failureCount < 3, @@ -56,7 +61,7 @@ export function useSandboxCustomImages() { }, ); - const customImagesEnabled = images !== undefined; + const customImagesEnabled = customImagesFlagEnabled && images !== undefined; const customImagesDisabled = error instanceof SandboxCustomImagesDisabledError;