-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[server] Infer config for non-configured repositories #7383
Conversation
bead804
to
5b76ac5
Compare
/werft run 👍 started the job as gitpod-build-se-init.4 |
/werft run 👍 started the job as gitpod-build-se-init.5 |
/werft run 👍 started the job as gitpod-build-se-init.6 |
/werft run 👍 started the job as gitpod-build-se-init.8 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UX works like a charm and definitely improves the onboarding experience for non-configured repos. 🔮
Left one minor comment (issue) which could be tackled separately. ❗
🍊 🍊 🍊 🍊
Wondering if there’s anything if could do to improve feature (auto-detection and file generation) visibility here and make it less surprising to users when they find out about the new untracked .gitpod.yml
file. Probably fine to do also out of the scope of this PR in the spirit of MVC (minimum viable change). ➿
For example, we could:
- Add an additional comment in the generated
.gtipod.yml
to describe what this file is and how to change it by linking to relevant docs. - Trigger (yet) another notification inside the editor to inform the user about project detection with an action to open the
.gitpod.yml
. - Inform the user about project type detection during workspace loading (workspace start page) for authorized users and during login for anonymous users.
Successful project detection is something we could also surface when the project is added, in #7271. 💡 Cc @jldec
🍋 🍋 🍋 🍋
Approving to unblock merging but holding in case someone from the team could take a closer look at the code changes. 👀
/hold
} | ||
} | ||
|
||
if (!customConfig) { | ||
return undefined; | ||
} | ||
|
||
return { customConfig, configBasePath }; | ||
return { customConfig, configBasePath, literalConfig: { '.gitpod.yml': customConfigString || ''} }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is pretty unrelated and should work as reliable as it does with other pending changes.
Related issue #7370
LGTM label has been added. Git tree hash: 6558a64c319c3a6cd6f31611246262722344d43a
|
That makes a ton of sense. We could also build a VS Code extension for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned on Slack, wow, this is epic! 🎸
Super clean implementation ✨ the code looks good to me, and works as advertised (I've even tested with an empty repository). 🔥🔥🔥
Bonus points for cleaning up the old code 🧹 (side note: I think we might also want to delete the language detection code in the future).
Also, I think a cool follow-up could be to add a comment to the generated .gitpod.yml
file (e.g. to briefly explain what this file is / why it's there).
/approve
if (typeof contextURLOrContext === 'string') { | ||
const normalizedContextUrl = this.contextParser.normalizeContextURL(contextURLOrContext); | ||
commitContext = (await this.contextParser.handle(ctx, user, normalizedContextUrl)) as CommitContext; | ||
} else { | ||
commitContext = contextURLOrContext; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
@@ -57,7 +57,6 @@ | |||
"express-mysql-session": "^2.1.0", | |||
"express-session": "^1.15.6", | |||
"fs-extra": "^10.0.0", | |||
"gitpod-yml-inferrer": "^1.2.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
/** | ||
* Copyright (c) 2020 Gitpod GmbH. All rights reserved. | ||
* Licensed under the GNU Affero General Public License (AGPL). | ||
* See License-AGPL.txt in the project root for license information. | ||
*/ | ||
|
||
import { inject, injectable, postConstruct } from "inversify"; | ||
import { CommitContext, User, WorkspaceConfig } from "@gitpod/gitpod-protocol"; | ||
import { HostContextProvider } from "../auth/host-context-provider"; | ||
import { Config } from "../config"; | ||
|
||
export type LanguageConfigProvider = (language: string, user: User, commit: CommitContext) => Promise<WorkspaceConfig | undefined>; | ||
|
||
@injectable() | ||
export class ConfigInferenceProvider { | ||
@inject(HostContextProvider) protected readonly hostContextProvider: HostContextProvider; | ||
@inject(Config) protected readonly config: Config; | ||
|
||
protected readonly languageConfigProvider = new Map<string, LanguageConfigProvider>(); | ||
|
||
@postConstruct() | ||
public registerLanguageInferrer() { | ||
this.languageConfigProvider.set('Go', this.computeGoConfig.bind(this)); | ||
} | ||
|
||
public async infer(user: User, commit: CommitContext): Promise<WorkspaceConfig | undefined> { | ||
const host = commit.repository.host; | ||
const hostContext = this.hostContextProvider.get(host); | ||
if (!hostContext || !hostContext.services) { | ||
return undefined; | ||
} | ||
const repoHost = hostContext.services; | ||
const languages = await repoHost.languagesProvider.getLanguages(commit.repository, user); | ||
const topLanguage = this.findTopLanguage(languages); | ||
if (topLanguage === undefined) { | ||
return undefined; | ||
} | ||
|
||
const configProvider = this.languageConfigProvider.get(topLanguage); | ||
if (configProvider === undefined) { | ||
return undefined; | ||
} | ||
|
||
return configProvider(topLanguage, user, commit); | ||
} | ||
|
||
protected findTopLanguage(languages: any) { | ||
let result: string | undefined; | ||
let topScore: number | undefined; | ||
Object.keys(languages).forEach(lang => { | ||
let score = languages[lang]; | ||
if (topScore === undefined || score > topScore) { | ||
result = lang; | ||
topScore = score; | ||
} | ||
}); | ||
return result; | ||
} | ||
|
||
protected async computeGoConfig(lang: String, user: User, commit: CommitContext): Promise<WorkspaceConfig | undefined> { | ||
return { | ||
ports: [], | ||
tasks: [ | ||
{ | ||
init: `test -f go.mod && go get -v ./...` | ||
} | ||
], | ||
image: this.config.workspaceDefaults.workspaceImage, | ||
} as WorkspaceConfig; | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
let customConfigString = await contextRepoConfig; | ||
let fromProjectDB = false; | ||
customConfigString = await contextRepoConfig; | ||
let origin: WorkspaceConfig["_origin"] = 'repo'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
if (!customConfigString) { | ||
// if there's still no configuration, let's infer one | ||
customConfigString = await inferredConfig; | ||
origin = "derived"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super-nit: Technically, I think this should be conditional on the inferrer returning something (however, in the current state of the code, this doesn't matter because of the if (!customConfig) { return undefined; }
below).
origin = "derived"; | |
if (customConfigString) { | |
origin = "derived"; | |
} |
if (config._origin === 'derived' && literalConfig) { | ||
(context as any as AdditionalContentContext).additionalFiles = { ... literalConfig }; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: gtsiolis, jankeromnes Associated issue: #6921 The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
/unhold |
This change will use the configuration inference for all workspaces as the fallback.
fixes #6921
Testing
Start a workspace on a repository without a
.gitpod.yml
and find a derived.gitpod.yml
in the opened workspace.Release Notes