mirror of
https://github.com/ko-build/ko.git
synced 2026-06-18 20:14:08 +02:00
Enable setting the working dir for the go tool (#365)
This change adds a `WorkingDirectory` field to `options.BuildOptions`, but doesn't expose this as a CLI flag. The default zero value means the current working directory. The value is used as the directory for executing `go` tool commands. When embedding ko in other tools, it is sometimes necessary to set the working directory for executing the `go` tool, instead of assuming the current process working directory. An example of where this is required from Skaffold: https://github.com/GoogleContainerTools/skaffold/tree/master/examples/microservices In this example, the working directory doesn't contain either `go.mod` or any Go files. The `skaffold.yaml` configuration file specifies a `context` field for each image, which is the directory where the `go` tool can find package information.
This commit is contained in:
+21
-13
@@ -1,16 +1,18 @@
|
||||
// Copyright 2018 Google LLC All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
Copyright 2018 Google LLC All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package build
|
||||
|
||||
@@ -24,6 +26,12 @@ import (
|
||||
// Interface abstracts different methods for turning a supported importpath
|
||||
// reference into a v1.Image.
|
||||
type Interface interface {
|
||||
// QualifyImport turns relative importpath references into complete importpaths.
|
||||
// It also adds the ko scheme prefix if necessary.
|
||||
// E.g., "github.com/google/ko/test" => "ko://github.com/google/ko/test"
|
||||
// and "./test" => "ko://github.com/google/ko/test"
|
||||
QualifyImport(string) (string, error)
|
||||
|
||||
// IsSupportedReference determines whether the given reference is to an
|
||||
// importpath reference that Ko supports building, returning an error
|
||||
// if it is not.
|
||||
|
||||
+74
-25
@@ -1,16 +1,18 @@
|
||||
// Copyright 2018 Google LLC All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
Copyright 2018 Google LLC All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package build
|
||||
|
||||
@@ -38,6 +40,7 @@ import (
|
||||
"github.com/google/go-containerregistry/pkg/v1/mutate"
|
||||
"github.com/google/go-containerregistry/pkg/v1/tarball"
|
||||
"github.com/google/go-containerregistry/pkg/v1/types"
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -64,7 +67,7 @@ For more information see:
|
||||
// GetBase takes an importpath and returns a base image.
|
||||
type GetBase func(context.Context, string) (Result, error)
|
||||
|
||||
type builder func(context.Context, string, v1.Platform, bool) (string, error)
|
||||
type builder func(context.Context, string, string, v1.Platform, bool) (string, error)
|
||||
|
||||
type buildContext interface {
|
||||
Import(path string, srcDir string, mode gb.ImportMode) (*gb.Package, error)
|
||||
@@ -83,6 +86,7 @@ type gobuild struct {
|
||||
mod *modules
|
||||
buildContext buildContext
|
||||
platformMatcher *platformMatcher
|
||||
dir string
|
||||
labels map[string]string
|
||||
}
|
||||
|
||||
@@ -98,6 +102,7 @@ type gobuildOpener struct {
|
||||
buildContext buildContext
|
||||
platform string
|
||||
labels map[string]string
|
||||
dir string
|
||||
}
|
||||
|
||||
func (gbo *gobuildOpener) Open() (Interface, error) {
|
||||
@@ -116,6 +121,7 @@ func (gbo *gobuildOpener) Open() (Interface, error) {
|
||||
mod: gbo.mod,
|
||||
buildContext: gbo.buildContext,
|
||||
labels: gbo.labels,
|
||||
dir: gbo.dir,
|
||||
platformMatcher: matcher,
|
||||
}, nil
|
||||
}
|
||||
@@ -136,14 +142,16 @@ type modInfo struct {
|
||||
// using go modules, otherwise returns nil.
|
||||
//
|
||||
// Related: https://github.com/golang/go/issues/26504
|
||||
func moduleInfo(ctx context.Context) (*modules, error) {
|
||||
func moduleInfo(ctx context.Context, dir string) (*modules, error) {
|
||||
modules := modules{
|
||||
deps: make(map[string]*modInfo),
|
||||
}
|
||||
|
||||
// TODO we read all the output as a single byte array - it may
|
||||
// be possible & more efficient to stream it
|
||||
output, err := exec.CommandContext(ctx, "go", "list", "-mod=readonly", "-json", "-m", "all").Output()
|
||||
cmd := exec.CommandContext(ctx, "go", "list", "-mod=readonly", "-json", "-m", "all")
|
||||
cmd.Dir = dir
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -186,22 +194,29 @@ func moduleInfo(ctx context.Context) (*modules, error) {
|
||||
// `ko` binary that expects a different GOROOT.
|
||||
//
|
||||
// See https://github.com/google/ko/issues/106
|
||||
func getGoroot(ctx context.Context) (string, error) {
|
||||
output, err := exec.CommandContext(ctx, "go", "env", "GOROOT").Output()
|
||||
func getGoroot(ctx context.Context, dir string) (string, error) {
|
||||
cmd := exec.CommandContext(ctx, "go", "env", "GOROOT")
|
||||
// It's probably not necessary to set the command working directory here,
|
||||
// but it helps keep everything consistent.
|
||||
cmd.Dir = dir
|
||||
output, err := cmd.Output()
|
||||
return strings.TrimSpace(string(output)), err
|
||||
}
|
||||
|
||||
// NewGo returns a build.Interface implementation that:
|
||||
// 1. builds go binaries named by importpath,
|
||||
// 2. containerizes the binary on a suitable base,
|
||||
func NewGo(ctx context.Context, options ...Option) (Interface, error) {
|
||||
// 2. containerizes the binary on a suitable base.
|
||||
//
|
||||
// The `dir` argument is the working directory for executing the `go` tool.
|
||||
// If `dir` is empty, the function uses the current process working directory.
|
||||
func NewGo(ctx context.Context, dir string, options ...Option) (Interface, error) {
|
||||
// TODO: We could do moduleInfo() and getGoroot() concurrently.
|
||||
module, err := moduleInfo(ctx)
|
||||
module, err := moduleInfo(ctx, dir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
goroot, err := getGoroot(ctx)
|
||||
goroot, err := getGoroot(ctx, dir)
|
||||
if err != nil {
|
||||
// On error, print the output and set goroot to "" to avoid using it later.
|
||||
log.Printf("Unexpected error running \"go env GOROOT\": %v\n%v", err, goroot)
|
||||
@@ -213,6 +228,7 @@ func NewGo(ctx context.Context, options ...Option) (Interface, error) {
|
||||
// If $(go env GOROOT) successfully returns a non-empty string that differs from
|
||||
// the default build context GOROOT, print a warning and use $(go env GOROOT).
|
||||
bc := gb.Default
|
||||
bc.Dir = dir
|
||||
if goroot != "" && bc.GOROOT != goroot {
|
||||
log.Printf(gorootWarningTemplate, bc.GOROOT, goroot, goroot)
|
||||
bc.GOROOT = goroot
|
||||
@@ -222,6 +238,9 @@ func NewGo(ctx context.Context, options ...Option) (Interface, error) {
|
||||
build: build,
|
||||
mod: module,
|
||||
buildContext: &bc,
|
||||
// dir is set on both buildContext and on gbo. Not ideal, but the
|
||||
// build.Context interface doesn't expose
|
||||
dir: dir,
|
||||
}
|
||||
|
||||
for _, option := range options {
|
||||
@@ -229,10 +248,39 @@ func NewGo(ctx context.Context, options ...Option) (Interface, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return gbo.Open()
|
||||
}
|
||||
|
||||
func (g *gobuild) qualifyLocalImport(importpath string) (string, error) {
|
||||
cfg := &packages.Config{
|
||||
Mode: packages.NeedName,
|
||||
Dir: g.dir,
|
||||
}
|
||||
pkgs, err := packages.Load(cfg, importpath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(pkgs) != 1 {
|
||||
return "", fmt.Errorf("found %d local packages, expected 1", len(pkgs))
|
||||
}
|
||||
return pkgs[0].PkgPath, nil
|
||||
}
|
||||
|
||||
// QualifyImport implements build.Interface
|
||||
func (g *gobuild) QualifyImport(importpath string) (string, error) {
|
||||
if gb.IsLocalImport(importpath) {
|
||||
var err error
|
||||
importpath, err = g.qualifyLocalImport(importpath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("qualifying local import %s: %v", importpath, err)
|
||||
}
|
||||
}
|
||||
if !strings.HasPrefix(importpath, StrictScheme) {
|
||||
importpath = StrictScheme + importpath
|
||||
}
|
||||
return importpath, nil
|
||||
}
|
||||
|
||||
// IsSupportedReference implements build.Interface
|
||||
//
|
||||
// Only valid importpaths that provide commands (i.e., are "package main") are
|
||||
@@ -303,7 +351,7 @@ func platformToString(p v1.Platform) string {
|
||||
return fmt.Sprintf("%s/%s", p.OS, p.Architecture)
|
||||
}
|
||||
|
||||
func build(ctx context.Context, ip string, platform v1.Platform, disableOptimizations bool) (string, error) {
|
||||
func build(ctx context.Context, ip string, dir string, platform v1.Platform, disableOptimizations bool) (string, error) {
|
||||
tmpDir, err := ioutil.TempDir("", "ko")
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -320,6 +368,7 @@ func build(ctx context.Context, ip string, platform v1.Platform, disableOptimiza
|
||||
args = addGo113TrimPathFlag(args)
|
||||
args = append(args, ip)
|
||||
cmd := exec.CommandContext(ctx, "go", args...)
|
||||
cmd.Dir = dir
|
||||
|
||||
// Last one wins
|
||||
defaultEnv := []string{
|
||||
@@ -536,7 +585,7 @@ func (g *gobuild) buildOne(ctx context.Context, s string, base v1.Image, platfor
|
||||
}
|
||||
|
||||
// Do the build into a temporary file.
|
||||
file, err := g.build(ctx, ref.Path(), *platform, g.disableOptimizations)
|
||||
file, err := g.build(ctx, ref.Path(), g.dir, *platform, g.disableOptimizations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+117
-16
@@ -1,16 +1,18 @@
|
||||
// Copyright 2018 Google LLC All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
Copyright 2018 Google LLC All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package build
|
||||
|
||||
@@ -23,6 +25,7 @@ import (
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -34,13 +37,107 @@ import (
|
||||
"github.com/google/go-containerregistry/pkg/v1/random"
|
||||
)
|
||||
|
||||
func repoRootDir() (string, error) {
|
||||
_, filename, _, ok := runtime.Caller(0)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("could not get current filename")
|
||||
}
|
||||
basepath := filepath.Dir(filename)
|
||||
repoDir := filepath.Join(basepath, "..", "..")
|
||||
return filepath.Rel(basepath, repoDir)
|
||||
}
|
||||
|
||||
func TestGoBuildQualifyImport(t *testing.T) {
|
||||
base, err := random.Image(1024, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("random.Image() = %v", err)
|
||||
}
|
||||
|
||||
repoDir, err := repoRootDir()
|
||||
if err != nil {
|
||||
t.Fatalf("could not get Git repository root directory")
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
description string
|
||||
rawImportpath string
|
||||
dir string
|
||||
qualifiedImportpath string
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
description: "strict qualified import path",
|
||||
rawImportpath: "ko://github.com/google/ko",
|
||||
dir: "",
|
||||
qualifiedImportpath: "ko://github.com/google/ko",
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
description: "strict qualified import path in subdirectory of go.mod",
|
||||
rawImportpath: "ko://github.com/google/ko/test",
|
||||
dir: "",
|
||||
qualifiedImportpath: "ko://github.com/google/ko/test",
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
description: "non-strict qualified import path",
|
||||
rawImportpath: "github.com/google/ko",
|
||||
dir: "",
|
||||
qualifiedImportpath: "ko://github.com/google/ko",
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
description: "non-strict local import path in repository root directory",
|
||||
rawImportpath: "./test",
|
||||
dir: repoDir,
|
||||
qualifiedImportpath: "ko://github.com/google/ko/test",
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
description: "non-strict local import path in subdirectory",
|
||||
rawImportpath: ".",
|
||||
dir: filepath.Join(repoDir, "test"),
|
||||
qualifiedImportpath: "ko://github.com/google/ko/test",
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
description: "non-existent non-strict local import path",
|
||||
rawImportpath: "./does-not-exist",
|
||||
dir: "/",
|
||||
qualifiedImportpath: "should return error",
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
ng, err := NewGo(context.Background(), test.dir, WithBaseImages(func(context.Context, string) (Result, error) { return base, nil }))
|
||||
if err != nil {
|
||||
t.Fatalf("NewGo() = %v", err)
|
||||
}
|
||||
gotImportpath, err := ng.QualifyImport(test.rawImportpath)
|
||||
if err != nil && test.expectError {
|
||||
return
|
||||
}
|
||||
if err != nil && !test.expectError {
|
||||
t.Errorf("QualifyImport(dir=%q)(%q) was error (%v), want nil error", test.dir, test.rawImportpath, err)
|
||||
}
|
||||
if err == nil && test.expectError {
|
||||
t.Errorf("QualifyImport(dir=%q)(%q) was nil error, want non-nil error", test.dir, test.rawImportpath)
|
||||
}
|
||||
if gotImportpath != test.qualifiedImportpath {
|
||||
t.Errorf("QualifyImport(dir=%q)(%q) = (%q, nil), want (%q, nil)", test.dir, test.rawImportpath, gotImportpath, test.qualifiedImportpath)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoBuildIsSupportedRef(t *testing.T) {
|
||||
base, err := random.Image(1024, 3)
|
||||
if err != nil {
|
||||
t.Fatalf("random.Image() = %v", err)
|
||||
}
|
||||
|
||||
ng, err := NewGo(context.Background(), WithBaseImages(func(context.Context, string) (Result, error) { return base, nil }))
|
||||
ng, err := NewGo(context.Background(), "", WithBaseImages(func(context.Context, string) (Result, error) { return base, nil }))
|
||||
if err != nil {
|
||||
t.Fatalf("NewGo() = %v", err)
|
||||
}
|
||||
@@ -100,7 +197,7 @@ func TestGoBuildIsSupportedRefWithModules(t *testing.T) {
|
||||
}),
|
||||
}
|
||||
|
||||
ng, err := NewGo(context.Background(), opts...)
|
||||
ng, err := NewGo(context.Background(), "", opts...)
|
||||
if err != nil {
|
||||
t.Fatalf("NewGo() = %v", err)
|
||||
}
|
||||
@@ -132,7 +229,7 @@ func TestGoBuildIsSupportedRefWithModules(t *testing.T) {
|
||||
}
|
||||
|
||||
// A helper method we use to substitute for the default "build" method.
|
||||
func writeTempFile(_ context.Context, s string, _ v1.Platform, _ bool) (string, error) {
|
||||
func writeTempFile(_ context.Context, s string, _ string, _ v1.Platform, _ bool) (string, error) {
|
||||
tmpDir, err := ioutil.TempDir("", "ko")
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -160,6 +257,7 @@ func TestGoBuildNoKoData(t *testing.T) {
|
||||
creationTime := v1.Time{Time: time.Unix(5000, 0)}
|
||||
ng, err := NewGo(
|
||||
context.Background(),
|
||||
"",
|
||||
WithCreationTime(creationTime),
|
||||
WithBaseImages(func(context.Context, string) (Result, error) { return base, nil }),
|
||||
withBuilder(writeTempFile),
|
||||
@@ -402,6 +500,7 @@ func TestGoBuild(t *testing.T) {
|
||||
creationTime := v1.Time{Time: time.Unix(5000, 0)}
|
||||
ng, err := NewGo(
|
||||
context.Background(),
|
||||
"",
|
||||
WithCreationTime(creationTime),
|
||||
WithBaseImages(func(context.Context, string) (Result, error) { return base, nil }),
|
||||
withBuilder(writeTempFile),
|
||||
@@ -474,6 +573,7 @@ func TestGoBuildIndex(t *testing.T) {
|
||||
creationTime := v1.Time{Time: time.Unix(5000, 0)}
|
||||
ng, err := NewGo(
|
||||
context.Background(),
|
||||
"",
|
||||
WithCreationTime(creationTime),
|
||||
WithBaseImages(func(context.Context, string) (Result, error) { return base, nil }),
|
||||
WithPlatforms("all"),
|
||||
@@ -546,6 +646,7 @@ func TestNestedIndex(t *testing.T) {
|
||||
creationTime := v1.Time{Time: time.Unix(5000, 0)}
|
||||
ng, err := NewGo(
|
||||
context.Background(),
|
||||
"",
|
||||
WithCreationTime(creationTime),
|
||||
WithBaseImages(func(context.Context, string) (Result, error) { return nestedBase, nil }),
|
||||
withBuilder(writeTempFile),
|
||||
|
||||
+20
-13
@@ -1,16 +1,18 @@
|
||||
// Copyright 2019 Google LLC All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
Copyright 2019 Google LLC All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package build
|
||||
|
||||
@@ -29,6 +31,11 @@ type Limiter struct {
|
||||
// Limiter implements Interface
|
||||
var _ Interface = (*Recorder)(nil)
|
||||
|
||||
// QualifyImport implements Interface
|
||||
func (l *Limiter) QualifyImport(ip string) (string, error) {
|
||||
return l.Builder.QualifyImport(ip)
|
||||
}
|
||||
|
||||
// IsSupportedReference implements Interface
|
||||
func (l *Limiter) IsSupportedReference(ip string) error {
|
||||
return l.Builder.IsSupportedReference(ip)
|
||||
|
||||
+20
-13
@@ -1,16 +1,18 @@
|
||||
// Copyright 2019 Google LLC All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
Copyright 2019 Google LLC All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package build
|
||||
|
||||
@@ -26,6 +28,11 @@ type sleeper struct{}
|
||||
|
||||
var _ Interface = (*sleeper)(nil)
|
||||
|
||||
// QualifyImport implements Interface
|
||||
func (r *sleeper) QualifyImport(ip string) (string, error) {
|
||||
return ip, nil
|
||||
}
|
||||
|
||||
// IsSupportedReference implements Interface
|
||||
func (r *sleeper) IsSupportedReference(ip string) error {
|
||||
return nil
|
||||
|
||||
+20
-13
@@ -1,16 +1,18 @@
|
||||
// Copyright 2018 Google LLC All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
Copyright 2018 Google LLC All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package build
|
||||
|
||||
@@ -29,6 +31,11 @@ type Recorder struct {
|
||||
// Recorder implements Interface
|
||||
var _ Interface = (*Recorder)(nil)
|
||||
|
||||
// QualifyImport implements Interface
|
||||
func (r *Recorder) QualifyImport(ip string) (string, error) {
|
||||
return r.Builder.QualifyImport(ip)
|
||||
}
|
||||
|
||||
// IsSupportedReference implements Interface
|
||||
func (r *Recorder) IsSupportedReference(ip string) error {
|
||||
return r.Builder.IsSupportedReference(ip)
|
||||
|
||||
+18
-13
@@ -1,16 +1,18 @@
|
||||
// Copyright 2018 Google LLC All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
Copyright 2018 Google LLC All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package build
|
||||
|
||||
@@ -28,6 +30,9 @@ type fake struct {
|
||||
|
||||
var _ Interface = (*fake)(nil)
|
||||
|
||||
// QualifyImport implements Interface
|
||||
func (r *fake) QualifyImport(ip string) (string, error) { return ip, nil }
|
||||
|
||||
// IsSupportedReference implements Interface
|
||||
func (r *fake) IsSupportedReference(ip string) error { return r.isr(ip) }
|
||||
|
||||
|
||||
+20
-13
@@ -1,16 +1,18 @@
|
||||
// Copyright 2018 Google LLC All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
Copyright 2018 Google LLC All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package build
|
||||
|
||||
@@ -64,6 +66,11 @@ func (c *Caching) Build(ctx context.Context, ip string) (Result, error) {
|
||||
return f.Get()
|
||||
}
|
||||
|
||||
// QualifyImport implements Interface
|
||||
func (c *Caching) QualifyImport(ip string) (string, error) {
|
||||
return c.inner.QualifyImport(ip)
|
||||
}
|
||||
|
||||
// IsSupportedReference implements Interface
|
||||
func (c *Caching) IsSupportedReference(ip string) error {
|
||||
return c.inner.IsSupportedReference(ip)
|
||||
|
||||
+17
-13
@@ -1,16 +1,18 @@
|
||||
// Copyright 2018 Google LLC All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
Copyright 2018 Google LLC All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package build
|
||||
|
||||
@@ -29,6 +31,8 @@ type slowbuild struct {
|
||||
// slowbuild implements Interface
|
||||
var _ Interface = (*slowbuild)(nil)
|
||||
|
||||
func (sb *slowbuild) QualifyImport(ip string) (string, error) { return ip, nil }
|
||||
|
||||
func (sb *slowbuild) IsSupportedReference(string) error { return nil }
|
||||
|
||||
func (sb *slowbuild) Build(context.Context, string) (Result, error) {
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
// Copyright 2019 Google LLC All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
Copyright 2019 Google LLC All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package options
|
||||
|
||||
@@ -24,7 +26,12 @@ import (
|
||||
type BuildOptions struct {
|
||||
// BaseImage enables setting the default base image programmatically.
|
||||
// If non-empty, this takes precedence over the value in `.ko.yaml`.
|
||||
BaseImage string
|
||||
BaseImage string
|
||||
|
||||
// WorkingDirectory allows for setting the working directory for invocations of the `go` tool.
|
||||
// Empty string means the current working directory.
|
||||
WorkingDirectory string
|
||||
|
||||
ConcurrentBuilds int
|
||||
DisableOptimizations bool
|
||||
Platform string
|
||||
|
||||
@@ -19,30 +19,12 @@ package commands
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
gb "go/build"
|
||||
"strings"
|
||||
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
"github.com/google/ko/pkg/build"
|
||||
"github.com/google/ko/pkg/publish"
|
||||
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
func qualifyLocalImport(importpath string) (string, error) {
|
||||
cfg := &packages.Config{
|
||||
Mode: packages.NeedName,
|
||||
}
|
||||
pkgs, err := packages.Load(cfg, importpath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(pkgs) != 1 {
|
||||
return "", fmt.Errorf("found %d local packages, expected 1", len(pkgs))
|
||||
}
|
||||
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) {
|
||||
return publishImages(ctx, importpaths, pub, b)
|
||||
@@ -51,17 +33,10 @@ func PublishImages(ctx context.Context, importpaths []string, pub publish.Interf
|
||||
func publishImages(ctx context.Context, importpaths []string, pub publish.Interface, b build.Interface) (map[string]name.Reference, error) {
|
||||
imgs := make(map[string]name.Reference)
|
||||
for _, importpath := range importpaths {
|
||||
if gb.IsLocalImport(importpath) {
|
||||
var err error
|
||||
importpath, err = qualifyLocalImport(importpath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
importpath, err := b.QualifyImport(importpath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !strings.HasPrefix(importpath, build.StrictScheme) {
|
||||
importpath = build.StrictScheme + importpath
|
||||
}
|
||||
|
||||
if err := b.IsSupportedReference(importpath); err != nil {
|
||||
return nil, fmt.Errorf("importpath %q is not supported: %v", importpath, err)
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ func makeBuilder(ctx context.Context, bo *options.BuildOptions) (*build.Caching,
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error setting up builder options: %v", err)
|
||||
}
|
||||
innerBuilder, err := build.NewGo(ctx, opt...)
|
||||
innerBuilder, err := build.NewGo(ctx, bo.WorkingDirectory, opt...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
// Copyright 2018 Google LLC All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
Copyright 2018 Google LLC All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package testing
|
||||
|
||||
@@ -36,6 +38,11 @@ func NewFixedBuild(entries map[string]build.Result) build.Interface {
|
||||
return &fixedBuild{entries}
|
||||
}
|
||||
|
||||
// QualifyImport implements build.Interface
|
||||
func (f *fixedBuild) QualifyImport(ip string) (string, error) {
|
||||
return ip, nil
|
||||
}
|
||||
|
||||
// IsSupportedReference implements build.Interface
|
||||
func (f *fixedBuild) IsSupportedReference(s string) error {
|
||||
s = strings.TrimPrefix(s, build.StrictScheme)
|
||||
|
||||
Reference in New Issue
Block a user