Skip to content
This repository has been archived by the owner on May 8, 2024. It is now read-only.

Commit

Permalink
Support $CIRRUS_CLONE_DIR
Browse files Browse the repository at this point in the history
Fixes #106
  • Loading branch information
fkorotkov committed Apr 19, 2021
1 parent b348387 commit c28f440
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 18 deletions.
6 changes: 6 additions & 0 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ task:
task:
name: Test (Linux)
alias: test-linux
env:
CIRRUS_WORKING_DIR: /tmp/custom-working-dir
TMPDIR: /tmp
modules_cache:
fingerprint_script: cat go.sum
folder: $GOPATH/pkg/mod
Expand All @@ -40,6 +43,9 @@ docker_builder:
task:
name: Test (macOS)
alias: test-macos
env:
CIRRUS_WORKING_DIR: /tmp/custom-working-dir
TMPDIR: /tmp
macos_instance:
image: big-sur-base
test_script:
Expand Down
59 changes: 41 additions & 18 deletions internal/executor/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,14 @@ func (executor *Executor) RunBuild() {
return
}

environment := getExpandedScriptEnvironment(executor, response.Environment)
environment := executor.GetExpandedScriptEnvironment(response.Environment)

if _, ok := environment["OS"]; !ok {
if _, ok := os.LookupEnv("OS"); !ok {
environment["OS"] = runtime.GOOS
}
}
environment["CIRRUS_OS"] = runtime.GOOS

workingDir, ok := environment["CIRRUS_WORKING_DIR"]
if ok {
Expand Down Expand Up @@ -178,35 +185,50 @@ func BoundedCommands(commands []*api.Command, fromName, toName string) []*api.Co
return commands[left:right]
}

func getExpandedScriptEnvironment(executor *Executor, responseEnvironment map[string]string) map[string]string {
func (executor *Executor) GetExpandedScriptEnvironment(responseEnvironment map[string]string) map[string]string {
if responseEnvironment == nil {
responseEnvironment = make(map[string]string)
}

if _, ok := responseEnvironment["OS"]; !ok {
if _, ok := os.LookupEnv("OS"); !ok {
responseEnvironment["OS"] = runtime.GOOS
_, hasCloneDir := responseEnvironment["CIRRUS_CLONE_DIR"]
_, hasWorkingDir := responseEnvironment["CIRRUS_WORKING_DIR"]

if hasCloneDir && hasWorkingDir {
// Do nothing. User did override both dirs
}
if hasCloneDir && !hasWorkingDir {
// Only clone was overridden. Make sure $CIRRUS_WORKING_DIR is set
responseEnvironment["CIRRUS_WORKING_DIR"] = responseEnvironment["CIRRUS_CLONE_DIR"]
}
if !hasCloneDir && hasWorkingDir {
// User did override working dir
if !strings.Contains(responseEnvironment["CIRRUS_WORKING_DIR"], "CIRRUS_CLONE_DIR") {
// If working dir doesn't depend on clone dir then we can default clone dir to the one provided by user
responseEnvironment["CIRRUS_CLONE_DIR"] = "$CIRRUS_WORKING_DIR"
}
}
responseEnvironment["CIRRUS_OS"] = runtime.GOOS

if !hasCloneDir && !hasWorkingDir {
// none of the dirs are explicitly set. Make sure they'll be the same
responseEnvironment["CIRRUS_WORKING_DIR"] = "$CIRRUS_CLONE_DIR"
}

// Use directory created by the persistent worker if CIRRUS_WORKING_DIR
// was not overridden in the task specification by the user
_, hasWorkingDir := responseEnvironment["CIRRUS_WORKING_DIR"]
if !hasWorkingDir && executor.preCreatedWorkingDir != "" {
responseEnvironment["CIRRUS_WORKING_DIR"] = executor.preCreatedWorkingDir
responseEnvironment["CIRRUS_CLONE_DIR"] = executor.preCreatedWorkingDir
}

if _, ok := responseEnvironment["CIRRUS_WORKING_DIR"]; !ok {
if _, ok := responseEnvironment["CIRRUS_CLONE_DIR"]; !ok {
defaultTempDirPath := filepath.Join(os.TempDir(), "cirrus-ci-build")
if _, err := os.Stat(defaultTempDirPath); os.IsNotExist(err) {
responseEnvironment["CIRRUS_WORKING_DIR"] = filepath.ToSlash(defaultTempDirPath)
responseEnvironment["CIRRUS_CLONE_DIR"] = filepath.ToSlash(defaultTempDirPath)
} else if executor.commandFrom != "" {
// Default folder exists and we continue execution. Therefore we need to use it.
responseEnvironment["CIRRUS_WORKING_DIR"] = filepath.ToSlash(defaultTempDirPath)
responseEnvironment["CIRRUS_CLONE_DIR"] = filepath.ToSlash(defaultTempDirPath)
} else {
uniqueTempDirPath, _ := ioutil.TempDir(os.TempDir(), fmt.Sprintf("cirrus-task-%d", executor.taskIdentification.TaskId))
responseEnvironment["CIRRUS_WORKING_DIR"] = filepath.ToSlash(uniqueTempDirPath)
responseEnvironment["CIRRUS_CLONE_DIR"] = filepath.ToSlash(uniqueTempDirPath)
}
}

Expand Down Expand Up @@ -386,7 +408,7 @@ func (executor *Executor) CloneRepository(env map[string]string) bool {

logUploader.Write([]byte("Using built-in Git...\n"))

working_dir := env["CIRRUS_WORKING_DIR"]
cloneDir := env["CIRRUS_CLONE_DIR"]
change := env["CIRRUS_CHANGE_IN_REPO"]
branch := env["CIRRUS_BRANCH"]
pr_number, is_pr := env["CIRRUS_PR"]
Expand Down Expand Up @@ -426,7 +448,7 @@ func (executor *Executor) CloneRepository(env map[string]string) bool {
var repo *git.Repository

if is_pr {
repo, err = git.PlainInit(working_dir, false)
repo, err = git.PlainInit(cloneDir, false)
if err != nil {
logUploader.Write([]byte(fmt.Sprintf("\nFailed to init repository: %s!", err)))
return false
Expand Down Expand Up @@ -498,13 +520,14 @@ func (executor *Executor) CloneRepository(env map[string]string) bool {
}
logUploader.Write([]byte(fmt.Sprintf("\nCloning %s...\n", cloneOptions.ReferenceName)))

repo, err = git.PlainClone(working_dir, false, &cloneOptions)
EnsureFolderExists(cloneDir)
repo, err = git.PlainClone(cloneDir, false, &cloneOptions)

if err != nil && retryableCloneError(err) {
logUploader.Write([]byte(fmt.Sprintf("\nRetryable error '%s' while cloning! Trying again...", err)))
os.RemoveAll(working_dir)
EnsureFolderExists(working_dir)
repo, err = git.PlainClone(working_dir, false, &cloneOptions)
os.RemoveAll(cloneDir)
EnsureFolderExists(cloneDir)
repo, err = git.PlainClone(cloneDir, false, &cloneOptions)
}

if err != nil {
Expand Down
84 changes: 84 additions & 0 deletions internal/executor/executor_unix_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// +build !windows !freebsd

package executor_test

import (
"github.com/cirruslabs/cirrus-ci-agent/internal/executor"
"github.com/stretchr/testify/require"
"testing"
)

func TestGetExpandedScriptEnvironment(t *testing.T) {
e := &executor.Executor{}
examples := []struct {
Description string
Given, Expected map[string]string
}{
{
"empty",
map[string]string{},
map[string]string{
"CIRRUS_CLONE_DIR": "/tmp/cirrus-ci-build",
"CIRRUS_WORKING_DIR": "/tmp/cirrus-ci-build",
},
},
{
"only working",
map[string]string{
"CIRRUS_WORKING_DIR": "/tmp/foo",
},
map[string]string{
"CIRRUS_CLONE_DIR": "/tmp/foo",
"CIRRUS_WORKING_DIR": "/tmp/foo",
},
},
{
"only working (monorepo)",
map[string]string{
"CIRRUS_WORKING_DIR": "$CIRRUS_CLONE_DIR/foo",
},
map[string]string{
"CIRRUS_CLONE_DIR": "/tmp/cirrus-ci-build",
"CIRRUS_WORKING_DIR": "/tmp/cirrus-ci-build/foo",
},
},
{
"only clone",
map[string]string{
"CIRRUS_CLONE_DIR": "/tmp/foo",
},
map[string]string{
"CIRRUS_CLONE_DIR": "/tmp/foo",
"CIRRUS_WORKING_DIR": "/tmp/foo",
},
},
{
"both",
map[string]string{
"CIRRUS_CLONE_DIR": "/tmp/foo",
"CIRRUS_WORKING_DIR": "/tmp/foo",
},
map[string]string{
"CIRRUS_CLONE_DIR": "/tmp/foo",
"CIRRUS_WORKING_DIR": "/tmp/foo",
},
},
{
"both (monorepo)",
map[string]string{
"CIRRUS_CLONE_DIR": "/tmp/foo",
"CIRRUS_WORKING_DIR": "$CIRRUS_CLONE_DIR/bar",
},
map[string]string{
"CIRRUS_CLONE_DIR": "/tmp/foo",
"CIRRUS_WORKING_DIR": "/tmp/foo/bar",
},
},
}

for _, example := range examples {
t.Run(example.Description, func(t *testing.T) {
require.Equal(t, example.Expected, e.GetExpandedScriptEnvironment(example.Given))
})
}
}

0 comments on commit c28f440

Please sign in to comment.