diff --git a/site/src/api/queries/templates.ts b/site/src/api/queries/templates.ts index 7bb34b74df124..b01cb2d31a3e9 100644 --- a/site/src/api/queries/templates.ts +++ b/site/src/api/queries/templates.ts @@ -120,3 +120,16 @@ export const updateActiveTemplateVersion = ( }, }; }; + +export const templateVersionGitAuthKey = (versionId: string) => [ + "templateVersion", + versionId, + "gitAuth", +]; + +export const templateVersionGitAuth = (versionId: string) => { + return { + queryKey: templateVersionGitAuthKey(versionId), + queryFn: () => API.getTemplateVersionGitAuth(versionId), + }; +}; diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.test.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.test.tsx index 7ca03313c5248..84036b0392921 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.test.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.test.tsx @@ -7,11 +7,13 @@ import { MockWorkspace, MockWorkspaceQuota, MockWorkspaceRequest, + MockWorkspaceRichParametersRequest, MockTemplateVersionParameter1, MockTemplateVersionParameter2, MockTemplateVersionParameter3, MockTemplateVersionGitAuth, MockOrganization, + MockTemplateVersionGitAuthAuthenticated, } from "testHelpers/entities"; import { renderWithAuth, @@ -31,17 +33,6 @@ const renderCreateWorkspacePage = () => { }); }; -Object.defineProperty(window, "BroadcastChannel", { - value: class { - addEventListener() { - // noop - } - close() { - // noop - } - }, -}); - describe("CreateWorkspacePage", () => { it("succeeds with default owner", async () => { jest @@ -71,9 +62,9 @@ describe("CreateWorkspacePage", () => { expect(API.createWorkspace).toBeCalledWith( MockUser.organization_ids[0], MockUser.id, - { - ...MockWorkspaceRequest, - }, + expect.objectContaining({ + ...MockWorkspaceRichParametersRequest, + }), ), ); }); @@ -165,6 +156,50 @@ describe("CreateWorkspacePage", () => { expect(validationError).toBeInTheDocument(); }); + it("gitauth authenticates and succeeds", async () => { + jest + .spyOn(API, "getWorkspaceQuota") + .mockResolvedValueOnce(MockWorkspaceQuota); + jest + .spyOn(API, "getUsers") + .mockResolvedValueOnce({ users: [MockUser], count: 1 }); + jest.spyOn(API, "createWorkspace").mockResolvedValueOnce(MockWorkspace); + jest + .spyOn(API, "getTemplateVersionGitAuth") + .mockResolvedValue([MockTemplateVersionGitAuth]); + + renderCreateWorkspacePage(); + await waitForLoaderToBeRemoved(); + + const nameField = await screen.findByLabelText(nameLabelText); + // have to use fireEvent b/c userEvent isn't cleaning up properly between tests + fireEvent.change(nameField, { + target: { value: "test" }, + }); + + const githubButton = await screen.findByText("Login with GitHub"); + await userEvent.click(githubButton); + + jest + .spyOn(API, "getTemplateVersionGitAuth") + .mockResolvedValue([MockTemplateVersionGitAuthAuthenticated]); + + await screen.findByText("Authenticated with GitHub"); + + const submitButton = screen.getByText(createWorkspaceText); + await userEvent.click(submitButton); + + await waitFor(() => + expect(API.createWorkspace).toBeCalledWith( + MockUser.organization_ids[0], + MockUser.id, + expect.objectContaining({ + ...MockWorkspaceRequest, + }), + ), + ); + }); + it("gitauth: errors if unauthenticated and submits", async () => { jest .spyOn(API, "getTemplateVersionGitAuth") @@ -210,4 +245,29 @@ describe("CreateWorkspacePage", () => { ); }); }); + + it("auto create a workspace if uses mode=auto and version=version-id", async () => { + const param = "first_parameter"; + const paramValue = "It works!"; + const createWorkspaceSpy = jest.spyOn(API, "createWorkspace"); + + renderWithAuth(, { + route: + "/templates/" + + MockTemplate.name + + `/workspace?param.${param}=${paramValue}&mode=auto&version=test-template-version`, + path: "/templates/:template/workspace", + }); + + await waitFor(() => { + expect(createWorkspaceSpy).toBeCalledWith( + MockOrganization.id, + "me", + expect.objectContaining({ + template_version_id: MockTemplate.active_version_id, + rich_parameter_values: [{ name: param, value: paramValue }], + }), + ); + }); + }); }); diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx index 60932170a5a2f..f7739a2acbed6 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx @@ -1,13 +1,11 @@ import { useMachine } from "@xstate/react"; import { - Template, - TemplateVersionGitAuth, TemplateVersionParameter, WorkspaceBuildParameter, } from "api/typesGenerated"; import { useMe } from "hooks/useMe"; import { useOrganizationId } from "hooks/useOrganizationId"; -import { FC } from "react"; +import { type FC, useCallback, useState, useEffect } from "react"; import { Helmet } from "react-helmet-async"; import { useNavigate, useParams, useSearchParams } from "react-router-dom"; import { pageTitle } from "utils/page"; @@ -25,6 +23,10 @@ import { colors, NumberDictionary, } from "unique-names-generator"; +import { useQuery } from "@tanstack/react-query"; +import { templateVersionGitAuth } from "api/queries/templates"; + +export type GitAuthPollingState = "idle" | "polling" | "abandoned"; const CreateWorkspacePage: FC = () => { const organizationId = useOrganizationId(); @@ -50,18 +52,49 @@ const CreateWorkspacePage: FC = () => { }, }, }); - const { - template, - error, - parameters, - permissions, - gitAuth, - defaultName, - versionId, - } = createWorkspaceState.context; + const { template, parameters, permissions, defaultName, versionId } = + createWorkspaceState.context; const title = createWorkspaceState.matches("autoCreating") ? "Creating workspace..." - : "Create Workspace"; + : "Create workspace"; + + const [gitAuthPollingState, setGitAuthPollingState] = + useState("idle"); + + const startPollingGitAuth = useCallback(() => { + setGitAuthPollingState("polling"); + }, []); + + const { data: gitAuth, error } = useQuery( + versionId + ? { + ...templateVersionGitAuth(versionId), + refetchInterval: gitAuthPollingState === "polling" ? 1000 : false, + } + : { enabled: false }, + ); + + const allSignedIn = gitAuth?.every((it) => it.authenticated); + + useEffect(() => { + if (allSignedIn) { + setGitAuthPollingState("idle"); + return; + } + + if (gitAuthPollingState !== "polling") { + return; + } + + // Poll for a maximum of one minute + const quitPolling = setTimeout( + () => setGitAuthPollingState("abandoned"), + 60_000, + ); + return () => { + clearTimeout(quitPolling); + }; + }, [gitAuthPollingState, allSignedIn]); return ( <> @@ -81,11 +114,13 @@ const CreateWorkspacePage: FC = () => { defaultOwner={me} defaultBuildParameters={defaultBuildParameters} error={error} - template={template as Template} + template={template!} versionId={versionId} - gitAuth={gitAuth as TemplateVersionGitAuth[]} + gitAuth={gitAuth ?? []} + gitAuthPollingState={gitAuthPollingState} + startPollingGitAuth={startPollingGitAuth} permissions={permissions as CreateWSPermissions} - parameters={parameters as TemplateVersionParameter[]} + parameters={parameters!} creatingWorkspace={createWorkspaceState.matches("creatingWorkspace")} onCancel={() => { navigate(-1); diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx index 77d078ea0c939..f46b5c42e26ff 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx @@ -30,6 +30,7 @@ import { CreateWSPermissions } from "xServices/createWorkspace/createWorkspaceXS import { GitAuth } from "./GitAuth"; import { ErrorAlert } from "components/Alert/ErrorAlert"; import { Stack } from "components/Stack/Stack"; +import { type GitAuthPollingState } from "./CreateWorkspacePage"; export interface CreateWorkspacePageViewProps { error: unknown; @@ -38,6 +39,8 @@ export interface CreateWorkspacePageViewProps { template: TypesGen.Template; versionId?: string; gitAuth: TypesGen.TemplateVersionGitAuth[]; + gitAuthPollingState: GitAuthPollingState; + startPollingGitAuth: () => void; parameters: TypesGen.TemplateVersionParameter[]; defaultBuildParameters: TypesGen.WorkspaceBuildParameter[]; permissions: CreateWSPermissions; @@ -56,6 +59,8 @@ export const CreateWorkspacePageView: FC = ({ template, versionId, gitAuth, + gitAuthPollingState, + startPollingGitAuth, parameters, defaultBuildParameters, permissions, @@ -113,7 +118,7 @@ export const CreateWorkspacePageView: FC = ({ > - {versionId && ( + {versionId && versionId !== template.active_version_id && ( = ({ description="This template requires authentication to automatically perform Git operations on create." > - {gitAuth.map((auth, index) => ( + {gitAuth.map((auth) => ( @@ -229,12 +236,8 @@ type GitAuthErrors = Record; const useGitAuthVerification = (gitAuth: TypesGen.TemplateVersionGitAuth[]) => { const [gitAuthErrors, setGitAuthErrors] = useState({}); + // Clear errors when gitAuth is refreshed useEffect(() => { - // templateGitAuth is refreshed automatically using a BroadcastChannel - // which may change the `authenticated` property. - // - // If the provider becomes authenticated, we want the error message - // to disappear. setGitAuthErrors({}); }, [gitAuth]); diff --git a/site/src/pages/CreateWorkspacePage/GitAuth.tsx b/site/src/pages/CreateWorkspacePage/GitAuth.tsx index 69315899b539c..bc81c3a73a1c9 100644 --- a/site/src/pages/CreateWorkspacePage/GitAuth.tsx +++ b/site/src/pages/CreateWorkspacePage/GitAuth.tsx @@ -9,20 +9,30 @@ import { BitbucketIcon } from "components/Icons/BitbucketIcon"; import { GitlabIcon } from "components/Icons/GitlabIcon"; import { FC } from "react"; import { makeStyles } from "@mui/styles"; +import { type GitAuthPollingState } from "./CreateWorkspacePage"; +import { Stack } from "components/Stack/Stack"; +import ReplayIcon from "@mui/icons-material/Replay"; +import { LoadingButton } from "components/LoadingButton/LoadingButton"; export interface GitAuthProps { type: TypesGen.GitProvider; authenticated: boolean; authenticateURL: string; + gitAuthPollingState: GitAuthPollingState; + startPollingGitAuth: () => void; error?: string; } -export const GitAuth: FC = ({ - type, - authenticated, - authenticateURL, - error, -}) => { +export const GitAuth: FC = (props) => { + const { + type, + authenticated, + authenticateURL, + gitAuthPollingState, + startPollingGitAuth, + error, + } = props; + const styles = useStyles({ error: typeof error !== "undefined", }); @@ -52,12 +62,11 @@ export const GitAuth: FC = ({ return ( -
- + ? `Authenticated with ${prettyName}` + : `Login with ${prettyName}`} + + {gitAuthPollingState === "abandoned" && ( + + )} {error && {error}} -
+
); }; diff --git a/site/src/pages/GitAuthPage/GitAuthPage.tsx b/site/src/pages/GitAuthPage/GitAuthPage.tsx index 0c64cad44d5e9..f0ebfa22f34ef 100644 --- a/site/src/pages/GitAuthPage/GitAuthPage.tsx +++ b/site/src/pages/GitAuthPage/GitAuthPage.tsx @@ -5,12 +5,11 @@ import { getGitAuthProvider, } from "api/api"; import { usePermissions } from "hooks"; -import { FC, useEffect } from "react"; +import { type FC } from "react"; import { useParams } from "react-router-dom"; import GitAuthPageView from "./GitAuthPageView"; import { ApiErrorResponse } from "api/errors"; import { isAxiosError } from "axios"; -import { REFRESH_GITAUTH_BROADCAST_CHANNEL } from "utils/gitAuth"; const GitAuthPage: FC = () => { const { provider } = useParams(); @@ -52,17 +51,6 @@ const GitAuthPage: FC = () => { query.state.status === "success" ? false : "always", }); - useEffect(() => { - if (!getGitAuthProviderQuery.data?.authenticated) { - return; - } - // This is used to notify the parent window that the Git auth token has been refreshed. - // It's critical in the create workspace flow! - const bc = new BroadcastChannel(REFRESH_GITAUTH_BROADCAST_CHANNEL); - // The message doesn't matter, any message refreshes the page! - bc.postMessage("noop"); - }, [getGitAuthProviderQuery.data?.authenticated]); - if (getGitAuthProviderQuery.isLoading || !getGitAuthProviderQuery.data) { return null; } diff --git a/site/src/pages/GitAuthPage/GitAuthPageView.tsx b/site/src/pages/GitAuthPage/GitAuthPageView.tsx index 5d15a677ea344..23ec8fd98ee0d 100644 --- a/site/src/pages/GitAuthPage/GitAuthPageView.tsx +++ b/site/src/pages/GitAuthPage/GitAuthPageView.tsx @@ -11,8 +11,7 @@ import { Avatar } from "components/Avatar/Avatar"; import { CopyButton } from "components/CopyButton/CopyButton"; import { SignInLayout } from "components/SignInLayout/SignInLayout"; import { Welcome } from "components/Welcome/Welcome"; -import { FC, useEffect } from "react"; -import { REFRESH_GITAUTH_BROADCAST_CHANNEL } from "utils/gitAuth"; +import { type FC } from "react"; export interface GitAuthPageViewProps { gitAuth: GitAuth; @@ -33,18 +32,6 @@ const GitAuthPageView: FC = ({ }) => { const styles = useStyles(); - useEffect(() => { - if (!gitAuth.authenticated) { - return; - } - // This is used to notify the parent window that the Git auth token has been refreshed. - // It's critical in the create workspace flow! - // eslint-disable-next-line compat/compat -- It actually is supported... not sure why it's complaining. - const bc = new BroadcastChannel(REFRESH_GITAUTH_BROADCAST_CHANNEL); - // The message doesn't matter, any message refreshes the page! - bc.postMessage("noop"); - }, [gitAuth.authenticated]); - if (!gitAuth.authenticated) { return ( @@ -76,7 +63,7 @@ const GitAuthPageView: FC = ({

- Hey @{gitAuth.user?.login} 👋!{" "} + Hey @{gitAuth.user?.login}! 👋{" "} {(!gitAuth.app_installable || gitAuth.installations.length > 0) && "You are now authenticated with Git. Feel free to close this window!"}

diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index 7933f10c2a1bf..b150f00f466cb 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -1172,18 +1172,24 @@ export const MockTemplateVersionVariable5: TypesGen.TemplateVersionVariable = { sensitive: false, }; -// requests the MockWorkspace export const MockWorkspaceRequest: TypesGen.CreateWorkspaceRequest = { name: "test", - template_id: "test-template", - rich_parameter_values: [ - { - name: MockTemplateVersionParameter1.name, - value: MockTemplateVersionParameter1.default_value, - }, - ], + template_version_id: "test-template-version", + rich_parameter_values: [], }; +export const MockWorkspaceRichParametersRequest: TypesGen.CreateWorkspaceRequest = + { + name: "test", + template_version_id: "test-template-version", + rich_parameter_values: [ + { + name: MockTemplateVersionParameter1.name, + value: MockTemplateVersionParameter1.default_value, + }, + ], + }; + export const MockUserAgent = { browser: "Chrome 99.0.4844", device: "Other", @@ -2166,6 +2172,14 @@ export const MockTemplateVersionGitAuth: TypesGen.TemplateVersionGitAuth = { authenticated: false, }; +export const MockTemplateVersionGitAuthAuthenticated: TypesGen.TemplateVersionGitAuth = + { + id: "github", + type: "github", + authenticate_url: "https://example.com/gitauth/github", + authenticated: true, + }; + export const MockDeploymentStats: TypesGen.DeploymentStats = { aggregated_from: "2023-03-06T19:08:55.211625Z", collected_at: "2023-03-06T19:12:55.211625Z", diff --git a/site/src/xServices/createWorkspace/createWorkspaceXService.ts b/site/src/xServices/createWorkspace/createWorkspaceXService.ts index 24d65608ad730..79dc44701430f 100644 --- a/site/src/xServices/createWorkspace/createWorkspaceXService.ts +++ b/site/src/xServices/createWorkspace/createWorkspaceXService.ts @@ -2,13 +2,11 @@ import { checkAuthorization, createWorkspace, getTemplateByName, - getTemplateVersionGitAuth, getTemplateVersionRichParameters, } from "api/api"; import { CreateWorkspaceRequest, Template, - TemplateVersionGitAuth, TemplateVersionParameter, User, Workspace, @@ -16,7 +14,6 @@ import { } from "api/typesGenerated"; import { assign, createMachine } from "xstate"; import { paramsUsedToCreateWorkspace } from "utils/workspace"; -import { REFRESH_GITAUTH_BROADCAST_CHANNEL } from "utils/gitAuth"; export type CreateWorkspaceMode = "form" | "auto"; @@ -33,7 +30,6 @@ type CreateWorkspaceContext = { template?: Template; parameters?: TemplateVersionParameter[]; permissions?: Record; - gitAuth?: TemplateVersionGitAuth[]; // Used on auto-create defaultBuildParameters?: WorkspaceBuildParameter[]; }; @@ -49,7 +45,7 @@ type RefreshGitAuthEvent = { }; export const createWorkspaceMachine = - /** @xstate-layout N4IgpgJg5mDOIC5QGMBOYCGAXMB1A9qgNawAOGyYAyltmAHQxZYCWAdlACpgC2pANnVgBiCPjYN2AN3xEGaTDgLEyFarRyMwzdl14ChCafmTYW4gNoAGALrWbiUKXywWrcY5AAPRABYATAA0IACeiACMvgCs9ADssQBsVgDM-v5JyQnJUQkAvrnBCnTKJOSUNHRaOhzcfII4ImIS9MZy9EVKhKVqFZpMrDX69XBGbDKm7mz2FuEOSCDOrpOePgjJAJzr9AAcVr4J677bCeFWB3vBYQgBvvQJB-5R6+GxVulPUfmF6MVdquUaBj9XS1AwNYRgVCoQj0MEAM0IPHaP06KjK6kqwMGdUMxgm5imtnsnkWbgJK0QGy2u32h2Op3OvkuiH8vis9HCDxO0XC2z5CX8XxAHTwf3RvSB2gGehxOCoyAAFrwMKJxJIxrJ5CjRWieoCqtLQcN5UqeBhRuMzJYibYSS4yR55qtTv52bFeYlfPEor4XuFmddwlscqz1mdfMlfZlfEKRSV-hi+lKQUM6CblRCoTD4YjkYodd0AZjk9iwdRFcqLSYrYS7Lb5qTlk6Im83R6El7Yj6-QH4gl6M8ctsoht7skrJ8CsLtfHxfqsTKywAFDCoDA8bSQxpqloatpxsV64vVRfDFdrjc4VCwKv4611uZOe1N0DOgXhOKRjZf-axR4Btl2XWWJngSKJtgCHJwnSWMZ0PIskxPI06HPddN2vTNoVQWF6gRVAkQPXUEMlJDUxwVDLy3W8a2mesnyWclmwQTl-A-WIv3WH8Ej-KIAyyW4Em2Z5XV5fx1m48JYPzWcj0Qw0yLAABxNwAEEAFcsAVVVmlaLVpPgxMSPk2UlNUjSFWoyZaMfBZn0Y18WSDfsfUEvlfEHViA2SbZ-HoDZwPSe4omCwUp0IwtDINFMTOUrB1M0zDs1w3NwoTCUotLYZYviiy8Rom0bMbezvEc8T6BcvkII8-1Qj8dZfP2R4fXEziUliKTfiIyKK2QIhdCXSEeBYWBXHEbcdL3eQlV6gb8OG0a2FgYkGzsx0HIQfwfJiKJXmSZJoO88IRwAqwP22aD3OeLshP2DrUQi9Ker6jhZqGkaCRESEsJw7A8II6aiFe+aPuW+iHTYCkNqiKxtgHVi+XWYK2SZWqNr5HZslAiNoJSSdvn0rr0rhFh+H4frV3XEQAGEACUAFEVM4OmAH1cAAeRpgBpKglxUqm6dB2yGLWkq0cecrdv2-xDuO1GXluRH9s5H1wKObi7oLNL9WJ0nyYvEQqDpgAZOmqc4Zm2dwAA5OmacFoqRdWcd0asSWkZuoJUbSftpc2vZ6rZDsXg1mTiLzMwOFDsBtPVGR9zgwn9Q6XQo8sglrLtYWIaYzbxZ2lIpZl5IA3O+hLvWeleSiVj6pDgzHpRFODMS7Cc3w8P7q1ypk8jgy0-ve3Vuz9bc+2yWDvO2WrjE2HMcybZYiOHJYm2fIpzYfAIDgTxUrnOhM-ByGAFoEgDE-6CsS+3n8d0nl9aW8enAmHvnEtTyEA+X1F4cOWryM0k5JyTiAZWS3DSKBdIC9zjZDronY8xkyzpjNJ-YqqxXjORXuEfaEYAh9gAtLO4aQNgenqkdSMsCX7wOisuCmlFrwoMdhETazl9hCQ2NLKwFd1gnRiCkMM51og8k2BQruclqFZTMppBhw9RZBldvQTa0FzgdnuF5Y4ZdgrumyI8JyC8RF700E9fqg1gZjWkZDUBWwDgjjElgnawE1GxAUUJPYglwIjjeDGMKCdKGaB1mTF6tD4ArSzpDfabwdiXxApseqtjT6o1SE4txrVXTpHSF4-GnVfF6QjlAKO5ic5RCOn5LsbwjpHWeJyAMZVThHUgvcCSvp9GyRyTgCABT1rhN8rsV2MTYmgQDC6BR7xuznByCcZpYcvqEA6aLSxdxFa2OyCBWIAYimwxXvwoMrp3GrzXkAA */ + /** @xstate-layout N4IgpgJg5mDOIC5QGMBOYCGAXMB1A9qgNawAOGyYAyltmAHTIAWYyRAlgHZQCy+EYAMQBtAAwBdRKFL5Y7LO3ycpIAB6IATABYAnPR2iDWgOwBmAGynRo4wFZbAGhABPRDoAc9d+8OnTARlF-Uy0NUQ0AXwinNEwcAmIyCmpaHEYWNi5efiFhf0kkEBk5BSUVdQQNU1svEPcq9wsDU3ctJ1dKv3pRd3NzHVNjf1sjHX8omPQ6BJJySho6egwAVyx8AGEphW5BCCUGLgA3fCIGWOnCWeSFtJW1zbishCP8ZGxFTjFxL5Vi+Q-yoh7MZ9MZjLoQqItN5jDp2ogALT+PSWWwaDR9dzGDTeXTuCYgc7xS5JeapBh3DZbLKCMCoVCEeikAA22AAZoQALaMLZ4ElzFKLSkPd7cZ6cY5vUqfCQ-Qp-aWAhAtPQtWxDaE+OxQ4zwhD+dw1US2cw4-zmLQ9WyicwEol8xICm4MZn4DAQLIAMS5ABFsBhdvt6C9Tjy4g6rmTFq73V7ff7xZL3kovnLpLJ-mVChVzNb6P5tDoMei7P5-G0XIgQqZ6BjbFrWuZGrC7byZqTBWkYx7uN7UJy-bRafTGSz2VywxdHddyfRu3H+4OMInXsmZd8JL8M4rs4hejWCzYLOYDSfjOY9SENPpgmYy+bgjodLbooS2-yZ4t2BBmUJ1gAlABRABBAAVQCAH1cAAeX-ABpKgAAVgPWQC0yKbcAV3BBLHMWs61EQZjQ0ZF3D1ewa36S0QlhasQlbcN2ydWciSyJjkkDTgDglE4znfacozSVjuHYygVylD5U03eVMKzUAc1MPRGh0cEtBMJ9Wj1MxPFsKwmg0DwwmGBip0jTs+MeESP0oYcGVQJlWSwDl+0nYkBPM1y2OssBxLXKSCnTEosPkxBQn8eh7FaewBjRU1THIwIb2CLQ+nrXN1SiV9OByeBCntUTzK3IK5LUKstFrWE4uNGxwQxPUkRsfNqnRfxzybE1+hMtyzOddJWA4bg+AEIrM2UbD6gq58qmqsFQgvSsEGfehLEMExWp0LRSK6iMO164VqW4EadxC5Ui2W0wNDBDVekfLTrx8cIAnBKxgVsbaCt6+de3jWgjuC0qcIsZbfBtPE-F1BaGn0AzIWxGK-HxV98u83rv1-P6SpzSx6EUtT+kIsYT38PUtFscKDTUw1zGxMmy3elGWIOqACoxsaTtNPCLs2-oGlNVq9SJ2tQcCS0eZS+n3N6+0IFZpV3A2-MtBadx1uRcIyIWuxPDsforEM6x7AlnrZ27QCR1QWXxthHHLrBJ8nxtJsSd0ehsQsJWNHrYYi0yiIgA */ createMachine( { id: "createWorkspaceState", @@ -64,7 +60,6 @@ export const createWorkspaceMachine = template: Template; permissions: CreateWSPermissions; parameters: TemplateVersionParameter[]; - gitAuth: TemplateVersionGitAuth[]; }; }; createWorkspace: { @@ -112,16 +107,6 @@ export const createWorkspaceMachine = }, }, idle: { - invoke: [ - { - src: () => (callback) => { - const channel = watchGitAuthRefresh(() => { - callback("REFRESH_GITAUTH"); - }); - return () => channel.close(); - }, - }, - ], on: { CREATE_WORKSPACE: { target: "creatingWorkspace", @@ -189,23 +174,24 @@ export const createWorkspaceMachine = rich_parameter_values: defaultBuildParameters, }); }, - loadFormData: async ({ templateName, organizationId }) => { + loadFormData: async ({ templateName, organizationId, versionId }) => { const [template, permissions] = await Promise.all([ getTemplateByName(organizationId, templateName), checkCreateWSPermissions(organizationId), ]); - const [parameters, gitAuth] = await Promise.all([ - getTemplateVersionRichParameters(template.active_version_id).then( - (p) => p.filter(paramsUsedToCreateWorkspace), + + const realizedVersionId = versionId ?? template.active_version_id; + const [parameters] = await Promise.all([ + getTemplateVersionRichParameters(realizedVersionId).then((p) => + p.filter(paramsUsedToCreateWorkspace), ), - getTemplateVersionGitAuth(template.active_version_id), ]); return { template, permissions, parameters, - gitAuth, + versionId: realizedVersionId, }; }, }, @@ -246,12 +232,6 @@ const checkCreateWSPermissions = async (organizationId: string) => { }) as Promise>; }; -export const watchGitAuthRefresh = (callback: () => void) => { - const bc = new BroadcastChannel(REFRESH_GITAUTH_BROADCAST_CHANNEL); - bc.addEventListener("message", callback); - return bc; -}; - export type CreateWSPermissions = Awaited< ReturnType >;