Skip to content

Commit 46d55a7

Browse files
svenefftingeroboquat
authored andcommitted
[server] infer extensions and add a comment
This commit adds vcode extensions to the inferred .gitpod.yml and adds a comment to the top, that links to the documentation.
1 parent 46df01a commit 46d55a7

File tree

3 files changed

+131
-12
lines changed

3 files changed

+131
-12
lines changed

components/server/src/config/config-inferrer.spec.ts

Lines changed: 84 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,36 @@ async function expect(files: {[path:string]:string}, config: WorkspaceConfig): P
2323
chai.assert.equal(JSON.stringify(result, null, ' '), JSON.stringify(config, null, ' '));
2424
}
2525

26+
describe('config serializer', () => {
27+
it('serialized proper YAML',
28+
async () => {
29+
const config: WorkspaceConfig = {
30+
tasks: [
31+
{
32+
'init': "yarn install",
33+
'command': "yarn run build"
34+
}
35+
],
36+
vscode: {
37+
extensions: [
38+
'foo', 'bar'
39+
]
40+
}
41+
}
42+
const cf = new ConfigInferrer()
43+
chai.assert.equal(cf.toYaml(config),
44+
`tasks:
45+
- init: yarn install
46+
command: yarn run build
47+
vscode:
48+
extensions:
49+
- foo
50+
- bar
51+
`);
52+
}
53+
)
54+
});
55+
2656
describe('config inferrer', () => {
2757
it('check node',
2858
async () => expect({
@@ -43,7 +73,12 @@ describe('config inferrer', () => {
4373
init: "yarn install && yarn run build",
4474
command: "yarn run watch"
4575
}
46-
]
76+
],
77+
vscode: {
78+
extensions: [
79+
'dbaeumer.vscode-eslint'
80+
]
81+
}
4782
})
4883
),
4984
it('[java] mvn wrapper',
@@ -55,7 +90,14 @@ describe('config inferrer', () => {
5590
{
5691
init: "./mvnw install -DskipTests=false"
5792
}
58-
]
93+
],
94+
vscode: {
95+
extensions: [
96+
'redhat.java',
97+
'vscjava.vscode-java-debug',
98+
'vscjava.vscode-maven'
99+
]
100+
}
59101
})
60102
),
61103
it('[java] mvn',
@@ -66,7 +108,14 @@ describe('config inferrer', () => {
66108
{
67109
init: "mvn install -DskipTests=false"
68110
}
69-
]
111+
],
112+
vscode: {
113+
extensions: [
114+
'redhat.java',
115+
'vscjava.vscode-java-debug',
116+
'vscjava.vscode-maven'
117+
]
118+
}
70119
})
71120
),
72121
it('[java] gradle',
@@ -78,7 +127,13 @@ describe('config inferrer', () => {
78127
{
79128
init: "gradle build"
80129
}
81-
]
130+
],
131+
vscode: {
132+
extensions: [
133+
'redhat.java',
134+
'vscjava.vscode-java-debug'
135+
]
136+
}
82137
})
83138
),
84139
it('[java] gradle wrapper',
@@ -90,7 +145,13 @@ describe('config inferrer', () => {
90145
{
91146
init: "./gradlew build"
92147
}
93-
]
148+
],
149+
vscode: {
150+
extensions: [
151+
'redhat.java',
152+
'vscjava.vscode-java-debug'
153+
]
154+
}
94155
})
95156
),
96157
it('[python] pip install',
@@ -101,7 +162,12 @@ describe('config inferrer', () => {
101162
{
102163
init: "pip install -r requirements.txt"
103164
}
104-
]
165+
],
166+
vscode: {
167+
extensions: [
168+
'ms-python.python'
169+
]
170+
}
105171
})
106172
),
107173
it('[go] go install',
@@ -113,7 +179,12 @@ describe('config inferrer', () => {
113179
init: "go get && go build ./... && go test ./...",
114180
command: "go run"
115181
}
116-
]
182+
],
183+
vscode: {
184+
extensions: [
185+
'golang.go'
186+
]
187+
}
117188
})
118189
),
119190
it('[rust] cargo',
@@ -125,7 +196,12 @@ describe('config inferrer', () => {
125196
init: "cargo build",
126197
command: "cargo watch -x run"
127198
}
128-
]
199+
],
200+
vscode: {
201+
extensions: [
202+
'matklad.rust-analyzer'
203+
]
204+
}
129205
})
130206
),
131207
it('[make] make',

components/server/src/config/config-inferrer.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export class ConfigInferrer {
6565
} catch (e) {
6666
console.log(e, pckjsonContent);
6767
}
68+
this.addExtension(ctx, 'dbaeumer.vscode-eslint');
6869
}
6970

7071
protected async checkJava(ctx: Context): Promise<void> {
@@ -74,6 +75,8 @@ export class ConfigInferrer {
7475
cmd = './gradlew';
7576
}
7677
this.addCommand(ctx.config, cmd + ' build', 'init');
78+
this.addExtension(ctx, 'redhat.java');
79+
this.addExtension(ctx, 'vscjava.vscode-java-debug');
7780
return;
7881
}
7982
if (await ctx.exists('pom.xml')) {
@@ -82,10 +85,23 @@ export class ConfigInferrer {
8285
cmd = './mvnw';
8386
}
8487
this.addCommand(ctx.config, cmd + ' install -DskipTests=false', 'init');
88+
this.addExtension(ctx, 'redhat.java');
89+
this.addExtension(ctx, 'vscjava.vscode-java-debug');
90+
this.addExtension(ctx, 'vscjava.vscode-maven');
8591
return;
8692
}
8793
}
8894

95+
protected addExtension(ctx: Context, extensionName: string) {
96+
if (!ctx.config.vscode || !ctx.config.vscode.extensions) {
97+
ctx.config.vscode = {
98+
extensions: []
99+
};
100+
}
101+
if (ctx.config.vscode.extensions?.indexOf(extensionName) === -1)
102+
ctx.config.vscode.extensions!.push(extensionName);
103+
}
104+
89105
protected async isMake(ctx: Context) {
90106
return await ctx.exists('Makefile') || await ctx.exists('makefile');
91107
}
@@ -105,15 +121,20 @@ export class ConfigInferrer {
105121
}
106122
if (await ctx.exists('requirements.txt')) {
107123
this.addCommand(ctx.config, 'pip install -r requirements.txt', 'init');
124+
this.addExtension(ctx, 'ms-python.python');
108125
} else if (await ctx.exists('setup.py')) {
109126
this.addCommand(ctx.config, 'pip install .', 'init');
127+
this.addExtension(ctx, 'ms-python.python');
110128
}
111129
if (await ctx.exists('main.py')) {
112130
this.addCommand(ctx.config, 'python main.py', 'command');
131+
this.addExtension(ctx, 'ms-python.python');
113132
} else if (await ctx.exists('app.py')) {
114133
this.addCommand(ctx.config, 'python app.py', 'command');
134+
this.addExtension(ctx, 'ms-python.python');
115135
} else if (await ctx.exists('runserver.py')) {
116136
this.addCommand(ctx.config, 'python runserver.py', 'command');
137+
this.addExtension(ctx, 'ms-python.python');
117138
}
118139
}
119140

@@ -123,13 +144,15 @@ export class ConfigInferrer {
123144
this.addCommand(ctx.config, 'go build ./...', 'init');
124145
this.addCommand(ctx.config, 'go test ./...', 'init');
125146
this.addCommand(ctx.config, 'go run', 'command');
147+
this.addExtension(ctx, 'golang.go');
126148
}
127149
}
128150

129151
protected async checkRust(ctx: Context) {
130152
if (await ctx.exists('Cargo.toml')) {
131153
this.addCommand(ctx.config, 'cargo build', 'init');
132154
this.addCommand(ctx.config, 'cargo watch -x run', 'command');
155+
this.addExtension(ctx, 'matklad.rust-analyzer');
133156
}
134157
}
135158

@@ -166,4 +189,19 @@ export class ConfigInferrer {
166189
}
167190
config.tasks[0][phase] = (existing ? existing + ' && ' : '') + command;
168191
}
192+
193+
toYaml(config: WorkspaceConfig): string {
194+
const i = ' ';
195+
let tasks = '';
196+
if (config.tasks) {
197+
tasks = `tasks:\n${i}- ${config.tasks.map(task => Object.entries(task).map(([phase, command]) => `${phase}: ${command}`).join('\n ')).join('\n - ')}`
198+
}
199+
let vscode = '';
200+
if (config.vscode?.extensions) {
201+
vscode = `vscode:\n${i}extensions:\n${config.vscode.extensions.map(extension => `${i + i}- ${extension}`).join('\n')}`
202+
}
203+
return `${tasks}
204+
${vscode}
205+
`;
206+
}
169207
}

components/server/src/config/configuration-service.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,22 @@ export class ConfigurationService {
3636
}
3737
// eagerly fetch for all files that the inferrer usually asks for.
3838
this.requestedPaths.forEach(path => !(path in cache) && readFile(path));
39-
const config: WorkspaceConfig = await new ConfigInferrer().getConfig({
39+
const configInferrer = new ConfigInferrer();
40+
const config: WorkspaceConfig = await configInferrer.getConfig({
4041
config: {},
4142
read: readFile,
4243
exists: async (path: string) => !!(await readFile(path)),
4344
});
4445
if (!config.tasks) {
4546
return;
4647
}
47-
const configString = `tasks:\n - ${config.tasks.map(task => Object.entries(task).map(([phase, command]) => `${phase}: ${command}`).join('\n ')).join('\n - ')}`;
48-
return configString;
48+
const configString = configInferrer.toYaml(config);
49+
return `# This configuration file was automatically generated by Gitpod.
50+
# Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file)
51+
# and commit this file to your remote git repository to share the goodness with others.
52+
53+
${configString}
54+
`;
4955
}
5056

5157
async fetchRepositoryConfiguration(ctx: TraceContext, user: User, contextURL: string): Promise<string | undefined> {
@@ -54,7 +60,6 @@ export class ConfigurationService {
5460
return configString;
5561
}
5662

57-
5863
protected async getRepositoryFileProviderAndCommitContext(ctx: TraceContext, user: User, contextURLOrContext: string | CommitContext): Promise<{fileProvider: FileProvider, commitContext: CommitContext}> {
5964
let commitContext: CommitContext;
6065
if (typeof contextURLOrContext === 'string') {

0 commit comments

Comments
 (0)