Skip to content

Commit c3d1c56

Browse files
Brad/exp 458 fe allow pasting in a git clone url to create project as (#18534)
* first pass at organizing components for project creation * allow creating from git clone url * cleanup * add creating state * cleanup * Update components/dashboard/src/projects/new-project/NewProjectCreateFromURL.tsx Co-authored-by: Filip Troníček <[email protected]> * improve git clone url parsing * Adding cancelation when query unmounts * fixing slug * showing some help text if they enter a url that isn't a clone url --------- Co-authored-by: Filip Troníček <[email protected]>
1 parent 95d14d3 commit c3d1c56

12 files changed

+1019
-622
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* Copyright (c) 2023 Gitpod GmbH. All rights reserved.
3+
* Licensed under the GNU Affero General Public License (AGPL).
4+
* See License.AGPL.txt in the project root for license information.
5+
*/
6+
7+
import { useQuery } from "@tanstack/react-query";
8+
import { getGitpodService } from "../../service/service";
9+
import { useAuthProviders } from "../auth-providers/auth-provider-query";
10+
import { useCurrentUser } from "../../user-context";
11+
12+
export const useIsGithubAppEnabled = () => {
13+
return useQuery(["github-app-enabled"], async () => {
14+
return await getGitpodService().server.isGitHubAppEnabled();
15+
});
16+
};
17+
18+
export const useAreGithubWebhooksUnauthorized = (providerHost: string) => {
19+
const { data: authProviders } = useAuthProviders();
20+
const { data: isGitHubAppEnabled } = useIsGithubAppEnabled();
21+
const { data: token } = useGetGitToken(providerHost);
22+
23+
// If the app is enabled, authorized
24+
if (isGitHubAppEnabled) {
25+
return false;
26+
}
27+
28+
// If we don't have auth providers or the provider host, we can't check yet, treat as authorized
29+
if (!authProviders || !providerHost) {
30+
return false;
31+
}
32+
33+
// Find matching auth provider - if none, treat as authorized
34+
const ap = authProviders?.find((ap) => ap.host === providerHost);
35+
if (!ap || ap.authProviderType !== "GitHub") {
36+
return false;
37+
}
38+
39+
// Finally, check token for the right scopes - if missing, then uanuthorized
40+
if (!token || !token.scopes.includes("repo")) {
41+
return true;
42+
}
43+
};
44+
45+
export const useGetGitToken = (providerHost: string) => {
46+
const user = useCurrentUser();
47+
48+
return useQuery(
49+
["git-token", { userId: user?.id }, { providerHost }],
50+
async () => {
51+
return await getGitpodService().server.getToken({ host: providerHost });
52+
},
53+
{
54+
enabled: !!user && !!providerHost,
55+
},
56+
);
57+
};
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* Copyright (c) 2023 Gitpod GmbH. All rights reserved.
3+
* Licensed under the GNU Affero General Public License (AGPL).
4+
* See License.AGPL.txt in the project root for license information.
5+
*/
6+
7+
import { useQuery } from "@tanstack/react-query";
8+
import { getGitpodService } from "../../service/service";
9+
import { useCurrentUser } from "../../user-context";
10+
import { CancellationTokenSource } from "vscode-jsonrpc";
11+
12+
type UseProviderRepositoriesQueryArgs = {
13+
provider: string;
14+
installationId?: string;
15+
};
16+
export const useProviderRepositoriesForUser = ({ provider, installationId }: UseProviderRepositoriesQueryArgs) => {
17+
const user = useCurrentUser();
18+
19+
return useQuery(
20+
["provider-repositories", { userId: user?.id }, { provider, installationId }],
21+
async ({ signal }) => {
22+
// jsonrpc cancellation token that we subscribe to the abort signal provided by react-query
23+
const cancelToken = new CancellationTokenSource();
24+
25+
signal?.addEventListener("abort", () => {
26+
cancelToken.cancel();
27+
});
28+
29+
return await getGitpodService().server.getProviderRepositoriesForUser(
30+
{
31+
provider,
32+
hints: { installationId },
33+
},
34+
// @ts-ignore - not sure why types don't support this
35+
cancelToken.token,
36+
);
37+
},
38+
{
39+
enabled: !!provider,
40+
},
41+
);
42+
};
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* Copyright (c) 2023 Gitpod GmbH. All rights reserved.
3+
* Licensed under the GNU Affero General Public License (AGPL).
4+
* See License.AGPL.txt in the project root for license information.
5+
*/
6+
7+
import { useMutation } from "@tanstack/react-query";
8+
import { getGitpodService } from "../../service/service";
9+
import { useCurrentOrg } from "../organizations/orgs-query";
10+
import { useRefreshProjects } from "./list-projects-query";
11+
import { CreateProjectParams, Project } from "@gitpod/gitpod-protocol";
12+
13+
export type CreateProjectArgs = Omit<CreateProjectParams, "teamId">;
14+
15+
export const useCreateProject = () => {
16+
const refreshProjects = useRefreshProjects();
17+
const { data: org } = useCurrentOrg();
18+
19+
return useMutation<Project, Error, CreateProjectArgs>(
20+
async ({ name, slug, cloneUrl, appInstallationId }) => {
21+
if (!org) {
22+
throw new Error("No org currently selected");
23+
}
24+
25+
return await getGitpodService().server.createProject({
26+
name,
27+
slug,
28+
cloneUrl,
29+
teamId: org.id,
30+
appInstallationId,
31+
});
32+
},
33+
{
34+
onSuccess: (project) => {
35+
if (org) {
36+
refreshProjects(org.id);
37+
}
38+
39+
// Kick off a prebuild for the new project
40+
getGitpodService().server.triggerPrebuild(project.id, null);
41+
},
42+
},
43+
);
44+
};

0 commit comments

Comments
 (0)