Commit f82bcaa8 authored by James Lopez's avatar James Lopez

refactored attempts stuff to use new build stages

parent 912b244a
Pipeline #5357485 passed with stages
in 28 minutes and 48 seconds
......@@ -187,13 +187,13 @@ func (b *Build) executeScript(executor Executor, abort chan interface{}) error {
err := b.executeStage(BuildStagePrepare, executor, abort)
if err == nil {
err = b.executeStage(BuildStageGetSources, executor, abort)
err = b.attemptExecuteStage(BuildStageGetSources, executor, abort, b.GetGetSourcesAttempts())
}
if err == nil {
err = b.executeStage(BuildStageDownloadArtifacts, executor, abort)
err = b.attemptExecuteStage(BuildStageDownloadArtifacts, executor, abort, b.GetDownloadArtifactsAttempts())
}
if err == nil {
err = b.executeStage(BuildStageRestoreCache, executor, abort)
err = b.attemptExecuteStage(BuildStageRestoreCache, executor, abort, b.GetRestoreCacheAttempts())
}
if err == nil {
......@@ -217,6 +217,18 @@ func (b *Build) executeScript(executor Executor, abort chan interface{}) error {
return err
}
func (b *Build) attemptExecuteStage(buildStage BuildStage, executor Executor, abort chan interface{}, attempts int) (err error) {
if attempts < 1 || attempts > 10 {
return fmt.Errorf("Number of attempts out of the range [1, 10] for stage: %s", buildStage)
}
for attempt := 0; attempt < attempts; attempt++ {
if err = b.executeStage(buildStage, executor, abort); err == nil {
return
}
}
return
}
func (b *Build) run(executor Executor) (err error) {
b.CurrentState = BuildRunRuntimeRunning
......@@ -402,3 +414,27 @@ func (b *Build) IsDebugTraceEnabled() bool {
func (b *Build) GetDockerAuthConfig() string {
return b.GetAllVariables().Get("DOCKER_AUTH_CONFIG")
}
func (b *Build) GetGetSourcesAttempts() int {
retries, err := strconv.Atoi(b.GetAllVariables().Get("GET_SOURCES_ATTEMPTS"))
if err != nil {
return DefaultGetSourcesAttempts
}
return retries
}
func (b *Build) GetDownloadArtifactsAttempts() int {
retries, err := strconv.Atoi(b.GetAllVariables().Get("ARTIFACT_DOWNLOAD_ATTEMPTS"))
if err != nil {
return DefaultArtifactDownloadAttempts
}
return retries
}
func (b *Build) GetRestoreCacheAttempts() int {
retries, err := strconv.Atoi(b.GetAllVariables().Get("RESTORE_CACHE_ATTEMPTS"))
if err != nil {
return DefaultRestoreCacheAttempts
}
return retries
}
......@@ -172,7 +172,7 @@ func TestRunFailure(t *testing.T) {
// Fail a build script
e.On("Shell").Return(&ShellScriptInfo{Shell: "script-shell"})
e.On("Run", mock.Anything).Return(errors.New("build fail")).Times(3)
e.On("Run", mock.Anything).Return(errors.New("build fail"))
e.On("Finish", errors.New("build fail")).Return().Once()
RegisterExecutor("build-run-run-failure", &p)
......@@ -187,8 +187,120 @@ func TestRunFailure(t *testing.T) {
},
},
}
err = build.Run(&Config{}, &Trace{Writer: os.Stdout})
assert.EqualError(t, err, "build fail")
}
func TestGetSourcesRunFailure(t *testing.T) {
e := MockExecutor{}
defer e.AssertExpectations(t)
p := MockExecutorProvider{}
defer p.AssertExpectations(t)
// Create executor
p.On("Create").Return(&e).Once()
// Prepare plan
e.On("Prepare", mock.Anything, mock.Anything, mock.Anything).Return(nil)
e.On("Cleanup").Return()
// Fail a build script
e.On("Shell").Return(&ShellScriptInfo{Shell: "script-shell"})
e.On("Run", mock.Anything).Return(nil).Once()
e.On("Run", mock.Anything).Return(errors.New("build fail")).Times(3)
e.On("Finish", errors.New("build fail")).Return().Once()
RegisterExecutor("build-get-sources-run-failure", &p)
successfulBuild, err := GetSuccessfulBuild()
assert.NoError(t, err)
build := &Build{
GetBuildResponse: successfulBuild,
Runner: &RunnerConfig{
RunnerSettings: RunnerSettings{
Executor: "build-get-sources-run-failure",
},
},
}
build.Variables = append(build.Variables, BuildVariable{Key: "GET_SOURCES_ATTEMPTS", Value: "3"})
err = build.Run(&Config{}, &Trace{Writer: os.Stdout})
assert.EqualError(t, err, "build fail")
}
func TestArtifactDownloadRunFailure(t *testing.T) {
e := MockExecutor{}
defer e.AssertExpectations(t)
p := MockExecutorProvider{}
defer p.AssertExpectations(t)
// Create executor
p.On("Create").Return(&e).Once()
// Prepare plan
e.On("Prepare", mock.Anything, mock.Anything, mock.Anything).Return(nil)
e.On("Cleanup").Return()
// Fail a build script
e.On("Shell").Return(&ShellScriptInfo{Shell: "script-shell"})
e.On("Run", mock.Anything).Return(nil).Times(2)
e.On("Run", mock.Anything).Return(errors.New("build fail")).Times(3)
e.On("Finish", errors.New("build fail")).Return().Once()
RegisterExecutor("build-artifacts-run-failure", &p)
successfulBuild, err := GetSuccessfulBuild()
assert.NoError(t, err)
build := &Build{
GetBuildResponse: successfulBuild,
Runner: &RunnerConfig{
RunnerSettings: RunnerSettings{
Executor: "build-artifacts-run-failure",
},
},
}
build.Variables = append(build.Variables, BuildVariable{Key: "ARTIFACT_DOWNLOAD_ATTEMPTS", Value: "3"})
err = build.Run(&Config{}, &Trace{Writer: os.Stdout})
assert.EqualError(t, err, "build fail")
}
func TestRestoreCacheRunFailure(t *testing.T) {
e := MockExecutor{}
defer e.AssertExpectations(t)
p := MockExecutorProvider{}
defer p.AssertExpectations(t)
// Create executor
p.On("Create").Return(&e).Once()
// Prepare plan
e.On("Prepare", mock.Anything, mock.Anything, mock.Anything).Return(nil)
e.On("Cleanup").Return()
// Fail a build script
e.On("Shell").Return(&ShellScriptInfo{Shell: "script-shell"})
e.On("Run", mock.Anything).Return(nil).Times(3)
e.On("Run", mock.Anything).Return(errors.New("build fail")).Times(3)
e.On("Finish", errors.New("build fail")).Return().Once()
RegisterExecutor("build-cache-run-failure", &p)
successfulBuild, err := GetSuccessfulBuild()
assert.NoError(t, err)
build := &Build{
GetBuildResponse: successfulBuild,
Runner: &RunnerConfig{
RunnerSettings: RunnerSettings{
Executor: "build-cache-run-failure",
},
},
}
build.Variables = append(build.Variables, BuildVariable{Key: "PRE_BUILD_ATTEMPTS", Value: "3"})
build.Variables = append(build.Variables, BuildVariable{Key: "RESTORE_CACHE_ATTEMPTS", Value: "3"})
err = build.Run(&Config{}, &Trace{Writer: os.Stdout})
assert.EqualError(t, err, "build fail")
}
......@@ -208,8 +320,9 @@ func TestRunWrongAttempts(t *testing.T) {
// Fail a build script
e.On("Shell").Return(&ShellScriptInfo{Shell: "script-shell"})
e.On("Run", mock.Anything).Return(errors.New("Number of attempts out of the range [1, 10]"))
e.On("Finish", errors.New("Number of attempts out of the range [1, 10]")).Return()
e.On("Run", mock.Anything).Return(nil).Once()
e.On("Run", mock.Anything).Return(errors.New("Number of attempts out of the range [1, 10] for stage: get_sources"))
e.On("Finish", errors.New("Number of attempts out of the range [1, 10] for stage: get_sources")).Return()
RegisterExecutor("build-run-attempt-failure", &p)
......@@ -224,9 +337,9 @@ func TestRunWrongAttempts(t *testing.T) {
},
}
build.Variables = append(build.Variables, BuildVariable{Key: "PRE_BUILD_ATTEMPTS", Value: "0"})
build.Variables = append(build.Variables, BuildVariable{Key: "GET_SOURCES_ATTEMPTS", Value: "0"})
err = build.Run(&Config{}, &Trace{Writer: os.Stdout})
assert.EqualError(t, err, "Number of attempts out of the range [1, 10]")
assert.EqualError(t, err, "Number of attempts out of the range [1, 10] for stage: get_sources")
}
func TestRunSuccessOnSecondAttempt(t *testing.T) {
......@@ -244,6 +357,7 @@ func TestRunSuccessOnSecondAttempt(t *testing.T) {
// Run script successfully
e.On("Shell").Return(&ShellScriptInfo{Shell: "script-shell"})
e.On("Run", mock.Anything).Return(nil)
e.On("Run", mock.Anything).Return(errors.New("build fail")).Once()
e.On("Run", mock.Anything).Return(nil)
......@@ -260,7 +374,7 @@ func TestRunSuccessOnSecondAttempt(t *testing.T) {
},
}
build.Variables = append(build.Variables, BuildVariable{Key: "PRE_BUILD_ATTEMPTS", Value: "3"})
build.Variables = append(build.Variables, BuildVariable{Key: "GET_SOURCES_ATTEMPTS", Value: "3"})
err = build.Run(&Config{}, &Trace{Writer: os.Stdout})
assert.NoError(t, err)
}
......@@ -16,6 +16,8 @@ const ShutdownTimeout = 30
const DefaultOutputLimit = 4096 // 4MB in kilobytes
const ForceTraceSentInterval = 30 * time.Second
const PreparationRetries = 3
const DefaultPreBuildAttempts = 1
const DefaultGetSourcesAttempts = 1
const DefaultArtifactDownloadAttempts = 1
const DefaultRestoreCacheAttempts = 1
var PreparationRetryInterval = 3 * time.Second
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