Skip to content

Commit 91c09f7

Browse files
svenefftingeroboquat
authored andcommitted
[server] derive configuration when no explicit one
Fixes #6921
1 parent de80cb9 commit 91c09f7

11 files changed

+115
-159
lines changed

components/server/ee/src/prebuilds/prebuild-manager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ export class PrebuildManager {
203203
return undefined;
204204
}
205205
const context = await contextParser!.handle({ span }, user, contextURL);
206-
return await this.configProvider.fetchConfig({ span }, user, context as CommitContext);
206+
return (await this.configProvider.fetchConfig({ span }, user, context as CommitContext)).config;
207207
} catch (err) {
208208
TraceContext.setError({ span }, err);
209209
throw err;

components/server/ee/src/workspace/workspace-factory.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export class WorkspaceFactoryEE extends WorkspaceFactory {
6060
}
6161
}
6262

63-
const config = await this.configProvider.fetchConfig({span}, user, context.actual);
63+
const { config } = await this.configProvider.fetchConfig({span}, user, context.actual);
6464
const imageSource = await this.imageSourceProvider.getImageSource(ctx, user, context.actual, config);
6565

6666
// Walk back the commit history to find suitable parent prebuild to start an incremental prebuild on.
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/**
2+
* Copyright (c) 2020 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 { CommitContext, User, WorkspaceConfig } from "@gitpod/gitpod-protocol";
8+
import { TraceContext } from "@gitpod/gitpod-protocol/lib/util/tracing";
9+
import { inject, injectable } from "inversify";
10+
import { HostContextProvider } from "../auth/host-context-provider";
11+
import { FileProvider } from "../repohost";
12+
import { ContextParser } from "../workspace/context-parser-service";
13+
import { ConfigInferrer } from "./config-inferrer";
14+
15+
16+
@injectable()
17+
export class ConfigurationService {
18+
19+
@inject(ContextParser) protected contextParser: ContextParser;
20+
@inject(HostContextProvider) protected readonly hostContextProvider: HostContextProvider;
21+
22+
// a static cache used to prefetch inferrer related files in parallel in advance
23+
private requestedPaths = new Set<string>();
24+
25+
async guessRepositoryConfiguration(ctx: TraceContext, user: User, contextURLOrContext: string | CommitContext): Promise<string | undefined> {
26+
const { fileProvider, commitContext } = await this.getRepositoryFileProviderAndCommitContext(ctx, user, contextURLOrContext);
27+
const cache: { [path: string]: Promise<string | undefined> } = {};
28+
const readFile = async (path: string) => {
29+
if (path in cache) {
30+
return await cache[path];
31+
}
32+
this.requestedPaths.add(path);
33+
const content = fileProvider.getFileContent(commitContext, user, path);
34+
cache[path] = content;
35+
return await content;
36+
}
37+
// eagerly fetch for all files that the inferrer usually asks for.
38+
this.requestedPaths.forEach(path => !(path in cache) && readFile(path));
39+
const config: WorkspaceConfig = await new ConfigInferrer().getConfig({
40+
config: {},
41+
read: readFile,
42+
exists: async (path: string) => !!(await readFile(path)),
43+
});
44+
if (!config.tasks) {
45+
return;
46+
}
47+
const configString = `tasks:\n - ${config.tasks.map(task => Object.entries(task).map(([phase, command]) => `${phase}: ${command}`).join('\n ')).join('\n - ')}`;
48+
return configString;
49+
}
50+
51+
async fetchRepositoryConfiguration(ctx: TraceContext, user: User, contextURL: string): Promise<string | undefined> {
52+
const { fileProvider, commitContext } = await this.getRepositoryFileProviderAndCommitContext(ctx, user, contextURL);
53+
const configString = await fileProvider.getGitpodFileContent(commitContext, user);
54+
return configString;
55+
}
56+
57+
58+
protected async getRepositoryFileProviderAndCommitContext(ctx: TraceContext, user: User, contextURLOrContext: string | CommitContext): Promise<{fileProvider: FileProvider, commitContext: CommitContext}> {
59+
let commitContext: CommitContext;
60+
if (typeof contextURLOrContext === 'string') {
61+
const normalizedContextUrl = this.contextParser.normalizeContextURL(contextURLOrContext);
62+
commitContext = (await this.contextParser.handle(ctx, user, normalizedContextUrl)) as CommitContext;
63+
} else {
64+
commitContext = contextURLOrContext;
65+
}
66+
const { host } = commitContext.repository;
67+
const hostContext = this.hostContextProvider.get(host);
68+
if (!hostContext || !hostContext.services) {
69+
throw new Error(`Cannot fetch repository configuration for host: ${host}`);
70+
}
71+
const fileProvider = hostContext.services.fileProvider;
72+
return { fileProvider, commitContext };
73+
}
74+
}

components/server/src/container-module.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { ConfigProvider } from './workspace/config-provider';
1717
import { MessageBusIntegration } from './workspace/messagebus-integration';
1818
import { MessageBusHelper, MessageBusHelperImpl } from '@gitpod/gitpod-messagebus/lib';
1919
import { IClientDataPrometheusAdapter, ClientDataPrometheusAdapterImpl } from './workspace/client-data-prometheus-adapter';
20-
import { ConfigInferenceProvider } from './workspace/config-inference-provider';
20+
import { ConfigurationService } from './config/configuration-service';
2121
import { IContextParser, IPrefixContextParser } from './workspace/context-parser';
2222
import { ContextParser } from './workspace/context-parser-service';
2323
import { SnapshotContextParser } from './workspace/snapshot-context-parser';
@@ -103,7 +103,7 @@ export const productionContainerModule = new ContainerModule((bind, unbind, isBo
103103
bind(GitpodFileParser).toSelf().inSingletonScope();
104104

105105
bind(ConfigProvider).toSelf().inSingletonScope();
106-
bind(ConfigInferenceProvider).toSelf().inSingletonScope();
106+
bind(ConfigurationService).toSelf().inSingletonScope();
107107

108108
bind(WorkspaceFactory).toSelf().inSingletonScope();
109109
bind(WorkspaceDeletionService).toSelf().inSingletonScope();

components/server/src/projects/projects-service.ts

Lines changed: 2 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,10 @@
66

77
import { inject, injectable } from "inversify";
88
import { DBWithTracing, ProjectDB, TeamDB, TracedWorkspaceDB, UserDB, WorkspaceDB } from "@gitpod/gitpod-db/lib";
9-
import { Branch, CommitContext, PrebuildWithStatus, CreateProjectParams, FindPrebuildsParams, Project, User, WorkspaceConfig } from "@gitpod/gitpod-protocol";
10-
import { TraceContext } from "@gitpod/gitpod-protocol/lib/util/tracing";
9+
import { Branch, PrebuildWithStatus, CreateProjectParams, FindPrebuildsParams, Project, User } from "@gitpod/gitpod-protocol";
1110
import { HostContextProvider } from "../auth/host-context-provider";
12-
import { FileProvider, RepoURL } from "../repohost";
11+
import { RepoURL } from "../repohost";
1312
import { log } from '@gitpod/gitpod-protocol/lib/util/logging';
14-
import { ContextParser } from "../workspace/context-parser-service";
15-
import { ConfigInferrer } from "./config-inferrer";
1613
import { PartialProject } from "@gitpod/gitpod-protocol/src/teams-projects-protocol";
1714

1815
@injectable()
@@ -23,7 +20,6 @@ export class ProjectsService {
2320
@inject(UserDB) protected readonly userDB: UserDB;
2421
@inject(TracedWorkspaceDB) protected readonly workspaceDb: DBWithTracing<WorkspaceDB>;
2522
@inject(HostContextProvider) protected readonly hostContextProvider: HostContextProvider;
26-
@inject(ContextParser) protected contextParser: ContextParser;
2723

2824
async getProject(projectId: string): Promise<Project | undefined> {
2925
return this.projectDB.findProjectById(projectId);
@@ -179,53 +175,6 @@ export class ProjectsService {
179175
return result;
180176
}
181177

182-
protected async getRepositoryFileProviderAndCommitContext(ctx: TraceContext, user: User, cloneUrl: string): Promise<{fileProvider: FileProvider, commitContext: CommitContext}> {
183-
const normalizedContextUrl = this.contextParser.normalizeContextURL(cloneUrl);
184-
const commitContext = (await this.contextParser.handle(ctx, user, normalizedContextUrl)) as CommitContext;
185-
const { host } = commitContext.repository;
186-
const hostContext = this.hostContextProvider.get(host);
187-
if (!hostContext || !hostContext.services) {
188-
throw new Error(`Cannot fetch repository configuration for host: ${host}`);
189-
}
190-
const fileProvider = hostContext.services.fileProvider;
191-
return { fileProvider, commitContext };
192-
}
193-
194-
async fetchRepositoryConfiguration(ctx: TraceContext, user: User, cloneUrl: string): Promise<string | undefined> {
195-
const { fileProvider, commitContext } = await this.getRepositoryFileProviderAndCommitContext(ctx, user, cloneUrl);
196-
const configString = await fileProvider.getGitpodFileContent(commitContext, user);
197-
return configString;
198-
}
199-
200-
// a static cache used to prefetch inferrer related files in parallel in advance
201-
private requestedPaths = new Set<string>();
202-
203-
async guessRepositoryConfiguration(ctx: TraceContext, user: User, cloneUrl: string): Promise<string | undefined> {
204-
const { fileProvider, commitContext } = await this.getRepositoryFileProviderAndCommitContext(ctx, user, cloneUrl);
205-
const cache: { [path: string]: Promise<string | undefined> } = {};
206-
const readFile = async (path: string) => {
207-
if (path in cache) {
208-
return await cache[path];
209-
}
210-
this.requestedPaths.add(path);
211-
const content = fileProvider.getFileContent(commitContext, user, path);
212-
cache[path] = content;
213-
return await content;
214-
}
215-
// eagerly fetch for all files that the inferrer usually asks for.
216-
this.requestedPaths.forEach(path => !(path in cache) && readFile(path));
217-
const config: WorkspaceConfig = await new ConfigInferrer().getConfig({
218-
config: {},
219-
read: readFile,
220-
exists: async (path: string) => !!(await readFile(path)),
221-
});
222-
if (!config.tasks) {
223-
return;
224-
}
225-
const configString = `tasks:\n - ${config.tasks.map(task => Object.entries(task).map(([phase, command]) => `${phase}: ${command}`).join('\n ')).join('\n - ')}`;
226-
return configString;
227-
}
228-
229178
async updateProjectPartial(partialProject: PartialProject): Promise<void> {
230179
return this.projectDB.updateProject(partialProject);
231180
}

components/server/src/workspace/config-inference-provider.ts

Lines changed: 0 additions & 72 deletions
This file was deleted.

0 commit comments

Comments
 (0)