Repository: honeydipper/honeydipper
Pull request #330 (2020-10-24 17:39:52)

chore(release): release
 * 4a5e195 fix(workflow): revert simplify export (#329)
 * 5a088c9 fix(pkg): driver api_timeout under data
 * 4cd662b chore(deps): update golang docker tag (#323)
 * 48b20ec fix(deps): update module cloud.google.com/go to v0.68.0 (#327)
 * e292546 fix(deps): update google.golang.org/genproto commit hash to 3860012 (#322)
 * bb1f2a7 fix(deps): update module casbin/casbin/v2 to v2.13.1 (#326)
 * 5fe6d9e fix(deps): update golang.org/x/crypto commit hash to 7f63de1 (#321)



Patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index f8a0d34..68d3595 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -1,14 +1,14 @@
 ---
 defaults: &defaults
   docker:
-    - image: golang:1.14.6-alpine3.11
+    - image: golang:1.15.2-alpine
       environment:
         - GO111MODULE=auto
   working_directory: /go/src/github.com/honeydipper/honeydipper
 
 license_finder: &license_finder
   docker:
-    - image: licensefinder/license_finder:6.7.0
+    - image: licensefinder/license_finder:6.8.2
       environment:
         - GO111MODULE=auto
   working_directory: /root/src/honeydipper
@@ -37,7 +37,7 @@ jobs:
   golangci-lint:
     <<: *defaults
     docker:
-      - image: golangci/golangci-lint:v1.29.0-alpine
+      - image: golangci/golangci-lint:v1.31.0-alpine
     steps:
       - checkout
       - run: golangci-lint run
@@ -61,7 +61,7 @@ jobs:
   integration:
     <<: *defaults
     docker:
-      - image: golang:1.14.6-alpine3.11
+      - image: golang:1.15.2-alpine
       - image: redis:5.0.9-alpine
     steps:
       - run:
diff --git a/build/docker/Dockerfile b/build/docker/Dockerfile
index 94ddf4c..bb5f79f 100644
--- a/build/docker/Dockerfile
+++ b/build/docker/Dockerfile
@@ -1,4 +1,4 @@
-FROM golang:1.14.6-alpine AS build
+FROM golang:1.15.2-alpine AS build
 
 ARG GOINSTALLOPTS
 ARG GOGC
diff --git a/cmd/honeydipper/configcheck.go b/cmd/honeydipper/configcheck.go
index fb7b946..8ddd200 100644
--- a/cmd/honeydipper/configcheck.go
+++ b/cmd/honeydipper/configcheck.go
@@ -22,13 +22,13 @@ import (
 )
 
 var (
-	// ErrorFieldCollision is the error message when two conflicting fields are set
+	// ErrorFieldCollision is the error message when two conflicting fields are set.
 	ErrorFieldCollision = fmt.Errorf("cannot define both")
-	// ErrorNotDefined is the error message when an required asset is not defined
+	// ErrorNotDefined is the error message when an required asset is not defined.
 	ErrorNotDefined = fmt.Errorf("not defined")
-	// ErrorNotAllowed is the message when a field is not allowed due to missing pairing field
+	// ErrorNotAllowed is the message when a field is not allowed due to missing pairing field.
 	ErrorNotAllowed = fmt.Errorf("not allowed without pairing field")
-	// ErrorNotAList is the message when a field is supposed to be a list
+	// ErrorNotAList is the message when a field is supposed to be a list.
 	ErrorNotAList = fmt.Errorf("must be a list or something interpolated into a list")
 )
 
@@ -146,6 +146,7 @@ func checkAuthRules(cfg *config.Config) int {
 		fmt.Printf("\nFound errors loading authorization tests definition:\n")
 		fmt.Println("─────────────────────────────────────────────────────────────")
 		fmt.Printf("%+v\n", aurora.Red(e))
+
 		return 1
 	}
 
@@ -191,6 +192,7 @@ func checkAuthRules(cfg *config.Config) int {
 		if err != nil {
 			e = err
 			processed = i
+
 			break
 		}
 		if ok != test.Result {
@@ -226,6 +228,7 @@ func checkAuthRules(cfg *config.Config) int {
 			)
 		}
 		fmt.Println()
+
 		return 1
 	}
 
@@ -243,6 +246,7 @@ func checkContext(cfg *config.Config, ctxWorkflowName string) (msg string) {
 		}
 	}()
 	checkObjectExists("workflow", ctxWorkflowName, cfg.DataSet.Workflows)
+
 	return msg
 }
 
@@ -387,11 +391,13 @@ func checkObjectExists(t, name string, m interface{}) {
 
 func hasLiteral(param string) bool {
 	s := strings.TrimSpace(param)
+
 	return s != "" && s[0] != '$' && !(strings.HasPrefix(s, "{{") && strings.HasSuffix(s, "}}")) && !strings.HasPrefix(s, ":yaml:")
 }
 
 func hasInterpolation(param string) bool {
 	s := strings.TrimSpace(param)
+
 	return s != "" && (s[0] == '$' || strings.Contains(s, "{{")) || strings.HasPrefix(s, ":yaml:")
 }
 
diff --git a/cmd/honeydipper/docgen.go b/cmd/honeydipper/docgen.go
index fb10821..77dffc5 100644
--- a/cmd/honeydipper/docgen.go
+++ b/cmd/honeydipper/docgen.go
@@ -28,7 +28,7 @@ import (
 )
 
 const (
-	// DefaultHTTPRequestTimeout is the default timeout for a HTTP request
+	// DefaultHTTPRequestTimeout is the default timeout for a HTTP request.
 	DefaultHTTPRequestTimeout time.Duration = time.Second * 10
 )
 
diff --git a/cmd/honeydipper/main.go b/cmd/honeydipper/main.go
index 1a049f3..2114fe4 100644
--- a/cmd/honeydipper/main.go
+++ b/cmd/honeydipper/main.go
@@ -71,6 +71,7 @@ loop:
 			if _, ok := os.LookupEnv("CHECK_REMOTE"); ok {
 				cfg.CheckRemote = true
 			}
+
 			break loop
 		case "docgen":
 			cfg.Services = []string{s}
@@ -85,6 +86,7 @@ loop:
 			} else {
 				cfg.DocDst = "docs/dst"
 			}
+
 			break loop
 		}
 	}
diff --git a/drivers/cmd/auth-simple/main.go b/drivers/cmd/auth-simple/main.go
index dad41cc..78d5bfb 100644
--- a/drivers/cmd/auth-simple/main.go
+++ b/drivers/cmd/auth-simple/main.go
@@ -80,6 +80,7 @@ func authWebRequest(m *dipper.Message) {
 			m.Reply <- dipper.Message{
 				Payload: subject,
 			}
+
 			return
 		} else if !errors.Is(err, ErrSkipped) {
 			break
@@ -112,6 +113,7 @@ func tokenAuth(m *dipper.Message) (string, error) {
 				if !ok || subject == nil {
 					return _EmptySubject, nil
 				}
+
 				return subject.(string), nil
 			}
 		}
@@ -153,6 +155,7 @@ func basicAuth(m *dipper.Message) (string, error) {
 				if !ok || subject == nil {
 					return _EmptySubject, nil
 				}
+
 				return subject.(string), nil
 			}
 		}
diff --git a/drivers/cmd/gcloud-dataflow/main.go b/drivers/cmd/gcloud-dataflow/main.go
index 763db4f..fe209c2 100644
--- a/drivers/cmd/gcloud-dataflow/main.go
+++ b/drivers/cmd/gcloud-dataflow/main.go
@@ -29,15 +29,15 @@ const (
 )
 
 var (
-	// ErrMissingProject means missing project
+	// ErrMissingProject means missing project.
 	ErrMissingProject = errors.New("project required")
-	// ErrMissingJobSpec means missing location
+	// ErrMissingJobSpec means missing location.
 	ErrMissingJobSpec = errors.New("job spec required")
-	// ErrMissingJobID means missing jobid
+	// ErrMissingJobID means missing jobid.
 	ErrMissingJobID = errors.New("jobid required")
-	// ErrMissingName means missing name
+	// ErrMissingName means missing name.
 	ErrMissingName = errors.New("name required")
-	// ErrJobNotFound means job not found
+	// ErrJobNotFound means job not found.
 	ErrJobNotFound = errors.New("job not found")
 )
 
@@ -95,6 +95,7 @@ func getCommonParams(params interface{}) (string, string, string) {
 			location = location[:len(location)-2]
 		}
 	}
+
 	return serviceAccountBytes, project, location
 }
 
@@ -216,6 +217,7 @@ found:
 			for _, j := range result.Jobs {
 				if j.Name == jobName {
 					job = j
+
 					break found
 				}
 			}
@@ -314,6 +316,7 @@ loop:
 						"error": fmt.Sprintf("failed to call polling method: %+v", err),
 					},
 				}
+
 				break loop
 			}
 
@@ -327,6 +330,7 @@ loop:
 						"reason": result.CurrentState,
 					},
 				}
+
 				break loop
 			}
 			time.Sleep(time.Duration(interval) * time.Second)
diff --git a/drivers/cmd/gcloud-gke/main.go b/drivers/cmd/gcloud-gke/main.go
index e0c4796..cb519c4 100644
--- a/drivers/cmd/gcloud-gke/main.go
+++ b/drivers/cmd/gcloud-gke/main.go
@@ -23,11 +23,11 @@ import (
 )
 
 var (
-	// ErrMissingProject means missing project
+	// ErrMissingProject means missing project.
 	ErrMissingProject = errors.New("project required")
-	// ErrMissingLocation means missing location
+	// ErrMissingLocation means missing location.
 	ErrMissingLocation = errors.New("location required")
-	// ErrMissingCluster means missing location
+	// ErrMissingCluster means missing location.
 	ErrMissingCluster = errors.New("cluster required")
 )
 
diff --git a/drivers/cmd/gcloud-pubsub/main.go b/drivers/cmd/gcloud-pubsub/main.go
index 754a06f..d9160ce 100644
--- a/drivers/cmd/gcloud-pubsub/main.go
+++ b/drivers/cmd/gcloud-pubsub/main.go
@@ -62,6 +62,7 @@ func getPubsubClient(serviceAccountBytes, project string) *pubsub.Client {
 	if err != nil {
 		panic(ErrFailedCreateClient)
 	}
+
 	return client
 }
 
@@ -88,11 +89,13 @@ func loadOptions() {
 			project, ok := dipper.GetMapDataStr(condition, "project")
 			if !ok {
 				dipper.Logger.Warningf("[%s] failed to get pubsub project in condition", driver.Service)
+
 				continue
 			}
 			subscriptionName, ok := dipper.GetMapDataStr(condition, "subscriptionName")
 			if !ok {
 				dipper.Logger.Warningf("[%s] failed to get pubsub subscription name in condition", driver.Service)
+
 				continue
 			}
 
@@ -147,6 +150,7 @@ func msgHandlerBuilder(config *SubscriberConfig) msgHandler {
 		for _, subCond := range conditions {
 			if dipper.CompareAll(actual, subCond) {
 				matched = true
+
 				break
 			}
 		}
diff --git a/drivers/cmd/gcloud-spanner/main.go b/drivers/cmd/gcloud-spanner/main.go
index 3081075..4937544 100644
--- a/drivers/cmd/gcloud-spanner/main.go
+++ b/drivers/cmd/gcloud-spanner/main.go
@@ -19,25 +19,25 @@ import (
 )
 
 const (
-	// DefaultBackupOpWaitTimeout is the default timeout in seconds for waiting for the backup to complete
+	// DefaultBackupOpWaitTimeout is the default timeout in seconds for waiting for the backup to complete.
 	DefaultBackupOpWaitTimeout time.Duration = 1800
 
-	// DefaultBackupExpireDuration is the default duration before a backup is expired and removed
+	// DefaultBackupExpireDuration is the default duration before a backup is expired and removed.
 	DefaultBackupExpireDuration time.Duration = time.Hour * 24 * 180
 )
 
 var (
-	// ErrMissingProject means missing project
+	// ErrMissingProject means missing project.
 	ErrMissingProject = errors.New("project required")
-	// ErrMissingLocation means missing location
+	// ErrMissingLocation means missing location.
 	ErrMissingLocation = errors.New("location required")
-	// ErrMissingDB means missing db
+	// ErrMissingDB means missing db.
 	ErrMissingDB = errors.New("db required")
-	// ErrMissingBackupOpID means missing backupOpID
+	// ErrMissingBackupOpID means missing backupOpID.
 	ErrMissingBackupOpID = errors.New("backupOpID required")
-	// ErrCreateClient means failure when creating API client
+	// ErrCreateClient means failure when creating API client.
 	ErrCreateClient = errors.New("fail to create client")
-	// ErrBackupOpNotFound means the backup operation not found
+	// ErrBackupOpNotFound means the backup operation not found.
 	ErrBackupOpNotFound = errors.New("backup op not found")
 )
 
diff --git a/drivers/cmd/gcloud-storage/main.go b/drivers/cmd/gcloud-storage/main.go
index 5e515fa..5fbc4e5 100644
--- a/drivers/cmd/gcloud-storage/main.go
+++ b/drivers/cmd/gcloud-storage/main.go
@@ -72,6 +72,7 @@ func getStorageClient(serviceAccountBytes string) *storage.Client {
 	if err != nil {
 		panic(ErrCreateClient)
 	}
+
 	return client
 }
 
@@ -81,6 +82,7 @@ func getCommonParams(params interface{}) (string, string) {
 	if !ok {
 		panic(ErrMissingProject)
 	}
+
 	return serviceAccountBytes, project
 }
 
diff --git a/drivers/cmd/kubernetes/main.go b/drivers/cmd/kubernetes/main.go
index e05b28a..0b86cf5 100644
--- a/drivers/cmd/kubernetes/main.go
+++ b/drivers/cmd/kubernetes/main.go
@@ -249,6 +249,7 @@ func waitForJob(m *dipper.Message) {
 
 		if len(job.Status.Conditions) > 0 && job.Status.Active == 0 {
 			returnJobStatus(job)
+
 			break
 		}
 
@@ -265,6 +266,7 @@ func waitForJob(m *dipper.Message) {
 				select {
 				case <-ctxWatch.Done():
 					EOW = true
+
 					break loop
 				case evt := <-jobstatus.ResultChan():
 					switch evt.Type {
@@ -272,6 +274,7 @@ func waitForJob(m *dipper.Message) {
 						e := evt.Object.(*metav1.Status)
 						if e.Code == http.StatusGone {
 							log.Warningf("[%s] error from watching channel for job [%s]: %+v", driver.Service, jobName, evt.Object)
+
 							break loop
 						} else {
 							log.Panicf("[%s] error from watching channel for job [%s]: %+v", driver.Service, jobName, evt.Object)
@@ -285,6 +288,7 @@ func waitForJob(m *dipper.Message) {
 						if len(job.Status.Conditions) > 0 && job.Status.Active == 0 {
 							returnJobStatus(job)
 							EOW = true
+
 							break loop
 						}
 					}
@@ -313,6 +317,7 @@ func getExistingJob(jobSpec *batchv1.Job, jobclient batchv1client.JobInterface)
 			return &job
 		}
 	}
+
 	return nil
 }
 
@@ -417,6 +422,7 @@ func recycleDeployment(m *dipper.Message) {
 	for _, currentRs := range rs.Items {
 		if currentRs.Annotations["deployment.kubernetes.io/revision"] == revision {
 			rsName = currentRs.Name
+
 			break
 		}
 	}
@@ -469,6 +475,7 @@ func prepareKubeConfig(m *dipper.Message) *kubernetes.Clientset {
 	if err != nil {
 		log.Panicf("[%s] unable to create k8 client", driver.Service)
 	}
+
 	return k8client
 }
 
diff --git a/drivers/cmd/redispubsub/main.go b/drivers/cmd/redispubsub/main.go
index c74e901..db17a5e 100644
--- a/drivers/cmd/redispubsub/main.go
+++ b/drivers/cmd/redispubsub/main.go
@@ -150,6 +150,7 @@ func subscribe() {
 					for k, v := range labelMap.(map[string]interface{}) {
 						if k == "service" && v != nil && v.(string) != "" && v.(string) != driver.Service {
 							skip = true
+
 							break
 						}
 						labels[k] = v.(string)
diff --git a/drivers/cmd/redisqueue/main.go b/drivers/cmd/redisqueue/main.go
index 17beb7a..cebcaf3 100644
--- a/drivers/cmd/redisqueue/main.go
+++ b/drivers/cmd/redisqueue/main.go
@@ -22,7 +22,7 @@ import (
 )
 
 const (
-	// TopicExpireTimeout is the timeout for a message in the topic to expire and be removed
+	// TopicExpireTimeout is the timeout for a message in the topic to expire and be removed.
 	TopicExpireTimeout time.Duration = time.Second * 1800
 )
 
diff --git a/drivers/cmd/webhook/main.go b/drivers/cmd/webhook/main.go
index 8b0368e..cd9a769 100644
--- a/drivers/cmd/webhook/main.go
+++ b/drivers/cmd/webhook/main.go
@@ -98,6 +98,7 @@ func hookHandler(w http.ResponseWriter, r *http.Request) {
 
 	if eventData["url"] == "/hz/alive" {
 		w.WriteHeader(http.StatusOK)
+
 		return
 	}
 
@@ -115,11 +116,13 @@ func hookHandler(w http.ResponseWriter, r *http.Request) {
 				})
 				if err != nil || string(authResult) != "authenticated" {
 					log.Warningf("[%s] failed to authenticate webhook request with %s error %+v", driver.Service, authDriver, err)
+
 					continue
 				}
 			}
 			if dipper.CompareAll(eventData, condition) {
 				matched = true
+
 				break
 			}
 		}
@@ -140,6 +143,7 @@ func hookHandler(w http.ResponseWriter, r *http.Request) {
 		} else {
 			w.WriteHeader(http.StatusOK)
 		}
+
 		return
 	}
 
diff --git a/drivers/pkg/redisclient/redisclient.go b/drivers/pkg/redisclient/redisclient.go
index 1b4e94a..f001d4c 100644
--- a/drivers/pkg/redisclient/redisclient.go
+++ b/drivers/pkg/redisclient/redisclient.go
@@ -26,5 +26,6 @@ func GetRedisOps(driver *dipper.Driver) *redis.Options {
 	if DB, ok := driver.GetOptionStr("data.connection.DB"); ok {
 		opts.DB = dipper.Must(strconv.Atoi(DB)).(int)
 	}
+
 	return opts
 }
diff --git a/go.mod b/go.mod
index 23e405c..79906cf 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module github.com/honeydipper/honeydipper
 go 1.13
 
 require (
-	cloud.google.com/go v0.65.0
+	cloud.google.com/go v0.68.0
 	cloud.google.com/go/pubsub v1.3.1
 	cloud.google.com/go/spanner v1.6.0
 	cloud.google.com/go/storage v1.10.0
@@ -11,7 +11,7 @@ require (
 	github.com/Masterminds/goutils v1.1.0 // indirect
 	github.com/Masterminds/semver v1.5.0 // indirect
 	github.com/Masterminds/sprig v2.22.0+incompatible
-	github.com/casbin/casbin/v2 v2.11.3
+	github.com/casbin/casbin/v2 v2.13.1
 	github.com/ghodss/yaml v1.0.0
 	github.com/gin-gonic/gin v1.6.3
 	github.com/go-errors/errors v1.1.1
@@ -29,10 +29,10 @@ require (
 	github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
 	github.com/qiangmzsx/string-adapter/v2 v2.1.0
 	github.com/stretchr/testify v1.6.1
-	golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
+	golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0
 	golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43
-	google.golang.org/api v0.30.0
-	google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d
+	google.golang.org/api v0.32.0
+	google.golang.org/genproto v0.0.0-20201002142447-3860012362da
 	gopkg.in/h2non/gock.v1 v1.0.15
 	gopkg.in/src-d/go-git.v4 v4.13.1
 	gopkg.in/yaml.v2 v2.3.0 // indirect
diff --git a/go.sum b/go.sum
index 3feb936..ebd99be 100644
--- a/go.sum
+++ b/go.sum
@@ -20,6 +20,8 @@ cloud.google.com/go v0.62.0 h1:RmDygqvj27Zf3fCQjQRtLyC7KwFcHkeJitcO0OoGOcA=
 cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
 cloud.google.com/go v0.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8=
 cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
+cloud.google.com/go v0.68.0 h1:AnVkaPGAuWaIY/8a75HlNzZNrHDee6YL4rWkwS+CeyE=
+cloud.google.com/go v0.68.0/go.mod h1:91NO4SCDjUfe1zeC0f4/dpckkUNpuNEyqm4X2KLrzNQ=
 cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
 cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
 cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
@@ -82,8 +84,8 @@ github.com/benbjohnson/clock v1.0.3 h1:vkLuvpK4fmtSCuo60+yC63p7y0BmQ8gm5ZXGuBCJy
 github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
 github.com/casbin/casbin/v2 v2.1.0 h1:FqE47qR7PNFrhh/mQFRqlXWdAM0lObvn/cl8ydyxi1c=
 github.com/casbin/casbin/v2 v2.1.0/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
-github.com/casbin/casbin/v2 v2.11.3 h1:nGpcPrD8KVhKjla29qGqe6ijKGD3Qkn+jP3S5hvgZ9U=
-github.com/casbin/casbin/v2 v2.11.3/go.mod h1:XXtYGrs/0zlOsJMeRteEdVi/FsB0ph7KgNfjoCoJUD8=
+github.com/casbin/casbin/v2 v2.13.1 h1:K2ChfTOlEgCd9H6J3efOCatqLPyBj2ZCKwyhVRq4XSg=
+github.com/casbin/casbin/v2 v2.13.1/go.mod h1:XXtYGrs/0zlOsJMeRteEdVi/FsB0ph7KgNfjoCoJUD8=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -200,6 +202,8 @@ github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
 github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
 github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
@@ -215,6 +219,7 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
 github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
 github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
 github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200905233945-acf8798be1f7/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
 github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
 github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -334,6 +339,7 @@ github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0B
 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
 go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@@ -351,8 +357,8 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
-golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE=
+golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -419,6 +425,8 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgN
 golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
 golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200927032502-5d4f70055728 h1:5wtQIAulKU5AbLQOkjxl32UufnIOqgBX72pS0AV14H0=
+golang.org/x/net v0.0.0-20200927032502-5d4f70055728/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -470,6 +478,8 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121 h1:rITEj+UZHYC927n8GT97eC3zr
 golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200803210538-64077c9b5642 h1:B6caxRw+hozq68X2MY7jEpZh/cr4/aHLv9xU8Kkadrw=
 golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f h1:Fqb3ao1hUmOR3GkUOg/Y+BadLwykBIzs5q8Ez2SbHyc=
+golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -527,6 +537,9 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc
 golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
 golang.org/x/tools v0.0.0-20200825202427-b303f430e36d h1:W07d4xkoAUSNOkOzdzXCdFGxT7o2rW4q8M34tB2i//k=
 golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
+golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d h1:vWQvJ/Z0Lu+9/8oQ/pAYXNzbc7CMnBl+tULGVHOy3oE=
+golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
@@ -552,6 +565,8 @@ google.golang.org/api v0.29.0 h1:BaiDisFir8O4IJxvAabCGGkQ6yCJegNQqSVoYUNAnbk=
 google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
 google.golang.org/api v0.30.0 h1:yfrXXP61wVuLb0vBcG6qaOoIoqYEzOQS8jum51jkv2w=
 google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
+google.golang.org/api v0.32.0 h1:Le77IccnTqEa8ryp9wIpX5W3zYm7Gf9LhOp9PHcwFts=
+google.golang.org/api v0.32.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -592,6 +607,8 @@ google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6D
 google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d h1:92D1fum1bJLKSdr11OJ+54YeCMCGYIygTA7R/YZxH5M=
 google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201002142447-3860012362da h1:DTQYk4u7nICKkkVZsBv0/0po0ChISxAJ5CTAfUhO0PQ=
+google.golang.org/genproto v0.0.0-20201002142447-3860012362da/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
 google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -606,6 +623,9 @@ google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE=
 google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
 google.golang.org/grpc v1.31.0 h1:T7P4R73V3SSDPhH7WW7ATbfViLtmamH0DKrP3f9AuDI=
 google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.32.0 h1:zWTV+LMdc3kaiJMSTOFz2UgSBgx8RNQoTGiZu3fR9S0=
+google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
diff --git a/internal/api/def.go b/internal/api/def.go
index deb65b9..69de8e5 100644
--- a/internal/api/def.go
+++ b/internal/api/def.go
@@ -58,5 +58,6 @@ func GetDefsByName() map[string]Def {
 			ret[def.Name] = def
 		}
 	}
+
 	return ret
 }
diff --git a/internal/api/response.go b/internal/api/response.go
index 72d9cc3..b731fe0 100644
--- a/internal/api/response.go
+++ b/internal/api/response.go
@@ -89,6 +89,7 @@ type ResponseFactory struct {
 func NewResponseFactory() *ResponseFactory {
 	r := &ResponseFactory{}
 	r.DefsByName = GetDefsByName()
+
 	return r
 }
 
@@ -103,6 +104,7 @@ func (rf *ResponseFactory) NewResponse(caller dipper.RPCCaller, eventbus io.Writ
 	def, ok := rf.DefsByName[method]
 	if !ok {
 		dipper.Logger.Warningf("Unknown API method: %s", method)
+
 		return nil
 	}
 	switch def.ReqType {
diff --git a/internal/api/store.go b/internal/api/store.go
index c49f10c..f9b1ccf 100644
--- a/internal/api/store.go
+++ b/internal/api/store.go
@@ -22,19 +22,19 @@ import (
 )
 
 const (
-	// DefaultAPIAckTimeout is the number of milliseconds to wait for acks
+	// DefaultAPIAckTimeout is the number of milliseconds to wait for acks.
 	DefaultAPIAckTimeout time.Duration = 10
 
-	// APIError is the base for all API related error
+	// APIError is the base for all API related error.
 	APIError dipper.Error = "API error"
 
-	// DefaultAPIWriteTimeout is the default timeout in seconds for responding to the request
+	// DefaultAPIWriteTimeout is the default timeout in seconds for responding to the request.
 	DefaultAPIWriteTimeout time.Duration = 10
 
-	// ACLAllow reprensts allowing the subject to access the API
+	// ACLAllow reprensts allowing the subject to access the API.
 	ACLAllow = "allow"
 
-	// ACLDeny reprensts denying the subject to access the API
+	// ACLDeny reprensts denying the subject to access the API.
 	ACLDeny = "deny"
 )
 
@@ -104,12 +104,14 @@ func (l *Store) HandleAPIReturn(m *dipper.Message) {
 	if errmsg, ok := m.Labels["error"]; ok {
 		api.err = fmt.Errorf("%w: from [%s]: %s", APIError, responder, errmsg)
 		api.received <- 1
+
 		return
 	}
 
 	if api.reqType == TypeFirst {
 		api.results[responder] = m.Payload
 		api.received <- 1
+
 		return
 	}
 
@@ -128,6 +130,7 @@ func NewStore(c dipper.RPCCaller) *Store {
 	}
 	store.apiDef = GetDefs()
 	store.newUUID = dipper.NewUUID
+
 	return store
 }
 
@@ -180,6 +183,7 @@ func (l *Store) AuthMiddleware() gin.HandlerFunc {
 		providers, ok := dipper.GetMapData(l.config, "auth-providers")
 		if !ok || providers == nil || len(providers.([]interface{})) == 0 {
 			c.Next()
+
 			return
 		}
 
@@ -198,6 +202,7 @@ func (l *Store) AuthMiddleware() gin.HandlerFunc {
 			} else {
 				c.Set("subject", dipper.DeserializeContent(subject))
 				c.Next()
+
 				return
 			}
 		}
@@ -218,6 +223,7 @@ func (l *Store) Authorize(c RequestContext, def Def) bool {
 	} else if err != nil {
 		dipper.Logger.Warningf("[api] denied access with enforcer error: %+v", err)
 	}
+
 	return false
 }
 
@@ -225,6 +231,7 @@ func (l *Store) Authorize(c RequestContext, def Def) bool {
 func (l *Store) HandleHTTPRequest(c RequestContext, def Def) {
 	if !l.Authorize(c, def) {
 		c.AbortWithStatusJSON(http.StatusForbidden, map[string]interface{}{"errors": "not allowed"})
+
 		return
 	}
 
diff --git a/internal/config/config.go b/internal/config/config.go
index ddc1738..97ed107 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -143,6 +143,7 @@ func (c *Config) parseWorkflowRegex() {
 			dipper.Recursive(v.Else, processor)
 			dipper.Recursive(v.Cases, processor)
 		}
+
 		return nil, false
 	}
 
@@ -153,6 +154,7 @@ func (c *Config) parseWorkflowRegex() {
 
 func (c *Config) isRepoLoaded(repo RepoInfo) bool {
 	_, ok := c.Loaded[repo]
+
 	return ok
 }
 
@@ -174,6 +176,7 @@ func (c *Config) GetDriverData(path string) (ret interface{}, ok bool) {
 	if c.DataSet == nil || c.DataSet.Drivers == nil {
 		return nil, false
 	}
+
 	return dipper.GetMapData(c.DataSet.Drivers, path)
 }
 
@@ -185,6 +188,7 @@ func (c *Config) GetDriverDataStr(path string) (ret string, ok bool) {
 	if c.DataSet == nil || c.DataSet.Drivers == nil {
 		return "", false
 	}
+
 	return dipper.GetMapDataStr(c.DataSet.Drivers, path)
 }
 
@@ -245,6 +249,7 @@ func SystemCopy(s *System) (*System, error) {
 	if err != nil {
 		return nil, err
 	}
+
 	return &scopy, nil
 }
 
@@ -266,6 +271,7 @@ func mergeDataSet(d *DataSet, s DataSet) error {
 	s.Contexts = dipper.MustDeepCopyMap(s.Contexts)
 	s.Drivers = dipper.MustDeepCopyMap(s.Drivers)
 	err := mergo.Merge(d, s, mergo.WithOverride, mergo.WithAppendSlice)
+
 	return err
 }
 
diff --git a/internal/config/file_reference.go b/internal/config/file_reference.go
index 4f33eb2..a386fe2 100644
--- a/internal/config/file_reference.go
+++ b/internal/config/file_reference.go
@@ -16,7 +16,7 @@ import (
 )
 
 const (
-	// FileError is all errors when accessing a file
+	// FileError is all errors when accessing a file.
 	FileError dipper.Error = "file error"
 )
 
@@ -25,6 +25,7 @@ func (c *Repo) normalizeFilePath(cwd string, file string) string {
 	if !strings.HasPrefix(fullpath, c.root+"/") {
 		panic(fmt.Errorf("invalid path: %s: %w", fullpath, FileError))
 	}
+
 	return fullpath
 }
 
@@ -41,28 +42,34 @@ func (c *Repo) normalizeFilePaths(currentFile string, content *DataSet) {
 				if err != nil {
 					panic(err)
 				}
+
 				return string(text), true
 			}
+
 			return nil, false
 		case Trigger:
 			dipper.Recursive(v.Match, processor)
 			dipper.Recursive(v.Parameters, processor)
 			dipper.Recursive(v.Export, processor)
+
 			return nil, false
 		case Function:
 			dipper.Recursive(v.Parameters, processor)
 			dipper.Recursive(v.Export, processor)
 			dipper.Recursive(v.ExportOnSuccess, processor)
 			dipper.Recursive(v.ExportOnFailure, processor)
+
 			return nil, false
 		case System:
 			dipper.Recursive(v.Triggers, processor)
 			dipper.Recursive(v.Functions, processor)
 			dipper.Recursive(v.Data, processor)
+
 			return nil, false
 		case Rule:
 			dipper.Recursive(&v.Do, processor)
 			dipper.Recursive(&v.When, processor)
+
 			return nil, false
 		case Workflow:
 			dipper.Recursive(v.Match, processor)
@@ -79,6 +86,7 @@ func (c *Repo) normalizeFilePaths(currentFile string, content *DataSet) {
 
 			return nil, false
 		}
+
 		return nil, false
 	}
 
diff --git a/internal/config/gitssh.go b/internal/config/gitssh.go
index 0bc817a..816f70e 100644
--- a/internal/config/gitssh.go
+++ b/internal/config/gitssh.go
@@ -57,5 +57,6 @@ func GetGitSSHAuth() transport.AuthMethod {
 	}
 
 	loadedSSHAuth = true
+
 	return currentSSHAuth
 }
diff --git a/internal/config/repo.go b/internal/config/repo.go
index 6efd9b2..675536b 100644
--- a/internal/config/repo.go
+++ b/internal/config/repo.go
@@ -48,6 +48,7 @@ func (c *Repo) assemble(assembled *DataSet, assembledList map[RepoInfo]*Repo) (*
 	}
 
 	dipper.Must(mergeDataSet(assembled, c.DataSet))
+
 	return assembled, assembledList
 }
 
@@ -189,6 +190,7 @@ func (c *Repo) refreshRepo() bool {
 	err = tree.Pull(opts)
 	if errors.Is(err, git.NoErrAlreadyUpToDate) {
 		dipper.Logger.Infof("no changes skip repo [%s]", c.repo.Repo)
+
 		return false
 	} else if err != nil {
 		panic(err)
@@ -202,6 +204,7 @@ func (c *Repo) refreshRepo() bool {
 	}
 	c.loadFile(path.Clean(path.Join(root, "init.yaml")))
 	dipper.Logger.Warningf("repo [%v] reloaded", c.repo.Repo)
+
 	return true
 }
 
diff --git a/internal/driver/driver.go b/internal/driver/driver.go
index b281b44..7cfedbb 100644
--- a/internal/driver/driver.go
+++ b/internal/driver/driver.go
@@ -18,10 +18,10 @@ import (
 )
 
 const (
-	// DriverError is the base for all driver related error
+	// DriverError is the base for all driver related error.
 	DriverError dipper.Error = "driver error"
 
-	// DriverMessageBuffer is the size of the driver message buffer
+	// DriverMessageBuffer is the size of the driver message buffer.
 	DriverMessageBuffer = 10
 )
 
@@ -62,6 +62,7 @@ func NewDriver(data map[string]interface{}) Handler {
 	if meta.Executable == "" {
 		panic(fmt.Errorf("executable not defined for driver: %s: %w", meta.Name, DriverError))
 	}
+
 	return dh
 }
 
diff --git a/internal/service/api.go b/internal/service/api.go
index bd07023..cad2e76 100644
--- a/internal/service/api.go
+++ b/internal/service/api.go
@@ -21,18 +21,18 @@ import (
 )
 
 const (
-	// APIServerGracefulTimeout is the timeout in seconds for waiting for a http.Server to shutdown gracefully
+	// APIServerGracefulTimeout is the timeout in seconds for waiting for a http.Server to shutdown gracefully.
 	APIServerGracefulTimeout time.Duration = 10
 )
 
 var (
-	// API is the service object for api service
+	// API is the service object for api service.
 	API *Service
-	// APIServer is the http server listening for api calls
+	// APIServer is the http server listening for api calls.
 	APIServer *http.Server
-	// APICfg contains configuration for the api service from driver.daemon.services.api
+	// APICfg contains configuration for the api service from driver.daemon.services.api.
 	APICfg interface{}
-	// APIRequestStore is the object holds and handles all live api calls
+	// APIRequestStore is the object holds and handles all live api calls.
 	APIRequestStore *api.Store
 )
 
@@ -54,8 +54,10 @@ func loadAPIConfig(cfg *config.Config) bool {
 	apiCfg, _ := dipper.GetMapData(cfg.DataSet.Drivers, "daemon.services.api")
 	if !reflect.DeepEqual(apiCfg, APICfg) {
 		APICfg = apiCfg
+
 		return true
 	}
+
 	return false
 }
 
@@ -128,5 +130,6 @@ func APIFeatures(s *config.DataSet) map[string]interface{} {
 			}
 		}
 	}
+
 	return features
 }
diff --git a/internal/service/operator.go b/internal/service/operator.go
index aabba8f..c78dcd7 100644
--- a/internal/service/operator.go
+++ b/internal/service/operator.go
@@ -17,7 +17,7 @@ import (
 )
 
 const (
-	// OperatorError is the base for all operator related error
+	// OperatorError is the base for all operator related error.
 	OperatorError dipper.Error = "operator error"
 )
 
@@ -161,6 +161,7 @@ func operatorRoute(msg *dipper.Message) (ret []RoutedMessage) {
 			},
 		}
 	}
+
 	return ret
 }
 
diff --git a/internal/service/receiver.go b/internal/service/receiver.go
index 89bca45..fed521e 100644
--- a/internal/service/receiver.go
+++ b/internal/service/receiver.go
@@ -39,6 +39,7 @@ func receiverRoute(msg *dipper.Message) (ret []RoutedMessage) {
 		}
 		ret = append(ret, rtmsg)
 	}
+
 	return ret
 }
 
@@ -88,6 +89,7 @@ func ReceiverFeatures(c *config.DataSet) map[string]interface{} {
 	}
 	numDynamicFeatures = len(dynamicData)
 	dipper.Logger.Debugf("[receiver] dynamicData return: %+v", dynamicData)
+
 	return dynamicData
 }
 
diff --git a/internal/service/service.go b/internal/service/service.go
index a431fd6..33f93ce 100644
--- a/internal/service/service.go
+++ b/internal/service/service.go
@@ -29,19 +29,19 @@ import (
 const (
 	FeatureEmitter = "emitter"
 
-	// ServiceError indicates error condition when rendering service
+	// ServiceError indicates error condition when rendering service.
 	ServiceError dipper.Error = "service error"
 
-	// DriverGracefulTimeout is the timeout in milliseconds for a driver to gracefully shutdown
+	// DriverGracefulTimeout is the timeout in milliseconds for a driver to gracefully shutdown.
 	DriverGracefulTimeout time.Duration = 50
 
-	// DriverReadyTimeout is the timeout in seconds for the driver to be ready
+	// DriverReadyTimeout is the timeout in seconds for the driver to be ready.
 	DriverReadyTimeout time.Duration = 10
 
-	// DriverRetryBackoff is the interval in seconds before retry loading a driver
+	// DriverRetryBackoff is the interval in seconds before retry loading a driver.
 	DriverRetryBackoff time.Duration = 30
 
-	// DriverRetryCount is the number of attempts to load a driver
+	// DriverRetryCount is the number of attempts to load a driver.
 	DriverRetryCount = 3
 )
 
@@ -146,9 +146,11 @@ func (s *Service) decryptDriverData(key string, val interface{}) (ret interface{
 				dipper.Logger.Panicf("encrypted data shoud be base64 encoded")
 			}
 			decrypted, _ := s.CallRaw("driver:"+encDriver, "decrypt", decoded)
+
 			return string(decrypted), true
 		}
 	}
+
 	return nil, false
 }
 
@@ -228,6 +230,7 @@ func (s *Service) loadFeature(feature string) (affected bool, driverName string,
 		affected = true
 		s.coldReload(&driverRuntime, oldRuntime)
 	}
+
 	return affected, driverName, nil
 }
 
@@ -325,6 +328,7 @@ func (s *Service) getFeatureList() map[string]bool {
 		}
 	}
 	dipper.Logger.Debugf("[%s] final feature list %+v", s.name, featureList)
+
 	return featureList
 }
 
@@ -571,6 +575,7 @@ func (s *Service) addExpect(expectKey string, processor ExpectHandler, timeout t
 					for i := range expects {
 						if &expects[i] == &processor {
 							expects = append(expects[:i], expects[i+1:]...)
+
 							break
 						}
 					}
@@ -588,6 +593,7 @@ func (s *Service) isExpecting(expectKey string) ([]ExpectHandler, bool) {
 	defer s.expectLock.Unlock()
 	s.expectLock.Lock()
 	ret, ok := s.expects[expectKey]
+
 	return ret, ok
 }
 
@@ -598,6 +604,7 @@ func (s *Service) deleteExpect(expectKey string) ([]ExpectHandler, bool) {
 	if ok {
 		delete(s.expects, expectKey)
 	}
+
 	return ret, ok
 }
 
@@ -606,6 +613,7 @@ func (s *Service) getDriverRuntime(feature string) *driver.Runtime {
 	if ok && runtime != nil {
 		return runtime.(*driver.Runtime)
 	}
+
 	return nil
 }
 
@@ -614,6 +622,7 @@ func (s *Service) setDriverRuntime(feature string, runtime *driver.Runtime) *dri
 	if oldone != nil {
 		return oldone.(*driver.Runtime)
 	}
+
 	return nil
 }
 
@@ -690,6 +699,7 @@ func handleAPI(from *driver.Runtime, m *dipper.Message) {
 	resp := s.ResponseFactory.NewResponse(s, s.getDriverRuntime("eventbus").Output, m)
 	if resp == nil {
 		dipper.Logger.Debugf("[%s] skipping handling API: %+v", s.name, m.Labels)
+
 		return
 	}
 	method := m.Labels["fn"]
diff --git a/internal/workflow/condition.go b/internal/workflow/condition.go
index 7580f92..00d6000 100644
--- a/internal/workflow/condition.go
+++ b/internal/workflow/condition.go
@@ -16,6 +16,7 @@ import (
 // isTruthy is a helper function to check if string represents Truey value.
 func isTruthy(c string) bool {
 	c = strings.ToLower(strings.TrimSpace(c))
+
 	return len(c) != 0 && c != "false" && c != "nil" && c != "0" && c != "{}" && c != "[]" && c != "<no value>"
 }
 
@@ -28,6 +29,7 @@ func (w *Session) checkCondition() bool {
 				return false
 			}
 		}
+
 		return true
 	case len(w.workflow.IfAny) > 0:
 		for _, c := range w.workflow.IfAny {
@@ -35,6 +37,7 @@ func (w *Session) checkCondition() bool {
 				return true
 			}
 		}
+
 		return false
 	case len(w.workflow.Unless) > 0:
 		for _, c := range w.workflow.Unless {
@@ -42,6 +45,7 @@ func (w *Session) checkCondition() bool {
 				return false
 			}
 		}
+
 		return true
 	case len(w.workflow.UnlessAll) > 0:
 		for _, c := range w.workflow.UnlessAll {
@@ -49,6 +53,7 @@ func (w *Session) checkCondition() bool {
 				return true
 			}
 		}
+
 		return false
 	case w.workflow.Match != nil:
 		return dipper.CompareAll(w.ctx, w.workflow.Match)
@@ -56,8 +61,10 @@ func (w *Session) checkCondition() bool {
 		if reflect.ValueOf(w.workflow.UnlessMatch).Len() > 0 {
 			return !dipper.CompareAll(w.ctx, w.workflow.UnlessMatch)
 		}
+
 		return true
 	}
+
 	return true
 }
 
@@ -67,6 +74,7 @@ func (w *Session) checkLoopCondition(msg *dipper.Message) bool {
 	case w.workflow.WhileMatch != nil:
 		envData := w.buildEnvData(msg)
 		scenario := dipper.Interpolate(w.workflow.WhileMatch, envData)
+
 		return dipper.CompareAll(w.ctx, scenario)
 	case w.workflow.UntilMatch != nil:
 		envData := w.buildEnvData(msg)
@@ -74,6 +82,7 @@ func (w *Session) checkLoopCondition(msg *dipper.Message) bool {
 		if scenario != nil && reflect.ValueOf(scenario).Len() > 0 {
 			return !dipper.CompareAll(w.ctx, scenario)
 		}
+
 		return true
 	case len(w.workflow.While) > 0:
 		envData := w.buildEnvData(msg)
@@ -83,6 +92,7 @@ func (w *Session) checkLoopCondition(msg *dipper.Message) bool {
 				return false
 			}
 		}
+
 		return true
 	case len(w.workflow.WhileAny) > 0:
 		envData := w.buildEnvData(msg)
@@ -92,6 +102,7 @@ func (w *Session) checkLoopCondition(msg *dipper.Message) bool {
 				return true
 			}
 		}
+
 		return false
 	case len(w.workflow.Until) > 0:
 		envData := w.buildEnvData(msg)
@@ -101,6 +112,7 @@ func (w *Session) checkLoopCondition(msg *dipper.Message) bool {
 				return false
 			}
 		}
+
 		return true
 	case len(w.workflow.UntilAll) > 0:
 		envData := w.buildEnvData(msg)
@@ -110,7 +122,9 @@ func (w *Session) checkLoopCondition(msg *dipper.Message) bool {
 				return true
 			}
 		}
+
 		return false
 	}
+
 	return true // not a loop
 }
diff --git a/internal/workflow/continue.go b/internal/workflow/continue.go
index 520d9fe..6beba83 100644
--- a/internal/workflow/continue.go
+++ b/internal/workflow/continue.go
@@ -16,18 +16,18 @@ import (
 )
 
 const (
-	// WorkflowNextComplete starts the list of statuses used for determine how to handle a session
+	// WorkflowNextComplete starts the list of statuses used for determine how to handle a session.
 	WorkflowNextComplete = iota
-	// WorkflowNextStep means the workflow will continue with next step in a multi-step workflow
+	// WorkflowNextStep means the workflow will continue with next step in a multi-step workflow.
 	WorkflowNextStep
-	// WorkflowNextThread means the workflow will continue waiting for the next threa to finish
+	// WorkflowNextThread means the workflow will continue waiting for the next threa to finish.
 	WorkflowNextThread
-	// WorkflowNextIteration means the workflow will continue process next item in the iteration list
+	// WorkflowNextIteration means the workflow will continue process next item in the iteration list.
 	WorkflowNextIteration
 	// WorkflowNextParallelIteration means the workflow will continue waiting for the next item
-	// to be processed in the iteration list
+	// to be processed in the iteration list.
 	WorkflowNextParallelIteration
-	// WorkflowNextRound means the workflow will continue with the next round of the loop
+	// WorkflowNextRound means the workflow will continue with the next round of the loop.
 	WorkflowNextRound
 )
 
@@ -74,6 +74,7 @@ func (w *Session) routeNext(msg *dipper.Message) int {
 		if w.workflow.Iterate != nil {
 			return WorkflowNextIteration
 		}
+
 		return WorkflowNextParallelIteration
 	}
 
@@ -85,10 +86,14 @@ func (w *Session) routeNext(msg *dipper.Message) int {
 }
 
 // mergeContext merges child workflow exported context to parent workflow.
-func (w *Session) mergeContext(exports map[string]interface{}) {
-	w.ctx = dipper.MergeMap(w.ctx, dipper.MustDeepCopy(exports))
-	w.processNoExport(exports)
-	w.exported = dipper.MergeMap(w.exported, exports)
+func (w *Session) mergeContext(exports []map[string]interface{}) {
+	for _, export := range exports {
+		w.ctx = dipper.MergeMap(w.ctx, export)
+		w.processNoExport(export)
+		if len(export) > 0 {
+			w.exported = append(w.exported, export)
+		}
+	}
 }
 
 // processNoExport prevent exporting the data into parent workflow session.
@@ -98,6 +103,7 @@ func (w *Session) processNoExport(exported map[string]interface{}) {
 			for k := range exported {
 				delete(exported, k)
 			}
+
 			break
 		}
 		delete(exported, key)
@@ -108,31 +114,40 @@ func (w *Session) processNoExport(exported map[string]interface{}) {
 
 // processExport export the data into parent workflow session.
 func (w *Session) processExport(msg *dipper.Message) {
-	if w.elseBranch == nil {
-		envData := w.buildEnvData(msg)
-		status := msg.Labels["status"]
-
-		if w.inFlyFunction != nil && status != SessionStatusError {
-			exports := config.ExportFunctionContext(w.inFlyFunction, envData, w.store.Helper.GetConfig())
-			w.mergeContext(exports)
-			delete(envData, "sysData")
-		}
-		if status != SessionStatusError {
-			w.postWorkflowExport(w.workflow.Export, envData)
-		}
-		if status == SessionStatusSuccess {
-			w.postWorkflowExport(w.workflow.ExportOnSuccess, envData)
-		}
-		if status == SessionStatusFailure {
-			w.postWorkflowExport(w.workflow.ExportOnFailure, envData)
+	if w.elseBranch != nil {
+		return
+	}
+
+	envData := w.buildEnvData(msg)
+	status := msg.Labels["status"]
+
+	if w.inFlyFunction != nil && status != SessionStatusError {
+		export := config.ExportFunctionContext(w.inFlyFunction, envData, w.store.Helper.GetConfig())
+		delete(envData, "sysData")
+		w.processNoExport(export)
+		if len(export) > 0 {
+			w.exported = append(w.exported, export)
 		}
 	}
+	if status != SessionStatusError {
+		w.postWorkflowExport(w.workflow.Export, envData)
+	}
+	if status == SessionStatusSuccess {
+		w.postWorkflowExport(w.workflow.ExportOnSuccess, envData)
+	}
+	if status == SessionStatusFailure {
+		w.postWorkflowExport(w.workflow.ExportOnFailure, envData)
+	}
 }
 
 func (w *Session) postWorkflowExport(exportMap map[string]interface{}, envData map[string]interface{}) {
 	delta := dipper.Interpolate(exportMap, envData).(map[string]interface{})
-	w.mergeContext(delta)
+	w.ctx = dipper.MergeMap(w.ctx, delta)
 	envData["ctx"] = w.ctx
+	w.processNoExport(delta)
+	if len(delta) > 0 {
+		w.exported = append(w.exported, delta)
+	}
 }
 
 // fireCompleteHooks fires all the hooks at completion time asychronously.
@@ -179,6 +194,7 @@ func (w *Session) isInCompleteHooks() bool {
 	case WorkflowHookExit:
 		return true
 	}
+
 	return false
 }
 
@@ -283,10 +299,11 @@ func (w *Session) continueAfterHook(msg *dipper.Message) {
 }
 
 // continueExec resume a session with given dipper message.
-func (w *Session) continueExec(msg *dipper.Message, exports map[string]interface{}) {
+func (w *Session) continueExec(msg *dipper.Message, exports []map[string]interface{}) {
 	w.mergeContext(exports)
 	if w.currentHook != "" {
 		w.continueAfterHook(msg)
+
 		return
 	}
 	route := w.routeNext(msg)
diff --git a/internal/workflow/execute.go b/internal/workflow/execute.go
index 4ab80ba..87849e9 100644
--- a/internal/workflow/execute.go
+++ b/internal/workflow/execute.go
@@ -167,6 +167,7 @@ func (w *Session) launchParallelIterations(msg *dipper.Message) {
 func (w *Session) executeIteration(msg *dipper.Message) {
 	if !w.isIteration() {
 		w.executeAction(msg)
+
 		return
 	}
 	w.current = 0
@@ -242,6 +243,7 @@ func (w *Session) executeSwitch(msg *dipper.Message) {
 			}
 			child := w.createChildSession(wf, msg)
 			child.execute(msg)
+
 			return
 		}
 	}
@@ -254,6 +256,7 @@ func (w *Session) executeSwitch(msg *dipper.Message) {
 		}
 		child := w.createChildSession(&defaultBranch, msg)
 		child.execute(msg)
+
 		return
 	}
 	w.noop(msg)
diff --git a/internal/workflow/hooks.go b/internal/workflow/hooks.go
index 230212c..f5a8541 100644
--- a/internal/workflow/hooks.go
+++ b/internal/workflow/hooks.go
@@ -19,6 +19,7 @@ func (w *Session) fireHook(name string, msg *dipper.Message) {
 		if w.currentHook == name {
 			// hook is cleared when called again
 			w.currentHook = ""
+
 			return
 		}
 		// this line might be unreachable but leave it here for safety
diff --git a/internal/workflow/session.go b/internal/workflow/session.go
index 895f670..3f06429 100644
--- a/internal/workflow/session.go
+++ b/internal/workflow/session.go
@@ -16,7 +16,7 @@ import (
 )
 
 const (
-	// WorkflowError is the base error for all workflow related errors
+	// WorkflowError is the base error for all workflow related errors.
 	WorkflowError dipper.Error = "workflow error"
 )
 
@@ -31,7 +31,7 @@ type Session struct {
 	parent         string
 	ctx            map[string]interface{}
 	event          map[string]interface{}
-	exported       map[string]interface{}
+	exported       []map[string]interface{}
 	elseBranch     *config.Workflow
 	inFlyFunction  *config.Function
 	store          *SessionStore
@@ -48,7 +48,7 @@ type Session struct {
 type SessionHandler interface {
 	prepare(msg *dipper.Message, parent interface{}, ctx map[string]interface{})
 	execute(msg *dipper.Message)
-	continueExec(msg *dipper.Message, exports map[string]interface{})
+	continueExec(msg *dipper.Message, exports []map[string]interface{})
 	onError()
 	GetName() string
 	GetDescription() string
@@ -56,23 +56,23 @@ type SessionHandler interface {
 	GetEventID() string
 	GetEventName() string
 	GetStatus() (string, string)
-	GetExported() map[string]interface{}
+	GetExported() []map[string]interface{}
 	Watch() <-chan struct{}
 }
 
 const (
-	// SessionStatusSuccess means the workflow executed successfully
+	// SessionStatusSuccess means the workflow executed successfully.
 	SessionStatusSuccess = "success"
-	// SessionStatusFailure means the workflow completed with failure
+	// SessionStatusFailure means the workflow completed with failure.
 	SessionStatusFailure = "failure"
-	// SessionStatusError means the workflow ran into error, and was not able to complete
+	// SessionStatusError means the workflow ran into error, and was not able to complete.
 	SessionStatusError = "error"
 
-	// SessionContextDefault is a builtin context for all workflows
+	// SessionContextDefault is a builtin context for all workflows.
 	SessionContextDefault = "_default"
-	// SessionContextEvents is a context with default values for all directly event triggered workflows
+	// SessionContextEvents is a context with default values for all directly event triggered workflows.
 	SessionContextEvents = "_events"
-	// SessionContextHooks is a context for all hooks workflows
+	// SessionContextHooks is a context for all hooks workflows.
 	SessionContextHooks = "_hooks"
 )
 
@@ -343,6 +343,7 @@ func (w *Session) inheritParentSettings(p *Session) {
 func (w *Session) createChildSession(wf *config.Workflow, msg *dipper.Message) *Session {
 	child := w.store.newSession(w.ID, w.EventID, wf)
 	child.prepare(msg, w, nil)
+
 	return child.(*Session)
 }
 
@@ -418,6 +419,7 @@ func (w *Session) createChildSessionWithName(name string, msg *dipper.Message) *
 		src.Name = name
 	}
 	wf := &src
+
 	return w.createChildSession(wf, msg)
 }
 
@@ -446,6 +448,7 @@ func (w *Session) Watch() <-chan struct{} {
 	if w.context == nil {
 		w.context, w.cancelFunc = context.WithCancel(context.Background())
 	}
+
 	return w.context.Done()
 }
 
@@ -459,11 +462,12 @@ func (w *Session) GetStatus() (string, string) {
 		status = SessionStatusSuccess
 	}
 	reason = w.savedMsg.Labels["reason"]
+
 	return status, reason
 }
 
 // GetExported returns the exported data from the session.
-func (w *Session) GetExported() map[string]interface{} {
+func (w *Session) GetExported() []map[string]interface{} {
 	return w.exported
 }
 
@@ -473,5 +477,6 @@ func (w *Session) GetEventName() string {
 	if ok {
 		return evn.(string)
 	}
+
 	return ""
 }
diff --git a/internal/workflow/store.go b/internal/workflow/store.go
index 06e5eaf..e437fca 100644
--- a/internal/workflow/store.go
+++ b/internal/workflow/store.go
@@ -34,6 +34,7 @@ func NewSessionStore(helper SessionStoreHelper) *SessionStore {
 		Helper:            helper,
 	}
 	dipper.InitIDMap(&s.sessions)
+
 	return s
 }
 
@@ -67,7 +68,7 @@ func (s *SessionStore) StartSession(wf *config.Workflow, msg *dipper.Message, ct
 }
 
 // ContinueSession resume a session with given dipper message.
-func (s *SessionStore) ContinueSession(sessionID string, msg *dipper.Message, exports map[string]interface{}) {
+func (s *SessionStore) ContinueSession(sessionID string, msg *dipper.Message, exports []map[string]interface{}) {
 	defer dipper.SafeExitOnError("[workflow] error when continuing workflow session %s", sessionID)
 	w := dipper.IDMapGet(&s.sessions, sessionID).(SessionHandler)
 	defer w.onError()
@@ -110,6 +111,7 @@ func (s *SessionStore) ByEventID(eventID string) []SessionHandler {
 			ret = append(ret, sh)
 		}
 	}
+
 	return ret
 }
 
@@ -121,5 +123,6 @@ func (s *SessionStore) GetEvents() []SessionHandler {
 			ret = append(ret, sh)
 		}
 	}
+
 	return ret
 }
diff --git a/pkg/dipper/comm.go b/pkg/dipper/comm.go
index 66225ec..d2105b8 100644
--- a/pkg/dipper/comm.go
+++ b/pkg/dipper/comm.go
@@ -265,5 +265,6 @@ func MessageCopy(m *Message) (*Message, error) {
 	if err != nil {
 		return nil, err
 	}
+
 	return &mcopy, nil
 }
diff --git a/pkg/dipper/commandHandler.go b/pkg/dipper/commandHandler.go
index bc40be9..23d5252 100644
--- a/pkg/dipper/commandHandler.go
+++ b/pkg/dipper/commandHandler.go
@@ -47,6 +47,7 @@ func (p *CommandProvider) ReturnError(call *Message, pattern string, args ...int
 		},
 	})
 	Logger.Warningf("[operator] %s", errText)
+
 	return Error(errText)
 }
 
diff --git a/pkg/dipper/condition.go b/pkg/dipper/condition.go
index c7194d0..07cbde1 100644
--- a/pkg/dipper/condition.go
+++ b/pkg/dipper/condition.go
@@ -35,6 +35,7 @@ func Compare(actual string, criteria interface{}) bool {
 				return true
 			}
 		}
+
 		return false
 	}
 
@@ -54,6 +55,7 @@ func CompareMap(actual interface{}, criteria interface{}) bool {
 				return true
 			}
 		}
+
 		return false
 	case map[string]interface{}:
 		value := reflect.ValueOf(actual)
@@ -78,6 +80,7 @@ func CompareMap(actual interface{}, criteria interface{}) bool {
 				}
 			}
 		}
+
 		return true
 	}
 	// map value with an unsupported criteria
@@ -104,6 +107,7 @@ func CompareAll(actual interface{}, criteria interface{}) bool {
 					return false
 				}
 			}
+
 			return true
 		}
 
@@ -113,6 +117,7 @@ func CompareAll(actual interface{}, criteria interface{}) bool {
 				return true
 			}
 		}
+
 		return false
 
 	case reflect.Map:
@@ -132,7 +137,9 @@ func RegexParser(key string, val interface{}) (ret interface{}, replace bool) {
 			}
 			Logger.Warningf("skipping invalid regex pattern %s", str[7:])
 		}
+
 		return nil, false
 	}
+
 	return nil, false
 }
diff --git a/pkg/dipper/driver.go b/pkg/dipper/driver.go
index 97762ea..158097d 100644
--- a/pkg/dipper/driver.go
+++ b/pkg/dipper/driver.go
@@ -23,7 +23,7 @@ const (
 	// the ExtraFiles list, this is always 3.
 	DriverLogDescriptor uintptr = 3
 
-	// DefaultAPITimeout is the default timeout for making an outbound API call
+	// DefaultAPITimeout is the default timeout for making an outbound API call.
 	DefaultAPITimeout time.Duration = 10
 )
 
@@ -71,6 +71,7 @@ func NewDriver(service string, name string) *Driver {
 	}
 
 	driver.GetLogger()
+
 	return &driver
 }
 
@@ -114,7 +115,7 @@ func (d *Driver) ReceiveOptions(msg *Message) {
 	Logger = nil
 	d.GetLogger()
 	d.APITimeout = DefaultAPITimeout
-	apiTimeoutStr, ok := d.GetOptionStr("api_timeout")
+	apiTimeoutStr, ok := d.GetOptionStr("data.api_timeout")
 	if ok {
 		apiTimeout, e := strconv.Atoi(apiTimeoutStr)
 		if e != nil {
@@ -186,8 +187,10 @@ func (d *Driver) GetLogger() *logging.Logger {
 		if logFile == nil {
 			logFile = os.NewFile(DriverLogDescriptor, "log")
 		}
+
 		return GetLogger(d.Name, levelstr, logFile)
 	}
+
 	return Logger
 }
 
@@ -215,6 +218,7 @@ func (d *Driver) EmitEvent(payload map[string]interface{}) string {
 			"eventID": id.String(),
 		},
 	})
+
 	return id.String()
 }
 
diff --git a/pkg/dipper/encryption.go b/pkg/dipper/encryption.go
index 76c322b..83fd2e0 100644
--- a/pkg/dipper/encryption.go
+++ b/pkg/dipper/encryption.go
@@ -25,9 +25,11 @@ func DecryptAll(rpc RPCCaller, from interface{}) {
 					Logger.Panicf("encrypted data shoud be base64 encoded")
 				}
 				decrypted, _ := rpc.CallRaw("driver:"+encDriver, "decrypt", decoded)
+
 				return string(decrypted), true
 			}
 		}
+
 		return nil, false
 	})
 }
diff --git a/pkg/dipper/errorHandling.go b/pkg/dipper/errorHandling.go
index 9877173..4b7f1d9 100644
--- a/pkg/dipper/errorHandling.go
+++ b/pkg/dipper/errorHandling.go
@@ -68,5 +68,6 @@ func Must(args ...interface{}) interface{} {
 	case 2:
 		return args[0]
 	}
+
 	return args[0 : l-1]
 }
diff --git a/pkg/dipper/idmap.go b/pkg/dipper/idmap.go
index b35cfc2..b237bad 100644
--- a/pkg/dipper/idmap.go
+++ b/pkg/dipper/idmap.go
@@ -75,5 +75,6 @@ func IDMapGet(m IDMap, key string) interface{} {
 
 	mapValue := reflect.ValueOf(m).Elem()
 	ret := mapValue.MapIndex(reflect.ValueOf(key)).Interface()
+
 	return ret
 }
diff --git a/pkg/dipper/interpolation.go b/pkg/dipper/interpolation.go
index 46d54a4..fd45ab9 100644
--- a/pkg/dipper/interpolation.go
+++ b/pkg/dipper/interpolation.go
@@ -18,7 +18,7 @@ import (
 )
 
 const (
-	// InterpolationError represents all errors thrown due to failure to interpolate
+	// InterpolationError represents all errors thrown due to failure to interpolate.
 	InterpolationError Error = "config error"
 )
 
@@ -33,6 +33,7 @@ var FuncMap = template.FuncMap{
 		if err != nil {
 			panic(err)
 		}
+
 		return string(s)
 	},
 }
@@ -43,6 +44,7 @@ func InterpolateStr(pattern string, data interface{}) string {
 	if ret != nil {
 		return fmt.Sprintf("%+v", ret)
 	}
+
 	return ""
 }
 
@@ -55,8 +57,10 @@ func InterpolateGoTemplate(pattern string, data interface{}) string {
 			Logger.Warningf("interpolation pattern failed: %+v", pattern)
 			Logger.Panicf("failed to interpolate: %+v", err)
 		}
+
 		return buf.String()
 	}
+
 	return pattern
 }
 
@@ -67,6 +71,7 @@ func ParseYaml(pattern string) interface{} {
 	if err != nil {
 		panic(err)
 	}
+
 	return data
 }
 
@@ -101,6 +106,7 @@ func InterpolateDollarStr(v string, data interface{}) interface{} {
 			if strings.HasPrefix(key, "sysData.") {
 				return Interpolate(ret, data)
 			}
+
 			return ret
 		}
 	}
@@ -109,6 +115,7 @@ func InterpolateDollarStr(v string, data interface{}) interface{} {
 		if parsed[quote] != parsed[len(parsed)-1] {
 			panic(fmt.Errorf("quotes not matching: %s: %w", parsed, InterpolationError))
 		}
+
 		return parsed[quote+1 : len(parsed)-1]
 	}
 
@@ -135,29 +142,34 @@ func Interpolate(source interface{}, data interface{}) interface{} {
 					panic(r)
 				}
 			}()
+
 			return ParseYaml(ret[6:])
 		}
-
 		ret = strings.TrimPrefix(ret, "\\")
+
 		return ret
 	case map[string]interface{}:
 		ret := map[string]interface{}{}
 		for k, val := range v {
 			ret[k] = Interpolate(val, data)
 		}
+
 		return ret
 	case []string:
 		ret := []string{}
 		for _, val := range v {
 			ret = append(ret, InterpolateStr(val, data))
 		}
+
 		return ret
 	case []interface{}:
 		ret := []interface{}{}
 		for _, val := range v {
 			ret = append(ret, Interpolate(val, data))
 		}
+
 		return ret
 	}
+
 	return source
 }
diff --git a/pkg/dipper/logging.go b/pkg/dipper/logging.go
index 21156ee..fa428e6 100644
--- a/pkg/dipper/logging.go
+++ b/pkg/dipper/logging.go
@@ -67,5 +67,6 @@ func GetLogger(module string, verbosity string, logFiles ...*os.File) *logging.L
 	}
 	logging.SetBackend(logBackends...)
 	Logger = logging.MustGetLogger(module)
+
 	return Logger
 }
diff --git a/pkg/dipper/mapUtils.go b/pkg/dipper/mapUtils.go
index a3192a7..9ca6231 100644
--- a/pkg/dipper/mapUtils.go
+++ b/pkg/dipper/mapUtils.go
@@ -17,10 +17,10 @@ import (
 )
 
 const (
-	// MapError are all errors thrown in map manipulation
+	// MapError are all errors thrown in map manipulation.
 	MapError Error = "map error"
 
-	// MergeError are all errors throw during map merge and combin
+	// MergeError are all errors throw during map merge and combin.
 	MergeError Error = "merge error"
 )
 
@@ -57,6 +57,7 @@ func GetMapData(from interface{}, path string) (ret interface{}, ok bool) {
 	if !current.IsValid() {
 		return nil, false
 	}
+
 	return current.Interface(), true
 }
 
@@ -66,6 +67,7 @@ func MustGetMapData(from interface{}, path string) interface{} {
 	if !ok {
 		panic(fmt.Errorf("path not valid: %s: %w", path, MapError))
 	}
+
 	return ret
 }
 
@@ -73,14 +75,17 @@ func MustGetMapData(from interface{}, path string) interface{} {
 func GetMapDataStr(from interface{}, path string) (ret string, ok bool) {
 	if data, ok := GetMapData(from, path); ok {
 		str, ok := data.(string)
+
 		return str, ok
 	}
+
 	return "", ok
 }
 
 // MustGetMapDataStr : get the data as string from the deep map following a KV path, may raise errors.
 func MustGetMapDataStr(from interface{}, path string) string {
 	ret := MustGetMapData(from, path)
+
 	return ret.(string)
 }
 
@@ -96,9 +101,11 @@ func GetMapDataBool(from interface{}, path string) (ret bool, ok bool) {
 			return (v != 0), true
 		case string:
 			flag, err := strconv.ParseBool(v)
+
 			return flag, (err == nil)
 		}
 	}
+
 	return false, false
 }
 
@@ -118,6 +125,7 @@ func MustGetMapDataBool(from interface{}, path string) bool {
 			if err != nil {
 				panic(err)
 			}
+
 			return flag
 		}
 	}
@@ -202,6 +210,7 @@ func LockGetMap(lock *sync.Mutex, resource interface{}, key interface{}) (ret in
 	if !retVal.IsValid() {
 		return nil, false
 	}
+
 	return retVal.Interface(), true
 }
 
@@ -221,6 +230,7 @@ func LockSetMap(lock *sync.Mutex, resource interface{}, key interface{}, val int
 	if retVal.IsValid() {
 		return retVal.Interface()
 	}
+
 	return nil
 }
 
@@ -248,6 +258,7 @@ func LockCheckDeleteMap(lock *sync.Mutex, resource interface{}, key interface{},
 	if retVal.IsValid() {
 		return retVal.Interface()
 	}
+
 	return nil
 }
 
@@ -264,6 +275,7 @@ func DeepCopyMap(m map[string]interface{}) (map[string]interface{}, error) {
 	if !ok {
 		return nil, fmt.Errorf("not a map: %w", MapError)
 	}
+
 	return retMap, nil
 }
 
@@ -279,6 +291,7 @@ func DeepCopy(m interface{}) (interface{}, error) {
 			}
 			ret[k] = vcopy
 		}
+
 		return ret, nil
 	case []interface{}:
 		ret := make([]interface{}, len(v))
@@ -289,8 +302,10 @@ func DeepCopy(m interface{}) (interface{}, error) {
 			}
 			ret[i] = vcopy
 		}
+
 		return ret, nil
 	}
+
 	return m, nil
 }
 
@@ -300,6 +315,7 @@ func MustDeepCopyMap(m map[string]interface{}) map[string]interface{} {
 	if err != nil {
 		panic(err)
 	}
+
 	return ret
 }
 
@@ -309,6 +325,7 @@ func MustDeepCopy(m interface{}) interface{} {
 	if err != nil {
 		panic(err)
 	}
+
 	return ret
 }
 
@@ -324,6 +341,7 @@ func CombineMap(dst map[string]interface{}, src interface{}) map[string]interfac
 	if err != nil {
 		panic(err)
 	}
+
 	return dst
 }
 
diff --git a/pkg/dipper/netutil.go b/pkg/dipper/netutil.go
index 6bac4d3..68a9f1e 100644
--- a/pkg/dipper/netutil.go
+++ b/pkg/dipper/netutil.go
@@ -23,8 +23,10 @@ func GetIP() string {
 			if slash := strings.IndexByte(ip, '/'); slash >= 0 {
 				ip = ip[0:slash]
 			}
+
 			return ip
 		}
 	}
+
 	return ""
 }
diff --git a/pkg/dipper/rpc.go b/pkg/dipper/rpc.go
index 8c364b2..4433f27 100644
--- a/pkg/dipper/rpc.go
+++ b/pkg/dipper/rpc.go
@@ -14,13 +14,13 @@ import (
 )
 
 const (
-	// TimeoutError indicates a timeout error
+	// TimeoutError indicates a timeout error.
 	TimeoutError Error = "timeout"
 
-	// RPCError indicates errors happened during RPC call
+	// RPCError indicates errors happened during RPC call.
 	RPCError Error = "rpc error"
 
-	// DefaultRPCTimeout is the default timeout in seconds for RPC calls
+	// DefaultRPCTimeout is the default timeout in seconds for RPC calls.
 	DefaultRPCTimeout time.Duration = 10
 )
 
@@ -70,6 +70,7 @@ func (c *RPCCallerBase) GetName() string {
 // Call : making a RPC call to another driver with structured data.
 func (c *RPCCallerBase) Call(feature string, method string, params interface{}) ([]byte, error) {
 	ret, err := c.CallRaw(feature, method, SerializeContent(params))
+
 	return ret, err
 }
 
@@ -97,6 +98,7 @@ func (c *RPCCallerBase) CallRaw(feature string, method string, params []byte) ([
 		} else if e, ok := msg.(error); ok {
 			return nil, e
 		}
+
 		return msg.([]byte), nil
 	case <-time.After(time.Second * DefaultRPCTimeout):
 		return nil, TimeoutError


Test patch:
diff --git a/internal/api/request_test.go b/internal/api/request_test.go
index 0a244cc..363b1ca 100644
--- a/internal/api/request_test.go
+++ b/internal/api/request_test.go
@@ -85,13 +85,23 @@ func requestTest(t *testing.T, caseName string) (*Store, *RequestTestCase) {
 		l.writeTimeout = time.Millisecond * 100
 	}
 
-	startSignal := make(chan struct{})
 	started := false
 	for _, st := range c.Steps {
 		mockRPCCaller.EXPECT().Call(gomock.Eq(st.Feature), gomock.Eq(st.Method), gomock.Eq(st.ExpectedMessage)).Times(1).DoAndReturn(func(_, _ string, _ map[string]interface{}) (interface{}, error) {
 			if !started {
 				started = true
-				close(startSignal)
+				go func() {
+					for _, st := range c.Returns {
+						dipper.Logger.Warning("delaying %d ms", st.Delay)
+						time.Sleep(st.Delay)
+						switch st.Msg.Labels["type"] {
+						case "ack":
+							l.HandleAPIACK(st.Msg)
+						case "result":
+							l.HandleAPIReturn(st.Msg)
+						}
+					}
+				}()
 			}
 			return st.ReturnMessage, st.Err
 		})
@@ -103,20 +113,6 @@ func requestTest(t *testing.T, caseName string) (*Store, *RequestTestCase) {
 		mockReqCtx.EXPECT().IndentedJSON(gomock.Eq(c.ExpectedCode), gomock.Eq(c.ExpectedContent)).Times(1)
 	}
 
-	go func() {
-		<-startSignal
-		for _, st := range c.Returns {
-			dipper.Logger.Warning("delaying %d ms", st.Delay)
-			time.Sleep(st.Delay)
-			switch st.Msg.Labels["type"] {
-			case "ack":
-				l.HandleAPIACK(st.Msg)
-			case "result":
-				l.HandleAPIReturn(st.Msg)
-			}
-		}
-	}()
-
 	l.HandleHTTPRequest(mockReqCtx, c.Def)
 	return l, c
 }
diff --git a/internal/workflow/main_test.go b/internal/workflow/main_test.go
index 37cd90d..48d3a6b 100644
--- a/internal/workflow/main_test.go
+++ b/internal/workflow/main_test.go
@@ -106,7 +106,7 @@ func syntheticTest(t *testing.T, configStr string, testcase map[string]interface
 			timeout = num.(time.Duration)
 		}
 		go func() {
-			store.ContinueSession(teststep["sessionID"].(string), teststep["msg"].(*dipper.Message), teststep["ctx"].(map[string]interface{}))
+			store.ContinueSession(teststep["sessionID"].(string), teststep["msg"].(*dipper.Message), []map[string]interface{}{teststep["ctx"].(map[string]interface{})})
 			daemon.Children.Wait()
 			signal <- 1
 		}()