Repository: ovh/cds
Pull request #4776 (2019-11-22 09:15:14)

fix(ui): display workflow error message correctly
Signed-off-by: Benjamin Coenen <benjamin.coenen@corp.ovh.com>

1. Description
1. Related issues
1. About tests
1. Mentions

@ovh/cds


ovh-cds: 
CDS Report ut-engine#11433.0 ✘  
* Stage 1
  * Engine Test with DB ✘  

ovh-cds: 
CDS Report cds-package#11433.0 ✘  
* build-package
  * Debian Engine Package ✘  
  * Docker Engine Package ✔ 
  * Package UI ✔ 


Patch:
diff --git a/cli/cdsctl/template_apply.go b/cli/cdsctl/template_apply.go
index 0a99a4413..4dc0ec775 100644
--- a/cli/cdsctl/template_apply.go
+++ b/cli/cdsctl/template_apply.go
@@ -326,7 +326,7 @@ func templateApplyRun(v cli.Values) error {
 			return err
 		}
 
-		// store the choosen workflow name to git config
+		// store the chosen workflow name to git config
 		if localRepoName != "" {
 			if err := r.LocalConfigSet("cds", "workflow", workflowName); err != nil {
 				return err
diff --git a/cli/cdsctl/workflow_init.go b/cli/cdsctl/workflow_init.go
index e46e27d6c..19f81cccf 100644
--- a/cli/cdsctl/workflow_init.go
+++ b/cli/cdsctl/workflow_init.go
@@ -284,7 +284,7 @@ func craftApplicationFile(proj *sdk.Project, existingApp *sdk.Application, fetch
 	}
 
 	// First collect all PGP and SSSH Keys/
-	// And try to find teh chosen key
+	// And try to find the chosen key
 	projectPGPKeys := make([]sdk.ProjectKey, 0, len(proj.Keys))
 	projectSSHKeys := make([]sdk.ProjectKey, 0, len(proj.Keys))
 	for i := range proj.Keys {
diff --git a/cli/cdsctl/workflow_transform_as_code.go b/cli/cdsctl/workflow_transform_as_code.go
index 549ce850a..86d740542 100644
--- a/cli/cdsctl/workflow_transform_as_code.go
+++ b/cli/cdsctl/workflow_transform_as_code.go
@@ -54,7 +54,7 @@ func workflowTransformAsCodeRun(v cli.Values) (interface{}, error) {
 	if err != nil {
 		return nil, fmt.Errorf("cannot read id from pull request URL %s: %v", ope.Setup.Push.PRLink, err)
 	}
-	reponse := struct {
+	response := struct {
 		URL string `cli:"url" json:"url"`
 		ID  int    `cli:"id" json:"id"`
 	}{
@@ -65,5 +65,5 @@ func workflowTransformAsCodeRun(v cli.Values) (interface{}, error) {
 	case sdk.OperationStatusError:
 		return nil, fmt.Errorf("cannot perform operation: %s", ope.Error)
 	}
-	return reponse, nil
+	return response, nil
 }
diff --git a/cli/cobra.go b/cli/cobra.go
index b857c488a..205ae2ede 100644
--- a/cli/cobra.go
+++ b/cli/cobra.go
@@ -59,6 +59,7 @@ func OSExit(code int) {
 	}
 }
 
+// SubCommands represents an array of cobra.Command
 type SubCommands []*cobra.Command
 
 // NewCommand creates a new cobra command with or without a RunFunc and eventually subCommands
diff --git a/cli/display.go b/cli/display.go
index f851cba2b..f23b1804c 100644
--- a/cli/display.go
+++ b/cli/display.go
@@ -50,6 +50,8 @@ func (d *Display) Do(ctx context.Context) {
 	}(d)
 }
 
+// Ellipsis return a trunckated string
+// if i parameter is < of string length
 func Ellipsis(s string, i int) string {
 	if len(s) > i {
 		return s[:i] + "…"
diff --git a/cli/types.go b/cli/types.go
index 558e72b7c..2a076b6d0 100644
--- a/cli/types.go
+++ b/cli/types.go
@@ -116,7 +116,7 @@ func (s args) Swap(i, j int) {
 	s[i], s[j] = s[j], s[i]
 }
 
-// Command represents the way to instanciate a cobra.Command
+// Command represents the way to instantiate a cobra.Command
 type Command struct {
 	Name         string
 	Ctx          []Arg
diff --git a/contrib/actions/cds-python-pylint.yml b/contrib/actions/cds-python-pylint.yml
index e99a64787..4099a81b1 100644
--- a/contrib/actions/cds-python-pylint.yml
+++ b/contrib/actions/cds-python-pylint.yml
@@ -216,7 +216,7 @@ steps:
   - '            with open(raw_output_file, "w") as raw_f:'
   - '                for line in lint_result:'
   - '                    raw_f.write(line)'
-  - '            LOG.info("Wrote raw pylint ouput to %s" % raw_output_file)'
+  - '            LOG.info("Wrote raw pylint output to %s" % raw_output_file)'
   - '        else:'
   - '            LOG.info("Pylint result : \n %s" % "\n".join(lint_result))'
   - '        with open(xml_output_file, "w") as xml_f:'
diff --git a/contrib/grpcplugins/action/clair/clairctl/clair/analyze.go b/contrib/grpcplugins/action/clair/clairctl/clair/analyze.go
index eccf4df68..c25c32d33 100644
--- a/contrib/grpcplugins/action/clair/clairctl/clair/analyze.go
+++ b/contrib/grpcplugins/action/clair/clairctl/clair/analyze.go
@@ -82,7 +82,7 @@ func analyzeLayer(id string) (v1.LayerEnvelope, error) {
 		return v1.LayerEnvelope{}, fmt.Errorf("reading layer analysis: %v", err)
 	}
 	if response.StatusCode != 200 {
-		//TODO(jgsqware): should I show reponse body in case of error?
+		//TODO(jgsqware): should I show response body in case of error?
 		return v1.LayerEnvelope{}, fmt.Errorf("receiving http error: %d", response.StatusCode)
 	}
 
diff --git a/contrib/grpcplugins/action/clair/clairctl/docker/dockerdist/dockerdist.go b/contrib/grpcplugins/action/clair/clairctl/docker/dockerdist/dockerdist.go
index f478e1ddc..7f419c432 100644
--- a/contrib/grpcplugins/action/clair/clairctl/docker/dockerdist/dockerdist.go
+++ b/contrib/grpcplugins/action/clair/clairctl/docker/dockerdist/dockerdist.go
@@ -117,7 +117,7 @@ func getRepositoryClient(image reference.Named, insecure bool, scopes ...string)
 		}
 		repository, confirmedV2, err = distribution.NewV2Repository(ctx, repoInfo, endpoint, metaHeaders, &types.AuthConfig{}, scopes...)
 		if err != nil {
-			fmt.Printf("cannot instanciate new v2 repository on %v\n", endpoint.URL)
+			fmt.Printf("cannot instantiate new v2 repository on %v\n", endpoint.URL)
 			return nil, err
 		}
 
diff --git a/contrib/grpcplugins/action/kafka-publish/README.md b/contrib/grpcplugins/action/kafka-publish/README.md
index eef0bc9a0..9d591dcc1 100644
--- a/contrib/grpcplugins/action/kafka-publish/README.md
+++ b/contrib/grpcplugins/action/kafka-publish/README.md
@@ -115,7 +115,7 @@ After that, the listener should receive files. Every file should be printed in y
     Context 1220 successfully closed
 ```
 
-Note that the context is mark as **closed**. It means that all file have been received and are availabe.
+Note that the context is mark as **closed**. It means that all file have been received and are available.
 In the current directory. a new file and a new directory have been created :
 
 ```shell
@@ -168,7 +168,7 @@ with, for instance `myScript.sh` as following :
     cat $1
 ```
 
-It run this script with the context file as first argument. So you can get the json file, parse it and do what you whant with all the files and artifacts.
+It run this script with the context file as first argument. So you can get the json file, parse it and do what you want with all the files and artifacts.
 
 Our example will prompt:
 
diff --git a/contrib/grpcplugins/action/kafka-publish/kafka_consumer.go b/contrib/grpcplugins/action/kafka-publish/kafka_consumer.go
index fd83c2a10..cbe454a8c 100644
--- a/contrib/grpcplugins/action/kafka-publish/kafka_consumer.go
+++ b/contrib/grpcplugins/action/kafka-publish/kafka_consumer.go
@@ -102,7 +102,7 @@ func consumeFromKafka(kafka, topic, group, user, password, key string, gpgPrivat
 				continue
 			}
 
-			//If we recieve a "Chunk" Message
+			//If we receive a "Chunk" Message
 			if kafkapublisher.IsChunk(msg) {
 				c, err := kafkapublisher.ReadBytes(msg)
 				if err != nil {
diff --git a/contrib/grpcplugins/action/npm-audit-parser/main.go b/contrib/grpcplugins/action/npm-audit-parser/main.go
index 02f4cb0d8..2ef39696a 100644
--- a/contrib/grpcplugins/action/npm-audit-parser/main.go
+++ b/contrib/grpcplugins/action/npm-audit-parser/main.go
@@ -41,7 +41,7 @@ func (actPlugin *npmAuditParserActionPlugin) Run(ctx context.Context, q *actionp
 	if err != nil {
 		return fail("Unable to read file %s: %v", file, err)
 	}
-	var npmAudit NpmAudit
+	var npmAudit npmAudit
 	if err := json.Unmarshal(b, &npmAudit); err != nil {
 		return fail("Unable to read npm report: %v", err)
 	}
diff --git a/contrib/grpcplugins/action/npm-audit-parser/types.go b/contrib/grpcplugins/action/npm-audit-parser/types.go
index 2d0d7ca8a..66e7f364f 100644
--- a/contrib/grpcplugins/action/npm-audit-parser/types.go
+++ b/contrib/grpcplugins/action/npm-audit-parser/types.go
@@ -1,11 +1,11 @@
 package main
 
-type NpmAudit struct {
-	Advisories map[int64]Advisory `json:"advisories"`
+type npmAudit struct {
+	Advisories map[int64]advisory `json:"advisories"`
 }
 
-type Advisory struct {
-	Findings        []Finding `json:"findings"`
+type advisory struct {
+	Findings        []finding `json:"findings"`
 	Title           string    `json:"title"`
 	Overview        string    `json:"overview"`
 	CVES            []string  `json:"cves"`
@@ -16,7 +16,7 @@ type Advisory struct {
 	CWE             string    `json:"cwe"`
 }
 
-type Finding struct {
+type finding struct {
 	Version string   `json:"version"`
 	Paths   []string `json:"paths"`
 }
diff --git a/contrib/helm/cds/values.yaml b/contrib/helm/cds/values.yaml
index 43464a3ba..d7a34ca6f 100644
--- a/contrib/helm/cds/values.yaml
+++ b/contrib/helm/cds/values.yaml
@@ -187,7 +187,7 @@ ui:
     initialDelaySeconds: 30
 
   ## Service configuration
-  # For minikube set this to NodePort. On docker for windows set this to ClusterIP and use port-foward
+  # For minikube set this to NodePort. On docker for windows set this to ClusterIP and use port-forward
   # Elsewhere use LoadBalancer or use ClusterIP if your setup includes ingress controller
   serviceType: LoadBalancer
 
diff --git a/engine/api/accesstoken/accesstoken.go b/engine/api/accesstoken/accesstoken.go
index ba6ea6060..085bfe583 100644
--- a/engine/api/accesstoken/accesstoken.go
+++ b/engine/api/accesstoken/accesstoken.go
@@ -101,7 +101,7 @@ func IsValid(db gorp.SqlExecutor, jwtToken string) (sdk.AccessToken, bool, error
 		return accessToken, false, sdk.WrapError(sdk.ErrUnauthorized, "unable find access token %s: %v", id, err)
 	}
 
-	// Check groups from the claims againts the groups in the database
+	// Check groups from the claims against the groups in the database
 	ids := sdk.GroupsToIDs(accessToken.Groups)
 	for _, groupID := range claims.Groups {
 		if !sdk.IsInInt64Array(groupID, ids) {
diff --git a/engine/api/api.go b/engine/api/api.go
index 0f9f71099..5c565869b 100644
--- a/engine/api/api.go
+++ b/engine/api/api.go
@@ -52,7 +52,7 @@ import (
 	"github.com/ovh/cds/sdk/log"
 )
 
-// Configuration is the configuraton structure for CDS API
+// Configuration is the configuration structure for CDS API
 type Configuration struct {
 	URL struct {
 		API string `toml:"api" default:"http://localhost:8081" json:"api"`
@@ -519,7 +519,7 @@ func (a *API) Serve(ctx context.Context) error {
 	if !hasWorker {
 		// If no worker, let's exit because CDS for run anything
 		log.Error("worker is unavailable for download. Please check your configuration file or the %s directory", a.Config.Directories.Download)
-		return errors.New("worker binary unavailabe")
+		return errors.New("worker binary unavailable")
 	}
 
 	//Initialize secret driver
diff --git a/engine/api/auth/auth.go b/engine/api/auth/auth.go
index 8624a0269..ae2f177f9 100644
--- a/engine/api/auth/auth.go
+++ b/engine/api/auth/auth.go
@@ -118,7 +118,7 @@ func GetWorker(db *gorp.DbMap, store cache.Store, workerID, workerName string) (
 //GetService returns the service instance from its hash
 func GetService(db *gorp.DbMap, store cache.Store, hash string) (*sdk.Service, error) {
 	//Load the service from the cache
-	//TODO: this should be embeded in the repository layer
+	//TODO: this should be embedded in the repository layer
 	var srv = &sdk.Service{}
 	key := cache.Key("services", hash)
 	find, err := store.Get(key, srv)
@@ -142,7 +142,7 @@ func GetService(db *gorp.DbMap, store cache.Store, hash string) (*sdk.Service, e
 	return srv, nil
 }
 
-// ContextValues retuns auth values of a context
+// ContextValues returns auth values of a context
 func ContextValues(ctx context.Context) map[interface{}]interface{} {
 	return map[interface{}]interface{}{
 		ContextHatchery: ctx.Value(ContextHatchery),
diff --git a/engine/api/observability/helper.go b/engine/api/observability/helper.go
index 8a6a23fc7..76ebb6fcb 100644
--- a/engine/api/observability/helper.go
+++ b/engine/api/observability/helper.go
@@ -62,7 +62,7 @@ func Current(ctx context.Context, tags ...trace.Attribute) *trace.Span {
 	return span
 }
 
-// Tag is helper function to instanciate trace.Attribute
+// Tag is helper function to instantiate trace.Attribute
 func Tag(key string, value interface{}) trace.Attribute {
 	return trace.StringAttribute(key, fmt.Sprintf("%v", value))
 }
diff --git a/engine/api/project_integration.go b/engine/api/project_integration.go
index ef118fba2..42860ce4d 100644
--- a/engine/api/project_integration.go
+++ b/engine/api/project_integration.go
@@ -78,7 +78,7 @@ func (api *API) putProjectIntegrationHandler() service.Handler {
 
 		tx, errT := api.mustDB().Begin()
 		if errT != nil {
-			return sdk.WrapError(errT, "putProjectIntegrationHandler> Cannot strat transaction")
+			return sdk.WrapError(errT, "putProjectIntegrationHandler> Cannot start transaction")
 		}
 		defer tx.Rollback()
 
diff --git a/engine/api/project_key.go b/engine/api/project_key.go
index 87095e5fe..a25f5b2bd 100644
--- a/engine/api/project_key.go
+++ b/engine/api/project_key.go
@@ -58,7 +58,7 @@ func (api *API) getAllKeysProjectHandler() service.Handler {
 
 		envKeys, errP := environment.LoadAllEnvironmentKeysByProject(api.mustDB(), p.ID)
 		if errP != nil {
-			return sdk.WrapError(errP, "getAllKeysProjectHandler> Cannot load environemnt keys")
+			return sdk.WrapError(errP, "getAllKeysProjectHandler> Cannot load environment keys")
 		}
 		allkeys.EnvironmentKeys = envKeys
 
diff --git a/engine/api/router_metrics.go b/engine/api/router_metrics.go
index e4c3e1182..1c3bee285 100644
--- a/engine/api/router_metrics.go
+++ b/engine/api/router_metrics.go
@@ -1,6 +1,6 @@
 package api
 
-// A part of this file is comming from https://github.com/census-instrumentation/opencensus-go/blob/master/plugin/ochttp/server.go
+// A part of this file is coming from https://github.com/census-instrumentation/opencensus-go/blob/master/plugin/ochttp/server.go
 
 // Copyright 2018, OpenCensus Authors
 //
diff --git a/engine/api/workflow/dao.go b/engine/api/workflow/dao.go
index 429b45a95..3d3177f44 100644
--- a/engine/api/workflow/dao.go
+++ b/engine/api/workflow/dao.go
@@ -1521,7 +1521,7 @@ func Push(ctx context.Context, db *gorp.DbMap, store cache.Store, proj *sdk.Proj
 
 	if !isDefaultBranch {
 		_ = tx.Rollback()
-		log.Debug("workflow %s rollbacked because it's not comming from the default branch", wf.Name)
+		log.Debug("workflow %s rollbacked because it's not coming from the default branch", wf.Name)
 	} else {
 		if err := tx.Commit(); err != nil {
 			return nil, nil, sdk.WrapError(err, "Cannot commit transaction")
diff --git a/engine/api/workflow/dao_node_run_job.go b/engine/api/workflow/dao_node_run_job.go
index 78f574326..3a3fd0941 100644
--- a/engine/api/workflow/dao_node_run_job.go
+++ b/engine/api/workflow/dao_node_run_job.go
@@ -19,7 +19,7 @@ import (
 	"github.com/ovh/cds/sdk/log"
 )
 
-// QueueFilter contains all criterias used to fetch queue
+// QueueFilter contains all criteria used to fetch queue
 type QueueFilter struct {
 	ModelType    []string
 	RatioService *int
diff --git a/engine/api/workflow/dao_run.go b/engine/api/workflow/dao_run.go
index 3362b5bba..d12a76ac3 100644
--- a/engine/api/workflow/dao_run.go
+++ b/engine/api/workflow/dao_run.go
@@ -146,7 +146,7 @@ func (r *Run) PostUpdate(db gorp.SqlExecutor) error {
 }
 
 //PostGet is a db hook on WorkflowRun
-//It loads column workflow wich is in JSONB in table workflow_run
+//It loads column workflow which is in JSONB in table workflow_run
 func (r *Run) PostGet(db gorp.SqlExecutor) error {
 	var res = struct {
 		W sql.NullString `db:"workflow"`
@@ -314,7 +314,7 @@ func LoadAndLockRunByJobID(db gorp.SqlExecutor, id int64, loadOpts LoadRunOption
 }
 
 //LoadRuns loads all runs
-//It retuns runs, offset, limit count and an error
+//It returns runs, offset, limit count and an error
 func LoadRuns(db gorp.SqlExecutor, projectkey, workflowname string, offset, limit int, tagFilter map[string]string) ([]sdk.WorkflowRun, int, int, int, error) {
 	var args = []interface{}{projectkey}
 	queryCount := `select count(workflow_run.id)
diff --git a/engine/api/workflow/execute_node_job_run.go b/engine/api/workflow/execute_node_job_run.go
index bbe410037..6b4e4f2c9 100644
--- a/engine/api/workflow/execute_node_job_run.go
+++ b/engine/api/workflow/execute_node_job_run.go
@@ -481,12 +481,12 @@ func LoadSecrets(db gorp.SqlExecutor, store cache.Store, nodeRun *sdk.WorkflowNo
 				if err != nil {
 					return nil, sdk.WrapError(err, "LoadSecrets> Cannot load application deployment strategies %d", app.ID)
 				}
-				strat, has := strats[pp.Name]
+				start, has := strats[pp.Name]
 
 				// Application deployment strategies variables
 				apv := []sdk.Variable{}
 				if has {
-					for k, v := range strat {
+					for k, v := range start {
 						apv = append(apv, sdk.Variable{
 							Name:  k,
 							Type:  v.Type,
diff --git a/engine/api/workflow/workflow_importer.go b/engine/api/workflow/workflow_importer.go
index 675a8b0a7..466b5207a 100644
--- a/engine/api/workflow/workflow_importer.go
+++ b/engine/api/workflow/workflow_importer.go
@@ -81,7 +81,7 @@ func Import(ctx context.Context, db gorp.SqlExecutor, store cache.Store, proj *s
 
 	// HookRegistration after workflow.Update.  It needs hooks to be created on DB
 	// Hook registration must only be done on default branch in case of workflow as-code
-	// The derivation branch is set in workflow parser it is not comming from the default branch
+	// The derivation branch is set in workflow parser it is not coming from the default branch
 	uptOptions := UpdateOptions{
 		DisableHookManagement: w.DerivationBranch != "",
 		OldWorkflow:           oldW,
diff --git a/engine/api/workflow_queue.go b/engine/api/workflow_queue.go
index d2407b9b7..3baf1ad2b 100644
--- a/engine/api/workflow_queue.go
+++ b/engine/api/workflow_queue.go
@@ -90,7 +90,7 @@ func (api *API) postTakeWorkflowJobHandler() service.Handler {
 		}
 
 		if !isGroupOK {
-      return sdk.WrapError(sdk.ErrForbidden, "Worker %s (%s) is not authorized to take this job:%d execGroups:%+v", getWorker(ctx).Name, workerModel, id, pbj.ExecGroups)
+			return sdk.WrapError(sdk.ErrForbidden, "Worker %s (%s) is not authorized to take this job:%d execGroups:%+v", getWorker(ctx).Name, workerModel, id, pbj.ExecGroups)
 		}
 
 		pbji := &sdk.WorkflowNodeJobRunData{}
diff --git a/engine/config.go b/engine/config.go
index f1146b585..022ebfaa9 100644
--- a/engine/config.go
+++ b/engine/config.go
@@ -80,11 +80,11 @@ func configSetDefaults() {
 		var gerrit vcs.GerritServerConfiguration
 		defaults.SetDefaults(&gerrit)
 		conf.VCS.Servers = map[string]vcs.ServerConfiguration{
-			"Github":         vcs.ServerConfiguration{URL: "https://github.com", Github: &github},
-			"Bitbucket":      vcs.ServerConfiguration{URL: "https://mybitbucket.com", Bitbucket: &bitbucket},
-			"bitbucketcloud": vcs.ServerConfiguration{BitbucketCloud: &bitbucketcloud},
-			"Gitlab":         vcs.ServerConfiguration{URL: "https://gitlab.com", Gitlab: &gitlab},
-			"Gerrit":         vcs.ServerConfiguration{URL: "http://localhost:8080", Gerrit: &gerrit},
+			"Github":         {URL: "https://github.com", Github: &github},
+			"Bitbucket":      {URL: "https://mybitbucket.com", Bitbucket: &bitbucket},
+			"bitbucketcloud": {BitbucketCloud: &bitbucketcloud},
+			"Gitlab":         {URL: "https://gitlab.com", Gitlab: &gitlab},
+			"Gerrit":         {URL: "http://localhost:8080", Gerrit: &gerrit},
 		}
 	}
 	if conf.Repositories != nil {
diff --git a/engine/hatchery/openstack/get.go b/engine/hatchery/openstack/get.go
index aaf71ea37..7281676a6 100644
--- a/engine/hatchery/openstack/get.go
+++ b/engine/hatchery/openstack/get.go
@@ -32,7 +32,7 @@ func (h *HatcheryOpenstack) flavorID(flavor string) (string, error) {
 	return "", fmt.Errorf("flavorID> flavor '%s' not found", flavor)
 }
 
-//This a embeded cache for images list
+//This a embedded cache for images list
 var limages = struct {
 	mu   sync.RWMutex
 	list []images.Image
@@ -89,7 +89,7 @@ func (h *HatcheryOpenstack) resetImagesCache() {
 	limages.mu.Unlock()
 }
 
-//This a embeded cache for servers list
+//This a embedded cache for servers list
 var lservers = struct {
 	mu   sync.RWMutex
 	list []servers.Server
diff --git a/engine/hatchery/swarm/swarm.go b/engine/hatchery/swarm/swarm.go
index f503ad4d8..30ed1fb39 100644
--- a/engine/hatchery/swarm/swarm.go
+++ b/engine/hatchery/swarm/swarm.go
@@ -471,7 +471,7 @@ func (h *HatcherySwarm) CanSpawn(model *sdk.Model, jobID int64, requirements []s
 			continue
 		}
 
-		//Checking teh number of container on each docker engine
+		//Checking the number of container on each docker engine
 		if nbContainersFromHatchery > dockerClient.MaxContainers {
 			log.Debug("hatchery> swarm> CanSpawn> max containers reached on %s. current:%d max:%d", dockerName, nbContainersFromHatchery, dockerClient.MaxContainers)
 			continue
diff --git a/engine/hatchery/swarm/swarm_util_kill.go b/engine/hatchery/swarm/swarm_util_kill.go
index e49ca925e..7931d8363 100644
--- a/engine/hatchery/swarm/swarm_util_kill.go
+++ b/engine/hatchery/swarm/swarm_util_kill.go
@@ -137,7 +137,7 @@ func (h *HatcherySwarm) killAndRemoveContainer(dockerClient *dockerClient, ID st
 	if err := dockerClient.ContainerRemove(ctxDockerRemove, ID, types.ContainerRemoveOptions{RemoveVolumes: true, Force: true}); err != nil {
 		// container could be already removed by a previous call to docker
 		if !strings.Contains(err.Error(), "No such container") && !strings.Contains(err.Error(), "is already in progress") {
-      log.Error("Unable to remove container %s from %s: %v", ID, dockerClient.name, err)
+			log.Error("Unable to remove container %s from %s: %v", ID, dockerClient.name, err)
 		}
 	}
 
diff --git a/engine/hatchery/vsphere/client.go b/engine/hatchery/vsphere/client.go
index 81d75444d..63813f111 100644
--- a/engine/hatchery/vsphere/client.go
+++ b/engine/hatchery/vsphere/client.go
@@ -21,7 +21,7 @@ import (
 
 const reqTimeout = 7 * time.Second
 
-//This a embeded cache for servers list
+//This a embedded cache for servers list
 var lservers = struct {
 	mu   sync.RWMutex
 	list []mo.VirtualMachine
@@ -72,7 +72,7 @@ func (h *HatcheryVSphere) getServers() []mo.VirtualMachine {
 	return lservers.list
 }
 
-//This a embeded cache for images list
+//This a embedded cache for images list
 var lmodels = struct {
 	mu   sync.RWMutex
 	list []mo.VirtualMachine
@@ -279,7 +279,7 @@ func (h *HatcheryVSphere) createVMConfig(vm *object.VirtualMachine, annot annota
 	return cloneSpec, folder, nil
 }
 
-// launchClientOp launch a script on the virtual machine given in paramters
+// launchClientOp launch a script on the virtual machine given in parameters
 func (h *HatcheryVSphere) launchClientOp(vm *object.VirtualMachine, script string, env []string) (int64, error) {
 	ctx := context.Background()
 	ctxC, cancelC := context.WithTimeout(ctx, reqTimeout)
diff --git a/engine/repositories/processor.go b/engine/repositories/processor.go
index 66ef1c2cf..f0978e7ae 100644
--- a/engine/repositories/processor.go
+++ b/engine/repositories/processor.go
@@ -19,7 +19,7 @@ func (s *Service) processor(ctx context.Context) error {
 			op := s.dao.loadOperation(uuid)
 			if err := s.do(*op); err != nil {
 				if err == errLockUnavailable {
-					log.Info("repositories > processor > lock unavailabe. Retry")
+					log.Info("repositories > processor > lock unavailable. Retry")
 					s.dao.pushOperation(op)
 				} else {
 					log.Error("repositories > processor > %v", err)
diff --git a/engine/service/http.go b/engine/service/http.go
index 007943483..fa8b224e2 100644
--- a/engine/service/http.go
+++ b/engine/service/http.go
@@ -26,10 +26,10 @@ type AsynchronousHandler func(ctx context.Context, r *http.Request) error
 // Middleware defines the HTTP Middleware used in CDS engine
 type Middleware func(ctx context.Context, w http.ResponseWriter, req *http.Request, rc *HandlerConfig) (context.Context, error)
 
-// HandlerFunc defines the way to instanciate a handler
+// HandlerFunc defines the way to instantiate a handler
 type HandlerFunc func() Handler
 
-// AsynchronousHandlerFunc defines the way to instanciate a handler
+// AsynchronousHandlerFunc defines the way to instantiate a handler
 type AsynchronousHandlerFunc func() AsynchronousHandler
 
 // RouterConfigParam is the type of anonymous function returned by POST, GET and PUT functions
diff --git a/engine/sql/162_action_for_group.sql b/engine/sql/162_action_for_group.sql
index a3041400c..f0dddc9d2 100644
--- a/engine/sql/162_action_for_group.sql
+++ b/engine/sql/162_action_for_group.sql
@@ -33,7 +33,7 @@ SELECT create_foreign_key_idx_cascade('FK_ACTION_REQUIREMENT_ACTION', 'action_re
 SELECT create_foreign_key_idx_cascade('FK_ACTION_EDGE_PARENT_ACTION', 'action_edge', 'action', 'parent_id', 'id');
 SELECT create_foreign_key_idx_cascade('FK_ACTION_EDGE_PARAMETER_ACTION_EDGE', 'action_edge_parameter', 'action_edge', 'action_edge_id', 'id');
 
--- change type for column name and type and add indexes (usefull to check if action exists)
+-- change type for column name and type and add indexes (useful to check if action exists)
 ALTER TABLE "action" ALTER COLUMN "name" TYPE VARCHAR(100) USING "name"::VARCHAR(100);
 CREATE INDEX idx_action_name ON "action" ("name");
 ALTER TABLE "action" ALTER COLUMN "type" TYPE VARCHAR(100) USING "type"::VARCHAR(100);
diff --git a/engine/ui/ui.go b/engine/ui/ui.go
index 7afde32ed..7477a75de 100644
--- a/engine/ui/ui.go
+++ b/engine/ui/ui.go
@@ -267,13 +267,6 @@ func (s *Service) buildFromSource() error {
 		return fmt.Errorf("You must have the directory ../ui with the ui source code")
 	}
 
-	log.Info("ui> checking node version")
-	if output, err := s.execCommand("node --version"); err != nil {
-		return err
-	} else if !strings.HasPrefix(output, "v12.4.") {
-		return fmt.Errorf("You must have node version > v12.4.0 to build CDS UI. Your version: %s", output)
-	}
-
 	if _, err := s.execCommand("npm install --no-audit"); err != nil {
 		return err
 	}
@@ -312,9 +305,6 @@ func (s *Service) execCommand(command string) (string, error) {
 	if err := cmd.Run(); err != nil {
 		return "", sdk.WrapError(err, "could not run command")
 	}
-	if err := cmd.Wait(); err != nil {
-		return "", sdk.WrapError(err, "could not wait for command")
-	}
 	return output, nil
 }
 
diff --git a/engine/ui/ui_router.go b/engine/ui/ui_router.go
index 86317b848..15003d750 100644
--- a/engine/ui/ui_router.go
+++ b/engine/ui/ui_router.go
@@ -46,9 +46,10 @@ func (s *Service) getReverseProxy(path, urlRemote string) *httputil.ReverseProxy
 		} else {
 			req.Header.Add("X-Forwarded-Host", req.Host)
 			req.Header.Add("X-Origin-Host", origin.Host)
-			req.URL.Scheme = "http"
+			req.URL.Scheme = origin.Scheme
 			req.URL.Host = origin.Host
 			req.URL.Path = reqPath
+			req.Host = origin.Host
 		}
 	}
 	return &httputil.ReverseProxy{Director: director}
diff --git a/engine/vcs/bitbucketcloud/bitbucketcloud.go b/engine/vcs/bitbucketcloud/bitbucketcloud.go
index dc69fcc87..95bcec4f2 100644
--- a/engine/vcs/bitbucketcloud/bitbucketcloud.go
+++ b/engine/vcs/bitbucketcloud/bitbucketcloud.go
@@ -22,7 +22,7 @@ type bitbucketcloudClient struct {
 	proxyURL            string
 }
 
-//bitbucketcloudConsumer implements vcs.Server and it's used to instanciate a githubClient
+//bitbucketcloudConsumer implements vcs.Server and it's used to instantiate a githubClient
 type bitbucketcloudConsumer struct {
 	ClientID            string `json:"client-id"`
 	ClientSecret        string `json:"-"`
diff --git a/engine/vcs/bitbucketcloud/client_status.go b/engine/vcs/bitbucketcloud/client_status.go
index b97edc244..24bd94242 100644
--- a/engine/vcs/bitbucketcloud/client_status.go
+++ b/engine/vcs/bitbucketcloud/client_status.go
@@ -135,7 +135,7 @@ func processEventWorkflowNodeRun(event sdk.Event, cdsUIURL string, disabledStatu
 	data := statusData{}
 	var eventNR sdk.EventRunWorkflowNode
 	if err := mapstructure.Decode(event.Payload, &eventNR); err != nil {
-		return data, sdk.WrapError(err, "Error durring consumption")
+		return data, sdk.WrapError(err, "Error during consumption")
 	}
 	//We only manage status Success, Failure and Stopped
 	if eventNR.Status == sdk.StatusChecking.String() ||
diff --git a/engine/vcs/bitbucketserver/bitbucketserver.go b/engine/vcs/bitbucketserver/bitbucketserver.go
index 8c74ce092..3f6cfbf0e 100644
--- a/engine/vcs/bitbucketserver/bitbucketserver.go
+++ b/engine/vcs/bitbucketserver/bitbucketserver.go
@@ -19,7 +19,7 @@ type bitbucketClient struct {
 	token             string
 }
 
-//bitbucketConsumer implements vcs.Server and it's used to instanciate a bitbucketClient
+//bitbucketConsumer implements vcs.Server and it's used to instantiate a bitbucketClient
 type bitbucketConsumer struct {
 	ConsumerKey      string `json:"consumer_key"`
 	PrivateKey       []byte `json:"-"`
diff --git a/engine/vcs/gerrit/gerrit.go b/engine/vcs/gerrit/gerrit.go
index fcfc178a7..2e695eb8b 100644
--- a/engine/vcs/gerrit/gerrit.go
+++ b/engine/vcs/gerrit/gerrit.go
@@ -20,7 +20,7 @@ type gerritClient struct {
 	reviewerToken       string
 }
 
-// gerritConsumer implements vcs.Server and it's used to instanciate a gerritClient
+// gerritConsumer implements vcs.Server and it's used to instantiate a gerritClient
 type gerritConsumer struct {
 	URL                 string `json:"url"`
 	cache               cache.Store
@@ -31,7 +31,7 @@ type gerritConsumer struct {
 	reviewerToken       string
 }
 
-// New instanciate a new gerrit consumer
+// New instantiate a new gerrit consumer
 func New(URL string, store cache.Store, disableStatus bool, disableStatusDetail bool, sshPort int, reviewerName, reviewerToken string) sdk.VCSServer {
 	return &gerritConsumer{
 		URL:                 URL,
diff --git a/engine/vcs/github/client_commit.go b/engine/vcs/github/client_commit.go
index 192abae37..aec698c13 100644
--- a/engine/vcs/github/client_commit.go
+++ b/engine/vcs/github/client_commit.go
@@ -108,7 +108,7 @@ func (g *githubClient) Commits(ctx context.Context, repo, theBranch, since, unti
 	var sinceDate time.Time
 	// Calculate since commit
 	if since == "" {
-		// If no since commit, take from the begining of the branch
+		// If no since commit, take from the beginning of the branch
 		b, errB := g.Branch(ctx, repo, theBranch)
 		if errB != nil {
 			return nil, errB
diff --git a/engine/vcs/github/client_status.go b/engine/vcs/github/client_status.go
index 718da8bef..1f4685ac1 100644
--- a/engine/vcs/github/client_status.go
+++ b/engine/vcs/github/client_status.go
@@ -153,7 +153,7 @@ func processEventWorkflowNodeRun(event sdk.Event, cdsUIURL string, disabledStatu
 	data := statusData{}
 	var eventNR sdk.EventRunWorkflowNode
 	if err := mapstructure.Decode(event.Payload, &eventNR); err != nil {
-		return data, sdk.WrapError(err, "Error durring consumption")
+		return data, sdk.WrapError(err, "Error during consumption")
 	}
 	//We only manage status Success and Failure
 	if eventNR.Status == sdk.StatusChecking.String() ||
diff --git a/engine/vcs/github/github.go b/engine/vcs/github/github.go
index 6d24ed0ca..0b13a0345 100644
--- a/engine/vcs/github/github.go
+++ b/engine/vcs/github/github.go
@@ -23,7 +23,7 @@ type githubClient struct {
 	token               string
 }
 
-//GithubConsumer implements vcs.Server and it's used to instanciate a githubClient
+//GithubConsumer implements vcs.Server and it's used to instantiate a githubClient
 type githubConsumer struct {
 	ClientID            string `json:"client-id"`
 	ClientSecret        string `json:"-"`
diff --git a/engine/vcs/gitlab/gitlab.go b/engine/vcs/gitlab/gitlab.go
index 2d4d0eb92..b94fcace3 100644
--- a/engine/vcs/gitlab/gitlab.go
+++ b/engine/vcs/gitlab/gitlab.go
@@ -24,7 +24,7 @@ type gitlabClient struct {
 	disableStatusDetail bool
 }
 
-// gitlabConsumer implements vcs.Server and it's used to instanciate a gitlabClient
+// gitlabConsumer implements vcs.Server and it's used to instantiate a gitlabClient
 type gitlabConsumer struct {
 	URL                      string `json:"url"`
 	appID                    string
@@ -37,18 +37,18 @@ type gitlabConsumer struct {
 	disableStatusDetail      bool
 }
 
-// New instanciate a new gitlab consumer
+// New instantiate a new gitlab consumer
 func New(appID, clientSecret, URL, callbackURL, uiURL, proxyURL string, store cache.Store, disableStatus bool, disableStatusDetail bool) sdk.VCSServer {
 	return &gitlabConsumer{
-		URL:    URL,
-		secret: clientSecret,
-		cache:  store,
-		appID:  appID,
+		URL:                      URL,
+		secret:                   clientSecret,
+		cache:                    store,
+		appID:                    appID,
 		AuthorizationCallbackURL: callbackURL,
-		uiURL:               uiURL,
-		proxyURL:            proxyURL,
-		disableStatus:       disableStatus,
-		disableStatusDetail: disableStatusDetail,
+		uiURL:                    uiURL,
+		proxyURL:                 proxyURL,
+		disableStatus:            disableStatus,
+		disableStatusDetail:      disableStatusDetail,
 	}
 }
 
diff --git a/engine/worker/cmd_run.go b/engine/worker/cmd_run.go
index c9423c73a..39f410c16 100644
--- a/engine/worker/cmd_run.go
+++ b/engine/worker/cmd_run.go
@@ -167,7 +167,7 @@ func runCmd(w *currentWorker) func(cmd *cobra.Command, args []string) {
 			for {
 				select {
 				case err := <-errs:
-					log.Error("An error has occured: %v", err)
+					log.Error("An error has occurred: %v", err)
 					if strings.Contains(err.Error(), "not authenticated") {
 						endFunc()
 						return
diff --git a/go.sum b/go.sum
index 38b870cbe..a7ae79e59 100644
--- a/go.sum
+++ b/go.sum
@@ -637,6 +637,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82 h1:vsphBvatvfbhlb4PO1BYSr9dzugGxJ/SQHoNufZJq1w=
 golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
 golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
diff --git a/sdk/action.go b/sdk/action.go
index adf78be9c..7c10cb72d 100644
--- a/sdk/action.go
+++ b/sdk/action.go
@@ -28,7 +28,7 @@ const (
 	DefaultGitCloneParameterTagValue = "{{.git.tag}}"
 )
 
-// NewAction instanciate a new Action
+// NewAction instantiate a new Action
 func NewAction(name string) *Action {
 	return &Action{
 		Name:    name,
diff --git a/sdk/authentification.go b/sdk/authentification.go
index dbc1c6b65..4933abb2d 100644
--- a/sdk/authentification.go
+++ b/sdk/authentification.go
@@ -20,7 +20,7 @@ type UserToken struct {
 	UserID             int64     `json:"-" db:"user_id"`
 }
 
-// NewAuth instanciate a new Authentification struct
+// NewAuth instantiate a new Authentification struct
 func NewAuth(hashedToken string) *Auth {
 	a := &Auth{
 		HashedTokenVerify: hashedToken,
diff --git a/sdk/environment.go b/sdk/environment.go
index 2c1722c4d..17fe1329e 100644
--- a/sdk/environment.go
+++ b/sdk/environment.go
@@ -72,7 +72,7 @@ func (e Environment) PGPKeys() []EnvironmentKey {
 	return keys
 }
 
-// NewEnvironment instanciate a new Environment
+// NewEnvironment instantiate a new Environment
 func NewEnvironment(name string) *Environment {
 	e := &Environment{
 		Name: name,
diff --git a/sdk/exportentities/workflow.go b/sdk/exportentities/workflow.go
index 983e8f8cd..bbd730c7b 100644
--- a/sdk/exportentities/workflow.go
+++ b/sdk/exportentities/workflow.go
@@ -543,7 +543,7 @@ func (w Workflow) GetWorkflow() (*sdk.Workflow, error) {
 	entries := w.Entries()
 	var attempt int
 	fakeID := rand.Int63n(5000)
-	// attempt is there to avoid infinit loop, but it should not happend becase we check validty and dependencies earlier
+	// attempt is there to avoid infinite loop, but it should not happened becase we check validty and dependencies earlier
 	for len(entries) != 0 && attempt < 10000 {
 		for name, entry := range entries {
 			entry.ID = fakeID
diff --git a/sdk/messages.go b/sdk/messages.go
index cd8a319bf..0e4a855e8 100644
--- a/sdk/messages.go
+++ b/sdk/messages.go
@@ -74,7 +74,7 @@ var (
 	MsgSpawnInfoWorkerForJobError          = &Message{"MsgSpawnInfoWorkerForJobError", trad{FR: "⚠ Ce worker %s a été créé pour lancer ce job, mais ne possède pas tous les pré-requis. Vérifiez que les prérequis suivants:%s", EN: "⚠ This worker %s was created to take this action, but does not have all prerequisites. Please verify the following prerequisites:%s"}, nil}
 	MsgSpawnInfoJobError                   = &Message{"MsgSpawnInfoJobError", trad{FR: "⚠ Impossible de lancer ce job : %s", EN: "⚠ Unable to run this job: %s"}, nil}
 	MsgWorkflowStarting                    = &Message{"MsgWorkflowStarting", trad{FR: "Le workflow %s#%s a été démarré", EN: "Workflow %s#%s has been started"}, nil}
-	MsgWorkflowError                       = &Message{"MsgWorkflowError", trad{FR: "⚠ Une erreur est survenue: %v", EN: "⚠ An error has occured: %v"}, nil}
+	MsgWorkflowError                       = &Message{"MsgWorkflowError", trad{FR: "⚠ Une erreur est survenue: %v", EN: "⚠ An error has occurred: %v"}, nil}
 	MsgWorkflowConditionError              = &Message{"MsgWorkflowConditionError", trad{FR: "Les conditions de lancement ne sont pas respectées.", EN: "Run conditions aren't ok."}, nil}
 	MsgWorkflowNodeStop                    = &Message{"MsgWorkflowNodeStop", trad{FR: "Le pipeline a été arrété par %s", EN: "The pipeline has been stopped by %s"}, nil}
 	MsgWorkflowNodeMutex                   = &Message{"MsgWorkflowNodeMutex", trad{FR: "Le pipeline %s est mis en attente tant qu'il est en cours sur un autre run", EN: "The pipeline %s is waiting while it's running on another run"}, nil}
@@ -89,7 +89,7 @@ var (
 	MsgWorkflowErrorBadApplicationName     = &Message{"MsgWorkflowErrorBadApplicationName", trad{FR: "L'application %s indiquée dans votre fichier yaml de workflow n'existe pas ou ne correspond pas aux normes ^[a-zA-Z0-9._-]{1,}$", EN: "The application %s mentioned in your workflow's yaml file doesn't exist or is incorrect with ^[a-zA-Z0-9._-]{1,}$"}, nil}
 	MsgWorkflowErrorBadEnvironmentName     = &Message{"MsgWorkflowErrorBadEnvironmentName", trad{FR: "L'environnement %s indiqué dans votre fichier yaml de workflow n'existe pas", EN: "The environment %s mentioned in your workflow's yaml file doesn't exist"}, nil}
 	MsgWorkflowErrorBadIntegrationName     = &Message{"MsgWorkflowErrorBadIntegrationName", trad{FR: "L'intégration %s indiquée dans votre fichier yaml n'existe pas", EN: "The integration %s mentioned in your yaml file doesn't exist"}, nil}
-	MsgWorkflowErrorBadCdsDir              = &Message{"MsgWorkflowErrorBadCdsDir", trad{FR: "Un problème est survenu avec votre répertoire .cds", EN: "A problem occured about your .cds directory"}, nil}
+	MsgWorkflowErrorBadCdsDir              = &Message{"MsgWorkflowErrorBadCdsDir", trad{FR: "Un problème est survenu avec votre répertoire .cds", EN: "A problem occurred about your .cds directory"}, nil}
 	MsgWorkflowErrorUnknownKey             = &Message{"MsgWorkflowErrorUnknownKey", trad{FR: "La clé '%s' est incorrecte ou n'existe pas", EN: "The key '%s' is incorrect or doesn't exist"}, nil}
 	MsgWorkflowErrorBadVCSStrategy         = &Message{"MsgWorkflowErrorBadVCSStrategy", trad{FR: "Vos informations vcs_* sont incorrectes", EN: "Your vcs_* fields are incorrects"}, nil}
 )
diff --git a/sdk/repositories_manager.go b/sdk/repositories_manager.go
index c9e35d0c0..784af257f 100644
--- a/sdk/repositories_manager.go
+++ b/sdk/repositories_manager.go
@@ -4,7 +4,7 @@ import (
 	"time"
 )
 
-// RepositoryEvents group all repostiory events
+// RepositoryEvents group all repository events
 type RepositoryEvents struct {
 	PushEvents        []VCSPushEvent        `json:"push_events" db:"-"`
 	CreateEvents      []VCSCreateEvent      `json:"create_events" db:"-"`
diff --git a/sdk/stage.go b/sdk/stage.go
index c4200b290..48051bf58 100644
--- a/sdk/stage.go
+++ b/sdk/stage.go
@@ -64,7 +64,7 @@ func (s *Stage) PlainConditions() []WorkflowNodeCondition {
 	return res
 }
 
-// NewStage instanciate a new Stage
+// NewStage instantiate a new Stage
 func NewStage(name string) *Stage {
 	s := &Stage{
 		Name: name,
diff --git a/sdk/user.go b/sdk/user.go
index 244257da5..4d8a444cd 100644
--- a/sdk/user.go
+++ b/sdk/user.go
@@ -24,7 +24,7 @@ type Favorite struct {
 // UserPermissions is the set of permissions for a user
 //easyjson:json
 type UserPermissions struct {
-	Groups        []string           `json:"Groups,omitempty"` // json key are capitalized to ensure exising data in cache are still valid
+	Groups        []string           `json:"Groups,omitempty"` // json key are capitalized to ensure existing data in cache are still valid
 	GroupsAdmin   []string           `json:"GroupsAdmin,omitempty"`
 	ProjectsPerm  UserPermissionsMap `json:"ProjectsPerm,omitempty"`
 	WorkflowsPerm UserPermissionsMap `json:"WorkflowsPerm,omitempty"`
@@ -85,7 +85,7 @@ type UserAPIResponse struct {
 // UserEmailPattern  pattern for user email address
 const UserEmailPattern = "(\\w[-._\\w]*\\w@\\w[-._\\w]*\\w\\.\\w{2,3})"
 
-// NewUser instanciate a new User
+// NewUser instantiate a new User
 func NewUser(username string) *User {
 	u := &User{
 		Username: username,
diff --git a/sdk/vcs/keys.go b/sdk/vcs/keys.go
index d223252f7..343876cfa 100644
--- a/sdk/vcs/keys.go
+++ b/sdk/vcs/keys.go
@@ -47,7 +47,8 @@ func CleanSSHKeys(path string, key *sdk.Variable) error {
 	return os.RemoveAll(filepath.Join(path, "cds.key."+key.Name+".priv"))
 }
 
-//TODO: To delete after gitclone migration
+// TODO: To delete after gitclone migration
+
 // SetupSSHKeyDEPRECATED writes all the keys in the path, or just the specified key it not nil
 func SetupSSHKeyDEPRECATED(vars []sdk.Variable, path string, key *sdk.Parameter) error {
 	if key == nil {
@@ -117,7 +118,8 @@ func GetSSHKey(vars []sdk.Variable, path string, key *sdk.Variable) (*SSHKey, er
 	return &SSHKey{Filename: p, Content: b}, nil
 }
 
-//TODO: To delete after gitclone migration
+// TODO: To delete after gitclone migration
+
 // GetSSHKeyDEPRECATED get a key in the path. If the key is nil, it will choose a default key among project, application and env variables
 func GetSSHKeyDEPRECATED(vars []sdk.Parameter, path string, key *sdk.Parameter) (*SSHKey, error) {
 	var k sdk.Parameter
diff --git a/sdk/workflow_hook.go b/sdk/workflow_hook.go
index 0e840b174..6e9c975fa 100644
--- a/sdk/workflow_hook.go
+++ b/sdk/workflow_hook.go
@@ -26,7 +26,7 @@ type NodeHook struct {
 	Conditions    WorkflowNodeConditions `json:"conditions" db:"conditions"`
 }
 
-//Equals checks functionnal equality between two hooks
+//Equals checks functional equality between two hooks
 func (h NodeHook) Equals(h1 NodeHook) bool {
 	if h.UUID != h1.UUID {
 		return false
diff --git a/sdk/workflow_template.go b/sdk/workflow_template.go
index 3113cc978..863ddc7e1 100644
--- a/sdk/workflow_template.go
+++ b/sdk/workflow_template.go
@@ -255,7 +255,7 @@ const (
 	ParameterTypeJSON       TemplateParameterType = "json"
 )
 
-// IsValid returns paramter type validity.
+// IsValid returns parameter type validity.
 func (t TemplateParameterType) IsValid() bool {
 	switch t {
 	case ParameterTypeString, ParameterTypeBoolean, ParameterTypeRepository, ParameterTypeJSON:
diff --git a/tools/debpacker/README.md b/tools/debpacker/README.md
index a17a54396..4546d0d69 100644
--- a/tools/debpacker/README.md
+++ b/tools/debpacker/README.md
@@ -86,7 +86,7 @@ Email of the maintener
 
 **Type:** *string[]*
 
-List of dependancies
+List of dependencies
 
 ### systemd-configuration
 
diff --git a/ui/src/app/model/pipeline.model.ts b/ui/src/app/model/pipeline.model.ts
index f99e59c69..57524b257 100644
--- a/ui/src/app/model/pipeline.model.ts
+++ b/ui/src/app/model/pipeline.model.ts
@@ -149,6 +149,7 @@ export class PipelineRunRequest {
 export class SpawnInfo {
     api_time: Date;
     remote_time: Date;
+    is_error: boolean;
     user_message: string;
 }
 
diff --git a/ui/src/app/views/workflow/run/workflow.run.component.ts b/ui/src/app/views/workflow/run/workflow.run.component.ts
index 54da6bd16..a43280ed7 100644
--- a/ui/src/app/views/workflow/run/workflow.run.component.ts
+++ b/ui/src/app/views/workflow/run/workflow.run.component.ts
@@ -40,6 +40,7 @@ export class WorkflowRunComponent implements OnInit {
     paramsSubs: Subscription;
     loadingRun = true;
     errorsMap = ErrorMessageMap;
+    displayError = false;
 
     // id, status, workflows, infos, num
     workflowRunData: {};
@@ -113,6 +114,10 @@ export class WorkflowRunComponent implements OnInit {
                 this.workflowRunData['infos'] = s.workflowRun.infos;
                 this.workflowRunData['num'] = s.workflowRun.num;
 
+                if (s.workflowRun.infos && s.workflowRun.infos.length > 0) {
+                    this.displayError = s.workflowRun.infos.some((info) => info.is_error);
+                }
+
                 this.updateTitle(s.workflowRun);
                 this._cd.markForCheck();
             } else {
@@ -135,17 +140,17 @@ export class WorkflowRunComponent implements OnInit {
                 this.notificationSubscription = this._notification.create(this._translate.instant('notification_on_workflow_success', {
                     workflowName: this.workflowName,
                 }), {
-                        icon: 'assets/images/checked.png',
-                        tag: `${this.workflowName}-${wr.num}.${wr.last_subnumber}`
-                    }).subscribe();
+                    icon: 'assets/images/checked.png',
+                    tag: `${this.workflowName}-${wr.num}.${wr.last_subnumber}`
+                }).subscribe();
                 break;
             case PipelineStatus.FAIL:
                 this.notificationSubscription = this._notification.create(this._translate.instant('notification_on_workflow_failing', {
                     workflowName: this.workflowName
                 }), {
-                        icon: 'assets/images/close.png',
-                        tag: `${this.workflowName}-${wr.num}.${wr.last_subnumber}`
-                    }).subscribe();
+                    icon: 'assets/images/close.png',
+                    tag: `${this.workflowName}-${wr.num}.${wr.last_subnumber}`
+                }).subscribe();
                 break;
         }
     }
diff --git a/ui/src/app/views/workflow/run/workflow.run.html b/ui/src/app/views/workflow/run/workflow.run.html
index e876a9f78..23fb56db2 100644
--- a/ui/src/app/views/workflow/run/workflow.run.html
+++ b/ui/src/app/views/workflow/run/workflow.run.html
@@ -1,13 +1,15 @@
-<div *ngIf="this.workflowRunData && this.workflowRunData['id']" class="workflowRun">
+<div *ngIf="workflowRunData && workflowRunData['id']" class="workflowRun">
     <app-workflow-run-summary [(direction)]="direction" [project]="project" [workflowName]="workflowName"
-        [class.above]="this.workflowRunData['status'] === pipelineStatusEnum.PENDING">
+        [class.above]="workflowRunData['status'] === pipelineStatusEnum.PENDING">
     </app-workflow-run-summary>
-    <ng-container *ngIf="this.workflowRunData['id'] !== pipelineStatusEnum.PENDING; else pendingBlock">
-        <ng-container *ngIf="this.workflowRunData['workflow'] && this.workflowRunData['workflow'].workflow_data">
-            <app-workflow-graph class="graph" [direction]="direction" [project]="project" [workflowData]="this.workflowRunData['workflow']">
+    <ng-container *ngIf="workflowRunData['id'] !== pipelineStatusEnum.PENDING; else pendingBlock">
+        <ng-container *ngIf="workflowRunData['workflow'] && workflowRunData['workflow'].workflow_data && !displayError">
+            <app-workflow-graph class="graph" [direction]="direction" [project]="project"
+                [workflowData]="workflowRunData['workflow']">
             </app-workflow-graph>
         </ng-container>
-        <ng-container *ngIf="!this.workflowRunData['workflow'] || !this.workflowRunData['workflow'].workflow_data">
+        <ng-container
+            *ngIf="!workflowRunData['workflow'] || !workflowRunData['workflow'].workflow_data || displayError">
             <div class="ui grid">
                 <div class="ui row">
                     <div class="ui one wide column mt">
@@ -15,9 +17,8 @@
                     <div class="ui fourteen wide column mt">
                         <!-- ERRORS PANEL -->
                         <sui-accordion class="styled fluid">
-                            <ng-container *ngFor="let info of this.workflowRunData['infos']; let first = first">
-                                <sui-accordion-panel [isOpen]="first"
-                                    *ngIf="info.message.id !== 'MsgWorkflowError' || this.workflowRunData['infos'].length === 1">
+                            <ng-container *ngFor="let info of workflowRunData['infos']; let first = first">
+                                <sui-accordion-panel [isOpen]="first" *ngIf="info.is_error">
                                     <div title>
                                         <i class="dropdown icon"></i>
                                         <i class="red exclamation triangle icon"></i>
@@ -58,4 +59,5 @@
         </div>
     </ng-template>
 </div>
-<div class="ui text active loader" *ngIf="!this.workflowRunData || !this.workflowRunData['id']">{{ 'workflow_loading' | translate }}</div>
+<div class="ui text active loader" *ngIf="!workflowRunData || !workflowRunData['id']">
+    {{ 'workflow_loading' | translate }}</div>


Test patch:
diff --git a/engine/api/pipeline_stage_test.go b/engine/api/pipeline_stage_test.go
index 910149416..cbe1ca94e 100644
--- a/engine/api/pipeline_stage_test.go
+++ b/engine/api/pipeline_stage_test.go
@@ -349,12 +349,12 @@ func TestInsertAndLoadPipelineWith1StageWithoutConditionAnd1StageWith2Conditions
 		Enabled:    true,
 		Conditions: sdk.WorkflowNodeConditions{
 			PlainConditions: []sdk.WorkflowNodeCondition{
-				sdk.WorkflowNodeCondition{
+				{
 					Variable: ".git.branch",
 					Operator: "regex",
 					Value:    "master",
 				},
-				sdk.WorkflowNodeCondition{
+				{
 					Variable: ".git.author",
 					Operator: "regex",
 					Value:    "someone@somewhere.com",
@@ -460,7 +460,7 @@ func TestDeleteStageByIDShouldDeleteStageConditions(t *testing.T) {
 		Enabled:    true,
 		Conditions: sdk.WorkflowNodeConditions{
 			PlainConditions: []sdk.WorkflowNodeCondition{
-				sdk.WorkflowNodeCondition{
+				{
 					Variable: ".git.banch",
 					Operator: "regex",
 					Value:    "master",
@@ -521,7 +521,7 @@ func TestUpdateStageShouldUpdateStageConditions(t *testing.T) {
 		Enabled:    true,
 		Conditions: sdk.WorkflowNodeConditions{
 			PlainConditions: []sdk.WorkflowNodeCondition{
-				sdk.WorkflowNodeCondition{
+				{
 					Variable: ".git.banch",
 					Operator: "regex",
 					Value:    "master",
@@ -536,12 +536,12 @@ func TestUpdateStageShouldUpdateStageConditions(t *testing.T) {
 
 	stage.Conditions = sdk.WorkflowNodeConditions{
 		PlainConditions: []sdk.WorkflowNodeCondition{
-			sdk.WorkflowNodeCondition{
+			{
 				Variable: "param1",
 				Operator: "regex",
 				Value:    "value1",
 			},
-			sdk.WorkflowNodeCondition{
+			{
 				Variable: "param2",
 				Operator: "regex",
 				Value:    "value2",
@@ -581,7 +581,7 @@ func TestUpdateStageShouldUpdateStageConditions(t *testing.T) {
 	// we update plan AND lua -> must record lua only
 	stage.Conditions = sdk.WorkflowNodeConditions{
 		PlainConditions: []sdk.WorkflowNodeCondition{
-			sdk.WorkflowNodeCondition{
+			{
 				Variable: "param1",
 				Operator: "regex",
 				Value:    "value1",
diff --git a/engine/api/test/test.go b/engine/api/test/test.go
index a8bf3193c..5a31f7cc6 100644
--- a/engine/api/test/test.go
+++ b/engine/api/test/test.go
@@ -127,7 +127,7 @@ func SetupPG(t log.Logger, bootstrapFunc ...Bootstrapf) (*gorp.DbMap, cache.Stor
 	return DBConnectionFactory.GetDBMap(), store, cancel
 }
 
-// LoadTestingConf loads test configuraiton tests.cfg.json
+// LoadTestingConf loads test configuration tests.cfg.json
 func LoadTestingConf(t log.Logger) map[string]string {
 	var f string
 	u, _ := user.Current()
diff --git a/engine/api/user_test.go b/engine/api/user_test.go
index bc10300ff..3facfc6c0 100644
--- a/engine/api/user_test.go
+++ b/engine/api/user_test.go
@@ -136,7 +136,7 @@ func TestVerifyResetExpired(t *testing.T) {
 		t.Fatalf("User shoud not be verified : %s", err)
 	}
 	if err.Error() != "Reset operation expired" {
-		t.Fatalf("Reset sould be expired")
+		t.Fatalf("Reset should be expired")
 	}
 }
 
diff --git a/engine/api/workflow_queue_test.go b/engine/api/workflow_queue_test.go
index ec813b83f..0808603d6 100644
--- a/engine/api/workflow_queue_test.go
+++ b/engine/api/workflow_queue_test.go
@@ -575,7 +575,7 @@ func Test_postWorkflowJobTestsResultsHandler(t *testing.T) {
 							{
 								Value:   "Fail",
 								Type:    "Assertion error",
-								Message: "Error occured",
+								Message: "Error occurred",
 							},
 						},
 					},
diff --git a/engine/api/workflow_run_test.go b/engine/api/workflow_run_test.go
index a17e8d3eb..8ba2d8850 100644
--- a/engine/api/workflow_run_test.go
+++ b/engine/api/workflow_run_test.go
@@ -1461,7 +1461,7 @@ func Test_postWorkflowRunHandlerWithoutRightConditionsOnHook(t *testing.T) {
 					PipelineID: pip.ID,
 				},
 				Hooks: []sdk.NodeHook{
-					sdk.NodeHook{
+					{
 						Conditions: sdk.WorkflowNodeConditions{
 							LuaScript: "return false",
 						},
@@ -1618,7 +1618,7 @@ func Test_postWorkflowRunHandlerHookWithMutex(t *testing.T) {
 					Mutex:      true,
 				},
 				Hooks: []sdk.NodeHook{
-					sdk.NodeHook{
+					{
 						HookModelName: sdk.WebHookModel.Name,
 						Config:        sdk.WebHookModel.DefaultConfig,
 						Ref:           "root.0",