Skip to content

Commit

Permalink
Implement Target support for ko builder (#6447)
Browse files Browse the repository at this point in the history
This implements support for the Target config field for the ko builder.
The Target field allows users to specify a target for `go build`. This
is necessary where the main package is not in the context directory.

Tracking: #6041
Related: #6054, #6437
  • Loading branch information
halvards authored Aug 20, 2021
1 parent c675a75 commit 7363674
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 13 deletions.
21 changes: 13 additions & 8 deletions pkg/skaffold/build/ko/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (b *Builder) Build(ctx context.Context, out io.Writer, a *latestV1.Artifact
}
defer koPublisher.Close()

imageRef, err := b.buildAndPublish(ctx, a.ImageName, koBuilder, koPublisher)
imageRef, err := b.buildAndPublish(ctx, a, koBuilder, koPublisher)
if err != nil {
return "", fmt.Errorf("could not build and publish ko image %q: %w", a.ImageName, err)
}
Expand All @@ -60,10 +60,10 @@ func (b *Builder) Build(ctx context.Context, out io.Writer, a *latestV1.Artifact
}

// buildAndPublish the image using the ko builder and publisher.
func (b *Builder) buildAndPublish(ctx context.Context, imageName string, koBuilder build.Interface, koPublisher publish.Interface) (name.Reference, error) {
importpath, err := getImportPath(imageName, koBuilder)
func (b *Builder) buildAndPublish(ctx context.Context, a *latestV1.Artifact, koBuilder build.Interface, koPublisher publish.Interface) (name.Reference, error) {
importpath, err := getImportPath(a, koBuilder)
if err != nil {
return nil, fmt.Errorf("could not determine Go import path for ko image %q: %w", imageName, err)
return nil, fmt.Errorf("could not determine Go import path for ko image %q: %w", a.ImageName, err)
}
imageMap, err := b.publishImages(ctx, []string{importpath}, koPublisher, koBuilder)
if err != nil {
Expand All @@ -86,11 +86,16 @@ func (b *Builder) buildAndPublish(ctx context.Context, imageName string, koBuild
//
// If the image name does _not_ start with `ko://`, determine the Go import
// path of the image workspace directory.
func getImportPath(imageName string, koBuilder build.Interface) (string, error) {
if strings.HasPrefix(imageName, build.StrictScheme) {
return imageName, nil
func getImportPath(a *latestV1.Artifact, koBuilder build.Interface) (string, error) {
if strings.HasPrefix(a.ImageName, build.StrictScheme) {
return a.ImageName, nil
}
return koBuilder.QualifyImport(".")
target := a.KoArtifact.Target
if target == "" {
// default to context directory
target = "."
}
return koBuilder.QualifyImport(target)
}

// getImageIdentifier returns the image tag or digest for published images (`pushImages=true`),
Expand Down
25 changes: 20 additions & 5 deletions pkg/skaffold/build/ko/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,12 @@ func Test_getImportPath(t *testing.T) {
expectedImportPath string
}{
{
description: "image name is ko-prefixed full Go import path",
description: "target is ignored when image name is ko-prefixed full Go import path",
artifact: &latestV1.Artifact{
ArtifactType: latestV1.ArtifactType{
KoArtifact: &latestV1.KoArtifact{},
KoArtifact: &latestV1.KoArtifact{
Target: "./target-should-be-ignored",
},
},
ImageName: "ko://git.example.com/org/foo",
},
Expand All @@ -113,9 +115,22 @@ func Test_getImportPath(t *testing.T) {
KoArtifact: &latestV1.KoArtifact{},
},
ImageName: "bar",
Workspace: "../docker",
Workspace: "./testdata/package-main-in-root",
},
expectedImportPath: "ko://github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/ko/testdata/package-main-in-root",
},
{
description: "plain image name with workspace directory and target",
artifact: &latestV1.Artifact{
ArtifactType: latestV1.ArtifactType{
KoArtifact: &latestV1.KoArtifact{
Target: "./baz",
},
},
ImageName: "baz-image",
Workspace: "./testdata/package-main-not-in-root",
},
expectedImportPath: "ko://github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/docker", // this package + "../docker"
expectedImportPath: "ko://github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/ko/testdata/package-main-not-in-root/baz",
},
}
for _, test := range tests {
Expand All @@ -124,7 +139,7 @@ func Test_getImportPath(t *testing.T) {
koBuilder, err := b.newKoBuilder(context.Background(), test.artifact)
t.CheckNoError(err)

gotImportPath, err := getImportPath(test.artifact.ImageName, koBuilder)
gotImportPath, err := getImportPath(test.artifact, koBuilder)
t.CheckNoError(err)

t.CheckDeepEqual(test.expectedImportPath, gotImportPath)
Expand Down
8 changes: 8 additions & 0 deletions pkg/skaffold/build/ko/schema/temporary.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ type KoArtifact struct {
// Defaults to `all` to build for all platforms supported by the
// base image.
Platforms []string `yaml:"platforms,omitempty"`

// Target is the location of the main package.
// If target is specified as a relative path, it is relative to the `context` directory.
// If target is empty, the ko builder looks for the main package in the `context` directory only, but not in any subdirectories.
// If target is a pattern with wildcards, such as `./...`, the expansion must contain only one main package, otherwise ko fails.
// Target is ignored if the `ImageName` starts with `ko://`.
// Example: `./cmd/foo`
Target string `yaml:"target,omitempty"`
}

// KoDependencies is used to specify dependencies for an artifact built by ko.
Expand Down
3 changes: 3 additions & 0 deletions pkg/skaffold/build/ko/testdata/package-main-in-root/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/ko/testdata/package-main-in-root

go 1.13
14 changes: 14 additions & 0 deletions pkg/skaffold/build/ko/testdata/package-main-in-root/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package main

import (
"fmt"
"time"
)

func main() {
for {
fmt.Println("Hello world!")

time.Sleep(time.Second * 1)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package main

import (
"fmt"
"time"
)

func main() {
for {
fmt.Println("Hello world!")

time.Sleep(time.Second * 1)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/ko/testdata/package-main-not-in-root

go 1.13

0 comments on commit 7363674

Please sign in to comment.