Commit c9bd231f authored by Steve Azzopardi's avatar Steve Azzopardi Committed by Kamil Trzciński

Add custom clone path for the build

When the user specifies `GIT_CLONE_PATH` environment variable inside of
the `.gitlab-ci.yml` if the path is valid it is used to clone and build.

`GIT_CLONE_PATH` takes precedence over the configured build dir and
the default build dir.

Closes #2211
parent 5140f2e7
......@@ -107,6 +107,10 @@ func (s *RegisterCommand) askDocker() {
}
s.Docker.Image = s.ask("docker-image", "Please enter the default Docker image (e.g. ruby:2.1):")
s.CustomBuildDir = &common.CustomBuildDir{
Enable: true,
}
for _, volume := range s.Docker.Volumes {
parts := strings.Split(volume, ":")
if parts[len(parts)-1] == "/cache" {
......@@ -195,6 +199,9 @@ func (s *RegisterCommand) askExecutorOptions() {
switch s.Executor {
case "kubernetes":
s.Kubernetes = kubernetes
s.CustomBuildDir = &common.CustomBuildDir{
Enable: true,
}
case "docker+machine":
s.Machine = machine
s.Docker = docker
......@@ -237,6 +244,9 @@ func (s *RegisterCommand) askExecutorOptions() {
// old CLI options/env variables were used.
func (s *RegisterCommand) prepareCache() {
cache := s.RunnerConfig.Cache
if cache == nil {
return
}
// Called to log deprecated usage, if old cli options/env variables are used
cache.Path = cache.GetPath()
......
......@@ -15,6 +15,9 @@ import (
"gitlab.com/ayufan/golang-cli-helpers"
"gitlab.com/gitlab-org/gitlab-runner/common"
_ "gitlab.com/gitlab-org/gitlab-runner/executors/docker/machine" // Register docker+machine as executor
_ "gitlab.com/gitlab-org/gitlab-runner/executors/kubernetes" // Register kubernetes as executor
"gitlab.com/gitlab-org/gitlab-runner/helpers/ssh"
)
func setupDockerRegisterCommand(dockerConfig *common.DockerConfig) *RegisterCommand {
......@@ -189,3 +192,217 @@ func TestRegisterCacheDeprecatedOptions_EnvVariables(t *testing.T) {
assert.Contains(t, output, "S3_BUCKET_LOCATION environment variables is deprecated and will be removed in GitLab Runner 12.0. Please use CACHE_S3_BUCKET_LOCATION instead")
assert.Contains(t, output, "S3_CACHE_INSECURE environment variables is deprecated and will be removed in GitLab Runner 12.0. Please use CACHE_S3_INSECURE instead")
}
func TestDefaultExecutorConfiguration(t *testing.T) {
tests := []struct {
executor string
expectedConfig common.RunnerConfig
}{
{
executor: "kubernetes",
expectedConfig: common.RunnerConfig{
Name: "ci-test",
RunnerCredentials: common.RunnerCredentials{
URL: "https://gitlab.com/",
Token: "test-token",
},
RunnerSettings: common.RunnerSettings{
Executor: "kubernetes",
CustomBuildDir: &common.CustomBuildDir{
Enable: true,
},
},
},
},
{
executor: "docker+machine",
expectedConfig: common.RunnerConfig{
Name: "ci-test",
RunnerCredentials: common.RunnerCredentials{
URL: "https://gitlab.com/",
Token: "test-token",
},
RunnerSettings: common.RunnerSettings{
Executor: "docker+machine",
CustomBuildDir: &common.CustomBuildDir{
Enable: true,
},
Docker: &common.DockerConfig{
Image: "ruby:2.1",
Volumes: []string{"/cache"},
},
},
},
},
{
executor: "docker-ssh+machine",
expectedConfig: common.RunnerConfig{
Name: "ci-test",
RunnerCredentials: common.RunnerCredentials{
URL: "https://gitlab.com/",
Token: "test-token",
},
RunnerSettings: common.RunnerSettings{
Executor: "docker-ssh+machine",
CustomBuildDir: &common.CustomBuildDir{
Enable: true,
},
Docker: &common.DockerConfig{
Image: "ruby:2.1",
Volumes: []string{"/cache"},
},
SSH: &ssh.Config{
User: "user",
Password: "password",
IdentityFile: "/home/user/.ssh/id_rsa",
},
},
},
},
{
executor: "docker",
expectedConfig: common.RunnerConfig{
Name: "ci-test",
RunnerCredentials: common.RunnerCredentials{
URL: "https://gitlab.com/",
Token: "test-token",
},
RunnerSettings: common.RunnerSettings{
Executor: "docker",
CustomBuildDir: &common.CustomBuildDir{
Enable: true,
},
Docker: &common.DockerConfig{
Image: "ruby:2.1",
Volumes: []string{"/cache"},
},
},
},
},
{
executor: "docker-ssh",
expectedConfig: common.RunnerConfig{
Name: "ci-test",
RunnerCredentials: common.RunnerCredentials{
URL: "https://gitlab.com/",
Token: "test-token",
},
RunnerSettings: common.RunnerSettings{
Executor: "docker-ssh",
CustomBuildDir: &common.CustomBuildDir{
Enable: true,
},
Docker: &common.DockerConfig{
Image: "ruby:2.1",
Volumes: []string{"/cache"},
},
SSH: &ssh.Config{
User: "user",
Password: "password",
IdentityFile: "/home/user/.ssh/id_rsa",
},
},
},
},
{
executor: "ssh",
expectedConfig: common.RunnerConfig{
Name: "ci-test",
RunnerCredentials: common.RunnerCredentials{
URL: "https://gitlab.com/",
Token: "test-token",
},
RunnerSettings: common.RunnerSettings{
Executor: "ssh",
SSH: &ssh.Config{
User: "user",
Password: "password",
Host: "my.server.com",
Port: "22",
IdentityFile: "/home/user/.ssh/id_rsa",
},
},
},
},
{
executor: "parallels",
expectedConfig: common.RunnerConfig{
Name: "ci-test",
RunnerCredentials: common.RunnerCredentials{
URL: "https://gitlab.com/",
Token: "test-token",
},
RunnerSettings: common.RunnerSettings{
Executor: "parallels",
SSH: &ssh.Config{
Host: "my.server.com",
Port: "22",
},
Parallels: &common.ParallelsConfig{
BaseName: "my-parallels-vm",
},
},
},
},
{
executor: "virtualbox",
expectedConfig: common.RunnerConfig{
Name: "ci-test",
RunnerCredentials: common.RunnerCredentials{
URL: "https://gitlab.com/",
Token: "test-token",
},
RunnerSettings: common.RunnerSettings{
Executor: "virtualbox",
SSH: &ssh.Config{
User: "user",
Password: "password",
IdentityFile: "/home/user/.ssh/id_rsa",
},
VirtualBox: &common.VirtualBoxConfig{
BaseName: "my-virtualbox-vm",
},
},
},
},
}
for _, test := range tests {
t.Run(test.executor, func(t *testing.T) {
fs := flag.NewFlagSet("", flag.ExitOnError)
ctx := cli.NewContext(cli.NewApp(), fs, nil)
fs.String("url", "https://gitlab.com/", "")
fs.String("registration-token", "test-registration-token", "")
fs.String("name", "ci-test", "")
fs.String("tag-list", "ci,test", "")
fs.String("executor", test.executor, "")
fs.String("docker-image", "ruby:2.1", "")
fs.String("ssh-user", "user", "")
fs.String("ssh-password", "password", "")
fs.String("ssh-identity-file", "/home/user/.ssh/id_rsa", "")
fs.String("ssh-host", "my.server.com", "")
fs.String("ssh-port", "22", "")
fs.String("parallels-base-name", "my-parallels-vm", "")
fs.String("virtualbox-base-name", "my-virtualbox-vm", "")
registerRunnerRep := common.RegisterRunnerResponse{
Token: "test-token",
}
mockNetwork := &common.MockNetwork{}
mockNetwork.On("RegisterRunner", mock.Anything, mock.Anything).Return(&registerRunnerRep, true).Once()
s := &RegisterCommand{
context: ctx,
NonInteractive: true,
}
s.SSH = &ssh.Config{}
s.Parallels = &common.ParallelsConfig{}
s.VirtualBox = &common.VirtualBoxConfig{}
s.network = mockNetwork
s.Execute(ctx)
assert.Equal(t, test.expectedConfig, s.RunnerConfig)
})
}
}
......@@ -156,15 +156,29 @@ func (b *Build) FullProjectDir() string {
return helpers.ToSlash(b.BuildDir)
}
func (b *Build) StartBuild(rootDir, cacheDir string, sharedDir bool) {
func (b *Build) TmpProjectDir() string {
return helpers.ToSlash(b.BuildDir) + ".tmp"
}
func (b *Build) StartBuild(rootDir, cacheDir string, customDirAllowed, sharedDir bool) error {
b.RootDir = rootDir
b.BuildDir = path.Join(rootDir, b.ProjectUniqueDir(sharedDir))
b.CacheDir = path.Join(cacheDir, b.ProjectUniqueDir(false))
// Job Specific build dir
b.BuildDir = b.GetAllVariables().Get("GIT_CLONE_PATH")
if b.BuildDir != "" && !customDirAllowed {
return errors.New("setting GIT_CLONE_PATH is not allowed, enable `custom_build_dir` feature")
}
if b.BuildDir == "" {
b.BuildDir = path.Join(rootDir, b.ProjectUniqueDir(sharedDir))
}
// invalidate variables cache:
// as some variables are based on dynamic
// state after build starts
b.allVariables = nil
return nil
}
func (b *Build) executeStage(ctx context.Context, buildStage BuildStage, executor Executor) error {
......
......@@ -93,7 +93,7 @@ func TestBuildPredefinedVariables(t *testing.T) {
// We run everything once
e.On("Prepare", mock.Anything).
Return(func(options ExecutorPrepareOptions) error {
options.Build.StartBuild("/root/dir", "/cache/dir", false)
options.Build.StartBuild("/root/dir", "/cache/dir", false, false)
return nil
}).Once()
e.On("Finish", nil).Return().Once()
......@@ -901,6 +901,125 @@ func TestIsFeatureFlagOn(t *testing.T) {
}
}
func TestStartBuild(t *testing.T) {
type startBuildArgs struct {
rootDir string
cacheDir string
customBuildDir bool
sharedDir bool
}
tests := []struct {
name string
args startBuildArgs
jobVariables JobVariables
expectedBuildDir string
expectedCacheDir string
expectedError bool
}{
{
name: "no job specific build dir with no shared dir",
args: startBuildArgs{
rootDir: "/build",
cacheDir: "/cache",
customBuildDir: true,
sharedDir: false,
},
jobVariables: JobVariables{},
expectedBuildDir: "/build/test-namespace/test-repo",
expectedCacheDir: "/cache/test-namespace/test-repo",
expectedError: false,
},
{
name: "no job specified build dir with shared dir",
args: startBuildArgs{
rootDir: "/builds",
cacheDir: "/cache",
customBuildDir: true,
sharedDir: true,
},
jobVariables: JobVariables{},
expectedBuildDir: "/builds/1234/0/test-namespace/test-repo",
expectedCacheDir: "/cache/test-namespace/test-repo",
expectedError: false,
},
{
name: "job specific build dir with no shared dir",
args: startBuildArgs{
rootDir: "/builds",
cacheDir: "/cache",
customBuildDir: true,
sharedDir: false,
},
jobVariables: JobVariables{
{Key: "GIT_CLONE_PATH", Value: "/go/src/gitlab.com/test-namespace/test-repo", Public: true},
},
expectedBuildDir: "/go/src/gitlab.com/test-namespace/test-repo",
expectedCacheDir: "/cache/test-namespace/test-repo",
expectedError: false,
},
{
name: "job specific build dir with shared dir",
args: startBuildArgs{
rootDir: "/builds",
cacheDir: "/cache",
customBuildDir: true,
sharedDir: true,
},
jobVariables: JobVariables{
{Key: "GIT_CLONE_PATH", Value: "/go/src/gitlab.com/test-namespace/test-repo", Public: true},
},
expectedBuildDir: "/go/src/gitlab.com/test-namespace/test-repo",
expectedCacheDir: "/cache/test-namespace/test-repo",
expectedError: false,
},
{
name: "custom build disabled",
args: startBuildArgs{
rootDir: "/builds",
cacheDir: "/cache",
customBuildDir: false,
sharedDir: false,
},
jobVariables: JobVariables{
{Key: "GIT_CLONE_PATH", Value: "/go/src/gitlab.com/test-namespace/test-repo", Public: true},
},
expectedBuildDir: "/builds/test-namespace/test-repo",
expectedCacheDir: "/cache/test-namespace/test-repo",
expectedError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
build := Build{
JobResponse: JobResponse{
GitInfo: GitInfo{
RepoURL: "https://gitlab.com/test-namespace/test-repo.git",
},
Variables: tt.jobVariables,
},
Runner: &RunnerConfig{
RunnerCredentials: RunnerCredentials{
Token: "1234",
},
},
}
err := build.StartBuild(tt.args.rootDir, tt.args.cacheDir, tt.args.customBuildDir, tt.args.sharedDir)
if tt.expectedError {
assert.Error(t, err)
return
}
assert.NoError(t, err)
assert.Equal(t, tt.expectedBuildDir, build.BuildDir)
assert.Equal(t, tt.args.rootDir, build.RootDir)
assert.Equal(t, tt.expectedCacheDir, build.CacheDir)
})
}
}
func TestWaitForTerminal(t *testing.T) {
cases := []struct {
name string
......@@ -1109,3 +1228,61 @@ func TestGitCleanFlags(t *testing.T) {
})
}
}
func TestDefaultVariables(t *testing.T) {
tests := []struct {
name string
jobVariables JobVariables
rootDir string
key string
expectedValue string
}{
{
name: "get default CI_SERVER value",
jobVariables: JobVariables{},
rootDir: "/builds",
key: "CI_SERVER",
expectedValue: "yes",
},
{
name: "get default CI_PROJECT_DIR value",
jobVariables: JobVariables{},
rootDir: "/builds",
key: "CI_PROJECT_DIR",
expectedValue: "/builds/test-namespace/test-repo",
},
{
name: "get overwritten CI_PROJECT_DIR value",
jobVariables: JobVariables{
{Key: "GIT_CLONE_PATH", Value: "/go/src/gitlab.com/gitlab-org/gitlab-runner", Public: true},
},
rootDir: "/builds",
key: "CI_PROJECT_DIR",
expectedValue: "/go/src/gitlab.com/gitlab-org/gitlab-runner",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
build := Build{
JobResponse: JobResponse{
GitInfo: GitInfo{
RepoURL: "https://gitlab.com/test-namespace/test-repo.git",
},
Variables: test.jobVariables,
},
Runner: &RunnerConfig{
RunnerCredentials: RunnerCredentials{
Token: "1234",
},
},
}
err := build.StartBuild(test.rootDir, "/cache", true, false)
assert.NoError(t, err)
variable := build.GetAllVariables().Get(test.key)
assert.Equal(t, test.expectedValue, variable)
})
}
}
......@@ -278,13 +278,14 @@ type RunnerSettings struct {
Shell string `toml:"shell,omitempty" json:"shell" long:"shell" env:"RUNNER_SHELL" description:"Select bash, cmd or powershell"`
SSH *ssh.Config `toml:"ssh,omitempty" json:"ssh" group:"ssh executor" namespace:"ssh"`
Docker *DockerConfig `toml:"docker,omitempty" json:"docker" group:"docker executor" namespace:"docker"`
Parallels *ParallelsConfig `toml:"parallels,omitempty" json:"parallels" group:"parallels executor" namespace:"parallels"`
VirtualBox *VirtualBoxConfig `toml:"virtualbox,omitempty" json:"virtualbox" group:"virtualbox executor" namespace:"virtualbox"`
Cache *CacheConfig `toml:"cache,omitempty" json:"cache" group:"cache configuration" namespace:"cache"`
Machine *DockerMachine `toml:"machine,omitempty" json:"machine" group:"docker machine provider" namespace:"machine"`
Kubernetes *KubernetesConfig `toml:"kubernetes,omitempty" json:"kubernetes" group:"kubernetes executor" namespace:"kubernetes"`
CustomBuildDir *CustomBuildDir `toml:"custom_build_dir,omitempty" json:"custom_build_dir" group:"custom build dir configuration" namespace:"custom_build_dir"`
SSH *ssh.Config `toml:"ssh,omitempty" json:"ssh" group:"ssh executor" namespace:"ssh"`
Docker *DockerConfig `toml:"docker,omitempty" json:"docker" group:"docker executor" namespace:"docker"`
Parallels *ParallelsConfig `toml:"parallels,omitempty" json:"parallels" group:"parallels executor" namespace:"parallels"`
VirtualBox *VirtualBoxConfig `toml:"virtualbox,omitempty" json:"virtualbox" group:"virtualbox executor" namespace:"virtualbox"`
Cache *CacheConfig `toml:"cache,omitempty" json:"cache" group:"cache configuration" namespace:"cache"`
Machine *DockerMachine `toml:"machine,omitempty" json:"machine" group:"docker machine provider" namespace:"machine"`
Kubernetes *KubernetesConfig `toml:"kubernetes,omitempty" json:"kubernetes" group:"kubernetes executor" namespace:"kubernetes"`
}
type RunnerConfig struct {
......@@ -321,6 +322,10 @@ type Config struct {
Loaded bool `toml:"-"`
}
type CustomBuildDir struct {
Enable bool `toml:"enable,omitempty" json:"enable" long:"enable" env:"CUSTOM_BUILD_DIR_ENABLE" description:"Enable job specific build directories"`
}
func getDeprecatedStringSetting(setting string, tomlField string, envVariable string, tomlReplacement string, envReplacement string) string {
if setting != "" {
logrus.Warningf("%s setting is deprecated and will be removed in GitLab Runner 12.0. Please use %s instead", tomlField, tomlReplacement)
......
......@@ -743,6 +743,34 @@ which is based on its compilation data. After updating the Runner to a new versi
Runner will try to download the proper image. This of course means that the image should be uploaded to the registry
before upgrading the Runner, otherwise the jobs will start failing with a "No such image" error.
## The `[runners.custom_build_dir]` section
NOTE: **Note:**
[Introduced][gitlab-runner-876] in Gitlab Runner 11.1
This section defines [custom build directories][custom-build-dir-docs] parameters.
Please notice, that the feature - if not configured explicitly - will be
enabled by default for `kubernetes`, `docker`, `docker-ssh`, `docker+machine`
and `docker-ssh+machine` executors. It will be disabled by default for all other
executors.
The feature will be also disabled when _shared_ environments (`shell`, `ssh`
executors and all `docker*` executors when working directory is mounted
as host volume shared between jobs) will be used together with `concurrent = 1`
set in global section.
| Parameter | Type | Description |
|-----------|---------|-------------|
| `enable` | boolean | Allow user to define a custom build directory for a job |
Example:
```bash
[runners.custom_build_dir]
enable = true
```
## Note
If you'd like to deploy to multiple servers using GitLab CI, you can create a
......@@ -758,3 +786,5 @@ It depends on what you'd like to do.
[priv-example]: https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#define-an-image-from-a-private-container-registry
[variable]: https://docs.gitlab.com/ee/ci/variables/#variables
[cronvendor]: https://github.com/gorhill/cronexpr#implementation
[gitlab-runner-876]: https://gitlab.com/gitlab-org/gitlab-runner/merge_requests/876
[custom-build-dir-docs]: https://docs.gitlab.com/ee/ci/yaml/README.html#custom-build-directories
......@@ -22,6 +22,10 @@ To override the `~/builds` directory, specify the `builds_dir` option under
the `[[runners]]` section in
[`config.toml`](../configuration/advanced-configuration.md).
You can also define [custom build
directories](https://docs.gitlab.com/ce/ci/yaml/README.html#custom-build-directories) per job using the
`GIT_CLONE_PATH`.
## Create a new base virtual machine
1. Install [VirtualBox](https://www.virtualbox.org) and if running from Windows,
......
......@@ -103,9 +103,10 @@ func (s *commandExecutor) Run(cmd common.ExecutorCommand) error {
func init() {
options := executors.ExecutorOptions{
DefaultBuildsDir: "/builds",
DefaultCacheDir: "/cache",
SharedBuildsDir: false,
DefaultCustomBuildsDirEnabled: true,
DefaultBuildsDir: "/builds",
DefaultCacheDir: "/cache",
SharedBuildsDir: false,
Shell: common.ShellScriptInfo{
Shell: "bash",
Type: common.NormalShell,
......
......@@ -83,8 +83,9 @@ func (s *sshExecutor) Cleanup() {
func init() {
options := executors.ExecutorOptions{
DefaultBuildsDir: "builds",
SharedBuildsDir: false,
DefaultCustomBuildsDirEnabled: true,
DefaultBuildsDir: "builds",
SharedBuildsDir: false,
Shell: common.ShellScriptInfo{
Shell: "bash",
Type: common.LoginShell,
......
......@@ -8,11 +8,12 @@ import (
)
type ExecutorOptions struct {
DefaultBuildsDir string
DefaultCacheDir string
SharedBuildsDir bool
Shell common.ShellScriptInfo
ShowHostname bool
DefaultCustomBuildsDirEnabled bool
DefaultBuildsDir string
DefaultCacheDir string
SharedBuildsDir bool
Shell common.ShellScriptInfo
ShowHostname bool
}
type AbstractExecutor struct {
......@@ -64,8 +65,13 @@ func (e *AbstractExecutor) startBuild() error {
if cacheDir == "" {
cacheDir = e.DefaultCacheDir
}
e.Build.StartBuild(rootDir, cacheDir, e.SharedBuildsDir)
return nil
customBuildDir := e.DefaultCustomBuildsDirEnabled
if e.Config.CustomBuildDir != nil {
customBuildDir = e.Config.CustomBuildDir.Enable
}
return e.Build.StartBuild(rootDir, cacheDir,
customBuildDir, e.SharedBuildsDir)
}
func (e *AbstractExecutor) Shell() *common.ShellScriptInfo {
......
......@@ -26,9 +26,10 @@ import (
var (
executorOptions = executors.ExecutorOptions{
DefaultBuildsDir: "/builds",
DefaultCacheDir: "/cache",
SharedBuildsDir: false,
DefaultBuildsDir: "/builds",
DefaultCacheDir: "/cache",
DefaultCustomBuildsDirEnabled: true,
SharedBuildsDir: false,
Shell: common.ShellScriptInfo{
Shell: "bash",
Type: common.NormalShell,
......
......@@ -337,8 +337,9 @@ func (s *executor) Cleanup() {
func init() {
options := executors.ExecutorOptions{
DefaultBuildsDir: "builds",
SharedBuildsDir: false,
DefaultCustomBuildsDirEnabled: false,
DefaultBuildsDir: "builds",
SharedBuildsDir: false,
Shell: common.ShellScriptInfo{
Shell: "bash",
Type: common.LoginShell,
......
......@@ -135,9 +135,10 @@ func init() {
}
options := executors.ExecutorOptions{
DefaultBuildsDir: "$PWD/builds",
DefaultCacheDir: "$PWD/cache",
SharedBuildsDir: true,
DefaultCustomBuildsDirEnabled: false,
DefaultBuildsDir: "$PWD/builds",
DefaultCacheDir: "$PWD/cache",
SharedBuildsDir: true,
Shell: common.ShellScriptInfo{
Shell: common.GetDefaultShell(),
Type: common.LoginShell,
......
......@@ -64,8 +64,9 @@ func (s *executor) Cleanup() {
func init() {
options := executors.ExecutorOptions{
DefaultBuildsDir: "builds",
SharedBuildsDir: true,
DefaultCustomBuildsDirEnabled: false,
DefaultBuildsDir: "builds",
SharedBuildsDir: true,
Shell: common.ShellScriptInfo{
Shell: "bash",
Type: common.LoginShell,
......
......@@ -299,8 +299,9 @@ func (s *executor) Cleanup() {
func init() {
options := executors.ExecutorOptions{
DefaultBuildsDir: "builds",
SharedBuildsDir: false,
DefaultCustomBuildsDirEnabled: false,
DefaultBuildsDir: "builds",
SharedBuildsDir: false,
Shell: common.ShellScriptInfo{
Shell: "bash",
Type: common.LoginShell,
......
......@@ -241,7 +241,7 @@ func (b *BashShell) GetConfiguration(info common.ShellScriptInfo) (script *commo
func (b *BashShell) GenerateScript(buildStage common.BuildStage, info common.ShellScriptInfo) (script string, err error) {
w := &BashWriter{
TemporaryPath: info.Build.FullProjectDir() + ".tmp",
TemporaryPath: info.Build.TmpProjectDir(),
}
if buildStage == common.BuildStagePrepare {
......
......@@ -255,7 +255,7 @@ func (b *CmdShell) GetConfiguration(info common.ShellScriptInfo) (script *common
func (b *CmdShell) GenerateScript(buildStage common.BuildStage, info common.ShellScriptInfo) (script string, err error) {
w := &CmdWriter{
TemporaryPath: info.Build.FullProjectDir() + ".tmp",
TemporaryPath: info.Build.TmpProjectDir(),
disableDelayedErrorLevelExpansion: info.Build.IsFeatureFlagOn("FF_CMD_DISABLE_DELAYED_ERROR_LEVEL_EXPANSION"),
}
......