From 564907ee1513c413f4c253934c39d22bd6e6ecc8 Mon Sep 17 00:00:00 2001 From: Axel von Bertoldi Date: Mon, 19 Sep 2022 10:50:43 -0600 Subject: [PATCH 01/19] [common] Inject tmp project dir into JobVariables This is a convenient place to put the tmp project dir such the it can be easily accessed by methods on JobVariables. We'll use it next to correctly expand variables that reference job variables. After a few attempts, this suggestion by @ajwalker is the cleanest way to inject the build tmp path and tmp file creation into the JobVariable or JobVariables object. --- common/build.go | 4 ++++ common/variables.go | 2 ++ 2 files changed, 6 insertions(+) diff --git a/common/build.go b/common/build.go index d80064237b3..c177282e83e 100644 --- a/common/build.go +++ b/common/build.go @@ -1179,6 +1179,10 @@ func (b *Build) GetAllVariables() JobVariables { variables = append(variables, AppVersion.Variables()...) variables = append(variables, b.secretsVariables...) + variables = append(variables, JobVariable{ + Key: tempProjectDirVariableKey, Value: b.TmpProjectDir(), Public: true, Internal: true, + }) + b.allVariables = variables.Expand() return b.allVariables diff --git a/common/variables.go b/common/variables.go index c3fd753590c..4090a1d45d7 100644 --- a/common/variables.go +++ b/common/variables.go @@ -24,6 +24,8 @@ func (b JobVariable) String() string { return fmt.Sprintf("%s=%s", b.Key, b.Value) } +const tempProjectDirVariableKey = "RUNNER_TEMP_PROJECT_DIR" + func (b JobVariables) PublicOrInternal() (variables JobVariables) { for _, variable := range b { if variable.Public || variable.Internal { -- GitLab From 9eef945e78bb266945b31fa69c68be293c538efe Mon Sep 17 00:00:00 2001 From: Axel von Bertoldi Date: Mon, 19 Sep 2022 10:50:15 -0600 Subject: [PATCH 02/19] [common] Correctly handle file variables The notion of file variables is arguably incomplete in the JobVariable implementation. There are things this type of object needs to be able to do (like generate a temporary file path), which it previously could not, which results in behaviour like https://gitlab.com/gitlab-org/gitlab/-/issues/29407. This is the first step in fixing this. The _value_ of the RUNNER_TEMP_PROJECT_DIR variable is some other object's responsibility, but once having been injected into a JobVariables instance, it's the latter's responsibility to create temporary file paths. Contrary to the suggestion in https://gitlab.com/gitlab-org/gitlab-runner/-/issues/29128, This strikes me is a more strictly correct place for this method than the Build object since the JobVariables object shuld be responsible for knowing which of its fields (Key, Value, ???) should be used to generate the temporary file path, while the Build object is responsible for specifying the builds temporary path. Now that the JobVariables object has a way to generate temporary file paths, we can correctly handle expanding both file variables and variables that reference (or point to) file variables. The effect of this change is that when we call `Get()` of a file variable, we'll get back the temp file path instead of the (intended) content of the file. This automatically fixes variables that reference file variables, since expansion of that type of variable will result in the file variable's tmp file path instead of its content. This mostly fixes https://gitlab.com/gitlab-org/gitlab/-/issues/29407, making some minor tweaks in the ShellWriters (later). --- common/variables.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/common/variables.go b/common/variables.go index 4090a1d45d7..7930a3a99a6 100644 --- a/common/variables.go +++ b/common/variables.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "os" + "path" "strconv" "strings" ) @@ -26,6 +27,14 @@ func (b JobVariable) String() string { const tempProjectDirVariableKey = "RUNNER_TEMP_PROJECT_DIR" +// tmpFile will return a canonical temp file path by prepending the job +// variables Key with the value of `RUNNER_TEMP_PROJECT_DIR` (typically the +// build's temporary directory). The returned path must be further expanded +// by/for each shell that uses it. +func (b JobVariables) tmpFile(s string) string { + return path.Join(b.Get(tempProjectDirVariableKey), s) +} + func (b JobVariables) PublicOrInternal() (variables JobVariables) { for _, variable := range b { if variable.Public || variable.Internal { @@ -51,6 +60,9 @@ func (b JobVariables) Get(key string) string { } for i := len(b) - 1; i >= 0; i-- { if b[i].Key == key { + if b[i].File { + return b.tmpFile(b[i].Key) + } return b[i].Value } } -- GitLab From f8ecddca6ca03406e0719ccb1619ec90794b6179 Mon Sep 17 00:00:00 2001 From: Axel von Bertoldi Date: Fri, 16 Sep 2022 16:07:28 -0600 Subject: [PATCH 03/19] [common] More unit tests for file variable expansion Ensure expansion for the following cases works: - file variable - variable that references a file variable - simple/regular variable - variable that references a simple/regular variable --- common/variables_test.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/common/variables_test.go b/common/variables_test.go index c0e66fe1b1a..15a0bbf31fd 100644 --- a/common/variables_test.go +++ b/common/variables_test.go @@ -223,6 +223,38 @@ func TestVariablesExpansion(t *testing.T) { assert.Equal(t, "value_of_ value_of_value_of_$undefined", expanded.ExpandValue("${public} ${private}")) } +func TestFileVariablesExpansion(t *testing.T) { + all := JobVariables{ + {Key: "a_file_var", Value: "some top secret stuff", File: true}, + {Key: "ref_file_var", Value: "${a_file_var}.txt"}, + {Key: "regular_var", Value: "bla bla bla"}, + {Key: "ref_regular_var", Value: "bla bla bla"}, + {Key: "RUNNER_TEMP_PROJECT_DIR", Value: "/foo/bar", Public: true, Internal: true}, + } + + validate := func(t *testing.T, variables JobVariables) { + assert.Len(t, variables, 5) + + // correct expansion of file variables + assert.Equal(t, "/foo/bar/a_file_var", variables.Get("a_file_var")) + + // correct expansion of variables that reference file variables + assert.Equal(t, "/foo/bar/a_file_var.txt", variables.Get("ref_file_var")) + assert.Equal(t, "/foo/bar/a_file_var.txt.blammo", variables.ExpandValue("${ref_file_var}.blammo")) + assert.Equal(t, "/foo/bar/a_file_var.blammo", variables.ExpandValue("${a_file_var}.blammo")) + + // correct expansion of regular variables, and variables that reference + // regular variables + assert.Equal(t, "bla bla bla", variables.Get("regular_var")) + assert.Equal(t, "bla bla bla", variables.Get("ref_regular_var")) + } + + expanded := all.Expand() + validate(t, expanded) + // calling Expand multiple times is idempotent. + validate(t, expanded.Expand()) +} + func TestSpecialVariablesExpansion(t *testing.T) { all := JobVariables{ {Key: "key", Value: "$$"}, -- GitLab From 219ef91ae6797704aeb37d863c46d23585d1036e Mon Sep 17 00:00:00 2001 From: Axel von Bertoldi Date: Wed, 7 Sep 2022 14:23:57 -0600 Subject: [PATCH 04/19] [bash] Refactor BashWriter.TmpFile() Move everything but the path concatenation to a new method, which we'll use later. Why do we need to do this at all? That tmp file path set by/in JobVariables is an approximate path. TO actually use it in the shell writer we need to tweak it a little. We'll use cleanPath() for that. --- shells/bash.go | 6 +++++- shells/bash_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/shells/bash.go b/shells/bash.go index e0211d0cc55..fd0cfd980c8 100644 --- a/shells/bash.go +++ b/shells/bash.go @@ -128,7 +128,11 @@ func (b *BashWriter) buildCommand(quoter stringQuoter, command string, arguments } func (b *BashWriter) TmpFile(name string) string { - return b.Absolute(path.Join(b.TemporaryPath, name)) + return b.cleanPath(path.Join(b.TemporaryPath, name)) +} + +func (b *BashWriter) cleanPath(name string) string { + return b.Absolute(name) } func (b *BashWriter) EnvVariableKey(name string) string { diff --git a/shells/bash_test.go b/shells/bash_test.go index 0b08669f495..2a6c6b4f70c 100644 --- a/shells/bash_test.go +++ b/shells/bash_test.go @@ -147,3 +147,27 @@ func TestBash_GetConfiguration(t *testing.T) { }) } } + +func Test_BashWriter_cleanPath(t *testing.T) { + tests := map[string]struct { + path, want string + }{ + "relative path": { + path: "foo/bar/KEY", + want: "$PWD/foo/bar/KEY", + }, + "absolute path": { + path: "/foo/bar/KEY", + want: "/foo/bar/KEY", + }, + } + + bw := BashWriter{TemporaryPath: "foo/bar"} + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + got := bw.cleanPath(tt.path) + assert.Equal(t, tt.want, got) + }) + } +} -- GitLab From 8f336a2e3e1c4c0671e4d76fc1b66cc816a39095 Mon Sep 17 00:00:00 2001 From: Axel von Bertoldi Date: Fri, 16 Sep 2022 11:48:51 -0600 Subject: [PATCH 05/19] [bash] make BashWriter.Absolute() idempotent Not sure if this is strictly encessary, but it's probably a good property for this method to have. --- shells/bash.go | 2 +- shells/bash_test.go | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/shells/bash.go b/shells/bash.go index fd0cfd980c8..5f7dac9d974 100644 --- a/shells/bash.go +++ b/shells/bash.go @@ -214,7 +214,7 @@ func (b *BashWriter) RmFilesRecursive(path string, name string) { } func (b *BashWriter) Absolute(dir string) string { - if path.IsAbs(dir) { + if path.IsAbs(dir) || strings.HasPrefix(dir, "$PWD") { return dir } return path.Join("$PWD", dir) diff --git a/shells/bash_test.go b/shells/bash_test.go index 2a6c6b4f70c..4ca45047e05 100644 --- a/shells/bash_test.go +++ b/shells/bash_test.go @@ -160,6 +160,10 @@ func Test_BashWriter_cleanPath(t *testing.T) { path: "/foo/bar/KEY", want: "/foo/bar/KEY", }, + "idempotent": { + path: "$PWD/foo/bar/KEY", + want: "$PWD/foo/bar/KEY", + }, } bw := BashWriter{TemporaryPath: "foo/bar"} -- GitLab From 5469160f91347008f74d94d72c198cb3cf2909d4 Mon Sep 17 00:00:00 2001 From: Axel von Bertoldi Date: Wed, 7 Sep 2022 14:24:50 -0600 Subject: [PATCH 06/19] [bash] Add isTmpFile() method to BashWriter This method tells us if the VALUE of a variable is a temporary file path, indicating that the variable is an alias of (or points to) another variable which is of type File. Once we've detected this approximate tmp path, we can tweak it as mentioned previously. --- shells/bash.go | 6 ++++++ shells/bash_test.go | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/shells/bash.go b/shells/bash.go index 5f7dac9d974..9bebb5a2f60 100644 --- a/shells/bash.go +++ b/shells/bash.go @@ -139,6 +139,12 @@ func (b *BashWriter) EnvVariableKey(name string) string { return fmt.Sprintf("$%s", name) } +// Intended to be used on unmodified paths only (i.e. paths that have not been +// cleaned with cleanPath()). +func (b *BashWriter) isTmpFile(path string) bool { + return strings.HasPrefix(path, b.TemporaryPath) +} + func (b *BashWriter) Variable(variable common.JobVariable) { if variable.File { variableFile := b.TmpFile(variable.Key) diff --git a/shells/bash_test.go b/shells/bash_test.go index 4ca45047e05..86fecaef9ae 100644 --- a/shells/bash_test.go +++ b/shells/bash_test.go @@ -3,6 +3,7 @@ package shells import ( + "path" "runtime" "testing" @@ -148,6 +149,25 @@ func TestBash_GetConfiguration(t *testing.T) { } } +func Test_BashWriter_isTmpFile(t *testing.T) { + tmpDir := "/foo/bar" + bw := BashWriter{TemporaryPath: tmpDir} + + tests := map[string]struct { + path string + want bool + }{ + "tmp file var": {path: path.Join(tmpDir, "BAZ"), want: true}, + "not tmp file var": {path: "bla bla bla", want: false}, + } + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + assert.Equal(t, tt.want, bw.isTmpFile(tt.path)) + }) + } +} + func Test_BashWriter_cleanPath(t *testing.T) { tests := map[string]struct { path, want string -- GitLab From 50044b811c6ddab6e98955b7f7b147cf9a258b13 Mon Sep 17 00:00:00 2001 From: Axel von Bertoldi Date: Wed, 7 Sep 2022 14:48:55 -0600 Subject: [PATCH 07/19] [bash] Correctly handle file variable alias variables Specifically, when a variable references or points to a file variable, the value of said variable should be the path/name of the file variable (not its contents), corrected for the current shell. --- shells/bash.go | 3 +++ shells/bash_test.go | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/shells/bash.go b/shells/bash.go index 9bebb5a2f60..3121dd9b80f 100644 --- a/shells/bash.go +++ b/shells/bash.go @@ -152,6 +152,9 @@ func (b *BashWriter) Variable(variable common.JobVariable) { b.Linef("printf '%%s' %s > %q", b.escape(variable.Value), variableFile) b.Linef("export %s=%q", b.escape(variable.Key), variableFile) } else { + if b.isTmpFile(variable.Value) { + variable.Value = b.cleanPath(variable.Value) + } b.Linef("export %s=%s", b.escape(variable.Key), b.escape(variable.Value)) } } diff --git a/shells/bash_test.go b/shells/bash_test.go index 86fecaef9ae..9ed9e65ff3e 100644 --- a/shells/bash_test.go +++ b/shells/bash_test.go @@ -195,3 +195,46 @@ func Test_BashWriter_cleanPath(t *testing.T) { }) } } + +func Test_BashWriter_Variable(t *testing.T) { + tests := map[string]struct { + variable common.JobVariable + writer BashWriter + want string + }{ + "file var, relative path": { + variable: common.JobVariable{Key: "KEY", Value: "the secret", File: true}, + writer: BashWriter{TemporaryPath: "foo/bar"}, + // nolint:lll + want: "mkdir -p \"foo/bar\"\nprintf '%s' $'the secret' > \"$PWD/foo/bar/KEY\"\nexport KEY=\"$PWD/foo/bar/KEY\"\n", + }, + "file var, absolute path": { + variable: common.JobVariable{Key: "KEY", Value: "the secret", File: true}, + writer: BashWriter{TemporaryPath: "/foo/bar"}, + // nolint:lll + want: "mkdir -p \"/foo/bar\"\nprintf '%s' $'the secret' > \"/foo/bar/KEY\"\nexport KEY=\"/foo/bar/KEY\"\n", + }, + "tmp file var, relative path": { + variable: common.JobVariable{Key: "KEY", Value: "foo/bar/KEY2"}, + writer: BashWriter{TemporaryPath: "foo/bar"}, + want: "export KEY=$'$PWD/foo/bar/KEY2'\n", + }, + "tmp file var, absolute path": { + variable: common.JobVariable{Key: "KEY", Value: "/foo/bar/KEY2"}, + writer: BashWriter{TemporaryPath: "/foo/bar"}, + want: "export KEY=$'/foo/bar/KEY2'\n", + }, + "regular var": { + variable: common.JobVariable{Key: "KEY", Value: "VALUE"}, + writer: BashWriter{TemporaryPath: "/foo/bar"}, + want: "export KEY=VALUE\n", + }, + } + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + tt.writer.Variable(tt.variable) + assert.Equal(t, tt.want, tt.writer.String()) + }) + } +} -- GitLab From fd72736be77ee0f687e7b0a97409b2c57db33f12 Mon Sep 17 00:00:00 2001 From: Axel von Bertoldi Date: Wed, 7 Sep 2022 14:52:18 -0600 Subject: [PATCH 08/19] [cmd] Refactor CmdWriter.TmpFile() ...same as with BashWriter --- shells/cmd.go | 7 +++++-- shells/cmd_test.go | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/shells/cmd.go b/shells/cmd.go index a98027418fd..38ddbef9e31 100644 --- a/shells/cmd.go +++ b/shells/cmd.go @@ -129,8 +129,11 @@ func (b *CmdWriter) buildCommand(quoter stringQuoter, command string, arguments } func (b *CmdWriter) TmpFile(name string) string { - filePath := b.Absolute(path.Join(b.TemporaryPath, name)) - return helpers.ToBackslash(filePath) + return b.cleanPath(path.Join(b.TemporaryPath, name)) +} + +func (b *CmdWriter) cleanPath(name string) string { + return helpers.ToBackslash(b.Absolute(name)) } func (b *CmdWriter) EnvVariableKey(name string) string { diff --git a/shells/cmd_test.go b/shells/cmd_test.go index 610a869ea1d..6cab5e8cd76 100644 --- a/shells/cmd_test.go +++ b/shells/cmd_test.go @@ -4,6 +4,7 @@ package shells import ( "fmt" + "runtime" "strconv" "testing" @@ -109,3 +110,38 @@ func TestCMD_DelayedExpanstionFeatureFlag(t *testing.T) { }) } } + +func Test_CmdWriter_cleanPath(t *testing.T) { + tests := map[string]struct { + path, wantLinux, wantWindows string + }{ + "relative path": { + path: "foo/bar/KEY", + wantLinux: "%CD%\\foo\\bar\\KEY", + wantWindows: "%CD%\\foo\\bar\\KEY", + }, + "absolute path": { + path: "/foo/bar/KEY", + wantLinux: "\\foo\\bar\\KEY", + wantWindows: "%CD%\\foo\\bar\\KEY", + }, + "absolute path with drive": { + path: "C:/foo/bar/KEY", + wantLinux: "%CD%\\C:\\foo\\bar\\KEY", + wantWindows: "C:\\foo\\bar\\KEY", + }, + } + + bw := CmdWriter{TemporaryPath: "foo/bar"} + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + got := bw.cleanPath(tt.path) + if runtime.GOOS == OSWindows { + assert.Equal(t, tt.wantWindows, got) + } else { + assert.Equal(t, tt.wantLinux, got) + } + }) + } +} -- GitLab From 0ca2e7f813e6047bf8085e217cc9d564a01307b0 Mon Sep 17 00:00:00 2001 From: Axel von Bertoldi Date: Wed, 7 Sep 2022 14:53:09 -0600 Subject: [PATCH 09/19] [cmd] Add isTmpFile() method to CmdWriter --- shells/cmd.go | 4 ++++ shells/cmd_test.go | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/shells/cmd.go b/shells/cmd.go index 38ddbef9e31..98b520e3be7 100644 --- a/shells/cmd.go +++ b/shells/cmd.go @@ -140,6 +140,10 @@ func (b *CmdWriter) EnvVariableKey(name string) string { return fmt.Sprintf("%%%s%%", name) } +func (b *CmdWriter) isTmpFile(path string) bool { + return strings.HasPrefix(path, b.TemporaryPath) +} + func (b *CmdWriter) Variable(variable common.JobVariable) { if variable.File { variableFile := b.TmpFile(variable.Key) diff --git a/shells/cmd_test.go b/shells/cmd_test.go index 6cab5e8cd76..6985e418bb2 100644 --- a/shells/cmd_test.go +++ b/shells/cmd_test.go @@ -4,6 +4,7 @@ package shells import ( "fmt" + "path" "runtime" "strconv" "testing" @@ -111,6 +112,25 @@ func TestCMD_DelayedExpanstionFeatureFlag(t *testing.T) { } } +func Test_CmdWriter_isTmpFile(t *testing.T) { + tmpDir := "/foo/bar" + bw := CmdWriter{TemporaryPath: tmpDir} + + tests := map[string]struct { + path string + want bool + }{ + "tmp file var": {path: path.Join(tmpDir, "BAZ"), want: true}, + "not tmp file var": {path: "bla bla bla", want: false}, + } + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + assert.Equal(t, tt.want, bw.isTmpFile(tt.path)) + }) + } +} + func Test_CmdWriter_cleanPath(t *testing.T) { tests := map[string]struct { path, wantLinux, wantWindows string -- GitLab From 7793d8c588a0742598026b02c6777bd40a745c36 Mon Sep 17 00:00:00 2001 From: Axel von Bertoldi Date: Wed, 7 Sep 2022 14:53:39 -0600 Subject: [PATCH 10/19] [cmd] Do the right thing with file variable alias variables --- shells/cmd.go | 3 +++ shells/cmd_test.go | 66 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/shells/cmd.go b/shells/cmd.go index 98b520e3be7..75152b36b94 100644 --- a/shells/cmd.go +++ b/shells/cmd.go @@ -151,6 +151,9 @@ func (b *CmdWriter) Variable(variable common.JobVariable) { b.Linef("echo %s > %s", batchEscapeVariable(variable.Value), batchEscape(variableFile)) b.Linef("SET %s=%s", batchEscapeVariable(variable.Key), batchEscape(variableFile)) } else { + if b.isTmpFile(variable.Value) { + variable.Value = b.cleanPath(variable.Value) + } b.Linef("SET %s=%s", batchEscapeVariable(variable.Key), batchEscapeVariable(variable.Value)) } } diff --git a/shells/cmd_test.go b/shells/cmd_test.go index 6985e418bb2..b0e39a75b51 100644 --- a/shells/cmd_test.go +++ b/shells/cmd_test.go @@ -165,3 +165,69 @@ func Test_CmdWriter_cleanPath(t *testing.T) { }) } } + +// nolint:lll +func Test_CmdWriter_Variable(t *testing.T) { + tests := map[string]struct { + variable common.JobVariable + writer CmdWriter + wantLinux, wantWindows string + }{ + "file var, relative path": { + variable: common.JobVariable{Key: "KEY", Value: "the secret", File: true}, + writer: CmdWriter{TemporaryPath: "foo/bar"}, + // nolint:lll + wantLinux: "md \"foo\\\\bar\" 2>NUL 1>NUL\r\necho the secret > %CD%\\foo\\bar\\KEY\r\nSET KEY=%CD%\\foo\\bar\\KEY\r\n", + wantWindows: "md \"foo\\\\bar\" 2>NUL 1>NUL\r\necho the secret > %CD%\\foo\\bar\\KEY\r\nSET KEY=%CD%\\foo\\bar\\KEY\r\n", + }, + "file var, absolute path": { + variable: common.JobVariable{Key: "KEY", Value: "the secret", File: true}, + writer: CmdWriter{TemporaryPath: "/foo/bar"}, + // nolint:lll + wantLinux: "md \"\\\\foo\\\\bar\" 2>NUL 1>NUL\r\necho the secret > \\foo\\bar\\KEY\r\nSET KEY=\\foo\\bar\\KEY\r\n", + wantWindows: "md \"\\\\foo\\\\bar\" 2>NUL 1>NUL\r\necho the secret > %CD%\\foo\\bar\\KEY\r\nSET KEY=%CD%\\foo\\bar\\KEY\r\n", + }, + "file var, absolute path with drive": { + variable: common.JobVariable{Key: "KEY", Value: "the secret", File: true}, + writer: CmdWriter{TemporaryPath: "C:/foo/bar"}, + // nolint:lll + wantLinux: "md \"C:\\\\foo\\\\bar\" 2>NUL 1>NUL\r\necho the secret > %CD%\\C:\\foo\\bar\\KEY\r\nSET KEY=%CD%\\C:\\foo\\bar\\KEY\r\n", + wantWindows: "md \"C:\\\\foo\\\\bar\" 2>NUL 1>NUL\r\necho the secret > C:\\foo\\bar\\KEY\r\nSET KEY=C:\\foo\\bar\\KEY\r\n", + }, + "tmp file var, relative path": { + variable: common.JobVariable{Key: "KEY", Value: "foo/bar/KEY2"}, + writer: CmdWriter{TemporaryPath: "foo/bar"}, + wantLinux: "SET KEY=%%CD%%\\foo\\bar\\KEY2\r\n", + wantWindows: "SET KEY=%%CD%%\\foo\\bar\\KEY2\r\n", + }, + "tmp file var, absolute path": { + variable: common.JobVariable{Key: "KEY", Value: "/foo/bar/KEY2"}, + writer: CmdWriter{TemporaryPath: "/foo/bar"}, + wantLinux: "SET KEY=\\foo\\bar\\KEY2\r\n", + wantWindows: "SET KEY=%%CD%%\\foo\\bar\\KEY2\r\n", + }, + "tmp file var, absolute path with drive": { + variable: common.JobVariable{Key: "KEY", Value: "C:/foo/bar/KEY2"}, + writer: CmdWriter{TemporaryPath: "C:/foo/bar"}, + wantLinux: "SET KEY=%%CD%%\\C:\\foo\\bar\\KEY2\r\n", + wantWindows: "SET KEY=C:\\foo\\bar\\KEY2\r\n", + }, + "regular var": { + variable: common.JobVariable{Key: "KEY", Value: "VALUE"}, + writer: CmdWriter{TemporaryPath: "C:/foo/bar"}, + wantLinux: "SET KEY=VALUE\r\n", + wantWindows: "SET KEY=VALUE\r\n", + }, + } + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + tt.writer.Variable(tt.variable) + if runtime.GOOS == OSWindows { + assert.Equal(t, tt.wantWindows, tt.writer.String()) + } else { + assert.Equal(t, tt.wantLinux, tt.writer.String()) + } + }) + } +} -- GitLab From 00794d3bf28004d4eb8e5c647d2e5ed1a0861f40 Mon Sep 17 00:00:00 2001 From: Axel von Bertoldi Date: Wed, 7 Sep 2022 14:54:12 -0600 Subject: [PATCH 11/19] [pwsh] Refactor power shell writer TmpFile() method --- shells/powershell.go | 11 +++++++++-- shells/powershell_test.go | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/shells/powershell.go b/shells/powershell.go index 32af28a0247..0d17529aa8c 100644 --- a/shells/powershell.go +++ b/shells/powershell.go @@ -222,8 +222,15 @@ func (p *PsWriter) TmpFile(name string) string { return p.Join(p.TemporaryPath, name) } - filePath := p.Absolute(p.Join(p.TemporaryPath, name)) - return p.fromSlash(filePath) + return p.cleanPath(p.Join(p.TemporaryPath, name)) +} + +func (p *PsWriter) cleanPath(name string) string { + if p.resolvePaths { + return name + } + + return p.fromSlash(p.Absolute(name)) } func (p *PsWriter) fromSlash(path string) string { diff --git a/shells/powershell_test.go b/shells/powershell_test.go index ef58bb81e7c..eb5c63280a7 100644 --- a/shells/powershell_test.go +++ b/shells/powershell_test.go @@ -473,3 +473,39 @@ func TestPowershell_GenerateScript(t *testing.T) { }) } } + +func Test_PsWriter_cleanPath(t *testing.T) { + tests := map[string]struct { + path, wantLinux, wantWindows string + }{ + "relative path": { + path: "foo/bar/KEY", + wantLinux: "$CurrentDirectory\\foo\\bar\\KEY", + wantWindows: "$CurrentDirectory\\foo\\bar\\KEY", + }, + "absolute path": { + path: "/foo/bar/KEY", + wantLinux: "\\foo\\bar\\KEY", + wantWindows: "$CurrentDirectory\\foo\\bar\\KEY", + }, + "absolute path with drive": { + path: "C:/foo/bar/KEY", + wantLinux: "$CurrentDirectory\\C:\\foo\\bar\\KEY", + wantWindows: "C:\\foo\\bar\\KEY", + }, + } + + bw := PsWriter{TemporaryPath: "foo/bar"} + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + got := bw.cleanPath(tt.path) + + if runtime.GOOS == OSWindows { + assert.Equal(t, tt.wantWindows, got) + } else { + assert.Equal(t, tt.wantLinux, got) + } + }) + } +} -- GitLab From c143c15aa3c3550177732f2dd57a9dcff893564f Mon Sep 17 00:00:00 2001 From: Axel von Bertoldi Date: Wed, 7 Sep 2022 14:55:02 -0600 Subject: [PATCH 12/19] [pwsh] Add isTmpFile() method to power shell writer --- shells/powershell.go | 4 ++++ shells/powershell_test.go | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/shells/powershell.go b/shells/powershell.go index 0d17529aa8c..86af1a61137 100644 --- a/shells/powershell.go +++ b/shells/powershell.go @@ -249,6 +249,10 @@ func (p *PsWriter) EnvVariableKey(name string) string { return fmt.Sprintf("$%s", name) } +func (p *PsWriter) isTmpFile(path string) bool { + return strings.HasPrefix(path, p.TemporaryPath) +} + func (p *PsWriter) Variable(variable common.JobVariable) { if variable.File { variableFile := p.TmpFile(variable.Key) diff --git a/shells/powershell_test.go b/shells/powershell_test.go index eb5c63280a7..c9a1a6d2320 100644 --- a/shells/powershell_test.go +++ b/shells/powershell_test.go @@ -4,6 +4,7 @@ package shells import ( "fmt" + "path" "runtime" "strings" "testing" @@ -474,6 +475,25 @@ func TestPowershell_GenerateScript(t *testing.T) { } } +func Test_PsWriter_isTmpFile(t *testing.T) { + tmpDir := "/foo/bar" + bw := PsWriter{TemporaryPath: tmpDir} + + tests := map[string]struct { + path string + want bool + }{ + "tmp file var": {path: path.Join(tmpDir, "BAZ"), want: true}, + "not tmp file var": {path: "bla bla bla", want: false}, + } + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + assert.Equal(t, tt.want, bw.isTmpFile(tt.path)) + }) + } +} + func Test_PsWriter_cleanPath(t *testing.T) { tests := map[string]struct { path, wantLinux, wantWindows string -- GitLab From 9e9e94e9b5a046aabffa3a50a74d04a64334442a Mon Sep 17 00:00:00 2001 From: Axel von Bertoldi Date: Wed, 7 Sep 2022 14:55:28 -0600 Subject: [PATCH 13/19] [pwsh] Do the right thing with file variable alias variables --- shells/powershell.go | 4 ++ shells/powershell_test.go | 95 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) diff --git a/shells/powershell.go b/shells/powershell.go index 86af1a61137..35271af7d76 100644 --- a/shells/powershell.go +++ b/shells/powershell.go @@ -264,6 +264,10 @@ func (p *PsWriter) Variable(variable common.JobVariable) { ) p.Linef("$%s=%s", variable.Key, p.resolvePath(variableFile)) } else { + if p.isTmpFile(variable.Value) { + variable.Value = p.cleanPath(variable.Value) + } + p.Linef("$%s=%s", variable.Key, psQuoteVariable(variable.Value)) } diff --git a/shells/powershell_test.go b/shells/powershell_test.go index c9a1a6d2320..1e5608966b5 100644 --- a/shells/powershell_test.go +++ b/shells/powershell_test.go @@ -529,3 +529,98 @@ func Test_PsWriter_cleanPath(t *testing.T) { }) } } + +// nolint:lll +func Test_PsWriter_Variable(t *testing.T) { + tests := map[string]struct { + variable common.JobVariable + writer PsWriter + wantLinux, wantWindows string + }{ + "file var, relative path": { + variable: common.JobVariable{Key: "KEY", Value: "the secret", File: true}, + writer: PsWriter{TemporaryPath: "foo/bar"}, + wantLinux: "$CurrentDirectory = (Resolve-Path ./).PathNew-Item -ItemType directory -Force -Path \"foo\\bar\" | out-null[System.IO.File]::WriteAllText(\"$CurrentDirectory\\foo\\bar\\KEY\", \"the secret\")$KEY=\"$CurrentDirectory\\foo\\bar\\KEY\"$env:KEY=$KEY", + wantWindows: "$CurrentDirectory = (Resolve-Path .\\).PathNew-Item -ItemType directory -Force -Path \"foo\\bar\" | out-null[System.IO.File]::WriteAllText(\"$CurrentDirectory\\foo\\bar\\KEY\", \"the secret\")$KEY=\"$CurrentDirectory\\foo\\bar\\KEY\"$env:KEY=$KEY", + }, + "file var, absolute path": { + variable: common.JobVariable{Key: "KEY", Value: "the secret", File: true}, + writer: PsWriter{TemporaryPath: "/foo/bar"}, + wantLinux: "New-Item -ItemType directory -Force -Path \"\\foo\\bar\" | out-null[System.IO.File]::WriteAllText(\"\\foo\\bar\\KEY\", \"the secret\")$KEY=\"\\foo\\bar\\KEY\"$env:KEY=$KEY", + wantWindows: "$CurrentDirectory = (Resolve-Path .\\).PathNew-Item -ItemType directory -Force -Path \"\\foo\\bar\" | out-null[System.IO.File]::WriteAllText(\"$CurrentDirectory\\foo\\bar\\KEY\", \"the secret\")$KEY=\"$CurrentDirectory\\foo\\bar\\KEY\"$env:KEY=$KEY", + }, + "file var, absolute path with drive": { + variable: common.JobVariable{Key: "KEY", Value: "the secret", File: true}, + writer: PsWriter{TemporaryPath: "C:/foo/bar"}, + wantLinux: "$CurrentDirectory = (Resolve-Path ./).PathNew-Item -ItemType directory -Force -Path \"C:\\foo\\bar\" | out-null[System.IO.File]::WriteAllText(\"$CurrentDirectory\\C:\\foo\\bar\\KEY\", \"the secret\")$KEY=\"$CurrentDirectory\\C:\\foo\\bar\\KEY\"$env:KEY=$KEY", + wantWindows: "New-Item -ItemType directory -Force -Path \"C:\\foo\\bar\" | out-null[System.IO.File]::WriteAllText(\"C:\\foo\\bar\\KEY\", \"the secret\")$KEY=\"C:\\foo\\bar\\KEY\"$env:KEY=$KEY", + }, + "tmp file var, relative path": { + variable: common.JobVariable{Key: "KEY", Value: "foo/bar/KEY2"}, + writer: PsWriter{TemporaryPath: "foo/bar"}, + wantLinux: "$CurrentDirectory = (Resolve-Path ./).Path$KEY=\"`$CurrentDirectory\\foo\\bar\\KEY2\"$env:KEY=$KEY", + wantWindows: "$CurrentDirectory = (Resolve-Path .\\).Path$KEY=\"`$CurrentDirectory\\foo\\bar\\KEY2\"$env:KEY=$KEY", + }, + "tmp file var, absolute path": { + variable: common.JobVariable{Key: "KEY", Value: "/foo/bar/KEY2"}, + writer: PsWriter{TemporaryPath: "/foo/bar"}, + wantLinux: "$KEY=\"\\foo\\bar\\KEY2\"$env:KEY=$KEY", + wantWindows: "$CurrentDirectory = (Resolve-Path .\\).Path$KEY=\"`$CurrentDirectory\\foo\\bar\\KEY2\"$env:KEY=$KEY", + }, + "regular var": { + variable: common.JobVariable{Key: "KEY", Value: "VALUE"}, + writer: PsWriter{TemporaryPath: "C:/foo/bar"}, + wantLinux: "$KEY=\"VALUE\"$env:KEY=$KEY", + wantWindows: "$KEY=\"VALUE\"$env:KEY=$KEY", + }, + + "file var, relative path, resolvePaths": { + variable: common.JobVariable{Key: "KEY", Value: "the secret", File: true}, + writer: PsWriter{TemporaryPath: "foo/bar", resolvePaths: true}, + wantLinux: "New-Item -ItemType directory -Force -Path $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\"foo/bar\") | out-null[System.IO.File]::WriteAllText($ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\"foo/bar/KEY\"), \"the secret\")$KEY=$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\"foo/bar/KEY\")$env:KEY=$KEY", + wantWindows: "New-Item -ItemType directory -Force -Path $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\"foo/bar\") | out-null[System.IO.File]::WriteAllText($ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\"foo/bar/KEY\"), \"the secret\")$KEY=$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\"foo/bar/KEY\")$env:KEY=$KEY", + }, + "file var, absolute path, resolvePaths": { + variable: common.JobVariable{Key: "KEY", Value: "the secret", File: true}, + writer: PsWriter{TemporaryPath: "/foo/bar", resolvePaths: true}, + wantLinux: "New-Item -ItemType directory -Force -Path $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\"/foo/bar\") | out-null[System.IO.File]::WriteAllText($ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\"/foo/bar/KEY\"), \"the secret\")$KEY=$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\"/foo/bar/KEY\")$env:KEY=$KEY", + wantWindows: "New-Item -ItemType directory -Force -Path $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\"/foo/bar\") | out-null[System.IO.File]::WriteAllText($ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\"/foo/bar/KEY\"), \"the secret\")$KEY=$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\"/foo/bar/KEY\")$env:KEY=$KEY", + }, + "file var, absolute path with drive, resolvePaths": { + variable: common.JobVariable{Key: "KEY", Value: "the secret", File: true}, + writer: PsWriter{TemporaryPath: "C:/foo/bar", resolvePaths: true}, + wantLinux: "New-Item -ItemType directory -Force -Path $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\"C:/foo/bar\") | out-null[System.IO.File]::WriteAllText($ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\"C:/foo/bar/KEY\"), \"the secret\")$KEY=$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\"C:/foo/bar/KEY\")$env:KEY=$KEY", + wantWindows: "New-Item -ItemType directory -Force -Path $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\"C:/foo/bar\") | out-null[System.IO.File]::WriteAllText($ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\"C:/foo/bar/KEY\"), \"the secret\")$KEY=$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath(\"C:/foo/bar/KEY\")$env:KEY=$KEY", + }, + "tmp file var, relative path, resolvePaths": { + variable: common.JobVariable{Key: "KEY", Value: "foo/bar/KEY2"}, + writer: PsWriter{TemporaryPath: "foo/bar", resolvePaths: true}, + wantLinux: "$KEY=\"foo/bar/KEY2\"$env:KEY=$KEY", + wantWindows: "$KEY=\"foo/bar/KEY2\"$env:KEY=$KEY", + }, + "tmp file var, absolute path, resolvePaths": { + variable: common.JobVariable{Key: "KEY", Value: "/foo/bar/KEY2"}, + writer: PsWriter{TemporaryPath: "/foo/bar", resolvePaths: true}, + wantLinux: "$KEY=\"/foo/bar/KEY2\"$env:KEY=$KEY", + wantWindows: "$KEY=\"/foo/bar/KEY2\"$env:KEY=$KEY", + }, + "tmp file var, absolute path with drive, resolvePaths": { + variable: common.JobVariable{Key: "KEY", Value: "C:/foo/bar/KEY2"}, + writer: PsWriter{TemporaryPath: "C:/foo/bar", resolvePaths: true}, + wantLinux: "$KEY=\"C:/foo/bar/KEY2\"$env:KEY=$KEY", + wantWindows: "$KEY=\"C:/foo/bar/KEY2\"$env:KEY=$KEY", + }, + } + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + tt.writer.Variable(tt.variable) + + if runtime.GOOS == OSWindows { + assert.Equal(t, tt.wantWindows, tt.writer.String()) + } else { + assert.Equal(t, tt.wantLinux, tt.writer.String()) + } + }) + } +} -- GitLab From a362379b49ee752bbf2302cd04792e58c1fcf567 Mon Sep 17 00:00:00 2001 From: Axel von Bertoldi Date: Thu, 13 Oct 2022 12:36:05 -0600 Subject: [PATCH 14/19] [buildtest] Integration test util for expanded file variables This is intended to be called from actual tests. Thanks to @ajwalker for the code. --- common/buildtest/variables.go | 52 +++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 common/buildtest/variables.go diff --git a/common/buildtest/variables.go b/common/buildtest/variables.go new file mode 100644 index 00000000000..ffcc8db088d --- /dev/null +++ b/common/buildtest/variables.go @@ -0,0 +1,52 @@ +package buildtest + +import ( + "regexp" + "runtime" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gitlab.com/gitlab-org/gitlab-runner/common" +) + +func RunBuildWithExpandedFileVariable(t *testing.T, config *common.RunnerConfig, setup BuildSetupFn) { + resp, err := common.GetRemoteSuccessfulBuildPrintVars( + config.Shell, + "MY_FILE_VARIABLE", + "MY_EXPANDED_FILE_VARIABLE", + "RUNNER_TEMP_PROJECT_DIR", + ) + require.NoError(t, err) + + build := &common.Build{ + JobResponse: resp, + Runner: config, + } + + build.Variables = append( + build.Variables, + common.JobVariable{Key: "MY_FILE_VARIABLE", Value: "FILE_CONTENTS", File: true}, + common.JobVariable{Key: "MY_EXPANDED_FILE_VARIABLE", Value: "${MY_FILE_VARIABLE}_FOOBAR"}, + ) + + if setup != nil { + setup(build) + } + + out, err := RunBuildReturningOutput(t, build) + require.NoError(t, err) + + matches := regexp.MustCompile(`RUNNER_TEMP_PROJECT_DIR=([^\$%].*)`).FindStringSubmatch(out) + require.Equal(t, 2, len(matches)) + + assert.NotRegexp(t, "MY_EXPANDED_FILE_VARIABLE=.*FILE_CONTENTS_FOOBAR", out) + + if runtime.GOOS == "windows" { + tmpPath := strings.TrimRight(matches[1], "\r") + assert.Contains(t, out, "MY_EXPANDED_FILE_VARIABLE="+tmpPath+"\\MY_FILE_VARIABLE_FOOBAR") + } else { + assert.Contains(t, out, "MY_EXPANDED_FILE_VARIABLE="+matches[1]+"/MY_FILE_VARIABLE_FOOBAR") + } +} -- GitLab From aba33f49a92fb2714ddfefd9d3094c006497264f Mon Sep 17 00:00:00 2001 From: Axel von Bertoldi Date: Thu, 13 Oct 2022 12:37:29 -0600 Subject: [PATCH 15/19] [shell] Integration test for file variable expansion Thanks to @ajwalker for this code. --- executors/shell/shell_integration_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/executors/shell/shell_integration_test.go b/executors/shell/shell_integration_test.go index b100b190143..e1e59c6e724 100644 --- a/executors/shell/shell_integration_test.go +++ b/executors/shell/shell_integration_test.go @@ -330,6 +330,13 @@ func TestBuildMasking(t *testing.T) { }) } +func TestBuildExpandedFileVariable(t *testing.T) { + shellstest.OnEachShell(t, func(t *testing.T, shell string) { + build := newBuild(t, common.JobResponse{}, shell) + buildtest.RunBuildWithExpandedFileVariable(t, build.Runner, nil) + }) +} + func TestBuildWithIndexLock(t *testing.T) { shellstest.OnEachShell(t, func(t *testing.T, shell string) { successfulBuild, err := common.GetSuccessfulBuild() -- GitLab From fdb414c9ca4688eb39324be1f517d28a7cd6588d Mon Sep 17 00:00:00 2001 From: Axel von Bertoldi Date: Thu, 13 Oct 2022 12:43:51 -0600 Subject: [PATCH 16/19] [docker] Integration test for file variable expansion Thanks to @ajwalker for this code. --- executors/docker/docker_command_integration_test.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/executors/docker/docker_command_integration_test.go b/executors/docker/docker_command_integration_test.go index 77408f4dfaa..f32441ea27a 100644 --- a/executors/docker/docker_command_integration_test.go +++ b/executors/docker/docker_command_integration_test.go @@ -626,6 +626,15 @@ func TestBuildMasking(t *testing.T) { buildtest.RunBuildWithMasking(t, getRunnerConfigForOS(t), nil) } +func TestBuildExpandedFileVariable(t *testing.T) { + helpers.SkipIntegrationTests(t, "docker", "info") + + shellstest.OnEachShell(t, func(t *testing.T, shell string) { + build := getBuildForOS(t, common.GetSuccessfulBuild) + buildtest.RunBuildWithExpandedFileVariable(t, build.Runner, nil) + }) +} + func TestDockerCommandTwoServicesFromOneImage(t *testing.T) { test.SkipIfGitLabCIOn(t, test.OSWindows) helpers.SkipIntegrationTests(t, "docker", "info") -- GitLab From cf5bc81bc7b34cb35ec7359f9f061259d48813ca Mon Sep 17 00:00:00 2001 From: Axel von Bertoldi Date: Thu, 13 Oct 2022 13:25:53 -0600 Subject: [PATCH 17/19] [kubernetes] Integration test for file variable expansion Thanks to @ajwalker for this code. --- executors/kubernetes/kubernetes_integration_test.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/executors/kubernetes/kubernetes_integration_test.go b/executors/kubernetes/kubernetes_integration_test.go index 9e75fd9e7bc..b99cf0d88ae 100644 --- a/executors/kubernetes/kubernetes_integration_test.go +++ b/executors/kubernetes/kubernetes_integration_test.go @@ -1966,6 +1966,15 @@ func TestKubernetesPwshFeatureFlag(t *testing.T) { } } +func TestBuildExpandedFileVariable(t *testing.T) { + helpers.SkipIntegrationTests(t, "kubectl", "cluster-info") + + shellstest.OnEachShell(t, func(t *testing.T, shell string) { + build := getTestBuild(t, common.GetRemoteSuccessfulBuild) + buildtest.RunBuildWithExpandedFileVariable(t, build.Runner, nil) + }) +} + func TestConflictingPullPolicies(t *testing.T) { helpers.SkipIntegrationTests(t, "kubectl", "cluster-info") -- GitLab From e2247746e35698f6e0ce4942d9601d27059c2a4f Mon Sep 17 00:00:00 2001 From: Axel von Bertoldi Date: Thu, 13 Oct 2022 13:44:17 -0600 Subject: [PATCH 18/19] [virtualbox] Integration test for file variable expansion Thanks to @ajwalker for this code. --- executors/virtualbox/virtualbox_integration_test.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/executors/virtualbox/virtualbox_integration_test.go b/executors/virtualbox/virtualbox_integration_test.go index e1c434f39ed..8994dbbf2c4 100644 --- a/executors/virtualbox/virtualbox_integration_test.go +++ b/executors/virtualbox/virtualbox_integration_test.go @@ -309,3 +309,12 @@ func TestCleanupProjectGitSubmoduleRecursive(t *testing.T) { untrackedSubSubmoduleFile, ) } + +func TestBuildExpandedFileVariable(t *testing.T) { + helpers.SkipIntegrationTests(t, vboxManage, "--version") + + shellstest.OnEachShell(t, func(t *testing.T, shell string) { + build := getTestBuild(t, common.GetRemoteSuccessfulBuild) + buildtest.RunBuildWithExpandedFileVariable(t, build.Runner, nil) + }) +} -- GitLab From afc52966efad6d95a97e70e638a95bd0bbe6d7a7 Mon Sep 17 00:00:00 2001 From: Axel von Bertoldi Date: Thu, 13 Oct 2022 13:45:28 -0600 Subject: [PATCH 19/19] [parallels] Integration test for file variable expansion Thanks to @ajwalker for this code. --- executors/parallels/parallels_integration_test.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/executors/parallels/parallels_integration_test.go b/executors/parallels/parallels_integration_test.go index af07ae36dfa..6dbd824a7fb 100644 --- a/executors/parallels/parallels_integration_test.go +++ b/executors/parallels/parallels_integration_test.go @@ -309,3 +309,12 @@ func TestCleanupProjectGitSubmoduleRecursive(t *testing.T) { untrackedSubSubmoduleFile, ) } + +func TestBuildExpandedFileVariable(t *testing.T) { + helpers.SkipIntegrationTests(t, prlCtl, "--version") + + shellstest.OnEachShell(t, func(t *testing.T, shell string) { + build := getTestBuild(t, common.GetRemoteSuccessfulBuild) + buildtest.RunBuildWithExpandedFileVariable(t, build.Runner, nil) + }) +} -- GitLab