-
-
Notifications
You must be signed in to change notification settings - Fork 546
chore!: extract image-related code to the top-level image package #2995
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
base: main
Are you sure you want to change the base?
Conversation
✅ Deploy Preview for testcontainers-go ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
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 like the idea of a smaller package with more focused responsibilities.
I've done a quick pass to capture some observations, however I wonder for if the current pattern of passing in a type which implements an interface hides the important elements making it harder to understand the logic and creating a hard dependency on external types such as types.ImageBuildOptions
.
Thinking from first principles for a minute, would it be better if we made the image follow the our new best practices. For example have Build method take the required arguments + functional options for example:
func Build(ctx context.Context, context io.Reader, options ... Option) (string, error) {
...
}
That way we can avoid hard dependences for consumers on external types and provide a cleaner more maintainable package going forward, thoughts?
) | ||
|
||
// Builder defines what is needed to build an image | ||
type Builder interface { |
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.
question: does this need to be an interface or would a concrete type work better or simplify?
Also this doesn't seem to do a build, but more provide information to a builder, so is this the right name?
GetContext() (io.Reader, error) // the path to the build context | ||
GetDockerfile() string // the relative path to the Dockerfile, including the file itself | ||
GetRepo() string // get repo label for image | ||
GetTag() string // get tag label for image |
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.
suggestion: make these more idiomatic, removing the Get prefixes.
@@ -0,0 +1,137 @@ | |||
package image |
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.
suggestion: use a generated mock if we want to keep the interface.
fileLocation := filepath.Join(targetDir, ".dockerignore") | ||
var excluded []string | ||
exists := false | ||
if f, openErr := os.Open(fileLocation); openErr == 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.
// List list images from the provider. If an image has multiple Tags, each tag is reported | ||
// individually with the same ID and same labels | ||
func List(ctx context.Context) ([]Info, error) { | ||
images := []Info{} |
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.
suggestion: use declared value instead
images := []Info{} | |
var images []Info |
return fmt.Errorf("opening output file %w", err) | ||
} | ||
defer func() { | ||
_ = outputFile.Close() |
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.
bug: you can loose data a not known it, name the return and assign on close.
defer func() { | ||
_ = imageReader.Close() | ||
}() |
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.
suggestion: no need for the wrap just call Close on a reader.
defer func() { | |
_ = imageReader.Close() | |
}() | |
defer imageReader.Close() |
_, err = outputFile.ReadFrom(imageReader) | ||
if err != 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.
suggestion: fold for more idiomatic code
_, err = outputFile.ReadFrom(imageReader) | |
if err != nil { | |
if _, err = outputFile.ReadFrom(imageReader); err != nil { |
@@ -0,0 +1,66 @@ | |||
package mock |
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.
question: is this just a move? Would a real mock be better?
|
||
// Build build an image from the given Builder, using the default docker client. | ||
// It returns the first tag of the image. | ||
func Build(ctx context.Context, img Builder) (string, error) { |
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.
suggestion: having it be a Builder type and img name is confusing, lets get consistent.
What does this PR do?
This PR refactors the code to extract the docker image related code to a top-level package:
image
.This package will be responsible of:
The related tests have been moved to the package, but there are "e2e" tests (they are actually using a ContainerRequest) that have been kept in the root package of the library.
Why is it important?
Separation of concerns, reducing the API surface in the root package.