Skip to content

Commit e6c7342

Browse files
committed
[server] Leverage 'gitpod-yml-inferrer' to guess a new Project's .gitpod.yml
1 parent f843ace commit e6c7342

File tree

6 files changed

+54
-2
lines changed

6 files changed

+54
-2
lines changed

components/dashboard/src/projects/ConfigureProject.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ export default function () {
7575
const project = projects.find(p => p.name === routeMatch?.params.projectSlug);
7676
if (project) {
7777
setProject(project);
78+
getGitpodService().server.guessProjectConfiguration(project.id).then(conf => console.log('guessed', conf)).catch(err => console.error('could not guess', err));
7879
const configString = await getGitpodService().server.fetchProjectRepositoryConfiguration(project.id);
7980
if (configString) {
8081
// TODO(janx): Link to .gitpod.yml directly instead of just the cloneUrl.

components/gitpod-protocol/src/gitpod-service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
132132
triggerPrebuild(projectId: string, branch: string): Promise<void>;
133133
setProjectConfiguration(projectId: string, configString: string): Promise<void>;
134134
fetchProjectRepositoryConfiguration(projectId: string): Promise<string | undefined>;
135+
guessProjectConfiguration(projectId: string): Promise<string | undefined>;
135136

136137
// content service
137138
getContentBlobUploadUrl(name: string): Promise<string>

components/server/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
"express-mysql-session": "^2.1.0",
5858
"express-session": "^1.15.6",
5959
"fs-extra": "^10.0.0",
60+
"gitpod-yml-inferrer": "^1.1.1",
6061
"google-protobuf": "3.15.8",
6162
"graphql": "^14.6.0",
6263
"graphql-tools": "^4.0.7",
@@ -83,7 +84,6 @@
8384
"ws": "^7.4.6"
8485
},
8586
"devDependencies": {
86-
"@types/cookie-parser": "^1.4.2",
8787
"@graphql-codegen/cli": "^1.19.4",
8888
"@graphql-codegen/introspection": "^1.18.1",
8989
"@graphql-codegen/typescript": "^1.19.0",
@@ -95,6 +95,7 @@
9595
"@types/body-parser": "^1.16.5",
9696
"@types/chai": "^4.1.2",
9797
"@types/chai-http": "^3.0.4",
98+
"@types/cookie-parser": "^1.4.2",
9899
"@types/cors": "^2.8.3",
99100
"@types/deep-equal": "^1.0.1",
100101
"@types/dotenv": "^4.0.2",

components/server/src/auth/rate-limiter.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ function getConfig(config: RateLimiterConfig): RateLimiterConfig {
9797
"triggerPrebuild": { group: "default", points: 1 },
9898
"setProjectConfiguration": { group: "default", points: 1 },
9999
"fetchProjectRepositoryConfiguration": { group: "default", points: 1 },
100+
"guessProjectConfiguration": { group: "default", points: 1 },
100101
"getContentBlobUploadUrl": { group: "default", points: 1 },
101102
"getContentBlobDownloadUrl": { group: "default", points: 1 },
102103
"getGitpodTokens": { group: "default", points: 1 },

components/server/src/workspace/gitpod-server-impl.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import { BlobServiceClient } from "@gitpod/content-service/lib/blobs_grpc_pb";
88
import { DownloadUrlRequest, DownloadUrlResponse, UploadUrlRequest, UploadUrlResponse } from '@gitpod/content-service/lib/blobs_pb';
99
import { AppInstallationDB, UserDB, UserMessageViewsDB, WorkspaceDB, DBWithTracing, TracedWorkspaceDB, DBGitpodToken, DBUser, UserStorageResourcesDB, TeamDB } from '@gitpod/gitpod-db/lib';
10-
import { AuthProviderEntry, AuthProviderInfo, Branding, CommitContext, Configuration, CreateWorkspaceMode, DisposableCollection, GetWorkspaceTimeoutResult, GitpodClient, GitpodServer, GitpodToken, GitpodTokenType, InstallPluginsParams, PermissionName, PortVisibility, PrebuiltWorkspace, PrebuiltWorkspaceContext, PreparePluginUploadParams, ResolvedPlugins, ResolvePluginsParams, SetWorkspaceTimeoutResult, StartPrebuildContext, StartWorkspaceResult, Terms, Token, UninstallPluginParams, User, UserEnvVar, UserEnvVarValue, UserInfo, WhitelistedRepository, Workspace, WorkspaceContext, WorkspaceCreationResult, WorkspaceImageBuild, WorkspaceInfo, WorkspaceInstance, WorkspaceInstancePort, WorkspaceInstanceUser, WorkspaceTimeoutDuration, GuessGitTokenScopesParams, GuessedGitTokenScopes, Team, TeamMemberInfo, TeamMembershipInvite, CreateProjectParams, Project, ProviderRepository, PrebuildInfo, TeamMemberRole, WithDefaultConfig, FindPrebuildsParams } from '@gitpod/gitpod-protocol';
10+
import { AuthProviderEntry, AuthProviderInfo, Branding, CommitContext, Configuration, CreateWorkspaceMode, DisposableCollection, GetWorkspaceTimeoutResult, GitpodClient, GitpodServer, GitpodToken, GitpodTokenType, InstallPluginsParams, PermissionName, PortVisibility, PrebuiltWorkspace, PrebuiltWorkspaceContext, PreparePluginUploadParams, ResolvedPlugins, ResolvePluginsParams, SetWorkspaceTimeoutResult, StartPrebuildContext, StartWorkspaceResult, Terms, Token, UninstallPluginParams, User, UserEnvVar, UserEnvVarValue, UserInfo, WhitelistedRepository, Workspace, WorkspaceContext, WorkspaceCreationResult, WorkspaceImageBuild, WorkspaceInfo, WorkspaceInstance, WorkspaceInstancePort, WorkspaceInstanceUser, WorkspaceTimeoutDuration, GuessGitTokenScopesParams, GuessedGitTokenScopes, Team, TeamMemberInfo, TeamMembershipInvite, CreateProjectParams, Project, ProviderRepository, PrebuildInfo, TeamMemberRole, WithDefaultConfig, FindPrebuildsParams, WorkspaceConfig } from '@gitpod/gitpod-protocol';
1111
import { AccountStatement } from "@gitpod/gitpod-protocol/lib/accounting-protocol";
1212
import { AdminBlockUserRequest, AdminGetListRequest, AdminGetListResult, AdminGetWorkspacesRequest, AdminModifyPermanentWorkspaceFeatureFlagRequest, AdminModifyRoleOrPermissionRequest, WorkspaceAndInstance } from '@gitpod/gitpod-protocol/lib/admin-protocol';
1313
import { GetLicenseInfoResult, LicenseFeature, LicenseValidationResult } from '@gitpod/gitpod-protocol/lib/license-protocol';
@@ -52,6 +52,7 @@ import { HeadlessLogUrls } from "@gitpod/gitpod-protocol/lib/headless-workspace-
5252
import { HeadlessLogService } from "./headless-log-service";
5353
import { InvalidGitpodYMLError } from "./config-provider";
5454
import { ProjectsService } from "../projects/projects-service";
55+
import { ConfigInferrer } from "gitpod-yml-inferrer";
5556

5657
@injectable()
5758
export class GitpodServerImpl<Client extends GitpodClient, Server extends GitpodServer> implements GitpodServer, Disposable {
@@ -1561,6 +1562,48 @@ export class GitpodServerImpl<Client extends GitpodClient, Server extends Gitpod
15611562
return configString;
15621563
}
15631564

1565+
public async guessProjectConfiguration(projectId: string): Promise<string | undefined> {
1566+
const user = this.checkUser("guessProjectConfiguration");
1567+
const span = opentracing.globalTracer().startSpan("guessProjectConfiguration");
1568+
span.setTag("projectId", projectId);
1569+
1570+
const project = await this.projectsService.getProject(projectId);
1571+
if (!project) {
1572+
throw new ResponseError(ErrorCodes.NOT_FOUND, "Project not found");
1573+
}
1574+
await this.guardProjectOperation(user, projectId, "get");
1575+
1576+
const normalizedContextUrl = this.contextParser.normalizeContextURL(project.cloneUrl);
1577+
const context = (await this.contextParser.handle({ span }, user, normalizedContextUrl)) as CommitContext;
1578+
const { host } = context.repository;
1579+
const hostContext = this.hostContextProvider.get(host);
1580+
if (!hostContext || !hostContext.services) {
1581+
throw new Error(`Cannot fetch repository configuration for host: ${host}`);
1582+
}
1583+
const repoHost = hostContext.services;
1584+
const cache: { [path: string]: string } = {};
1585+
const readFile = async (path: string) => {
1586+
if (path in cache) {
1587+
return cache[path];
1588+
}
1589+
const content = await repoHost.fileProvider.getFileContent(context, user, path);
1590+
if (content) {
1591+
cache[path] = content;
1592+
}
1593+
return content;
1594+
}
1595+
const config: WorkspaceConfig = await new ConfigInferrer().getConfig({
1596+
config: {},
1597+
read: readFile,
1598+
exists: async (path: string) => !!(await readFile(path)),
1599+
});
1600+
if (config.tasks) {
1601+
const configString = `tasks:\n - ${config.tasks.map(task => Object.entries(task).map(([phase, command]) => `${phase}: ${command}`).join('\n ')).join('\n - ')}`;
1602+
return configString;
1603+
}
1604+
return;
1605+
}
1606+
15641607
public async getContentBlobUploadUrl(name: string): Promise<string> {
15651608
const user = this.checkAndBlockUser("getContentBlobUploadUrl");
15661609
await this.guardAccess({ kind: "contentBlob", name: name, userID: user.id }, "create");

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11055,6 +11055,11 @@ gitconfiglocal@^1.0.0:
1105511055
dependencies:
1105611056
ini "^1.3.2"
1105711057

11058+
gitpod-yml-inferrer@^1.1.1:
11059+
version "1.1.1"
11060+
resolved "https://registry.yarnpkg.com/gitpod-yml-inferrer/-/gitpod-yml-inferrer-1.1.1.tgz#79392c981abb5ef5f33ba9f7ac46d832b87ac0c9"
11061+
integrity sha512-ccQ4o3iEV7SX07HPSzmqRW5S82xyGiDXP2JfJ9bQVjWKa5JKe0w+jBsmPZImCkOfP9fM/LmgctIHBIcZ3KrPKA==
11062+
1105811063
glob-base@^0.3.0:
1105911064
version "0.3.0"
1106011065
resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"

0 commit comments

Comments
 (0)