Repository: GoogleContainerTools/skaffold
Pull request #7430 (2022-05-20 00:32:55)

fix: running skaffold from a directory other than repository root
<!-- Thank you for your contribution! -->

<!-- Include if applicable: -->
Fixes: #7281
**Related**: #7251

**Description**

1. The `bazel cquery` runs in the directory corresponding to the context and returns the tar path relative to that path. 
2. The `docker.Push()` function is invoked with the same working directory as the current working directory of the process.

Prior to #7251, the path returned by `bazel cquery` was appended with an absolute path returned by `bazel info bazel-bin`, so it ended up being an absolute path. With #7251 merged, this no longer happens, so `docker.Push()` receives a relative path returned by `bazel cquery`.

If `skaffold build` is executed in a directory different from the repository root, `docker.Push()` will receive a relative path against the repository root and won't find the file.

Take the following example. There is a `skaffold.yaml` file in `projects/acme/some-project`:
```yaml
apiVersion: skaffold/v2beta26
kind: Config
build:
  artifacts:
  - image: quay.io/acme/some-project
    context: ../../..
...
```
If one does:
```
cd projects/acme/some-projects && skaffold build
```
It will no longer work. It will fail with an error like:
> build [quay.io/acme/some-project] failed: reading image "bazel-out/darwin-fastbuild-ST-4a519fd6d3e4/bin/projects/some-project/docker.tar": open bazel-out/darwin-fastbuild-ST-4a519fd6d3e4/bin/projects/some-project/docker.tar: no such file or directory

This error may be confusing because the path does exist relative to the repository root. It does not exist relative to the current working directory though.


Patch:
diff --git a/cmd/skaffold/app/cmd/runner.go b/cmd/skaffold/app/cmd/runner.go
index 6546faebf..d4628ddfa 100644
--- a/cmd/skaffold/app/cmd/runner.go
+++ b/cmd/skaffold/app/cmd/runner.go
@@ -83,6 +83,7 @@ func runContext(ctx context.Context, out io.Writer, opts config.SkaffoldOptions)
 	if err != nil {
 		return nil, nil, err
 	}
+	setDefaultRendererAndDeployer(cfgSet)
 
 	if err := validation.Process(cfgSet, validation.GetValidationOpts(opts)); err != nil {
 		return nil, nil, fmt.Errorf("invalid skaffold config: %w", err)
@@ -149,3 +150,13 @@ func warnIfUpdateIsAvailable() {
 		log.Entry(context.TODO()).Warn(warning)
 	}
 }
+
+func setDefaultRendererAndDeployer(configs parser.SkaffoldConfigSet) {
+	// do not set a default deployer or renderer in a multi-config application.
+	if len(configs) > 1 {
+		return
+	}
+	// there always exists at least one config
+	defaults.SetDefaultRenderer(configs[0].SkaffoldConfig)
+	defaults.SetDefaultDeployer(configs[0].SkaffoldConfig)
+}
diff --git a/integration/examples/multi-config-microservices/leeroy-app/skaffold.yaml b/integration/examples/multi-config-microservices/leeroy-app/skaffold.yaml
index a7d7c2564..7dc9aedf0 100644
--- a/integration/examples/multi-config-microservices/leeroy-app/skaffold.yaml
+++ b/integration/examples/multi-config-microservices/leeroy-app/skaffold.yaml
@@ -13,6 +13,8 @@ build:
 manifests:
   rawYaml:
     - kubernetes/*
+deploy:
+  kubectl: {}
 portForward:
 - resourceType: deployment
   resourceName: leeroy-app
diff --git a/integration/examples/multi-config-microservices/leeroy-web/skaffold.yaml b/integration/examples/multi-config-microservices/leeroy-web/skaffold.yaml
index ff9bd6014..d428d6d68 100644
--- a/integration/examples/multi-config-microservices/leeroy-web/skaffold.yaml
+++ b/integration/examples/multi-config-microservices/leeroy-web/skaffold.yaml
@@ -11,8 +11,10 @@ build:
     - image: base
       alias: BASE
 manifests:
-    rawYaml:
-      - kubernetes/*
+  rawYaml:
+    - kubernetes/*
+deploy:
+  kubectl: {}
 portForward:
 - resourceType: deployment
   resourceName: leeroy-web
diff --git a/pkg/skaffold/build/bazel/build.go b/pkg/skaffold/build/bazel/build.go
index 4e3b57130..5fc40c76c 100644
--- a/pkg/skaffold/build/bazel/build.go
+++ b/pkg/skaffold/build/bazel/build.go
@@ -23,6 +23,7 @@ import (
 	"io"
 	"os"
 	"os/exec"
+	"path/filepath"
 	"strings"
 
 	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker"
@@ -84,7 +85,7 @@ func (b *Builder) buildTar(ctx context.Context, out io.Writer, workspace string,
 		return "", fmt.Errorf("getting bazel tar path: %w", err)
 	}
 
-	return tarPath, nil
+	return filepath.Join(workspace, tarPath), nil
 }
 
 func (b *Builder) loadImage(ctx context.Context, out io.Writer, tarPath string, a *latest.BazelArtifact, tag string) (string, error) {
diff --git a/pkg/skaffold/schema/defaults/defaults.go b/pkg/skaffold/schema/defaults/defaults.go
index b79ea6df5..d1a06b6dc 100644
--- a/pkg/skaffold/schema/defaults/defaults.go
+++ b/pkg/skaffold/schema/defaults/defaults.go
@@ -108,8 +108,6 @@ func Set(c *latest.SkaffoldConfig) error {
 	}
 
 	setDefaultTestWorkspace(c)
-	SetDefaultRenderer(c)
-	SetDefaultDeployer(c)
 	return nil
 }
 


Test patch:
diff --git a/integration/testdata/modules/app1/skaffold.yaml b/integration/testdata/modules/app1/skaffold.yaml
index b397b2a4b..8654d50a0 100644
--- a/integration/testdata/modules/app1/skaffold.yaml
+++ b/integration/testdata/modules/app1/skaffold.yaml
@@ -19,3 +19,6 @@ build:
 manifests:
   rawYaml:
   - 'k8s.yaml'
+
+deploy:
+  kubectl: {}
diff --git a/integration/testdata/modules/app2/skaffold.yaml b/integration/testdata/modules/app2/skaffold.yaml
index 659f45bf7..378908298 100644
--- a/integration/testdata/modules/app2/skaffold.yaml
+++ b/integration/testdata/modules/app2/skaffold.yaml
@@ -20,3 +20,6 @@ build:
 manifests:
   rawYaml:
   - 'k8s.yaml'
+
+deploy:
+  kubectl: {}
diff --git a/integration/testdata/modules/app3/skaffold.yaml b/integration/testdata/modules/app3/skaffold.yaml
index 240f278b0..3cc508552 100644
--- a/integration/testdata/modules/app3/skaffold.yaml
+++ b/integration/testdata/modules/app3/skaffold.yaml
@@ -15,3 +15,6 @@ build:
 manifests:
   rawYaml:
   - 'k8s.yaml'
+
+deploy:
+  kubectl: {}
diff --git a/pkg/skaffold/build/bazel/build_test.go b/pkg/skaffold/build/bazel/build_test.go
index 5e376582a..dc4d08e41 100644
--- a/pkg/skaffold/build/bazel/build_test.go
+++ b/pkg/skaffold/build/bazel/build_test.go
@@ -52,6 +52,29 @@ func TestBuildBazel(t *testing.T) {
 	})
 }
 
+func TestBazelTarPathFRespectWorkspace(t *testing.T) {
+	testutil.Run(t, "", func(t *testutil.T) {
+		t.Override(&util.DefaultExecCommand, testutil.CmdRun("bazel build //:app.tar --color=no").AndRunOut(
+			"bazel cquery //:app.tar --output starlark --starlark:expr target.files.to_list()[0].path",
+			"app.tar"))
+		testutil.CreateFakeImageTar("bazel:app", "../app.tar")
+
+		artifact := &latest.Artifact{
+			Workspace: "..",
+			ArtifactType: latest.ArtifactType{
+				BazelArtifact: &latest.BazelArtifact{
+					BuildTarget: "//:app.tar",
+				},
+			},
+		}
+
+		builder := NewArtifactBuilder(fakeLocalDaemon(), &mockConfig{}, false)
+		_, err := builder.Build(context.Background(), ioutil.Discard, artifact, "img:tag", platform.Matcher{})
+
+		t.CheckNoError(err)
+	})
+}
+
 func TestBuildBazelFailInvalidTarget(t *testing.T) {
 	testutil.Run(t, "", func(t *testutil.T) {
 		artifact := &latest.Artifact{