-
Notifications
You must be signed in to change notification settings - Fork 404
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
Enable embedding of ko publish #348
Conversation
Codecov Report
@@ Coverage Diff @@
## main #348 +/- ##
==========================================
+ Coverage 38.27% 43.64% +5.36%
==========================================
Files 33 33
Lines 1523 1558 +35
==========================================
+ Hits 583 680 +97
+ Misses 846 753 -93
- Partials 94 125 +31
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.
Thanks for proposing this change! I'm excited to see ko
being used and adopted in more contexts and tools. 👍
pkg/commands/options/publish.go
Outdated
@@ -25,6 +25,9 @@ import ( | |||
|
|||
// PublishOptions encapsulates options when publishing. | |||
type PublishOptions struct { | |||
// DockerRepo overrides the KO_DOCKER_REPO environment variable, if present | |||
DockerRepo 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.
I'd like to push back on this change, or at least consider it in the larger goal of unifying ko
's configuration options.
Today we have .ko.yaml, env vars to override .ko.yaml provided by viper, env vars for KO_DOCKER_REPO
, flags, etc., and I think all in all we don't have a cohesive story for how people should configure the tool.
This one in particular raises alarms because KO_DOCKER_REPO
is necessary to use ko
today, and historically we chose to configure it with an env var because we expect each developer to push to their own registry location. Making this overrideable with a flag might encourage teams/tools to document setting this for all calls, which isn't bad necessarily, it's just a departure I want to make sure we're making intentionally.
In the meantime, is it possible to extract this change from this 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.
I have similar feelings. I'd like to formalize the differences between project config, user config, and invocation-specific config a bit better, and this goes in the opposite direction (I think).
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'd be happy to consider alternatives here, and I agree that formalizing the different config types in ko would be helpful.
Currently, makePublisher()
grabs the envvar directly, but this feels like depending too much on the execution context in the core implementation logic. I'd expect something that's closer to the command-line logic to have parsed the config option at this point.
Do you have any alternative recommendations on how to allow the repo to be set programmatically?
For some context, Skaffold has a similar 'default repo' concept, which can be set as a flag, envvar, or in global config: https://skaffold.dev/docs/environment/image-registries/
In the meantime, I'll extract a separate PR for this change.
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.
New PR for programmatically setting the destination image repo: #351
@@ -41,6 +41,11 @@ func qualifyLocalImport(importpath string) (string, error) { | |||
return pkgs[0].PkgPath, nil | |||
} | |||
|
|||
// PublishImages publishes images | |||
func PublishImages(ctx context.Context, importpaths []string, pub publish.Interface, b build.Interface) (map[string]name.Reference, 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.
Is there a reason to prefer exporting this new wrapper method, versus exporting publishImages
directly?
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 makes the diff smaller, which is nice. I kind of like it :P
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'd be okay with it as a specific diff-shrinking measure that we intend to clean up with a followup 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.
Yes, it was just to keep the diff small.
@@ -127,11 +138,19 @@ func makeBuilder(ctx context.Context, bo *options.BuildOptions) (*build.Caching, | |||
return build.NewCaching(innerBuilder) | |||
} | |||
|
|||
// MakePublisher creates a ko publisher | |||
func MakePublisher(po *options.PublishOptions) (publish.Interface, error) { | |||
return makePublisher(po) |
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.
Same comment about makePublisher
vs MakePublisher
, makeBuilder
, etc. -- if we're going to export them, I'd prefer to just export them.
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.
As above. I was thinking of an expand-and-contract style of approach (https://www.martinfowler.com/bliki/ParallelChange.html).
@@ -204,6 +223,7 @@ type nopPublisher struct { | |||
} | |||
|
|||
func (n nopPublisher) Publish(_ context.Context, br build.Result, s string) (name.Reference, error) { | |||
s = strings.TrimPrefix(s, build.StrictScheme) |
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 is this change necessary?
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, that was unrelated - the nopPublisher failed in a unit test because the scheme prefix wasn't trimmed.
This enables programmatically setting the destination image repository when embedding ko's `publish` functionality in other tools. See ko-build#348
This enables programmatically setting the destination image repository when embedding ko's `publish` functionality in other tools. See ko-build#348
* Add flag and PublishOption for destination repo This enables programmatically setting the destination image repository when embedding ko's `publish` functionality in other tools. See #348 * Set DockerRepo PublishOption from KO_DOCKER_REPO This enables programmatically setting the destination image repository and avoids exposing a flag. * Update comment on DockerRepo option * Fix readme and copyright headers
pkg/commands/config.go
Outdated
@@ -39,6 +41,16 @@ var ( | |||
baseImageOverrides map[string]name.Reference | |||
) | |||
|
|||
// SetDefaultBaseImage enables programmatically overriding the base image | |||
func SetDefaultBaseImage(baseImage 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.
I don't love this being a package global. Can we add this to the BuildOptions and and plumb it down through to https://github.com/google/ko/blob/1b023d30207f385020a5829deec7c147719a1ff9/pkg/commands/resolver.go#L82?
It's a private function, so we can just add another parameter to getBaseImage
and pass in the defaultBaseImage
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.
Good point. I removed the exported function and added BaseDir
to BuildOptions
.
I also found that we could set the variable without modifying the getBaseImage
function signature, but please let me know if you'd rather add a parameter.
On a related note, I was thinking to make UserAgent
an overrideable option, but it's used by both Builder (to fetch the base image) and by Publisher (to push to the registry). We could have two different user-agent options, or introduce some shared build/publish option.
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.
please let me know if you'd rather add a parameter
I think I'd prefer as a parameter, because this is still mutating package-global state. If you call MakeBuilder
twice from the same program, they would interfere with each other.
On that note, we might want to rename MakeBuilder
to NewBuilder
? I think that's more in line with idiomatic constructor names in go?
We could have two different user-agent options, or introduce some shared build/publish option.
I'm fine with whatever's easiest -- if I were implementing this I'd probably just add a second publisher option, but I'm curious about your opinion as a consumer. I know it's kind of gross to have to specify that twice.
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.
Great point, I've changed it to a parameter.
I've also added UserAgent
fields to both BuildOptions
and PublishOptions
. Having to specify them both programmatically didn't seem like a big deal.
Was there a problem with GitHub Actions? A log of the checks failed, but all I see is "This check failed", and no output. |
Something strange is happening, you might need to rebase |
b5536ec
to
b0bdca1
Compare
pkg/commands/resolver.go
Outdated
if bo.BaseImage != "" { | ||
baseImageRef, err := name.ParseReference(bo.BaseImage) | ||
if err != nil { | ||
return nil, fmt.Errorf("'gobuildOptions': error parsing %q as image reference: %v", bo.BaseImage, err) | ||
} | ||
defaultBaseImage = baseImageRef | ||
} |
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 bo.BaseImage != "" { | |
baseImageRef, err := name.ParseReference(bo.BaseImage) | |
if err != nil { | |
return nil, fmt.Errorf("'gobuildOptions': error parsing %q as image reference: %v", bo.BaseImage, err) | |
} | |
defaultBaseImage = baseImageRef | |
} |
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.
Fixed. Apologies, missed this in the rebase.
- Export functions and a variable to enable embedding of ko's `publish` functionality to be embedded in other tools. See GoogleContainerTools/skaffold#5611 - Remove DockerRepo PublishOption and flag. This removes the `DockerRepo` config option and `--docker-repo` flag from the PR. New PR with the extracted config option: ko-build#351 - Fix copyright headers for boilerplate check. - Use DockerRepo PublishOption instead of env var. - Override defaultBaseImage using BuildOptions. Remove exported package global SetDefaultBaseImage and instead allow programmatic override of the default base image using the field `BaseImage` in `options.BuildOptions`. Also fix copyright header years. - Add BuildOptions parameter to getBaseImage This enables access to BaseImage for programmatically overriding the default base image from `.ko.yaml`. - Add UserAgent to BuildOptions and PublishOptions This enables programmatically overriding the `User-Agent` HTTP request header for both pulling the base image and pushing the built image. - Rename MakeBuilder to NewBuilder and MakePublisher to NewPublisher. For more idiomatic constructor function names.
b0bdca1
to
a27762f
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.
lgtm
@imjasonh any final objections?
Thanks for all the help with this! Please let me know if you'd like me to remove the indirection of the |
Enable embedding of ko's
publish
functionality to be in other tools.MakeBuilder()
,MakePublisher()
andPublishImages()
frompkg/commands
UserAgent()
DockerRepo
flag toPublishOptions
inpkg/commands/options
See GoogleContainerTools/skaffold#5611