-
Notifications
You must be signed in to change notification settings - Fork 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
Refactor runBuild #294
Refactor runBuild #294
Conversation
Codecov Report
@@ Coverage Diff @@
## master #294 +/- ##
==========================================
+ Coverage 53.46% 53.52% +0.05%
==========================================
Files 218 220 +2
Lines 14642 14679 +37
==========================================
+ Hits 7829 7857 +28
- Misses 6327 6338 +11
+ Partials 486 484 -2 |
2bb292d
to
adac20d
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.
My takeaway from this is that the code is harder to understand as the separation points seem quite arbitrary. I don't know what is buildIDFile, buildInput, buildBuffer etc. and I would guess people even less familiar with this code wouldn't know either. Many functions raise questions about why these parameters would be needed based on the function name, or methods use private struct properties in non-obvious places. 100+ new lines.
cli/command/image/build.go
Outdated
} | ||
|
||
progressOutput := newProgaressOutput(dockerCli.Out(), buildBuffer.progress) |
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.
Progress
cli/command/image/build.go
Outdated
// printed elsewhere, so do nothing. | ||
func (bb *buildBuffer) PrintImageIDIfQuiet() { | ||
if bb.quiet { | ||
fmt.Fprintf(bb.stdout, "%s", bb.output) |
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.
Still printing io.Writer
as a string, please let's not do this.
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.
Fair, We should cast it to bytes.Buffer
first, and panic if it's the wrong type.
Since this is now encapsulated, it's easy to verify that the writer is the correct type when quiet
.
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 don't think cast is a correct solution. For the case where it appeared it would have just meant a different error. Type safety is the main thing protecting against incorrect code changes.
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.
Sorry, by "cast", I meant "type assertion". We can check if the field is a buffer, and call buffer.String()
instead.
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 fixed. We are no longer printing io.Writer
, and I renamed buildBuffer
to buildOutputBuffer
and made it more generic.
cli/command/image/build.go
Outdated
|
||
// SetOutput to a new Writer. If quiet is set then do nothing. | ||
func (bb *buildBuffer) SetOutput(out io.Writer) { | ||
if !bb.quiet { |
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 didn't check but would guess this breaks showing progress output on errors.
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'll look into it further. It seems --stream
is using these buffers differently.
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 is the correct behaviour when --stream --quiet
are both set?
Will stream print the errors correctly to the buffer or do we need a special case like we have with just --quiet
?
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.
For now the behaviour is that --stream
overrides the buffer, which means that progress/output buffers will not be printed by the --quiet
special case.
I'm not sure if this is correct or not, because I'm not sure how --stream
handles quiet.
This is just a first iteration. I think some of the naming could be improved quite a bit. Overall separating concerns will make code much easier to read in the long run. The existing code is completely unreadable, so I don't see how this could possibly make it worse.
They are far from arbitrary. The code is separated by functional groups. A big part of this
The name seems fairly obvious to me (it's a file which stores a build ID). The implementation also makes it obvious, it's an object that is created from How can I help make this more clear?
This name is not great. Any suggestions for a better name? This is the input to a build. The build context and the Dockerfile.
Again, the name could be improved. These are output buffers. So maybe
Please comment on these where you see them so the naming can be improved. I just looked over them again and they all seem pretty logical to me.
I'm not sure what you mean by this. Please comment on the line.
Most of the new lines are new tests, blank lines, and imports. Even if it wasn't, optimizing for fewer lines does not make for clean code. Fewer lines is great when there is duplication to remove, but otherwise it leads to less readable code. |
I didn't mean that they are not correctly picked, just that this is complex code and drawing boundaries with a ruler to complex code doesn't necessarily improve it. Example: the first function
The obvious question is what makes this different than any other file so it needs to be wrapped like this. The answer seems to be that it is to preserve one specific error being outputted in the
I would if I had better ideas. I don't want to argue about this much as this is far from the worst things we have merged. After spending time on it I'm starting to understand what is going on, but I'm not sure if I want other people to have the same experience of repeatedly switching through a lot of files looking for the code that I know needs to be somewhere to understand it. |
Exactly, that's kind of the point! The caller shouldn't be aware of any of the implementation details. It should only be concerned with the high level operation it needs to perform (save the file, or remove the file).
I don't see how this PR changes this. Before this change there was plenty of code that was not in By splitting it up further we get a better sense of the high level work done as part of "build". You shouldn't need to understand the implementation of every function to understand what build does. Every line in |
adac20d
to
0727caa
Compare
The bulk of this function was already implemented in a re-usable way. Also cleanup unnecessary args that should be part of the closure Signed-off-by: Daniel Nephin <dnephin@docker.com>
This struct handles branching logging for quiet output mode. Signed-off-by: Daniel Nephin <dnephin@docker.com>
Signed-off-by: Daniel Nephin <dnephin@docker.com>
…dInput struct Signed-off-by: Daniel Nephin <dnephin@docker.com>
Signed-off-by: Daniel Nephin <dnephin@docker.com>
Also rename it to buildOutputBuffer Signed-off-by: Daniel Nephin <dnephin@docker.com>
0727caa
to
f1c2552
Compare
ping @dnephin @tonistiigi what is the status here ? |
The build command still needs to be refactored. |
Fixes #242
Details about each change in the git commits