-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Support build artifact dependencies #4752
Conversation
…troller; validations
Codecov Report
@@ Coverage Diff @@
## master #4752 +/- ##
==========================================
+ Coverage 73.81% 73.97% +0.16%
==========================================
Files 347 346 -1
Lines 13761 13848 +87
==========================================
+ Hits 10157 10244 +87
Misses 2971 2971
Partials 633 633
Continue to review full report at Codecov.
|
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.
Looking good!
if namesMap[d.ImageName] == seen { | ||
errs = append(errs, fmt.Errorf("invalid build dependency for artifact %q: image name %q repeated", a.ImageName, d.ImageName)) | ||
namesMap[d.ImageName] = recorded | ||
} else if namesMap[d.ImageName] == unseen { | ||
namesMap[d.ImageName] = seen | ||
} |
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.
Why do we disallow repeated image names? We do know some people have several artifacts using the same context.
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 believe this is just validating that for each artifact, all dependency aliases/image names are unique. I don't think we want to allow two distinct dependencies which share an image name (and are then effectively the same dependency), right?
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.
exactly what @nkubala said
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 code is validating that
- all aliases are unique, and
- all image references are unique
I agree with (1). But people use multi-stage Dockerfiles with a number of build images with names. We can let that decision be set in the skaffold.yaml
.
artifacts:
- image: our/jarbuild
- image: our/app
requires:
- alias: lib1
image: our/jarbuild
- alias: lib2
image: our/jarbuild
Or let me turn this around: what's the compelling reason why we cannot let the same image have multiple aliases?
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.
^^^ (Github didn't unresolve the conversation when I submitted this comment as part of a review)
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.
@briandealwis I think I get your point now.
The dockerfile:
FROM $builder as builder1
RUN foo1
FROM $builder as builder2
RUN foo2
FROM bar
COPY --from=builder1 foobar
can be simplified into:
FROM $builder1
RUN foo1
FROM $builder2
RUN foo2
FROM bar
COPY --from=$builder1 foobar
where $builder1 and $builder2 both reference the same image that $builder referenced earlier.
Is this what you mean? Although would this really work since $builder1 and $builder2 resolve to the same value wouldn't it be ambiguous?
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's no compelling reason for this validation, I just thought that it didn't seem valuable to permit multiple aliases referencing the same image. But I'll remove it anyway.
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.
Removed this extra validation in latest 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.
a few comments but in general this is looking good
pkg/skaffold/build/scheduler.go
Outdated
for _, dep := range a.requiredArtifactChans { | ||
// wait for dependency to complete build | ||
select { | ||
case <-ctx.Done(): |
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.
do we need to catch ctx.Cancelled()
here as well? or is that handled somewhere further down/up?
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 I follow. context
here has already been setup with cancellation so when cancel
gets called in the main go routine it'll close this done channel.
From docs WithCancel arranges for Done to be closed when cancel is called;
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 get it know.
case <-ctx.Done():
if ctx.Err() == ctx.Cancelled():
...
I'll add that. Thanks!
for _, artifact := range artifacts { | ||
if err := dfs(artifact, visited, make(map[string]bool), m); err != nil { | ||
errs = append(errs, err) | ||
return |
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.
since this is part of a larger error collection block that finishes all checks and surfaces all errors, should we not fail fast here and let this run its course?
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.
since this validation is for cycle detection, we'll get stuck on a specific cycle if it exists and it seemed non-trivial to exit that cycle and then try to find the other cycles. So we won't be able to collect all cycle violations at a go which is why I thought to just surface out the first violation and the user can fix it one by one. WDYT?
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.
@briandealwis WDYT?
if namesMap[d.ImageName] == seen { | ||
errs = append(errs, fmt.Errorf("invalid build dependency for artifact %q: image name %q repeated", a.ImageName, d.ImageName)) | ||
namesMap[d.ImageName] = recorded | ||
} else if namesMap[d.ImageName] == unseen { | ||
namesMap[d.ImageName] = seen | ||
} |
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 believe this is just validating that for each artifact, all dependency aliases/image names are unique. I don't think we want to allow two distinct dependencies which share an image name (and are then effectively the same dependency), right?
Co-authored-by: Brian de Alwis <[email protected]>
Co-authored-by: Brian de Alwis <[email protected]>
PTAL again @nkubala and @briandealwis |
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.
What happens / should happen if there when one of the artifacts encounters a build error?
if namesMap[d.ImageName] == seen { | ||
errs = append(errs, fmt.Errorf("invalid build dependency for artifact %q: image name %q repeated", a.ImageName, d.ImageName)) | ||
namesMap[d.ImageName] = recorded | ||
} else if namesMap[d.ImageName] == unseen { | ||
namesMap[d.ImageName] = seen | ||
} |
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 code is validating that
- all aliases are unique, and
- all image references are unique
I agree with (1). But people use multi-stage Dockerfiles with a number of build images with names. We can let that decision be set in the skaffold.yaml
.
artifacts:
- image: our/jarbuild
- image: our/app
requires:
- alias: lib1
image: our/jarbuild
- alias: lib2
image: our/jarbuild
Or let me turn this around: what's the compelling reason why we cannot let the same image have multiple aliases?
Handling dependency errors can be done in |
Currently it just runs all other builds even if a required build has failed since I haven't introduced the dependency I'm thinking about changing the current behavior where we just report about the first failed build (see here) and instead |
yes, that's the intention. Let me know if you want me to add code to handle dependency build failures in this PR itself. Otherwise I'll do that in the followup |
closing this for now, will reopen after incorporating changes from #4794 when that gets approved. |
Related: #4713
Description:
ArtifactDependency
struct toArtifact
. This will allow us to define arequires
section in the skaffold configAdded skaffold config validations:
Replaced
InSequence
andInParallel
build controllers with anInOrder
function inscheduler.go
Next steps:
docker
andbuildpacks
builder where it's obvious that this info will be passed in asbuild args
andenv variable
respectively.