-
Notifications
You must be signed in to change notification settings - Fork 54
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
Fix: include starter projects for $PROJECT_SOURCE path selection #1190
Conversation
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #1190 +/- ##
==========================================
+ Coverage 52.90% 52.98% +0.08%
==========================================
Files 84 84
Lines 7551 7583 +32
==========================================
+ Hits 3995 4018 +23
- Misses 3273 3276 +3
- Partials 283 289 +6
☔ View full report in Codecov by Sentry. |
pkg/library/projects/util.go
Outdated
// Returns all projects (including starter projects) present in a DevWorkspaceTemplateSpec | ||
func GetAllProjects(workspace *dw.DevWorkspaceTemplateSpec) []dw.Project { | ||
projects := workspace.Projects | ||
|
||
// Note: starter project does not allow for specifying clonePath | ||
for _, starterProject := range workspace.StarterProjects { | ||
|
||
project := dw.Project{ | ||
Name: starterProject.Name, | ||
Attributes: starterProject.Attributes, | ||
ProjectSource: starterProject.ProjectSource, | ||
} | ||
projects = append(projects, project) | ||
} | ||
return 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'm not sure this is correct behavior, in-context (haven't had a chance to verify though).
If a resolved workspace ends up with e.g. no projects and two starterProjects, with the second one being the "selected" project, how does the caller know that e.g. the first project will not be cloned but the second one will?
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.
You're correct - there's a conflict with the "selected" starter project and how getProjectSourcePath()
only selects the first available project to set $PROJECT_SOURCE.
I wasn't sure if this rule of "the first available project is what $PROJECT_SOURCE maps to" was documented somewhere, and I couldn't find it, or if it was just a decision that made sense at the time.
I'll rework things to respect the selected starter project attribute.
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.
The env var is (poorly) documented as part of the Devfile schema, in .commands.exec.commandline
:
$PROJECT_SOURCE: A path to a project source ($PROJECTS_ROOT/). If there are multiple projects, this will point to the directory of the first one.
Extending this to starterProjects, maybe it makes sense that it's the first project, with starterProjects coming after all regular 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.
Thank you for clarifying on the documentation of $PROJECT_SOURCE
@amisevsk 🙏
@l0rd @ibuziuk do you have any input on this? For context:
eclipse-che/che#22601 specifies that the value of $PROJECT_SOURCE
should point to the first starterProject. This PR resolves that requirement.
However, with #1130, you can now use the controller.devfile.io/use-starter-project
attribute in a devworkspace to select which starterProject should be cloned.
With the current implementation of my PR, you could encounter a bug where $PROJECT_SOURCE
is set to a starterProject that was not cloned.
E.g. given the following devworkspace, $PROJECT_SOURCE
will be set to /projects/community
but redhat-product
will be cloned:
kind: DevWorkspace
apiVersion: workspace.devfile.io/v1alpha2
metadata:
name: plain-starter-projects
spec:
started: true
routingClass: 'basic'
template:
attributes:
controller.devfile.io/use-starter-project: redhat-product
starterProjects:
- name: community
zip:
location: https://code.quarkus.io/d?e=io.quarkus%3Aquarkus-resteasy&e=io.quarkus%3Aquarkus-micrometer&e=io.quarkus%3Aquarkus-smallrye-health&e=io.quarkus%3Aquarkus-openshift&cn=devfile
- name: redhat-product
zip:
location: https://code.quarkus.redhat.com/d?e=io.quarkus%3Aquarkus-resteasy&e=io.quarkus%3Aquarkus-smallrye-health&e=io.quarkus%3Aquarkus-openshift
components:
- name: web-terminal
container:
image: quay.io/wto/web-terminal-tooling:next
memoryRequest: 256Mi
memoryLimit: 512Mi
mountSources: true
command:
- "tail"
- "-f"
- "/dev/null"
I could try and rework this PR to fix this conflict with the use-starter-project
attribute, and merge it if it is ready fast enough for DWO 0.24.0. Or we can merge it as-is and make a followup issue/PR to address this bug.
Also AFAIK, we are currently not allowing the user to select a starter project in Che's UI yet.
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 attribute controller.devfile.io/use-starter-project
is set, then we should configure PROJECT_SOURCE accordingly, otherwise we should fall back on the first project.
And Eclipse Che dashboard is currently setting the attribute at startup (without interaction).
0f3b6c6
to
49ee964
Compare
@amisevsk I've added 2 extra commits to address the cases where the I also updated the PR description, including 2 new test cases. The commit description 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.
A few comments -- I think we're going down the path of patching existing code to do something different when rewriting the logic makes things clearer.
pkg/library/container/container.go
Outdated
err = handleMountSources(k8sContainer, component.Container, workspace) | ||
if err != nil { | ||
return nil, err | ||
} |
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.
(Optional, feel free to just resolve)
err = handleMountSources(k8sContainer, component.Container, workspace) | |
if err != nil { | |
return nil, err | |
} | |
if err := handleMountSources(k8sContainer, component.Container, workspace); err != nil { | |
return nil, err | |
} |
I always think it's a little weird that Go code goes around reassigning err
over and over again
// 3. If the workspace has at least one starter project, but none are selected, | ||
// the name of the first starter project will be used as the project source path. |
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 this may break more than it fixes. If there are starterProjects but none selected, then $PROJECT_SOURCE
will point to a nonexistent directory since project-clone won't clone anything.
It might be better to just take 1, 2, and 4 from this list. From my understanding, what Che will do is automatically "select" the first starterProject anyways, so this won't break their use case either.
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 this may break more than it fixes. If there are starterProjects but none selected, then
$PROJECT_SOURCE
will point to a nonexistent directory since project-clone won't clone anything.
Good catch, I hadn't considered that. Keeping points 1,2 and 4 as suggested.
projects := projectslib.GetAllProjects(workspace) | ||
if len(projects) > 0 { | ||
selectedStarterProject, err := projectslib.GetStarterProject(workspace) | ||
if err != nil { | ||
return "", err | ||
} | ||
// Only use the selected starterProject if we have no regular projects | ||
if selectedStarterProject != nil && len(workspace.Projects) == 0 { | ||
return selectedStarterProject.Name, nil | ||
} | ||
|
||
firstProject := projects[0] | ||
if firstProject.ClonePath != "" { | ||
projectPath = firstProject.ClonePath | ||
} else { | ||
projectPath = firstProject.Name | ||
return firstProject.ClonePath, nil | ||
} | ||
return firstProject.Name, nil | ||
} | ||
return projectPath | ||
return "", nil |
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 still looks strange to me -- I think there's some duplication of work here since both projectslib.GetAllProjects()
and projectslib.GetStarterProject()
check for the selected starter project, so we're searching through workspace.StarterProjects
twice. We're also aliasing projects
to refer to "all projects", which is confusing given that there's a workspace.Projects
Would it make more sense to do something like
// If there are any projects, return the first one's clone path
if len(workspace.Projects) > 0 {
return projectslib.GetClonePath(workspace.Projects[0])
}
// No projects, check for starter project
starterProject, err := projectslib.GetStarterProject(workspace)
if err != nil {
return "", err
} else if starterProject == nil {
return "", nil
}
return starterProject.Name
This approach also won't throw an error here (but maybe will elsewhere) if there's a regular project but the selected starter project is misconfigured.
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 agree this is a better approach and is a lot more obvious as to what's going on (especially without requiring the list of projects to be sorted with regular projects first, then starter projects second). This also eliminates the need for projectslib.GetAllProjects()
, which felt a bit awkward of a function anyhow.
@@ -38,7 +38,6 @@ const ( | |||
tmpLogFilePath = "/tmp/" + logFileName | |||
) | |||
|
|||
// TODO: Handle sparse checkout | |||
func main() { |
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.
You might consider also moving GetClonePath
to the projects library, since we're doing it both in container
and project-clone
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 comment is here because it's the only file in project-clone
in this PR, this has nothing to do with removing the TODO (thanks!) :D
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 ended up moving GetClonePath
since it made sense anyhow :P
if selectedStarterProject != nil && len(workspace.Projects) == 0 { | ||
return selectedStarterProject.Name, nil | ||
} | ||
|
||
firstProject := projects[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.
This relies on GetAllProjects
returning the projects with starterProjects being in the list after regular projects, which should either be documented as a requirement on the function (and maybe have a test case to verify) or be handled differently.
IMO it's easier to just check workspace.Projects
first, and if it's empty check workspace.StarterProjects
.
5d50c82
to
e1a656d
Compare
@amisevsk Thank you for the great feedback, this PR is looking a lot better now. I also updated the PR description & test cases, as well as the requirements on the original issue to specify that the starterProject must be selected in order to be used 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.
LGTM 👍
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: amisevsk, AObuchow 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 |
e1a656d
to
d3a3639
Compare
New changes are detected. LGTM label has been removed. |
Signed-off-by: Andrew Obuchowicz <[email protected]>
Fix devfile#1189 Signed-off-by: Andrew Obuchowicz <[email protected]>
Support for sparse checkout was added in ece5b67 Signed-off-by: Andrew Obuchowicz <[email protected]>
d3a3639
to
f13b5fe
Compare
What does this PR do?
This PR adds all starterProjects to the list of projects used when determining the value of the
$PROJECT_SOURCE
environment variable used in workspace deployments.Now, when determining the value of
$PROJECT_SOURCE
, the following rules are considered (in order of priority):If the workspace has at least one regular project, the first one will be selected. If the first project has a clone path, it will be used, otherwise the project's name will be used for the project source path. This was the default behaviour prior to this PR.
If the workspace has a starter project that is selected using the
controller.devfile.io/use-starter-project
workspace attribute, its name will be used for project source path.Otherwise, the returned project source path will be an empty string, i.e.
$PROJECT_SOURCE = /projects/
I also removed a completed TODO comment about adding sparseCheckout support to the project clone container and moved the
GetClonePath()
function to be accessible from other packages.What issues does this PR fix or reference?
#1189
Is it tested? How?
There are 4 cases to test, each is described below.
devworkspace with only starter projects
$PROJECT_SOURCE
environment variable set to/projects/
as no starter project has been selected. For the previously given devworkspace, we should have:devworkspace with starter projects and regular projects
$PROJECT_SOURCE
environment variable set to/projects/<first-project-name>
. For the previously given devworkspace, we should have:devworkspace with only starter projects, with a starter project being selected
controller.devfile.io/use-starter-project
attribute, such as the following:$PROJECT_SOURCE
environment variable set to the starter project that was selected. For the previously given devworkspace, we should have:devworkspace with regular and starter projects, with a selected starter project
controller.devfile.io/use-starter-project
attribute, such as the following:$PROJECT_SOURCE
environment variable set to/projects/<first-project-name>
. The regular project takes priority over the selected starter project when setting$PROJECT_SOURCE
. For the previously given devworkspace, we should have:PR Checklist
/test v8-devworkspace-operator-e2e, v8-che-happy-path
to trigger)v8-devworkspace-operator-e2e
: DevWorkspace e2e testv8-che-happy-path
: Happy path for verification integration with Che