diff --git a/config/parser.go b/config/parser.go index 6d92b3f..a17864c 100644 --- a/config/parser.go +++ b/config/parser.go @@ -33,14 +33,14 @@ func getStageTypeModuleName(stageType string) string { return strings.ToLower(stageType) } -func Parse(configData *map[interface{}]interface{}) (*pipelines.Pipeline, error) { +func Parse(configData *map[interface{}]interface{}) (*pipelines.Resources, error) { envs := NewEnvVariables() return ParseWithSpecifiedEnvs(configData, envs) } -// TODO: need refactoring +// TODO: make parser process a struct (for simplifying redundant functions and reducing the number of function parameters) func ParseWithSpecifiedEnvs(configData *map[interface{}]interface{}, - envs *EnvVariables) (*pipelines.Pipeline, error) { + envs *EnvVariables) (*pipelines.Resources, error) { // parse service block serviceOps, ok := (*configData)["service"].(map[interface{}]interface{}) var repoService services.Service @@ -93,9 +93,7 @@ func ParseWithSpecifiedEnvs(configData *map[interface{}]interface{}, } // parse pipeline block - var pipeline *pipelines.Pipeline = &pipelines.Pipeline{ - Reporter: messenger, RepoService: repoService, Cleanup: cleanup, - } + var pipeline *pipelines.Pipeline = &pipelines.Pipeline{} pipelineData, ok := (*configData)["pipeline"].([]interface{}) if ok == false { @@ -108,7 +106,9 @@ func ParseWithSpecifiedEnvs(configData *map[interface{}]interface{}, for stageItem := stageList.Front(); stageItem != nil; stageItem = stageItem.Next() { pipeline.AddStage(stageItem.Value.(stages.Stage)) } - return pipeline, nil + var resources = &pipelines.Resources{Pipeline: pipeline, Cleanup: cleanup, Reporter: messenger, RepoService: repoService} + + return resources, nil } func mapMessenger(messengerMap map[interface{}]interface{}, envs *EnvVariables) (messengers.Messenger, error) { diff --git a/config/parser_test.go b/config/parser_test.go index 984f88a..8483187 100644 --- a/config/parser_test.go +++ b/config/parser_test.go @@ -27,8 +27,8 @@ import ( func TestParseFromFile(t *testing.T) { configData := ReadConfig("../tests/fixtures/pipeline.yml") - pipeline, err := Parse(configData) - actual := pipeline.Stages.Front().Value.(*stages.CommandStage).Command + resources, err := Parse(configData) + actual := resources.Pipeline.Stages.Front().Value.(*stages.CommandStage).Command assert.Equal(t, "echo \"hello, world\"", actual) assert.Nil(t, err) } @@ -60,10 +60,10 @@ func TestParseConfWithChildren(t *testing.T) { type: command command: echo "hello, world, command_stage_3_group_1"`)) result, err := Parse(configData) - assert.Equal(t, 1, result.Size()) + assert.Equal(t, 1, result.Pipeline.Size()) assert.Nil(t, err) - childStages := result.Stages.Front().Value.(stages.Stage).GetChildStages() + childStages := result.Pipeline.Stages.Front().Value.(stages.Stage).GetChildStages() assert.Equal(t, 2, childStages.Len()) } @@ -73,7 +73,7 @@ func TestParseConfDefaultStageTypeIsCommand(t *testing.T) { command: echo "hello, world" `)) result, err := Parse(configData) - actual := result.Stages.Front().Value.(*stages.CommandStage).Command + actual := result.Pipeline.Stages.Front().Value.(*stages.CommandStage).Command assert.Equal(t, "echo \"hello, world\"", actual) assert.Nil(t, err) } @@ -86,7 +86,7 @@ func TestParseConfWithDirectory(t *testing.T) { directory: /usr/local `)) result, err := Parse(configData) - actual := result.Stages.Front().Value.(*stages.CommandStage).Directory + actual := result.Pipeline.Stages.Front().Value.(*stages.CommandStage).Directory assert.Nil(t, err) assert.Equal(t, "/usr/local", actual) } @@ -98,7 +98,7 @@ func TestParseConfWithShellScriptStage(t *testing.T) { file: ../stages/test_sample.sh `)) result, err := Parse(configData) - actual := result.Stages.Front().Value.(*stages.ShellScriptStage).File + actual := result.Pipeline.Stages.Front().Value.(*stages.ShellScriptStage).File assert.Equal(t, "../stages/test_sample.sh", actual) assert.Nil(t, err) } @@ -179,7 +179,7 @@ func TestParseConfWithEnvVariable(t *testing.T) { envs := NewEnvVariables() envs.Add("USER_NAME", "takahi-i") result, err := ParseWithSpecifiedEnvs(configData, envs) - actual := result.Stages.Front().Value.(*stages.CommandStage).Command + actual := result.Pipeline.Stages.Front().Value.(*stages.CommandStage).Command assert.Equal(t, "echo \"hello $USER_NAME\"", actual) assert.Nil(t, err) } @@ -205,7 +205,7 @@ func TestParseConfWithNoExistEnvVariable(t *testing.T) { envs := NewEnvVariables() envs.Add("USER_NAME", "takahi-i") result, err := ParseWithSpecifiedEnvs(configData, envs) - actual := result.Stages.Front().Value.(*stages.CommandStage).Command + actual := result.Pipeline.Stages.Front().Value.(*stages.CommandStage).Command assert.Equal(t, "echo \"hello $NO_SUCH_A_ENV_VARIABLE\"", actual) // NOTE: No env variable name is shown when there is no env variable assert.Nil(t, err) } @@ -240,8 +240,8 @@ func TestParseConfigWithDeprecatedProperties(t *testing.T) { command: echo "hello, world" `)) result, err := Parse(configData) - assert.Equal(t, 1, result.Size()) + assert.Equal(t, 1, result.Pipeline.Size()) assert.Nil(t, err) - actual := result.Stages.Front().Value.(*stages.CommandStage).Command + actual := result.Pipeline.Stages.Front().Value.(*stages.CommandStage).Command assert.Equal(t, "echo \"hello, world\"", actual) } diff --git a/engine/engine.go b/engine/engine.go index 7690687..32ca6a3 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -27,9 +27,9 @@ import ( ) type Engine struct { - Pipeline *pipelines.Pipeline - Opts *config.Opts + Resources *pipelines.Resources MonitorCh *chan stages.Mediator + Opts *config.Opts } type Result struct { @@ -45,8 +45,8 @@ func (r *Result) IsSucceeded() bool { } func (e *Engine) RunOnce() *Result { - pipe_result := e.executePipeline(e.Pipeline, "pipeline") - cleanup_result := e.executePipeline(e.Pipeline.Cleanup, "cleanup") + pipe_result := e.executePipeline(e.Resources.Pipeline, "pipeline") + cleanup_result := e.executePipeline(e.Resources.Cleanup, "cleanup") return &Result{Pipeline: &pipe_result, Cleanup: &cleanup_result} } @@ -92,7 +92,7 @@ func (e *Engine) ExecuteStage(stage stages.Stage) { result = false } log.Debugf("Stage execution results: %+v, %+v", stage.GetStageName(), result) - e.Pipeline.ReportStageResult(stage, result) + e.Resources.ReportStageResult(stage, result) mediator := stages.Mediator{States: make(map[string]string)} mediator.States[stage.GetStageName()] = fmt.Sprintf("%v", result) diff --git a/engine/engine_test.go b/engine/engine_test.go index 47f09e8..1f9c832 100644 --- a/engine/engine_test.go +++ b/engine/engine_test.go @@ -67,7 +67,7 @@ func execute(stage stages.Stage) stages.Mediator { mon := make(chan stages.Mediator) e := &Engine{ MonitorCh: &mon, - Pipeline: &pipelines.Pipeline{ + Resources: &pipelines.Resources{ Reporter: &messengers.FakeMessenger{}, }, } @@ -102,15 +102,16 @@ func execute(stage stages.Stage) stages.Mediator { } func TestRunOnce(t *testing.T) { - pipeline := &pipelines.Pipeline{ + resources := &pipelines.Resources{ Reporter: &messengers.FakeMessenger{}, + Pipeline: &pipelines.Pipeline{}, Cleanup: &pipelines.Pipeline{}, } - pipeline.AddStage(createCommandStage("echo foobar")) - pipeline.AddStage(createCommandStage("echo baz")) + resources.Pipeline.AddStage(createCommandStage("echo foobar")) + resources.Pipeline.AddStage(createCommandStage("echo baz")) monitorCh := make(chan stages.Mediator) engine := &Engine{ - Pipeline: pipeline, + Resources: resources, MonitorCh: &monitorCh, } result := engine.RunOnce() @@ -122,14 +123,15 @@ func TestRunOnce(t *testing.T) { } func TestRunOnceWithShellScriptStage(t *testing.T) { - pipeline := &pipelines.Pipeline{ + resources := &pipelines.Resources{ Reporter: &messengers.FakeMessenger{}, + Pipeline: &pipelines.Pipeline{}, Cleanup: &pipelines.Pipeline{}, } - pipeline.AddStage(createShellScriptStage("foobar-shell", "../stages/test_sample.sh")) + resources.Pipeline.AddStage(createShellScriptStage("foobar-shell", "../stages/test_sample.sh")) monitorCh := make(chan stages.Mediator) engine := &Engine{ - Pipeline: pipeline, + Resources: resources, MonitorCh: &monitorCh, } result := engine.RunOnce() @@ -141,17 +143,18 @@ func TestRunOnceWithShellScriptStage(t *testing.T) { } func TestRunOnceWithOptsOffStopOnAnyFailure(t *testing.T) { - pipeline := &pipelines.Pipeline{ + resources := &pipelines.Resources{ Reporter: &messengers.FakeMessenger{}, + Pipeline: &pipelines.Pipeline{}, Cleanup: &pipelines.Pipeline{}, } - pipeline.AddStage(createCommandStage("echo foobar")) - pipeline.AddStage(createCommandStage("thisiserrorcommand")) - pipeline.AddStage(createCommandStage("echo foobar2")) + resources.Pipeline.AddStage(createCommandStage("echo foobar")) + resources.Pipeline.AddStage(createCommandStage("thisiserrorcommand")) + resources.Pipeline.AddStage(createCommandStage("echo foobar2")) monitorCh := make(chan stages.Mediator) o := &config.Opts{StopOnAnyFailure: false} engine := &Engine{ - Pipeline: pipeline, + Resources: resources, MonitorCh: &monitorCh, Opts: o, } @@ -162,17 +165,18 @@ func TestRunOnceWithOptsOffStopOnAnyFailure(t *testing.T) { } func TestRunOnceWithOptsOnStopOnAnyFailure(t *testing.T) { - pipeline := &pipelines.Pipeline{ + resources := &pipelines.Resources{ Reporter: &messengers.FakeMessenger{}, + Pipeline: &pipelines.Pipeline{}, Cleanup: &pipelines.Pipeline{}, } - pipeline.AddStage(createCommandStage("echo foobar")) - pipeline.AddStage(createCommandStage("thisiserrorcommand")) - pipeline.AddStage(createCommandStage("echo foobar2")) + resources.Pipeline.AddStage(createCommandStage("echo foobar")) + resources.Pipeline.AddStage(createCommandStage("thisiserrorcommand")) + resources.Pipeline.AddStage(createCommandStage("echo foobar2")) monitorCh := make(chan stages.Mediator) o := &config.Opts{StopOnAnyFailure: true} engine := &Engine{ - Pipeline: pipeline, + Resources: resources, MonitorCh: &monitorCh, Opts: o, } @@ -186,17 +190,18 @@ func TestRunOnceWithOptsOnStopOnAnyFailure(t *testing.T) { } func TestRunOnceWithOnlyIfFailure(t *testing.T) { - pipeline := &pipelines.Pipeline{ + resources := &pipelines.Resources{ Reporter: &messengers.FakeMessenger{}, + Pipeline: &pipelines.Pipeline{}, Cleanup: &pipelines.Pipeline{}, } - pipeline.AddStage(createCommandStageWithOnlyIf("first", "echo first", "test 1 -lt 1")) - pipeline.AddStage(createCommandStageWithName("second", "echo second")) - pipeline.AddStage(createCommandStageWithName("third", "echo third")) + resources.Pipeline.AddStage(createCommandStageWithOnlyIf("first", "echo first", "test 1 -lt 1")) + resources.Pipeline.AddStage(createCommandStageWithName("second", "echo second")) + resources.Pipeline.AddStage(createCommandStageWithName("third", "echo third")) monitorCh := make(chan stages.Mediator) o := &config.Opts{} engine := &Engine{ - Pipeline: pipeline, + Resources: resources, MonitorCh: &monitorCh, Opts: o, } @@ -212,17 +217,18 @@ func TestRunOnceWithOnlyIfFailure(t *testing.T) { } func TestRunOnceWithOnlyIfSuccess(t *testing.T) { - pipeline := &pipelines.Pipeline{ + resources := &pipelines.Resources{ Reporter: &messengers.FakeMessenger{}, + Pipeline: &pipelines.Pipeline{}, Cleanup: &pipelines.Pipeline{}, } - pipeline.AddStage(createCommandStageWithOnlyIf("first", "echo first", "test 1 -eq 1")) - pipeline.AddStage(createCommandStageWithName("second", "echo second")) - pipeline.AddStage(createCommandStageWithName("third", "echo third")) + resources.Pipeline.AddStage(createCommandStageWithOnlyIf("first", "echo first", "test 1 -eq 1")) + resources.Pipeline.AddStage(createCommandStageWithName("second", "echo second")) + resources.Pipeline.AddStage(createCommandStageWithName("third", "echo third")) monitorCh := make(chan stages.Mediator) o := &config.Opts{} engine := &Engine{ - Pipeline: pipeline, + Resources: resources, MonitorCh: &monitorCh, Opts: o, } @@ -241,16 +247,17 @@ func TestRunOnceWithCleanup(t *testing.T) { cleanup := &pipelines.Pipeline{} cleanup.AddStage(createCommandStage("echo cleanup")) cleanup.AddStage(createCommandStage("echo baz")) - pipeline := &pipelines.Pipeline{ + resources := &pipelines.Resources{ Reporter: &messengers.FakeMessenger{}, + Pipeline: &pipelines.Pipeline{}, Cleanup: cleanup, } - pipeline.AddStage(createCommandStage("echo foobar")) - pipeline.AddStage(createCommandStage("echo baz")) + resources.Pipeline.AddStage(createCommandStage("echo foobar")) + resources.Pipeline.AddStage(createCommandStage("echo baz")) monitorCh := make(chan stages.Mediator) engine := &Engine{ - Pipeline: pipeline, + Resources: resources, MonitorCh: &monitorCh, } result := engine.RunOnce() @@ -264,16 +271,17 @@ func TestRunOnceWithCleanup(t *testing.T) { func TestRunOnceWithFailedCleanup(t *testing.T) { cleanup := &pipelines.Pipeline{} cleanup.AddStage(createCommandStage("nosuchacommand")) - pipeline := &pipelines.Pipeline{ + resources := &pipelines.Resources{ Reporter: &messengers.FakeMessenger{}, + Pipeline: &pipelines.Pipeline{}, Cleanup: cleanup, } - pipeline.AddStage(createCommandStage("echo foobar")) - pipeline.AddStage(createCommandStage("echo baz")) + resources.Pipeline.AddStage(createCommandStage("echo foobar")) + resources.Pipeline.AddStage(createCommandStage("echo baz")) monitorCh := make(chan stages.Mediator) engine := &Engine{ - Pipeline: pipeline, + Resources: resources, MonitorCh: &monitorCh, } result := engine.RunOnce() diff --git a/pipelines/pipeline.go b/pipelines/pipeline.go index b808887..7ed345e 100644 --- a/pipelines/pipeline.go +++ b/pipelines/pipeline.go @@ -26,13 +26,17 @@ import ( ) type Pipeline struct { - Stages list.List + Stages list.List +} + +type Resources struct { + Pipeline *Pipeline + Cleanup *Pipeline Reporter messengers.Messenger RepoService services.Service - Cleanup *Pipeline } -func (self *Pipeline) ReportStageResult(stage stages.Stage, result bool) { +func (self *Resources) ReportStageResult(stage stages.Stage, result bool) { name := stage.GetStageName() self.Reporter.Post( fmt.Sprintf("Stage execution results: %+v, %+v", name, result)) diff --git a/pipelines/pipeline_test.go b/pipelines/pipeline_test.go index 056741c..7a01768 100644 --- a/pipelines/pipeline_test.go +++ b/pipelines/pipeline_test.go @@ -58,7 +58,7 @@ func (mock *MockMessenger) Post(msg string) bool { func TestReportStageResult(t *testing.T) { mock := &MockMessenger{} - p := Pipeline{ + p := Resources{ Reporter: mock, } @@ -76,7 +76,7 @@ func TestReportStageResult(t *testing.T) { func TestReportStageResultWithFullOutput(t *testing.T) { mock := &MockMessenger{} - p := Pipeline{ + p := Resources{ Reporter: mock, } diff --git a/walter/walter.go b/walter/walter.go index b85a93c..b27443e 100644 --- a/walter/walter.go +++ b/walter/walter.go @@ -37,24 +37,24 @@ type Walter struct { func New(opts *config.Opts) (*Walter, error) { configData := config.ReadConfig(opts.PipelineFilePath) - pipeline, err := config.Parse(configData) + resources, err := config.Parse(configData) if err != nil { return nil, err } monitorCh := make(chan stages.Mediator) engine := &engine.Engine{ - Pipeline: pipeline, + Resources: resources, Opts: opts, MonitorCh: &monitorCh, } return &Walter{ Opts: opts, Engine: engine, - }, err + }, nil } func (e *Walter) Run() bool { - repoServiceValue := reflect.ValueOf(e.Engine.Pipeline.RepoService) + repoServiceValue := reflect.ValueOf(e.Engine.Resources.RepoService) if e.Engine.Opts.Mode == "local" || repoServiceValue.Type().String() == "*services.LocalClient" { log.Info("Starting Walter in local mode") @@ -68,13 +68,13 @@ func (e *Walter) Run() bool { func (e *Walter) runService() bool { // load .walter-update - log.Infof("Loading update file... \"%s\"", e.Engine.Pipeline.RepoService.GetUpdateFilePath()) - update, err := services.LoadLastUpdate(e.Engine.Pipeline.RepoService.GetUpdateFilePath()) + log.Infof("Loading update file... \"%s\"", e.Engine.Resources.RepoService.GetUpdateFilePath()) + update, err := services.LoadLastUpdate(e.Engine.Resources.RepoService.GetUpdateFilePath()) log.Infof("Succeeded loading update file") log.Info("Updating status...") update.Status = "inprogress" - result := services.SaveLastUpdate(e.Engine.Pipeline.RepoService.GetUpdateFilePath(), update) + result := services.SaveLastUpdate(e.Engine.Resources.RepoService.GetUpdateFilePath(), update) if result == false { log.Error("Failed to save status update") return false @@ -83,7 +83,7 @@ func (e *Walter) runService() bool { // get latest commit and pull requests log.Info("downloading commits and pull requests...") - commits, err := e.Engine.Pipeline.RepoService.GetCommits(update) + commits, err := e.Engine.Resources.RepoService.GetCommits(update) if err != nil { log.Errorf("Failed getting commits: %s", err) return false @@ -111,7 +111,7 @@ func (e *Walter) runService() bool { log.Info("Saving update file...") update.Status = "finished" update.Time = time.Now() - result = services.SaveLastUpdate(e.Engine.Pipeline.RepoService.GetUpdateFilePath(), update) + result = services.SaveLastUpdate(e.Engine.Resources.RepoService.GetUpdateFilePath(), update) if result == false { log.Error("Failed to save update") return false @@ -139,7 +139,7 @@ func (e *Walter) processTrunkCommit(commit github.RepositoryCommit) bool { // register the result to hosting service if result.IsSucceeded() { log.Info("Succeeded.") - e.Engine.Pipeline.RepoService.RegisterResult( + e.Engine.Resources.RepoService.RegisterResult( services.Result{ State: "success", Message: "Succeeded running pipeline...", @@ -147,7 +147,7 @@ func (e *Walter) processTrunkCommit(commit github.RepositoryCommit) bool { return true } else { log.Error("Error reported...") - e.Engine.Pipeline.RepoService.RegisterResult( + e.Engine.Resources.RepoService.RegisterResult( services.Result{ State: "failure", Message: "Failed running pipleline ...", @@ -183,7 +183,7 @@ func (e *Walter) processPullRequest(pullrequest github.PullRequest) bool { // register the result to hosting service if result.IsSucceeded() { log.Info("succeeded.") - e.Engine.Pipeline.RepoService.RegisterResult( + e.Engine.Resources.RepoService.RegisterResult( services.Result{ State: "success", Message: "Succeeded running pipeline...", @@ -191,7 +191,7 @@ func (e *Walter) processPullRequest(pullrequest github.PullRequest) bool { return true } else { log.Error("Error reported...") - e.Engine.Pipeline.RepoService.RegisterResult( + e.Engine.Resources.RepoService.RegisterResult( services.Result{ State: "failure", Message: "Failed running pipleline ...",