Commit 7ba2b026 authored by Tomasz Maczukin's avatar Tomasz Maczukin

Merge branch...

Merge branch '4080-build-environment-no-longer-cleaned-up-with-gitlab-runner-11-9-0-on-windows' into 'master'

Use delayed variable expansion for error check in cmd

Closes #4080

See merge request gitlab-org/gitlab-runner!1260
parents 83d4b48d a8f328d2
...@@ -20,7 +20,7 @@ import ( ...@@ -20,7 +20,7 @@ import (
) )
const ( const (
repoRemoteURL = "https://gitlab.com/gitlab-org/ci-cd/tests/gitlab-test.git" RepoRemoteURL = "https://gitlab.com/gitlab-org/ci-cd/tests/gitlab-test.git"
repoRefType = RefTypeBranch repoRefType = RefTypeBranch
...@@ -76,7 +76,7 @@ func GetRemoteSuccessfulBuild() (JobResponse, error) { ...@@ -76,7 +76,7 @@ func GetRemoteSuccessfulBuild() (JobResponse, error) {
func GetRemoteSuccessfulLFSBuild() (JobResponse, error) { func GetRemoteSuccessfulLFSBuild() (JobResponse, error) {
response, err := GetRemoteBuildResponse("echo Hello World") response, err := GetRemoteBuildResponse("echo Hello World")
response.GitInfo = GetLFSGitInfo(repoRemoteURL) response.GitInfo = GetLFSGitInfo(RepoRemoteURL)
return response, err return response, err
} }
...@@ -187,7 +187,7 @@ func getBuildResponse(repoURL string, commands []string) JobResponse { ...@@ -187,7 +187,7 @@ func getBuildResponse(repoURL string, commands []string) JobResponse {
} }
func GetRemoteBuildResponse(commands ...string) (JobResponse, error) { func GetRemoteBuildResponse(commands ...string) (JobResponse, error) {
return getBuildResponse(repoRemoteURL, commands), nil return getBuildResponse(RepoRemoteURL, commands), nil
} }
func GetLocalBuildResponse(commands ...string) (JobResponse, error) { func GetLocalBuildResponse(commands ...string) (JobResponse, error) {
......
...@@ -30,5 +30,7 @@ change hidden behind the feature flag disabled a corresponding environment varia ...@@ -30,5 +30,7 @@ change hidden behind the feature flag disabled a corresponding environment varia
|--------------------------------------|---------------|------------|--------------------|-------------| |--------------------------------------|---------------|------------|--------------------|-------------|
| `FF_K8S_USE_ENTRYPOINT_OVER_COMMAND` | `true` | ✓ | 12.0 | Enables [the fix][mr-1010] for entrypoint configuration when `kubernetes` executor is used. | | `FF_K8S_USE_ENTRYPOINT_OVER_COMMAND` | `true` | ✓ | 12.0 | Enables [the fix][mr-1010] for entrypoint configuration when `kubernetes` executor is used. |
| `FF_DOCKER_HELPER_IMAGE_V2` | `false` | ✓ | 12.0 | Enable the helper image to use the new commands when [helper_image](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnersdocker-section) is specified. This will start using the new API that will be used in 12.0 and stop showing the warning message in the build log. | | `FF_DOCKER_HELPER_IMAGE_V2` | `false` | ✓ | 12.0 | Enable the helper image to use the new commands when [helper_image](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnersdocker-section) is specified. This will start using the new API that will be used in 12.0 and stop showing the warning message in the build log. |
| `FF_CMD_DISABLE_DELAYED_ERROR_LEVEL_EXPANSION` | `false` | ✓ | TBA | Disables [EnableDelayedExpansion](https://ss64.com/nt/delayedexpansion.html) for error checking for when using [Window Batch](https://docs.gitlab.com/runner/shells/#windows-batch) shell. |
[mr-1010]: https://gitlab.com/gitlab-org/gitlab-runner/merge_requests/1010 [mr-1010]: https://gitlab.com/gitlab-org/gitlab-runner/merge_requests/1010
...@@ -779,6 +779,47 @@ func TestBuildWithGitSSLAndStrategyFetch(t *testing.T) { ...@@ -779,6 +779,47 @@ func TestBuildWithGitSSLAndStrategyFetch(t *testing.T) {
}) })
} }
func TestBuildWithUntrackedDirFromPreviousBuild(t *testing.T) {
shellstest.OnEachShell(t, func(t *testing.T, shell string) {
successfulBuild, err := common.GetRemoteSuccessfulBuild()
assert.NoError(t, err)
build, cleanup := newBuild(t, successfulBuild, shell)
defer cleanup()
build.Variables = append(build.Variables, common.JobVariable{Key: "GIT_STRATEGY", Value: "fetch"})
out, err := runBuildReturningOutput(t, build)
assert.NoError(t, err)
assert.Contains(t, out, "Created fresh repository")
err = os.MkdirAll(fmt.Sprintf("%s/.test", build.FullProjectDir()), 0644)
require.NoError(t, err)
out, err = runBuildReturningOutput(t, build)
assert.NoError(t, err)
assert.Contains(t, out, "Removing .test/")
})
}
func TestBuildChangesBranchesWhenFetchingRepo(t *testing.T) {
shellstest.OnEachShell(t, func(t *testing.T, shell string) {
successfulBuild, err := common.GetRemoteSuccessfulBuild()
assert.NoError(t, err)
build, cleanup := newBuild(t, successfulBuild, shell)
defer cleanup()
build.Variables = append(build.Variables, common.JobVariable{Key: "GIT_STRATEGY", Value: "fetch"})
out, err := runBuildReturningOutput(t, build)
assert.NoError(t, err)
assert.Contains(t, out, "Created fresh repository")
// Another build using the same repo but different branch.
build.GitInfo = common.GetLFSGitInfo(common.RepoRemoteURL)
out, err = runBuildReturningOutput(t, build)
assert.NoError(t, err)
assert.Contains(t, out, "Checking out 2371dd05 as add-lfs-object...")
})
}
func TestInteractiveTerminal(t *testing.T) { func TestInteractiveTerminal(t *testing.T) {
cases := []struct { cases := []struct {
app string app string
......
...@@ -154,6 +154,7 @@ func (b *AbstractShell) writeRefspecFetchCmd(w ShellWriter, build *common.Build, ...@@ -154,6 +154,7 @@ func (b *AbstractShell) writeRefspecFetchCmd(w ShellWriter, build *common.Build,
w.Command("git", "init", projectDir, "--template", templateDir) w.Command("git", "init", projectDir, "--template", templateDir)
w.Cd(projectDir) w.Cd(projectDir)
b.writeGitCleanup(w)
// fetching // fetching
if depth > 0 { if depth > 0 {
...@@ -167,7 +168,6 @@ func (b *AbstractShell) writeRefspecFetchCmd(w ShellWriter, build *common.Build, ...@@ -167,7 +168,6 @@ func (b *AbstractShell) writeRefspecFetchCmd(w ShellWriter, build *common.Build,
w.Notice("Created fresh repository.") w.Notice("Created fresh repository.")
w.Else() w.Else()
w.Command("git", "remote", "set-url", "origin", build.GetRemoteURL()) w.Command("git", "remote", "set-url", "origin", build.GetRemoteURL())
b.writeGitCleanup(w)
w.EndIf() w.EndIf()
fetchArgs := []string{"fetch", "origin", "--prune"} fetchArgs := []string{"fetch", "origin", "--prune"}
......
...@@ -20,8 +20,9 @@ type CmdShell struct { ...@@ -20,8 +20,9 @@ type CmdShell struct {
type CmdWriter struct { type CmdWriter struct {
bytes.Buffer bytes.Buffer
TemporaryPath string TemporaryPath string
indent int indent int
disableDelayedErrorLevelExpansion bool
} }
func batchQuote(text string) string { func batchQuote(text string) string {
...@@ -80,10 +81,19 @@ func (b *CmdWriter) Unindent() { ...@@ -80,10 +81,19 @@ func (b *CmdWriter) Unindent() {
} }
func (b *CmdWriter) checkErrorLevel() { func (b *CmdWriter) checkErrorLevel() {
b.Line("IF %errorlevel% NEQ 0 exit /b %errorlevel%") errCheck := "IF !errorlevel! NEQ 0 exit /b !errorlevel!"
b.Line(b.updateErrLevelCheck(errCheck))
b.Line("") b.Line("")
} }
func (b *CmdWriter) updateErrLevelCheck(errCheck string) string {
if b.disableDelayedErrorLevelExpansion {
return strings.Replace(errCheck, "!", "%", -1)
}
return errCheck
}
func (b *CmdWriter) Command(command string, arguments ...string) { func (b *CmdWriter) Command(command string, arguments ...string) {
b.Line(b.buildCommand(command, arguments...)) b.Line(b.buildCommand(command, arguments...))
b.checkErrorLevel() b.checkErrorLevel()
...@@ -134,14 +144,16 @@ func (b *CmdWriter) IfFile(path string) { ...@@ -134,14 +144,16 @@ func (b *CmdWriter) IfFile(path string) {
func (b *CmdWriter) IfCmd(cmd string, arguments ...string) { func (b *CmdWriter) IfCmd(cmd string, arguments ...string) {
cmdline := b.buildCommand(cmd, arguments...) cmdline := b.buildCommand(cmd, arguments...)
b.Line(fmt.Sprintf("%s 2>NUL 1>NUL", cmdline)) b.Line(fmt.Sprintf("%s 2>NUL 1>NUL", cmdline))
b.Line("IF %errorlevel% EQU 0 (") errCheck := "IF !errorlevel! EQU 0 ("
b.Line(b.updateErrLevelCheck(errCheck))
b.Indent() b.Indent()
} }
func (b *CmdWriter) IfCmdWithOutput(cmd string, arguments ...string) { func (b *CmdWriter) IfCmdWithOutput(cmd string, arguments ...string) {
cmdline := b.buildCommand(cmd, arguments...) cmdline := b.buildCommand(cmd, arguments...)
b.Line(fmt.Sprintf("%s", cmdline)) b.Line(fmt.Sprintf("%s", cmdline))
b.Line("IF %errorlevel% EQU 0 (") errCheck := "IF !errorlevel! EQU 0 ("
b.Line(b.updateErrLevelCheck(errCheck))
b.Indent() b.Indent()
} }
...@@ -243,7 +255,8 @@ func (b *CmdShell) GetConfiguration(info common.ShellScriptInfo) (script *common ...@@ -243,7 +255,8 @@ func (b *CmdShell) GetConfiguration(info common.ShellScriptInfo) (script *common
func (b *CmdShell) GenerateScript(buildStage common.BuildStage, info common.ShellScriptInfo) (script string, err error) { func (b *CmdShell) GenerateScript(buildStage common.BuildStage, info common.ShellScriptInfo) (script string, err error) {
w := &CmdWriter{ w := &CmdWriter{
TemporaryPath: info.Build.FullProjectDir() + ".tmp", TemporaryPath: info.Build.FullProjectDir() + ".tmp",
disableDelayedErrorLevelExpansion: info.Build.IsFeatureFlagOn("FF_CMD_DISABLE_DELAYED_ERROR_LEVEL_EXPANSION"),
} }
if buildStage == common.BuildStagePrepare { if buildStage == common.BuildStagePrepare {
......
...@@ -2,6 +2,7 @@ package shells ...@@ -2,6 +2,7 @@ package shells
import ( import (
"fmt" "fmt"
"strconv"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
...@@ -50,7 +51,7 @@ func TestCMD_CDShellEscapes(t *testing.T) { ...@@ -50,7 +51,7 @@ func TestCMD_CDShellEscapes(t *testing.T) {
} { } {
writer := &CmdWriter{} writer := &CmdWriter{}
writer.Cd(tc.in) writer.Cd(tc.in)
expected := fmt.Sprintf("cd /D \"%s\"\r\nIF %%errorlevel%% NEQ 0 exit /b %%errorlevel%%\r\n\r\n", tc.out) expected := fmt.Sprintf("cd /D \"%s\"\r\nIF !errorlevel! NEQ 0 exit /b !errorlevel!\r\n\r\n", tc.out)
assert.Equal(t, expected, writer.String(), "case %d", i) assert.Equal(t, expected, writer.String(), "case %d", i)
} }
} }
...@@ -59,12 +60,31 @@ func TestCMD_CommandShellEscapes(t *testing.T) { ...@@ -59,12 +60,31 @@ func TestCMD_CommandShellEscapes(t *testing.T) {
writer := &CmdWriter{} writer := &CmdWriter{}
writer.Command("foo", "x&(y)") writer.Command("foo", "x&(y)")
assert.Equal(t, "\"foo\" \"x^&(y)\"\r\nIF %errorlevel% NEQ 0 exit /b %errorlevel%\r\n\r\n", writer.String()) assert.Equal(t, "\"foo\" \"x^&(y)\"\r\nIF !errorlevel! NEQ 0 exit /b !errorlevel!\r\n\r\n", writer.String())
} }
func TestCMD_IfCmdShellEscapes(t *testing.T) { func TestCMD_IfCmdShellEscapes(t *testing.T) {
writer := &CmdWriter{} writer := &CmdWriter{}
writer.IfCmd("foo", "x&(y)") writer.IfCmd("foo", "x&(y)")
assert.Equal(t, "\"foo\" \"x^&(y)\" 2>NUL 1>NUL\r\nIF %errorlevel% EQU 0 (\r\n", writer.String()) assert.Equal(t, "\"foo\" \"x^&(y)\" 2>NUL 1>NUL\r\nIF !errorlevel! EQU 0 (\r\n", writer.String())
}
func TestCMD_DelayedExpanstionFeatureFlag(t *testing.T) {
cases := map[bool]string{
true: "\"foo\"\r\nIF %errorlevel% NEQ 0 exit /b %errorlevel%\r\n\r\n",
false: "\"foo\"\r\nIF !errorlevel! NEQ 0 exit /b !errorlevel!\r\n\r\n",
}
for disableDelayedErrorLevelExpansion, expectedCmd := range cases {
t.Run("disableDelayedErrorLevelExpansion_"+strconv.FormatBool(disableDelayedErrorLevelExpansion), func(t *testing.T) {
writer := &CmdWriter{
disableDelayedErrorLevelExpansion: disableDelayedErrorLevelExpansion,
}
writer.Command("foo")
assert.Equal(t, expectedCmd, writer.String())
})
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment