Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement `parallel' (just alias of run_after) #108

Merged
merged 4 commits into from Apr 22, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 21 additions & 0 deletions README.md
Expand Up @@ -94,6 +94,27 @@ The following is the parameter of Shell script stage.
|:----------------:|:----------:|:--------------------------------------:|
| file | false | shell script file run in the stage |

## Parallel stages

You can set child stages and run these stages in parallel like this.

```yaml
pipeline:
- name: parallel stages
parallel:
- name: parallel command 1
type: command
command: parallel command 1
- name: parallel command 2
type: command
command: parallel command 2
- name: parallel command 3
type: command
command: parallel command 3
```

`parallel command 1`, `parallel command 2` and `parallel command 3` are executed in parallel.

## Cleanup pipeline

Walter configuraiton can have one **cleanup** block; cleanup is another pipeline which needs to be executed after a pipeline has either failed or passed.
Expand Down
13 changes: 10 additions & 3 deletions config/parser.go
Expand Up @@ -219,9 +219,16 @@ func mapStage(stageMap map[interface{}]interface{}, envs *EnvVariables) (stages.
}
}

if runAfters := stageMap["run_after"]; runAfters != nil {
for _, runAfter := range runAfters.([]interface{}) {
childStage, err := mapStage(runAfter.(map[interface{}]interface{}), envs)
parallelStages := stageMap["parallel"]
if parallelStages == nil {
if parallelStages = stageMap["run_after"]; parallelStages != nil {
log.Warn("`run_after' will be obsoleted in near future. Use `parallel' instead.")
}
}

if parallelStages != nil {
for _, parallelStages := range parallelStages.([]interface{}) {
childStage, err := mapStage(parallelStages.(map[interface{}]interface{}), envs)
if err != nil {
return nil, err
}
Expand Down
30 changes: 30 additions & 0 deletions config/parser_test.go
Expand Up @@ -67,6 +67,24 @@ func TestParseConfWithChildren(t *testing.T) {
assert.Equal(t, 2, childStages.Len())
}

func TestParseConfWithParallel(t *testing.T) {
configData := ReadConfigBytes([]byte(`pipeline:
- name: parallel stages
parallel:
- name: parallel command 1
type: command
command: echo "hello, world, parallel command 1"
- name: parallel command 2
type: command
command: echo "hello, world, parallel command 2"`))
result, err := Parse(configData)
assert.Equal(t, 1, result.Pipeline.Size())
assert.Nil(t, err)

childStages := result.Pipeline.Stages.Front().Value.(stages.Stage).GetChildStages()
assert.Equal(t, 2, childStages.Len())
}

func TestParseConfDefaultStageTypeIsCommand(t *testing.T) {
configData := ReadConfigBytes([]byte(`pipeline:
- name: command_stage_1
Expand Down Expand Up @@ -148,6 +166,18 @@ func TestParseConfWithInvalidChildStage(t *testing.T) {
assert.NotNil(t, err)
}

func TestParseConfWithInvalidParallelStage(t *testing.T) {
configData := ReadConfigBytes([]byte(`pipeline:
- name: parallel stages
parallel:
- name: parallel command 1
type: xxxxx
`))
result, err := Parse(configData)
assert.Nil(t, result)
assert.NotNil(t, err)
}

func TestParseConfWithServiceBlock(t *testing.T) {
configData := ReadConfigBytes([]byte(`
service:
Expand Down