-
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
Allow multiple projects per repo #18774
Conversation
cc1c7cf
to
a19c9a7
Compare
@@ -10,8 +10,7 @@ import { TransactionalDB } from "./typeorm/transactional-db-impl"; | |||
export const ProjectDB = Symbol("ProjectDB"); | |||
export interface ProjectDB extends TransactionalDB<ProjectDB> { | |||
findProjectById(projectId: string): Promise<Project | undefined>; | |||
findProjectByCloneUrl(cloneUrl: string): Promise<Project | undefined>; | |||
findProjectsByCloneUrls(cloneUrls: string[]): Promise<(Project & { teamOwners?: string[] })[]>; | |||
findProjectsByCloneUrl(cloneUrl: string): Promise<Project[]>; |
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.
we still need a method like this because we need to look up the project(s) when a webhook event comes in.
@@ -710,16 +711,19 @@ export class TypeORMWorkspaceDBImpl extends TransactionalDBImpl<WorkspaceDB> imp | |||
|
|||
// Find the (last triggered) prebuild for a given commit | |||
public async findPrebuiltWorkspaceByCommit( | |||
cloneURL: string, | |||
projectId: string, |
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.
A cloneURL
was used across the board to identify the project. Since we now can have multiple projects per cloneURL this is no longer the case, so we pass on the projected instead. This is the majority of this changeset.
if (!commit || !cloneURL) { | ||
return undefined; | ||
if (!commit || !projectId) { | ||
throw new ApplicationError(ErrorCodes.INTERNAL_SERVER_ERROR, "Illegal arguments", { projectId, commit }); |
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.
we should not silently ignore such a state
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.
Agree, but how comes that this is necessary in the persistence layer given the mandatory arguments. Let's check the call sites, too.
a19c9a7
to
0dd4dd0
Compare
)} | ||
<Button onClick={() => onRepoSelected(r)} loading={isCreating}> | ||
Select | ||
</Button> |
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.
we no longer forbid creating a project if one for that repo already exists
user.id, | ||
context.repository.cloneUrl, | ||
); | ||
if (projects.length > 1) { |
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 the user didn't pass in a projectId but we find more than one candidate we throw and need to tell the user.
48a3c89
to
faca93c
Compare
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.
Just stopping by to leave on comment on an issue which could be unrelated to the changes of this PR. Other than that, UX LGTM. 🏁
cloneURL: string, | ||
webhookInstaller: User, | ||
): Promise<{ user: User; project?: Project }> { | ||
private async findProjectOwner(project: Project, webhookInstaller: User): Promise<User> { |
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.
praise: Just wanted to say it feels so good to see this kind of control where 3 repository instances with different prebuilds settings (not enabled, all branches, default branch) work side-by-side like this. Don't know if it's ok, but I only see one webhook in the project, see https://gitlab.com/gitpod-io/rails/-/hooks. Cc @AlexTugarev 🙏
); | ||
} | ||
const projects = await this.projectService.findProjectsByCloneUrl(user.id, cloneURL); | ||
for (const project of projects) { |
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.
I think it would be good to guard per project as well, otherwise if anything goes south with the first project at hand, e.g. context parsing, the other projects won't be processed.
(same applies to the other *-app.ts)
import { UserService } from "../user/user-service"; | ||
import { ProjectsService } from "../projects/projects-service"; | ||
import { SYSTEM_USER } from "../authorization/authorizer"; |
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.
👀
const context = (await this.contextParser.handle({ span }, installationOwner, contextURL)) as CommitContext; | ||
const projects = await this.projectService.findProjectsByCloneUrl(SYSTEM_USER, context.repository.cloneUrl); | ||
for (const project of projects) { | ||
const user = await this.findProjectOwner(project, installationOwner); |
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.
ah! this is how we handle FGA for prebuild.
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.
LGTM!
faca93c
to
649cec2
Compare
/unhold |
const abortedState: PrebuiltWorkspaceState = "aborted"; | ||
const repo = await this.getPrebuiltWorkspaceRepo(); | ||
|
||
let query = repo.createQueryBuilder("pws"); | ||
query = query.where("pws.cloneURL = :cloneURL", { cloneURL }); | ||
query = query.where("pws.projectId != :projectId", { projectId }); |
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.
should be a match, correct?
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.
Yes 🙈
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.
fixing via a840064 in parallel. Shall we create a separate PR?
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.
fine with me to put it into your pr
Description
This PR includes implementation changes that are necessary to relax the 1:1 constraint between a repo and a project.
Summary generated by Copilot
🤖 Generated by Copilot at cc1c7cf
No summary available (Limit exceeded: required to process 212218 tokens, but only 50000 are allowed per call)
Related Issue(s)
Fixes EXP-640, EXP-649, EXP-648, EXP-653
How to test
Join this org: https://se-multiple-projects.preview.gitpod-dev.com/orgs/join?inviteId=58fb7dc4-2d43-41e0-a7e8-be1a43e7e9ab
It is set up with all SCMs we support
Documentation
Preview status
Gitpod was successfully deployed to your preview environment.
Build Options
Build
Run the build with werft instead of GHA
Run Leeway with
--dont-test
Publish
Installer
Add desired feature flags to the end of the line above, space separated
Preview Environment / Integration Tests
If enabled this will build
install/preview
If enabled this will create the environment on GCE infra
Valid options are
all
,workspace
,webapp
,ide
,jetbrains
,vscode
,ssh
. If enabled,with-preview
andwith-large-vm
will be enabled./hold