From 0fba169219dd0fb651c6e314b2d038a3c7743d91 Mon Sep 17 00:00:00 2001 From: Alex Tugarev Date: Wed, 22 Nov 2023 12:13:59 +0100 Subject: [PATCH] [server] Removes unused RepositoryService.canInstall (#19112) * [server] Remove obsolete branch from `createWorkspace` We're no longer supporting `/prebuild` in context parser, thus this is obsolete. * [server] remove unused `RepositoryService.canInstallAutomatedPrebuilds` --- .../bitbucket-server-service.spec.ts | 32 --------------- .../src/prebuilds/bitbucket-server-service.ts | 37 ++++------------- .../server/src/prebuilds/bitbucket-service.ts | 26 ++++-------- .../server/src/prebuilds/github-service.ts | 41 ++++--------------- .../server/src/prebuilds/gitlab-service.ts | 29 ++++--------- .../server/src/repohost/repo-service.ts | 4 -- .../test/service-testing-container-module.ts | 3 -- .../src/workspace/gitpod-server-impl.ts | 26 ------------ 8 files changed, 32 insertions(+), 166 deletions(-) diff --git a/components/server/src/prebuilds/bitbucket-server-service.spec.ts b/components/server/src/prebuilds/bitbucket-server-service.spec.ts index 0d0883296d1f10..9bfad03e73ca59 100644 --- a/components/server/src/prebuilds/bitbucket-server-service.spec.ts +++ b/components/server/src/prebuilds/bitbucket-server-service.spec.ts @@ -89,38 +89,6 @@ class TestBitbucketServerService { }; } - @test async test_canInstallAutomatedPrebuilds_unauthorized() { - const result = await this.service.canInstallAutomatedPrebuilds( - this.user, - "https://bitbucket.gitpod-self-hosted.com/users/jldec/repos/test-repo", - ); - expect(result).to.be.false; - } - - @test async test_canInstallAutomatedPrebuilds_in_project_ok() { - const result = await this.service.canInstallAutomatedPrebuilds( - this.user, - "https://bitbucket.gitpod-self-hosted.com/projects/jldec/repos/jldec-repo-march-30", - ); - expect(result).to.be.true; - } - - @test async test_canInstallAutomatedPrebuilds_ok() { - const result = await this.service.canInstallAutomatedPrebuilds( - this.user, - "https://bitbucket.gitpod-self-hosted.com/projects/FOO/repos/repo123", - ); - expect(result).to.be.true; - } - - @test async test_canInstallAutomatedPrebuilds_users_project_ok() { - const result = await this.service.canInstallAutomatedPrebuilds( - this.user, - "https://bitbucket.gitpod-self-hosted.com/scm/~alextugarev/yolo.git", - ); - expect(result).to.be.true; - } - @test async test_installAutomatedPrebuilds_ok() { try { await this.service.installAutomatedPrebuilds( diff --git a/components/server/src/prebuilds/bitbucket-server-service.ts b/components/server/src/prebuilds/bitbucket-server-service.ts index 1d157ac177a9a6..ff6fe9e1e95a70 100644 --- a/components/server/src/prebuilds/bitbucket-server-service.ts +++ b/components/server/src/prebuilds/bitbucket-server-service.ts @@ -8,7 +8,6 @@ import { RepositoryService } from "../repohost/repo-service"; import { ProviderRepository, User } from "@gitpod/gitpod-protocol"; import { inject, injectable } from "inversify"; import { BitbucketServerApi } from "../bitbucket-server/bitbucket-server-api"; -import { AuthProviderParams } from "../auth/auth-provider"; import { BitbucketServerContextParser } from "../bitbucket-server/bitbucket-server-context-parser"; import { Config } from "../config"; import { TokenService } from "../user/token-service"; @@ -19,11 +18,14 @@ import { CancellationToken } from "vscode-jsonrpc"; export class BitbucketServerService extends RepositoryService { static PREBUILD_TOKEN_SCOPE = "prebuilds"; - @inject(BitbucketServerApi) protected api: BitbucketServerApi; - @inject(Config) protected readonly config: Config; - @inject(AuthProviderParams) protected authProviderConfig: AuthProviderParams; - @inject(TokenService) protected tokenService: TokenService; - @inject(BitbucketServerContextParser) protected contextParser: BitbucketServerContextParser; + constructor( + @inject(BitbucketServerApi) private readonly api: BitbucketServerApi, + @inject(Config) private readonly config: Config, + @inject(TokenService) private readonly tokenService: TokenService, + @inject(BitbucketServerContextParser) private readonly contextParser: BitbucketServerContextParser, + ) { + super(); + } async getRepositoriesForAutomatedPrebuilds( user: User, @@ -44,29 +46,6 @@ export class BitbucketServerService extends RepositoryService { }); } - async canInstallAutomatedPrebuilds(user: User, cloneUrl: string): Promise { - const { host, repoKind, owner, repoName } = await this.contextParser.parseURL(user, cloneUrl); - if (host !== this.authProviderConfig.host) { - return false; - } - - const identity = user.identities.find((i) => i.authProviderId === this.authProviderConfig.id); - if (!identity) { - console.error(`BBS: no identity found.`, { host: this.authProviderConfig.host, userId: user.id, cloneUrl }); - return false; - } - - try { - await this.api.getWebhooks(user, { repoKind, repositorySlug: repoName, owner }); - // reading webhooks to check if admin scope is provided - } catch (error) { - console.log(`BBS: could not read webhooks.`, error, { error, cloneUrl }); - return false; - } - // return true once it can get webhooks, fallback to let SCM itself to check permission - return true; - } - async installAutomatedPrebuilds(user: User, cloneUrl: string): Promise { const { owner, repoName, repoKind } = await this.contextParser.parseURL(user, cloneUrl); diff --git a/components/server/src/prebuilds/bitbucket-service.ts b/components/server/src/prebuilds/bitbucket-service.ts index 20a10c305d6e7e..c3f65870982ec0 100644 --- a/components/server/src/prebuilds/bitbucket-service.ts +++ b/components/server/src/prebuilds/bitbucket-service.ts @@ -8,7 +8,6 @@ import { RepositoryService } from "../repohost/repo-service"; import { User } from "@gitpod/gitpod-protocol"; import { inject, injectable } from "inversify"; import { BitbucketApiFactory } from "../bitbucket/bitbucket-api-factory"; -import { AuthProviderParams } from "../auth/auth-provider"; import { BitbucketApp } from "./bitbucket-app"; import { Config } from "../config"; import { TokenService } from "../user/token-service"; @@ -18,24 +17,13 @@ import { BitbucketContextParser } from "../bitbucket/bitbucket-context-parser"; export class BitbucketService extends RepositoryService { static PREBUILD_TOKEN_SCOPE = "prebuilds"; - @inject(BitbucketApiFactory) protected api: BitbucketApiFactory; - @inject(Config) protected readonly config: Config; - @inject(AuthProviderParams) protected authProviderConfig: AuthProviderParams; - @inject(TokenService) protected tokenService: TokenService; - @inject(BitbucketContextParser) protected bitbucketContextParser: BitbucketContextParser; - - async canInstallAutomatedPrebuilds(user: User, cloneUrl: string): Promise { - const { host, owner, repoName } = await this.bitbucketContextParser.parseURL(user, cloneUrl); - if (host !== this.authProviderConfig.host) { - return false; - } - - // only admins may install webhooks on repositories - const api = await this.api.create(user); - const response = await api.user.listPermissionsForRepos({ - q: `repository.full_name="${owner}/${repoName}"`, - }); - return !!response.data?.values && response.data.values[0]?.permission === "admin"; + constructor( + @inject(BitbucketApiFactory) private readonly api: BitbucketApiFactory, + @inject(Config) private readonly config: Config, + @inject(TokenService) private readonly tokenService: TokenService, + @inject(BitbucketContextParser) private readonly bitbucketContextParser: BitbucketContextParser, + ) { + super(); } async installAutomatedPrebuilds(user: User, cloneUrl: string): Promise { diff --git a/components/server/src/prebuilds/github-service.ts b/components/server/src/prebuilds/github-service.ts index ead47429cdc855..327179d0d963be 100644 --- a/components/server/src/prebuilds/github-service.ts +++ b/components/server/src/prebuilds/github-service.ts @@ -8,7 +8,6 @@ import { RepositoryService } from "../repohost/repo-service"; import { inject, injectable } from "inversify"; import { GitHubGraphQlEndpoint, GitHubRestApi } from "../github/api"; import { GitHubEnterpriseApp } from "./github-enterprise-app"; -import { AuthProviderParams } from "../auth/auth-provider"; import { GithubContextParser } from "../github/github-context-parser"; import { ProviderRepository, User } from "@gitpod/gitpod-protocol"; import { Config } from "../config"; @@ -18,12 +17,15 @@ import { TokenService } from "../user/token-service"; export class GitHubService extends RepositoryService { static PREBUILD_TOKEN_SCOPE = "prebuilds"; - @inject(GitHubGraphQlEndpoint) protected readonly githubQueryApi: GitHubGraphQlEndpoint; - @inject(GitHubRestApi) protected readonly githubApi: GitHubRestApi; - @inject(Config) protected readonly config: Config; - @inject(AuthProviderParams) protected authProviderConfig: AuthProviderParams; - @inject(TokenService) protected tokenService: TokenService; - @inject(GithubContextParser) protected githubContextParser: GithubContextParser; + constructor( + @inject(GitHubGraphQlEndpoint) protected readonly githubQueryApi: GitHubGraphQlEndpoint, + @inject(GitHubRestApi) protected readonly githubApi: GitHubRestApi, + @inject(Config) private readonly config: Config, + @inject(TokenService) private readonly tokenService: TokenService, + @inject(GithubContextParser) private readonly githubContextParser: GithubContextParser, + ) { + super(); + } // TODO: consider refactoring this to either use GH Search API w/ typeahead search only OR // return results in a stream, appending pages as being fetched (via callback below) OR @@ -53,31 +55,6 @@ export class GitHubService extends RepositoryService { return repositories; } - async canInstallAutomatedPrebuilds(user: User, cloneUrl: string): Promise { - const { host, owner, repoName: repo } = await this.githubContextParser.parseURL(user, cloneUrl); - if (host !== this.authProviderConfig.host) { - return false; - } - try { - // You need "ADMIN" permission on a repository to be able to install a webhook. - // Ref: https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-roles-for-an-organization#permissions-for-each-role - // Ref: https://docs.github.com/en/graphql/reference/enums#repositorypermission - const result: any = await this.githubQueryApi.runQuery( - user, - ` - query { - repository(name: "${repo}", owner: "${owner}") { - viewerPermission - } - } - `, - ); - return result.data.repository && result.data.repository.viewerPermission === "ADMIN"; - } catch (err) { - return false; - } - } - async installAutomatedPrebuilds(user: User, cloneUrl: string): Promise { const { owner, repoName: repo } = await this.githubContextParser.parseURL(user, cloneUrl); const webhooks = (await this.githubApi.run(user, (gh) => gh.repos.listWebhooks({ owner, repo }))).data; diff --git a/components/server/src/prebuilds/gitlab-service.ts b/components/server/src/prebuilds/gitlab-service.ts index 746b423542ec8e..a609f991de6c60 100644 --- a/components/server/src/prebuilds/gitlab-service.ts +++ b/components/server/src/prebuilds/gitlab-service.ts @@ -8,7 +8,6 @@ import { RepositoryService } from "../repohost/repo-service"; import { User } from "@gitpod/gitpod-protocol"; import { inject, injectable } from "inversify"; import { GitLabApi, GitLab } from "../gitlab/api"; -import { AuthProviderParams } from "../auth/auth-provider"; import { GitLabApp } from "./gitlab-app"; import { Config } from "../config"; import { TokenService } from "../user/token-service"; @@ -19,25 +18,13 @@ import { log } from "@gitpod/gitpod-protocol/lib/util/logging"; export class GitlabService extends RepositoryService { static PREBUILD_TOKEN_SCOPE = "prebuilds"; - @inject(GitLabApi) protected api: GitLabApi; - @inject(Config) protected readonly config: Config; - @inject(AuthProviderParams) protected authProviderConfig: AuthProviderParams; - @inject(TokenService) protected tokenService: TokenService; - @inject(GitlabContextParser) protected gitlabContextParser: GitlabContextParser; - - async canInstallAutomatedPrebuilds(user: User, cloneUrl: string): Promise { - const { host, owner, repoName } = await this.gitlabContextParser.parseURL(user, cloneUrl); - if (host !== this.authProviderConfig.host) { - return false; - } - const api = await this.api.create(user); - const response = (await api.Projects.show(`${owner}/${repoName}`)) as unknown as GitLab.Project; - if (GitLab.ApiError.is(response)) { - throw response; - } - // one need to have at least the access level of a maintainer (40) in order to install webhooks on a project - // cf. https://docs.gitlab.com/ee/api/members.html#valid-access-levels - return GitLab.Permissions.hasMaintainerAccess(response); + constructor( + @inject(GitLabApi) protected api: GitLabApi, + @inject(Config) private readonly config: Config, + @inject(TokenService) private readonly tokenService: TokenService, + @inject(GitlabContextParser) private readonly gitlabContextParser: GitlabContextParser, + ) { + super(); } async installAutomatedPrebuilds(user: User, cloneUrl: string): Promise { @@ -69,7 +56,7 @@ export class GitlabService extends RepositoryService { log.info("Installed Webhook for " + cloneUrl, { cloneUrl, userId: user.id }); } - protected getHookUrl() { + private getHookUrl() { return this.config.hostUrl .asPublicServices() .with({ diff --git a/components/server/src/repohost/repo-service.ts b/components/server/src/repohost/repo-service.ts index 3cb1d421b51c0c..e2768a6b49958d 100644 --- a/components/server/src/repohost/repo-service.ts +++ b/components/server/src/repohost/repo-service.ts @@ -17,10 +17,6 @@ export class RepositoryService { return []; } - async canInstallAutomatedPrebuilds(user: User, cloneUrl: string): Promise { - return false; - } - async installAutomatedPrebuilds(user: User, cloneUrl: string): Promise { throw new Error("unsupported"); } diff --git a/components/server/src/test/service-testing-container-module.ts b/components/server/src/test/service-testing-container-module.ts index 1602deb9ce41ae..7a4ec8930f9efc 100644 --- a/components/server/src/test/service-testing-container-module.ts +++ b/components/server/src/test/service-testing-container-module.ts @@ -110,9 +110,6 @@ const mockApplyingContainerModule = new ContainerModule((bind, unbound, isbound, installAutomatedPrebuilds: async (user: any, cloneUrl: string) => { webhooks.add(cloneUrl); }, - canInstallAutomatedPrebuilds: async () => { - throw "not expected to be called"; - }, }, repositoryProvider: { hasReadAccess: async (user: any, owner: string, repo: string) => { diff --git a/components/server/src/workspace/gitpod-server-impl.ts b/components/server/src/workspace/gitpod-server-impl.ts index e9370e3c06586a..26c874815a6308 100644 --- a/components/server/src/workspace/gitpod-server-impl.ts +++ b/components/server/src/workspace/gitpod-server-impl.ts @@ -29,7 +29,6 @@ import { PrebuiltWorkspace, PrebuiltWorkspaceContext, SetWorkspaceTimeoutResult, - StartPrebuildContext, StartWorkspaceResult, Token, User, @@ -96,7 +95,6 @@ import { SupportedWorkspaceClass } from "@gitpod/gitpod-protocol/lib/workspace-c import { WorkspaceManagerClientProvider } from "@gitpod/ws-manager/lib/client-provider"; import { StopWorkspacePolicy, TakeSnapshotRequest } from "@gitpod/ws-manager/lib/core_pb"; import { inject, injectable } from "inversify"; -import { URL } from "url"; import { v4 as uuidv4, validate as uuidValidate } from "uuid"; import { Disposable, CancellationToken } from "vscode-jsonrpc"; import { IAnalyticsWriter } from "@gitpod/gitpod-protocol/lib/analytics"; @@ -1122,30 +1120,6 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable { context = WithDefaultConfig.mark(context); } - // if this is an explicit prebuild, check if the user wants to install an app. - if ( - StartPrebuildContext.is(context) && - CommitContext.is(context.actual) && - context.actual.repository.cloneUrl - ) { - const cloneUrl = context.actual.repository.cloneUrl; - const host = new URL(cloneUrl).hostname; - const hostContext = this.hostContextProvider.get(host); - const services = hostContext && hostContext.services; - if (!hostContext || !services) { - console.error("Unknown host: " + host); - } else { - // on purpose to not await on that installation process, because it‘s not required of workspace start - // See https://github.com/gitpod-io/gitpod/pull/6420#issuecomment-953499632 for more detail - (async () => { - if (await services.repositoryService.canInstallAutomatedPrebuilds(user, cloneUrl)) { - console.log("Installing automated prebuilds for " + cloneUrl); - await services.repositoryService.installAutomatedPrebuilds(user, cloneUrl); - } - })().catch((e) => console.error("Install automated prebuilds failed", e)); - } - } - if (!options.ignoreRunningWorkspaceOnSameCommit && !context.forceCreateNewWorkspace) { const runningForContext = await runningForContextPromise; if (runningForContext.length > 0) {