Repository: ovh/cds
Pull request #5037 (2020-03-03 09:36:22)

fix(api): reload old workflow just before update it
Signed-off-by: Yvonnick Esnault <yvonnick.esnault@corp.ovh.com>


ovh-cds: 
CDS Report build-all-cds#12630.0 ✘  
* Build
  * Build and Package All ✘  
  * Build Debpacker ✔ 
  * Build OS-Ansible-Inventory ✔ 
  * Build SMTPMock ✔ 
  * Lint UI Translate ✔ 
  * Test CLI ✔ 
  * Test Engine ✘  
  * Test SDK ✔ 
  * Test SDK Rust ✔ 
  * Test UI ✔ 

ovh-cds: 
CDS Report build-all-cds#12631.0 ✘  
* Build
  * Build and Package All ✔ 
  * Build Debpacker ✔ 
  * Build OS-Ansible-Inventory ✔ 
  * Build SMTPMock ✔ 
  * Lint UI Translate ✔ 
  * Test CLI ✔ 
  * Test Engine ✔ 
  * Test SDK ✔ 
  * Test SDK Rust ✔ 
  * Test UI ✔ 
* Package
  * Docker ✔ 
  * Docs ✔ 
* Integration
  * Docker Compose Tests ✔ 
  * Helm Tests -   
  * Standalone Tests ✘  

ovh-cds: 
CDS Report build-all-cds#12659.0 ✘  
* Build
  * Build and Package All ✘  
  * Build Debpacker ✔ 
  * Build OS-Ansible-Inventory ✔ 
  * Build SMTPMock ✔ 
  * Lint UI Translate ✔ 
  * Test CLI ✘  
  * Test Engine ✘  
  * Test SDK ✘  
  * Test SDK Rust ✔ 
  * Test UI ✔ 

ovh-cds: 
CDS Report build-all-cds#12660.0 ✘  
* Build
  * Build and Package All ✘  
  * Build Debpacker ✔ 
  * Build OS-Ansible-Inventory ✔ 
  * Build SMTPMock ✔ 
  * Lint UI Translate ✔ 
  * Test CLI ✘  
  * Test Engine ✘  
  * Test SDK ✔ 
  * Test SDK Rust ✔ 
  * Test UI ✔ 

ovh-cds: 
CDS Report build-all-cds#12665.0 ✘  
* Build
  * Build and Package All ✔ 
  * Build Debpacker ✔ 
  * Build OS-Ansible-Inventory ✔ 
  * Build SMTPMock ✔ 
  * Lint UI Translate ✔ 
  * Test CLI ✔ 
  * Test Engine ✘  
  * Test SDK ✔ 
  * Test SDK Rust ✔ 
  * Test UI ✔ 

ovh-cds: 
CDS Report build-all-cds#12671.0 ✘  
* Build
  * Build and Package All ✔ 
  * Build Debpacker ✔ 
  * Build OS-Ansible-Inventory ✔ 
  * Build SMTPMock ✔ 
  * Lint UI Translate ✔ 
  * Test CLI ✔ 
  * Test Engine ✔ 
  * Test SDK ✔ 
  * Test SDK Rust ✔ 
  * Test UI ✔ 
* Package
  * Docker ✔ 
  * Docs ✔ 
* Integration
  * Docker Compose Tests ✔ 
  * Helm Tests -   
  * Standalone Tests ✘  

ovh-cds: 
CDS Report build-all-cds#12722.0 ✘  
* Build
  * Build and Package All ✔ 
  * Build Debpacker ✔ 
  * Build OS-Ansible-Inventory ✔ 
  * Build SMTPMock ✔ 
  * Lint UI Translate ✔ 
  * Test CLI ✔ 
  * Test Engine ✔ 
  * Test SDK ✔ 
  * Test SDK Rust ✔ 
  * Test UI ✔ 
* Package
  * Docker ✔ 
  * Docs ✔ 
* Integration
  * Docker Compose Tests ✔ 
  * Helm Tests -   
  * Standalone Tests ✘  


Patch:
diff --git a/cli/cdsctl/workflow_run.go b/cli/cdsctl/workflow_run.go
index ce20931cf..e2157e3d6 100644
--- a/cli/cdsctl/workflow_run.go
+++ b/cli/cdsctl/workflow_run.go
@@ -121,7 +121,7 @@ func workflowRunManualRun(v cli.Values) error {
 		}
 
 		// Check if we are on the same repository and if we have a git.branch in the default payload
-		if wf.WorkflowData != nil && wf.WorkflowData.Node.Context != nil && wf.WorkflowData.Node.Context.ApplicationID != 0 {
+		if wf.WorkflowData.Node.Context != nil && wf.WorkflowData.Node.Context.ApplicationID != 0 {
 			app := wf.GetApplication(wf.WorkflowData.Node.Context.ApplicationID)
 			if remoteURL != "" && strings.Contains(remoteURL, app.RepositoryFullname) && currentBranch != "" {
 				defaultPayload, err := wf.WorkflowData.Node.Context.DefaultPayloadToMap()
diff --git a/engine/api/repositories_manager.go b/engine/api/repositories_manager.go
index abda80b0a..9a1b2da79 100644
--- a/engine/api/repositories_manager.go
+++ b/engine/api/repositories_manager.go
@@ -557,6 +557,7 @@ func (api *API) attachRepositoriesManagerHandler() service.Handler {
 					return err
 				}
 
+				// second load for publish the event below
 				wfOld, err := workflow.LoadByID(ctx, db, api.Cache, *proj, wf.ID, workflow.LoadOptions{})
 				if err != nil {
 					return err
@@ -585,7 +586,7 @@ func (api *API) attachRepositoriesManagerHandler() service.Handler {
 
 				wfDB.WorkflowData.Node.Context.DefaultPayload = defaultPayload
 
-				if err := workflow.Update(ctx, db, api.Cache, *proj, wfDB, workflow.UpdateOptions{DisableHookManagement: true, OldWorkflow: wfOld}); err != nil {
+				if err := workflow.Update(ctx, db, api.Cache, *proj, wfDB, workflow.UpdateOptions{DisableHookManagement: true}); err != nil {
 					return sdk.WrapError(err, "cannot update node context %d", wf.WorkflowData.Node.Context.ID)
 				}
 
diff --git a/engine/api/workflow.go b/engine/api/workflow.go
index 5f68816c6..5c2060a6f 100644
--- a/engine/api/workflow.go
+++ b/engine/api/workflow.go
@@ -368,10 +368,6 @@ func (api *API) postWorkflowHandler() service.Handler {
 			return err
 		}
 
-		if data.WorkflowData == nil {
-			return sdk.WrapError(sdk.ErrWrongRequest, "no node found")
-		}
-
 		if err := workflow.RenameNode(ctx, api.mustDB(), &data); err != nil {
 			return err
 		}
@@ -457,7 +453,7 @@ func (api *API) putWorkflowHandler() service.Handler {
 		}
 		defer tx.Rollback() // nolint
 
-		if err := workflow.Update(ctx, tx, api.Cache, *p, &wf, workflow.UpdateOptions{OldWorkflow: oldW}); err != nil {
+		if err := workflow.Update(ctx, tx, api.Cache, *p, &wf, workflow.UpdateOptions{}); err != nil {
 			return sdk.WrapError(err, "cannot update workflow")
 		}
 
diff --git a/engine/api/workflow/dao.go b/engine/api/workflow/dao.go
index c303b4010..f981e27d2 100644
--- a/engine/api/workflow/dao.go
+++ b/engine/api/workflow/dao.go
@@ -79,7 +79,6 @@ type LoadOptions struct {
 // UpdateOptions is option to parse a workflow
 type UpdateOptions struct {
 	DisableHookManagement bool
-	OldWorkflow           *sdk.Workflow
 }
 
 // CountVarInWorkflowData represents the result of CountVariableInWorkflow function
@@ -190,8 +189,8 @@ func (w *Workflow) PostGet(db gorp.SqlExecutor) error {
 	}
 	w.PurgeTags = purgeTags
 
-	data := &sdk.WorkflowData{}
-	if err := gorpmapping.JSONNullString(res.WorkflowData, data); err != nil {
+	data := sdk.WorkflowData{}
+	if err := gorpmapping.JSONNullString(res.WorkflowData, &data); err != nil {
 		return sdk.WrapError(err, "Unable to unmarshall workflow data")
 	}
 	if data.Node.ID != 0 {
@@ -901,86 +900,77 @@ func RenameNode(ctx context.Context, db gorp.SqlExecutor, w *sdk.Workflow) error
 }
 
 // Update updates a workflow
-func Update(ctx context.Context, db gorp.SqlExecutor, store cache.Store, proj sdk.Project, w *sdk.Workflow, uptOption UpdateOptions) error {
+func Update(ctx context.Context, db gorp.SqlExecutor, store cache.Store, proj sdk.Project, wf *sdk.Workflow, uptOption UpdateOptions) error {
 	ctx, end := observability.Span(ctx, "workflow.Update")
 	defer end()
-	if err := IsValid(ctx, store, db, w, proj, LoadOptions{}); err != nil {
+	if err := IsValid(ctx, store, db, wf, proj, LoadOptions{}); err != nil {
 		return err
 	}
 
-	if err := DeleteNotifications(db, w.ID); err != nil {
-		return sdk.WrapError(err, "unable to delete all notifications on workflow(%d - %s)", w.ID, w.Name)
+	if err := DeleteNotifications(db, wf.ID); err != nil {
+		return sdk.WrapError(err, "unable to delete all notifications on workflow(%d - %s)", wf.ID, wf.Name)
 	}
 
-	if err := integration.DeleteFromWorkflow(db, w.ID); err != nil {
-		return sdk.WrapError(err, "unable to delete all integrations on workflow(%d - %s)", w.ID, w.Name)
+	if err := integration.DeleteFromWorkflow(db, wf.ID); err != nil {
+		return sdk.WrapError(err, "unable to delete all integrations on workflow(%d - %s)", wf.ID, wf.Name)
 	}
 
-	// Delete workflow data
-	if uptOption.OldWorkflow != nil && uptOption.OldWorkflow.ID != 0 {
-		if err := DeleteWorkflowData(db, *uptOption.OldWorkflow); err != nil {
-			return sdk.WrapError(err, "unable to delete from old workflow data(%d - %s)", w.ID, w.Name)
-		}
-	} else {
-		oldW, err := Load(ctx, db, store, proj, w.Name, LoadOptions{})
-		if err != nil && !sdk.ErrorIs(err, sdk.ErrWorkflowNotFound) {
-			return sdk.WrapError(err, "unable to load old workflow to delete workflow data")
-		}
-		if err == nil {
-			if err := DeleteWorkflowData(db, *oldW); err != nil {
-				return sdk.WrapError(err, "unable to delete from workflow data(%d - %s)", oldW.ID, oldW.Name)
-			}
-		}
+	// reload workflow to delete the current workflow data
+	oldWf, err := LoadByID(ctx, db, store, proj, wf.ID, LoadOptions{})
+	if err != nil {
+		return sdk.WrapError(err, "Unable to load existing workflow with proj:%s ID:%d", proj.Key, wf.ID)
+	}
+	if err := DeleteWorkflowData(db, *oldWf); err != nil {
+		return sdk.WrapError(err, "unable to delete from old workflow data(%d - %s)", wf.ID, wf.Name)
 	}
 
 	// Delete all node ID
-	w.ResetIDs()
+	wf.ResetIDs()
 
 	filteredPurgeTags := []string{}
-	for _, t := range w.PurgeTags {
+	for _, t := range wf.PurgeTags {
 		if t != "" {
 			filteredPurgeTags = append(filteredPurgeTags, t)
 		}
 	}
-	w.PurgeTags = filteredPurgeTags
-
-	if w.WorkflowData.Node.Context != nil && w.WorkflowData.Node.Context.ApplicationID != 0 {
+	wf.PurgeTags = filteredPurgeTags
+	if wf.WorkflowData.Node.Context != nil && wf.WorkflowData.Node.Context.ApplicationID != 0 {
 		var err error
-		if w.WorkflowData.Node.Context.DefaultPayload, err = DefaultPayload(ctx, db, store, proj, w); err != nil {
+		if wf.WorkflowData.Node.Context.DefaultPayload, err = DefaultPayload(ctx, db, store, proj, wf); err != nil {
 			log.Warning(ctx, "workflow.Update> Cannot set default payload : %v", err)
 		}
 	}
 
 	if !uptOption.DisableHookManagement {
-		if err := hookRegistration(ctx, db, store, proj, w, uptOption.OldWorkflow); err != nil {
+		if err := hookRegistration(ctx, db, store, proj, wf, oldWf); err != nil {
 			return err
 		}
-		if uptOption.OldWorkflow != nil {
-			hookToDelete := computeHookToDelete(w, uptOption.OldWorkflow)
+		if oldWf != nil {
+			hookToDelete := computeHookToDelete(wf, oldWf)
 			if err := hookUnregistration(ctx, db, store, proj, hookToDelete); err != nil {
 				return err
 			}
 		}
 	}
 
-	if err := InsertWorkflowData(db, w); err != nil {
+	if err := InsertWorkflowData(db, wf); err != nil {
 		return sdk.WrapError(err, "Update> Unable to insert workflow data")
 	}
 
 	// Insert notifications
-	for i := range w.Notifications {
-		n := &w.Notifications[i]
-		if err := InsertNotification(db, w, n); err != nil {
-			return sdk.WrapError(err, "Unable to update workflow(%d) notification (%#v)", w.ID, n)
+	for i := range wf.Notifications {
+		n := &wf.Notifications[i]
+		if err := InsertNotification(db, wf, n); err != nil {
+			return sdk.WrapError(err, "Unable to update workflow(%d) notification (%#v)", wf.ID, n)
 		}
 	}
 
-	w.LastModified = time.Now()
-	dbw := Workflow(*w)
+	wf.LastModified = time.Now()
+	dbw := Workflow(*wf)
 	if _, err := db.Update(&dbw); err != nil {
 		return sdk.WrapError(err, "Unable to update workflow")
 	}
-	*w = sdk.Workflow(dbw)
+	*wf = sdk.Workflow(dbw)
 
 	return nil
 }
@@ -1035,10 +1025,6 @@ func IsValid(ctx context.Context, store cache.Store, db gorp.SqlExecutor, w *sdk
 		return sdk.NewError(sdk.ErrWorkflowInvalid, fmt.Errorf("Invalid project key"))
 	}
 
-	if w.WorkflowData == nil {
-		return sdk.WithStack(fmt.Errorf("bad workflow, workflow data must not be null"))
-	}
-
 	if w.Icon != "" {
 		if !strings.HasPrefix(w.Icon, sdk.IconFormat) {
 			return sdk.WithStack(sdk.ErrIconBadFormat)
@@ -1386,8 +1372,8 @@ func Push(ctx context.Context, db *gorp.DbMap, store cache.Store, proj *sdk.Proj
 	var workflowExists bool
 	var oldWf *sdk.Workflow
 
-	if opts != nil && opts.OldWorkflow != nil {
-		oldWf = opts.OldWorkflow
+	if opts != nil && opts.OldWorkflow.ID > 0 {
+		oldWf = &opts.OldWorkflow
 	} else {
 		// load the workflow from database if exists
 		workflowExists, err = Exists(db, proj.Key, data.wrkflw.GetName())
diff --git a/engine/api/workflow/dao_data.go b/engine/api/workflow/dao_data.go
index 221e13554..ad0a2868d 100644
--- a/engine/api/workflow/dao_data.go
+++ b/engine/api/workflow/dao_data.go
@@ -19,21 +19,18 @@ func CountPipeline(db gorp.SqlExecutor, pipelineID int64) (bool, error) {
 }
 
 // DeleteWorkflowData delete the relation representation of the workflow
-func DeleteWorkflowData(db gorp.SqlExecutor, w sdk.Workflow) error {
-	if w.WorkflowData == nil {
-		return nil
-	}
-	log.Debug("DeleteWorkflowData> deleting workflow data %d", w.ID)
+func DeleteWorkflowData(db gorp.SqlExecutor, wf sdk.Workflow) error {
+	log.Debug("DeleteWorkflowData> deleting workflow data %d", wf.ID)
 
 	// Delete all JOINs
-	for _, j := range w.WorkflowData.Joins {
+	for _, j := range wf.WorkflowData.Joins {
 		if err := deleteJoinData(db, j); err != nil {
-			return sdk.WrapError(err, "DeleteWorkflowData> unable to delete all join on workflow(%d)", w.ID)
+			return sdk.WrapError(err, "DeleteWorkflowData> unable to delete all join on workflow(%d)", wf.ID)
 		}
 	}
 
 	//Delete root
-	if err := deleteNodeData(db, w.WorkflowData.Node); err != nil {
+	if err := deleteNodeData(db, wf.WorkflowData.Node); err != nil {
 		return sdk.WrapError(err, "DeleteWorkflowData> Unable to delete workflow root")
 	}
 
diff --git a/engine/api/workflow/repository.go b/engine/api/workflow/repository.go
index f2f00a4a4..8963e5e9e 100644
--- a/engine/api/workflow/repository.go
+++ b/engine/api/workflow/repository.go
@@ -36,16 +36,16 @@ type PushOption struct {
 	RepositoryStrategy sdk.RepositoryStrategy
 	HookUUID           string
 	Force              bool
-	OldWorkflow        *sdk.Workflow
+	OldWorkflow        sdk.Workflow
 }
 
 // CreateFromRepository a workflow from a repository
-func CreateFromRepository(ctx context.Context, db *gorp.DbMap, store cache.Store, p *sdk.Project, w *sdk.Workflow,
+func CreateFromRepository(ctx context.Context, db *gorp.DbMap, store cache.Store, p *sdk.Project, wf *sdk.Workflow,
 	opts sdk.WorkflowRunPostHandlerOption, u sdk.Identifiable, decryptFunc keys.DecryptFunc) ([]sdk.Message, error) {
 	ctx, end := observability.Span(ctx, "workflow.CreateFromRepository")
 	defer end()
 
-	ope, err := createOperationRequest(*w, opts)
+	ope, err := createOperationRequest(*wf, opts)
 	if err != nil {
 		return nil, sdk.WrapError(err, "unable to create operation request")
 	}
@@ -63,17 +63,17 @@ func CreateFromRepository(ctx context.Context, db *gorp.DbMap, store cache.Store
 		uuid = opts.Hook.WorkflowNodeHookUUID
 	} else {
 		// Search for repo web hook uuid
-		for _, h := range w.WorkflowData.Node.Hooks {
+		for _, h := range wf.WorkflowData.Node.Hooks {
 			if h.HookModelName == sdk.RepositoryWebHookModelName {
 				uuid = h.UUID
 				break
 			}
 		}
 	}
-	return extractWorkflow(ctx, db, store, p, w, ope, u, decryptFunc, uuid)
+	return extractWorkflow(ctx, db, store, p, wf, ope, u, decryptFunc, uuid)
 }
 
-func extractWorkflow(ctx context.Context, db *gorp.DbMap, store cache.Store, p *sdk.Project, w *sdk.Workflow,
+func extractWorkflow(ctx context.Context, db *gorp.DbMap, store cache.Store, p *sdk.Project, wf *sdk.Workflow,
 	ope sdk.Operation, ident sdk.Identifiable, decryptFunc keys.DecryptFunc, hookUUID string) ([]sdk.Message, error) {
 	ctx, end := observability.Span(ctx, "workflow.extractWorkflow")
 	defer end()
@@ -93,17 +93,17 @@ func extractWorkflow(ctx context.Context, db *gorp.DbMap, store cache.Store, p *
 		FromRepository:     ope.RepositoryInfo.FetchURL,
 		IsDefaultBranch:    ope.Setup.Checkout.Tag == "" && ope.Setup.Checkout.Branch == ope.RepositoryInfo.DefaultBranch,
 		HookUUID:           hookUUID,
-		OldWorkflow:        w,
+		OldWorkflow:        *wf,
 	}
 
 	allMsg, workflowPushed, _, errP := Push(ctx, db, store, p, tr, opt, ident, decryptFunc)
 	if errP != nil {
 		return allMsg, sdk.WrapError(errP, "unable to get workflow from file")
 	}
-	*w = *workflowPushed
+	*wf = *workflowPushed
 
-	if w.Name != workflowPushed.Name {
-		log.Debug("workflow.extractWorkflow> Workflow has been renamed from %s to %s", w.Name, workflowPushed.Name)
+	if wf.Name != workflowPushed.Name {
+		log.Debug("workflow.extractWorkflow> Workflow has been renamed from %s to %s", wf.Name, workflowPushed.Name)
 	}
 
 	return append(allMsgs, allMsg...), nil
diff --git a/engine/api/workflow/workflow_importer.go b/engine/api/workflow/workflow_importer.go
index a8456361d..aadea92a9 100644
--- a/engine/api/workflow/workflow_importer.go
+++ b/engine/api/workflow/workflow_importer.go
@@ -75,7 +75,6 @@ func Import(ctx context.Context, db gorp.SqlExecutor, store cache.Store, proj sd
 	// The derivation branch is set in workflow parser it is not coming from the default branch
 	uptOptions := UpdateOptions{
 		DisableHookManagement: w.DerivationBranch != "",
-		OldWorkflow:           oldW,
 	}
 
 	if err := Update(ctx, db, store, proj, w, uptOptions); err != nil {
diff --git a/engine/api/workflow_ascode.go b/engine/api/workflow_ascode.go
index f0f2decb1..1055109e1 100644
--- a/engine/api/workflow_ascode.go
+++ b/engine/api/workflow_ascode.go
@@ -147,12 +147,7 @@ func (api *API) migrateWorkflowAsCode(ctx context.Context, w http.ResponseWriter
 		}
 		wf.WorkflowData.Node.Hooks = append(wf.WorkflowData.Node.Hooks, h)
 
-		oldW, errOld := workflow.LoadByID(ctx, api.mustDB(), api.Cache, *proj, wf.ID, workflow.LoadOptions{})
-		if errOld != nil {
-			return errOld
-		}
-
-		if err := workflow.Update(ctx, api.mustDB(), api.Cache, *proj, wf, workflow.UpdateOptions{OldWorkflow: oldW}); err != nil {
+		if err := workflow.Update(ctx, api.mustDB(), api.Cache, *proj, wf, workflow.UpdateOptions{}); err != nil {
 			return err
 		}
 	}
diff --git a/engine/sql/193_clean_workflow_data_node.sql b/engine/sql/193_clean_workflow_data_node.sql
new file mode 100644
index 000000000..9611f728b
--- /dev/null
+++ b/engine/sql/193_clean_workflow_data_node.sql
@@ -0,0 +1,32 @@
+-- +migrate Up
+
+-- clean w_node_trigger child_node
+WITH workflowInfo AS (
+	SELECT id, name, CAST(workflow_data->'node'->>'id' AS BIGINT) as rootNodeID
+	FROM workflow
+),
+oldNode as (
+	SELECT w_node.id as nodeID, w_node.name as nodeName, workflowInfo.id as wID, workflowInfo.name as WName
+	FROM w_node
+	JOIN workflowInfo ON workflowInfo.id = w_node.workflow_id
+	WHERE w_node.id < workflowInfo.rootNodeID
+)
+DELETE FROM w_node_trigger where child_node_id IN (SELECT nodeID FROM oldNode);
+
+
+-- clean w_node
+WITH workflowInfo AS (
+	SELECT id, name, CAST(workflow_data->'node'->>'id' AS BIGINT) as rootNodeID
+	FROM workflow
+),
+oldNode as (
+	SELECT w_node.id as nodeID, w_node.name as nodeName, workflowInfo.id as wID, workflowInfo.name as WName
+	FROM w_node
+	JOIN workflowInfo ON workflowInfo.id = w_node.workflow_id
+	WHERE w_node.id < workflowInfo.rootNodeID
+)
+DELETE FROM w_node where id IN (SELECT nodeID FROM oldNode);
+
+
+-- +migrate Down
+SELECT 1;
diff --git a/sdk/exportentities/v1/workflow.go b/sdk/exportentities/v1/workflow.go
index 43f8b3647..54596dbe3 100644
--- a/sdk/exportentities/v1/workflow.go
+++ b/sdk/exportentities/v1/workflow.go
@@ -185,7 +185,7 @@ func (w Workflow) GetWorkflow() (*sdk.Workflow, error) {
 	var wf = new(sdk.Workflow)
 	wf.Name = w.Name
 	wf.Description = w.Description
-	wf.WorkflowData = &sdk.WorkflowData{}
+	wf.WorkflowData = sdk.WorkflowData{}
 	// Init map
 	wf.Applications = make(map[int64]sdk.Application)
 	wf.Pipelines = make(map[int64]sdk.Pipeline)
diff --git a/sdk/exportentities/v2/workflow.go b/sdk/exportentities/v2/workflow.go
index 1d58f393b..189b57b86 100644
--- a/sdk/exportentities/v2/workflow.go
+++ b/sdk/exportentities/v2/workflow.go
@@ -344,7 +344,7 @@ func (w Workflow) GetWorkflow() (*sdk.Workflow, error) {
 	var wf = new(sdk.Workflow)
 	wf.Name = w.Name
 	wf.Description = w.Description
-	wf.WorkflowData = &sdk.WorkflowData{}
+	wf.WorkflowData = sdk.WorkflowData{}
 	// Init map
 	wf.Applications = make(map[int64]sdk.Application)
 	wf.Pipelines = make(map[int64]sdk.Pipeline)
diff --git a/sdk/exportentities/workflow.go b/sdk/exportentities/workflow.go
index 60226022c..8a1aaf79a 100644
--- a/sdk/exportentities/workflow.go
+++ b/sdk/exportentities/workflow.go
@@ -7,8 +7,8 @@ import (
 	"gopkg.in/yaml.v2"
 
 	"github.com/ovh/cds/sdk"
-	"github.com/ovh/cds/sdk/exportentities/v1"
-	"github.com/ovh/cds/sdk/exportentities/v2"
+	v1 "github.com/ovh/cds/sdk/exportentities/v1"
+	v2 "github.com/ovh/cds/sdk/exportentities/v2"
 )
 
 // Name pattern for pull files.
diff --git a/sdk/workflow.go b/sdk/workflow.go
index 99a523f3e..7aa4f35dd 100644
--- a/sdk/workflow.go
+++ b/sdk/workflow.go
@@ -49,7 +49,7 @@ type Workflow struct {
 	Labels                  []Label                      `json:"labels" db:"-" cli:"labels"`
 	ToDelete                bool                         `json:"to_delete" db:"to_delete" cli:"-"`
 	Favorite                bool                         `json:"favorite" db:"-" cli:"favorite"`
-	WorkflowData            *WorkflowData                `json:"workflow_data" db:"-" cli:"-"`
+	WorkflowData            WorkflowData                 `json:"workflow_data" db:"-" cli:"-"`
 	EventIntegrations       []ProjectIntegration         `json:"event_integrations" db:"-" cli:"-"`
 	AsCodeEvent             []AsCodeEvent                `json:"as_code_events" db:"-" cli:"-"`
 	// aggregates
@@ -94,7 +94,7 @@ func (w *Workflow) ResetIDs() {
 
 //AddTrigger adds a trigger to the destination node from the node found by its name
 func (w *Workflow) AddTrigger(name string, dest Node) {
-	if w.WorkflowData == nil || w.WorkflowData.Node.Name == "" {
+	if w.WorkflowData.Node.Name == "" {
 		return
 	}
 
diff --git a/sdk/workflow_hook.go b/sdk/workflow_hook.go
index aef23fcf4..c99374b21 100644
--- a/sdk/workflow_hook.go
+++ b/sdk/workflow_hook.go
@@ -76,10 +76,6 @@ func (h NodeHook) Equals(h1 NodeHook) bool {
 
 // FilterHooksConfig filter all hooks configuration and remove some configuration key
 func (w *Workflow) FilterHooksConfig(s ...string) {
-	if w.WorkflowData == nil {
-		return
-	}
-
 	w.WorkflowData.Node.FilterHooksConfig(s...)
 	for i := range w.WorkflowData.Joins {
 		w.WorkflowData.Joins[i].FilterHooksConfig(s...)
diff --git a/sdk/workflow_node.go b/sdk/workflow_node.go
index 5876fba72..eb382edb5 100644
--- a/sdk/workflow_node.go
+++ b/sdk/workflow_node.go
@@ -206,7 +206,7 @@ func (n *Node) maps(m map[int64]*Node) map[int64]*Node {
 	return m
 }
 
-func (n *Node) Ancestors(w *WorkflowData) []int64 {
+func (n *Node) Ancestors(w WorkflowData) []int64 {
 	if n == nil {
 		return nil
 	}


Test patch:
diff --git a/engine/api/application/dao_test.go b/engine/api/application/dao_test.go
index 3e3d42583..db7d721d3 100644
--- a/engine/api/application/dao_test.go
+++ b/engine/api/application/dao_test.go
@@ -182,7 +182,7 @@ func TestLoadByWorkflowID(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Context: &sdk.NodeContext{
diff --git a/engine/api/ascode_test.go b/engine/api/ascode_test.go
index f323114fe..e7cada647 100644
--- a/engine/api/ascode_test.go
+++ b/engine/api/ascode_test.go
@@ -356,7 +356,7 @@ vcs_ssh_key: proj-blabla
 		Name:       sdk.RandomString(10),
 		ProjectID:  p.ID,
 		ProjectKey: p.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
diff --git a/engine/api/pipeline/pipeline_test.go b/engine/api/pipeline/pipeline_test.go
index f8d54d0a8..592159cc8 100644
--- a/engine/api/pipeline/pipeline_test.go
+++ b/engine/api/pipeline/pipeline_test.go
@@ -167,7 +167,7 @@ func TestLoadByWorkflowID(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Context: &sdk.NodeContext{
diff --git a/engine/api/project_group_test.go b/engine/api/project_group_test.go
index 71ad7c27a..2f95ba609 100644
--- a/engine/api/project_group_test.go
+++ b/engine/api/project_group_test.go
@@ -30,7 +30,7 @@ func Test_ProjectPerms(t *testing.T) {
 
 	newWf := sdk.Workflow{
 		Name: sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
diff --git a/engine/api/repositories_manager_test.go b/engine/api/repositories_manager_test.go
index 2086b95bf..f97d7a5ee 100644
--- a/engine/api/repositories_manager_test.go
+++ b/engine/api/repositories_manager_test.go
@@ -139,6 +139,8 @@ func TestAPI_detachRepositoriesManagerHandler(t *testing.T) {
 				if err := enc.Encode(pr); err != nil {
 					return writeError(w, err)
 				}
+			case "/vcs/github/repos/sguiheux/demo/hooks?url=http%3A%2F%2Flolcat.host&id=666":
+				// do nothing
 			default:
 				t.Fatalf("UNKNOWN ROUTE: %s", r.URL.String())
 			}
@@ -194,7 +196,7 @@ vcs_ssh_key: proj-blabla
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "node1",
 				Ref:  "node1",
diff --git a/engine/api/test/assets/assets.go b/engine/api/test/assets/assets.go
index 7dbbcc47e..487e0b88e 100644
--- a/engine/api/test/assets/assets.go
+++ b/engine/api/test/assets/assets.go
@@ -534,7 +534,7 @@ func InsertTestWorkflow(t *testing.T, db gorp.SqlExecutor, store cache.Store, pr
 		Name:       name,
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "node1",
 				Ref:  "node1",
diff --git a/engine/api/worker_model_test.go b/engine/api/worker_model_test.go
index e695bc48c..d13356c3f 100644
--- a/engine/api/worker_model_test.go
+++ b/engine/api/worker_model_test.go
@@ -253,7 +253,7 @@ func Test_WorkerModelUsage(t *testing.T) {
 		Name:       "workflow1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Context: &sdk.NodeContext{
diff --git a/engine/api/workflow/dao_run_test.go b/engine/api/workflow/dao_run_test.go
index 1819218a7..9f02fa629 100644
--- a/engine/api/workflow/dao_run_test.go
+++ b/engine/api/workflow/dao_run_test.go
@@ -51,7 +51,7 @@ func TestCanBeRun(t *testing.T) {
 			Name:       "test_1",
 			ProjectID:  1,
 			ProjectKey: "key",
-			WorkflowData: &sdk.WorkflowData{
+			WorkflowData: sdk.WorkflowData{
 				Node: nodeRoot,
 			},
 		},
@@ -196,7 +196,7 @@ vcs_ssh_key: proj-blabla
 		Name:       "test_purge_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "node1",
 				Ref:  "node1",
@@ -284,7 +284,7 @@ func TestPurgeWorkflowRunWithRunningStatus(t *testing.T) {
 		Name:       "test_purge_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "node1",
 				Ref:  "node1",
@@ -471,7 +471,7 @@ vcs_ssh_key: proj-blabla
 		Name:       "test_purge_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "node1",
 				Ref:  "node1",
@@ -662,7 +662,7 @@ vcs_ssh_key: proj-blabla
 		Name:       "test_purge_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "node1",
 				Ref:  "node1",
@@ -753,7 +753,7 @@ func TestPurgeWorkflowRunWithoutTags(t *testing.T) {
 		Name:       "test_purge_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "node1",
 				Ref:  "node1",
@@ -839,7 +839,7 @@ func TestPurgeWorkflowRunWithoutTagsBiggerHistoryLength(t *testing.T) {
 		Name:       "test_purge_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "node1",
 				Ref:  "node1",
diff --git a/engine/api/workflow/dao_staticfiles_test.go b/engine/api/workflow/dao_staticfiles_test.go
index eecac9146..cb068e286 100644
--- a/engine/api/workflow/dao_staticfiles_test.go
+++ b/engine/api/workflow/dao_staticfiles_test.go
@@ -47,7 +47,7 @@ func TestInsertStaticFiles(t *testing.T) {
 		Name:       "test_staticfiles_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "node1",
 				Ref:  "node1",
diff --git a/engine/api/workflow/dao_test.go b/engine/api/workflow/dao_test.go
index 77961eebd..c3843b0e2 100644
--- a/engine/api/workflow/dao_test.go
+++ b/engine/api/workflow/dao_test.go
@@ -67,7 +67,7 @@ func TestInsertSimpleWorkflowAndExport(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "node1",
 				Ref:  "node1",
@@ -129,7 +129,7 @@ func TestInsertSimpleWorkflowWithWrongName(t *testing.T) {
 		Name:       "test_ 1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Ref:  "root",
@@ -181,7 +181,7 @@ func TestInsertSimpleWorkflowWithApplicationAndEnv(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "node1",
 				Ref:  "node1",
@@ -252,7 +252,7 @@ func TestInsertComplexeWorkflowAndExport(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "Root",
 				Ref:  "root",
@@ -393,7 +393,7 @@ func TestInsertComplexeWorkflowWithBadOperator(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "Root",
 				Type: sdk.NodeTypePipeline,
@@ -557,7 +557,7 @@ func TestUpdateSimpleWorkflowWithApplicationEnvPipelineParametersAndPayload(t *t
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "node1",
 				Type: sdk.NodeTypePipeline,
@@ -676,7 +676,7 @@ func TestInsertComplexeWorkflowWithJoinsAndExport(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Joins: []sdk.Node{
 				{
 					Type: sdk.NodeTypeJoin,
@@ -910,7 +910,7 @@ func TestInsertComplexeWorkflowWithComplexeJoins(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Context: &sdk.NodeContext{
@@ -1146,7 +1146,7 @@ func TestUpdateWorkflowWithJoins(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Context: &sdk.NodeContext{
@@ -1346,7 +1346,7 @@ func TestInsertSimpleWorkflowWithHookAndExport(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Context: &sdk.NodeContext{
@@ -1716,7 +1716,7 @@ vcs_ssh_key: proj-blabla
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
 		Name:       sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -1757,7 +1757,7 @@ vcs_ssh_key: proj-blabla
 		HookModelID: webHookID,
 	})
 
-	assert.NoError(t, workflow.Update(context.TODO(), db, cache, *proj, &w, workflow.UpdateOptions{OldWorkflow: oldW}))
+	assert.NoError(t, workflow.Update(context.TODO(), db, cache, *proj, &w, workflow.UpdateOptions{}))
 
 	// Add check on HOOKS
 	assert.Equal(t, 2, len(w.WorkflowData.Node.Hooks))
@@ -1782,7 +1782,7 @@ vcs_ssh_key: proj-blabla
 		HookModelID: schedulerID,
 	})
 
-	assert.NoError(t, workflow.Update(context.TODO(), db, cache, *proj, &w, workflow.UpdateOptions{OldWorkflow: oldW}))
+	assert.NoError(t, workflow.Update(context.TODO(), db, cache, *proj, &w, workflow.UpdateOptions{}))
 
 	// Add check on HOOKS
 	assert.Equal(t, 3, len(w.WorkflowData.Node.Hooks))
@@ -1818,7 +1818,7 @@ vcs_ssh_key: proj-blabla
 		}
 	}
 	w.WorkflowData.Node.Hooks = append(w.WorkflowData.Node.Hooks[:index], w.WorkflowData.Node.Hooks[index+1:]...)
-	assert.NoError(t, workflow.Update(context.TODO(), db, cache, *proj, &w, workflow.UpdateOptions{OldWorkflow: oldW}))
+	assert.NoError(t, workflow.Update(context.TODO(), db, cache, *proj, &w, workflow.UpdateOptions{}))
 
 	// Add check on HOOKS
 	assert.Equal(t, 2, len(w.WorkflowData.Node.Hooks))
diff --git a/engine/api/workflow/process_node_test.go b/engine/api/workflow/process_node_test.go
index 3c4be99e4..71c8b71f0 100644
--- a/engine/api/workflow/process_node_test.go
+++ b/engine/api/workflow/process_node_test.go
@@ -167,7 +167,7 @@ func TestHookRunWithoutPayloadProcessNodeBuildParameter(t *testing.T) {
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
 		Name:       sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -349,7 +349,7 @@ func TestHookRunWithHashOnlyProcessNodeBuildParameter(t *testing.T) {
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
 		Name:       sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -515,7 +515,7 @@ func TestManualRunWithPayloadProcessNodeBuildParameter(t *testing.T) {
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
 		Name:       sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -660,7 +660,7 @@ func TestManualRunBranchAndCommitInPayloadProcessNodeBuildParameter(t *testing.T
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
 		Name:       sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -874,7 +874,7 @@ func TestManualRunBranchAndRepositoryInPayloadProcessNodeBuildParameter(t *testi
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
 		Name:       sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -1096,7 +1096,7 @@ func TestManualRunBuildParameterMultiApplication(t *testing.T) {
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
 		Name:       sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -1301,7 +1301,7 @@ func TestGitParamOnPipelineWithoutApplication(t *testing.T) {
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
 		Name:       sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -1485,7 +1485,7 @@ func TestGitParamOnApplicationWithoutRepo(t *testing.T) {
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
 		Name:       sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -1680,7 +1680,7 @@ func TestGitParamOn2ApplicationSameRepo(t *testing.T) {
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
 		Name:       sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -1879,7 +1879,7 @@ func TestGitParamWithJoin(t *testing.T) {
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
 		Name:       sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Ref:  "root",
@@ -2098,7 +2098,7 @@ func TestGitParamOn2ApplicationSameRepoWithFork(t *testing.T) {
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
 		Name:       sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Ref:  "root",
@@ -2291,7 +2291,7 @@ func TestManualRunWithPayloadAndRunCondition(t *testing.T) {
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
 		Name:       sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
diff --git a/engine/api/workflow/run_workflow_test.go b/engine/api/workflow/run_workflow_test.go
index e7ca7f562..2be405b68 100644
--- a/engine/api/workflow/run_workflow_test.go
+++ b/engine/api/workflow/run_workflow_test.go
@@ -78,7 +78,7 @@ func TestManualRun1(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "node1",
 				Ref:  "node1",
@@ -237,7 +237,7 @@ func TestManualRun2(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "node1",
 				Ref:  "node1",
@@ -489,7 +489,7 @@ func TestManualRun3(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "node1",
 				Ref:  "node1",
@@ -815,7 +815,7 @@ func TestNoStage(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "node1",
 				Ref:  "node1",
@@ -892,7 +892,7 @@ func TestNoJob(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "node1",
 				Ref:  "node1",
diff --git a/engine/api/workflow/workflow_exporter_test.go b/engine/api/workflow/workflow_exporter_test.go
index 75d1d5749..0936e90b8 100644
--- a/engine/api/workflow/workflow_exporter_test.go
+++ b/engine/api/workflow/workflow_exporter_test.go
@@ -91,7 +91,7 @@ func TestPull(t *testing.T) {
 		ProjectKey: proj.Key,
 		Metadata:   sdk.Metadata{"triggered_by": "bla"},
 		PurgeTags:  []string{"aa", "bb"},
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "node1",
 				Ref:  "node1",
diff --git a/engine/api/workflow/workflow_importer_test.go b/engine/api/workflow/workflow_importer_test.go
index 7682d5c78..f90094027 100644
--- a/engine/api/workflow/workflow_importer_test.go
+++ b/engine/api/workflow/workflow_importer_test.go
@@ -109,7 +109,7 @@ func TestImport(t *testing.T) {
 					Name:      "test-1",
 					Metadata:  sdk.Metadata{"triggered_by": "bla"},
 					PurgeTags: []string{"aa", "bb"},
-					WorkflowData: &sdk.WorkflowData{
+					WorkflowData: sdk.WorkflowData{
 						Node: sdk.Node{
 							Name: "pipeline",
 							Ref:  "pipeline",
@@ -129,7 +129,7 @@ func TestImport(t *testing.T) {
 			args: args{
 				w: &sdk.Workflow{
 					Name: "test-1",
-					WorkflowData: &sdk.WorkflowData{
+					WorkflowData: sdk.WorkflowData{
 						Node: sdk.Node{
 							Name: "pipeline",
 							Ref:  "pipeline",
@@ -149,7 +149,7 @@ func TestImport(t *testing.T) {
 			args: args{
 				w: &sdk.Workflow{
 					Name: "test-1",
-					WorkflowData: &sdk.WorkflowData{
+					WorkflowData: sdk.WorkflowData{
 						Node: sdk.Node{
 							Name: "pipeline",
 							Ref:  "pipeline",
@@ -169,7 +169,7 @@ func TestImport(t *testing.T) {
 			args: args{
 				w: &sdk.Workflow{
 					Name: "test-2",
-					WorkflowData: &sdk.WorkflowData{
+					WorkflowData: sdk.WorkflowData{
 						Node: sdk.Node{
 							Name: "pipeline",
 							Ref:  "pipeline",
@@ -191,7 +191,7 @@ func TestImport(t *testing.T) {
 			args: args{
 				w: &sdk.Workflow{
 					Name: "test-3",
-					WorkflowData: &sdk.WorkflowData{
+					WorkflowData: sdk.WorkflowData{
 						Node: sdk.Node{
 							Name: "pipeline",
 							Ref:  "pipeline",
@@ -223,7 +223,7 @@ func TestImport(t *testing.T) {
 			args: args{
 				w: &sdk.Workflow{
 					Name: "test-3",
-					WorkflowData: &sdk.WorkflowData{
+					WorkflowData: sdk.WorkflowData{
 						Node: sdk.Node{
 							Name: "pipeline",
 							Ref:  "pipeline",
@@ -266,7 +266,7 @@ func TestImport(t *testing.T) {
 			args: args{
 				w: &sdk.Workflow{
 					Name: "test-4",
-					WorkflowData: &sdk.WorkflowData{
+					WorkflowData: sdk.WorkflowData{
 						Node: sdk.Node{
 							Name: "A",
 							Ref:  "A",
@@ -398,7 +398,7 @@ func TestImport(t *testing.T) {
 			args: args{
 				w: &sdk.Workflow{
 					Name: "test-5",
-					WorkflowData: &sdk.WorkflowData{
+					WorkflowData: sdk.WorkflowData{
 						Node: sdk.Node{
 							Name: "pipeline",
 							Ref:  "pipeline",
@@ -420,7 +420,7 @@ func TestImport(t *testing.T) {
 			args: args{
 				w: &sdk.Workflow{
 					Name: "test-6",
-					WorkflowData: &sdk.WorkflowData{
+					WorkflowData: sdk.WorkflowData{
 						Node: sdk.Node{
 							Name: "pipeline",
 							Ref:  "pipeline",
@@ -446,7 +446,7 @@ func TestImport(t *testing.T) {
 			args: args{
 				w: &sdk.Workflow{
 					Name: "test-1",
-					WorkflowData: &sdk.WorkflowData{
+					WorkflowData: sdk.WorkflowData{
 						Node: sdk.Node{
 							Name: "pipeline",
 							Ref:  "pipeline",
diff --git a/engine/api/workflow/workflow_run_event_test.go b/engine/api/workflow/workflow_run_event_test.go
index a996d3172..f4f7b4cc8 100644
--- a/engine/api/workflow/workflow_run_event_test.go
+++ b/engine/api/workflow/workflow_run_event_test.go
@@ -2,6 +2,7 @@ package workflow_test
 
 import (
 	"context"
+
 	"github.com/go-gorp/gorp"
 	"github.com/golang/mock/gomock"
 	"github.com/ovh/cds/engine/api/services/mock_services"
@@ -65,7 +66,7 @@ func TestResyncCommitStatusNotifDisabled(t *testing.T) {
 			},
 		},
 		Workflow: sdk.Workflow{
-			WorkflowData: &sdk.WorkflowData{
+			WorkflowData: sdk.WorkflowData{
 				Node: sdk.Node{
 					ID: 1,
 					Context: &sdk.NodeContext{
@@ -169,7 +170,7 @@ func TestResyncCommitStatusSetStatus(t *testing.T) {
 			},
 		},
 		Workflow: sdk.Workflow{
-			WorkflowData: &sdk.WorkflowData{
+			WorkflowData: sdk.WorkflowData{
 				Node: sdk.Node{
 					ID: 1,
 					Context: &sdk.NodeContext{
@@ -293,7 +294,7 @@ func TestResyncCommitStatusCommentPR(t *testing.T) {
 			},
 		},
 		Workflow: sdk.Workflow{
-			WorkflowData: &sdk.WorkflowData{
+			WorkflowData: sdk.WorkflowData{
 				Node: sdk.Node{
 					ID: 1,
 					Context: &sdk.NodeContext{
diff --git a/engine/api/workflow_ascode_test.go b/engine/api/workflow_ascode_test.go
index 19e6c3fe9..dd0f76721 100644
--- a/engine/api/workflow_ascode_test.go
+++ b/engine/api/workflow_ascode_test.go
@@ -449,7 +449,7 @@ func initWorkflow(t *testing.T, db gorp.SqlExecutor, proj *sdk.Project, app *sdk
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
 		Name:       sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
diff --git a/engine/api/workflow_export_test.go b/engine/api/workflow_export_test.go
index 266c18e15..eb7d9cbb3 100644
--- a/engine/api/workflow_export_test.go
+++ b/engine/api/workflow_export_test.go
@@ -66,7 +66,7 @@ func Test_getWorkflowExportHandler(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Context: &sdk.NodeContext{
@@ -214,7 +214,7 @@ func Test_getWorkflowExportHandlerWithPermissions(t *testing.T) {
 				Permission: 7,
 			},
 		},
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Context: &sdk.NodeContext{
@@ -324,7 +324,7 @@ func Test_getWorkflowPullHandler(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Context: &sdk.NodeContext{
diff --git a/engine/api/workflow_group_test.go b/engine/api/workflow_group_test.go
index 0b561d8c9..b15c13b35 100644
--- a/engine/api/workflow_group_test.go
+++ b/engine/api/workflow_group_test.go
@@ -35,7 +35,7 @@ func Test_postWorkflowGroupHandler(t *testing.T) {
 
 	w := sdk.Workflow{
 		Name: sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -107,7 +107,7 @@ func Test_postWorkflowGroupWithLessThanRWXProjectHandler(t *testing.T) {
 
 	w := sdk.Workflow{
 		Name: sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -173,7 +173,7 @@ func Test_putWorkflowGroupHandler(t *testing.T) {
 
 	w := sdk.Workflow{
 		Name: sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -277,7 +277,7 @@ func Test_deleteWorkflowGroupHandler(t *testing.T) {
 
 	w := sdk.Workflow{
 		Name: sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -359,7 +359,7 @@ func Test_UpdateProjectPermsWithWorkflow(t *testing.T) {
 
 	newWf := sdk.Workflow{
 		Name: sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -459,7 +459,7 @@ func Test_PermissionOnWorkflowInferiorOfProject(t *testing.T) {
 
 	newWf := sdk.Workflow{
 		Name: sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -627,7 +627,7 @@ func Test_PermissionOnWorkflowWithRestrictionOnNode(t *testing.T) {
 
 	newWf := sdk.Workflow{
 		Name: sdk.RandomString(10),
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
diff --git a/engine/api/workflow_hook_test.go b/engine/api/workflow_hook_test.go
index 3a093996a..d7774298c 100644
--- a/engine/api/workflow_hook_test.go
+++ b/engine/api/workflow_hook_test.go
@@ -54,7 +54,7 @@ func Test_getWorkflowHookModelsHandlerAsLambdaUser(t *testing.T) {
 		Name:       sdk.RandomString(10),
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -121,7 +121,7 @@ func Test_getWorkflowHookModelsHandlerAsAdminUser(t *testing.T) {
 		Name:       sdk.RandomString(10),
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
diff --git a/engine/api/workflow_import_test.go b/engine/api/workflow_import_test.go
index 2ba737b6e..57d1351b6 100644
--- a/engine/api/workflow_import_test.go
+++ b/engine/api/workflow_import_test.go
@@ -184,7 +184,7 @@ func Test_putWorkflowImportHandler(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Name: "pip1",
@@ -247,7 +247,7 @@ func Test_putWorkflowImportHandlerWithJoinAndCondition(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Name: "pip1",
@@ -374,7 +374,7 @@ func Test_putWorkflowImportHandlerWithJoinWithOrWithoutCondition(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Name: "pip1",
@@ -507,7 +507,7 @@ func Test_putWorkflowImportHandlerWithJoinWithoutCondition(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Name: "pip1",
@@ -720,7 +720,7 @@ func Test_getWorkflowPushHandler(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -813,7 +813,7 @@ func Test_putWorkflowImportHandlerMustNotHave2Joins(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Name: "pip1",
diff --git a/engine/api/workflow_queue_test.go b/engine/api/workflow_queue_test.go
index de90f8794..0ab4b1cb6 100644
--- a/engine/api/workflow_queue_test.go
+++ b/engine/api/workflow_queue_test.go
@@ -151,7 +151,7 @@ func testRunWorkflow(t *testing.T, api *API, router *Router) testRunWorkflowCtx
 		Name:       "wkf-" + sdk.RandomString(10),
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "node-1",
 				Ref:  "node-1",
@@ -951,7 +951,7 @@ func TestPostVulnerabilityReportHandler(t *testing.T) {
 		Name:       sdk.RandomString(10),
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "node1",
 				Ref:  "node1",
@@ -1102,7 +1102,7 @@ func TestInsertNewCodeCoverageReport(t *testing.T) {
 		Name:       sdk.RandomString(10),
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "node1",
 				Ref:  "node1",
diff --git a/engine/api/workflow_run_test.go b/engine/api/workflow_run_test.go
index c87f88b53..6e9911371 100644
--- a/engine/api/workflow_run_test.go
+++ b/engine/api/workflow_run_test.go
@@ -88,7 +88,7 @@ func Test_getWorkflowNodeRunHistoryHandler(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -215,7 +215,7 @@ func Test_getWorkflowRunsHandler(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -370,7 +370,7 @@ func Test_getWorkflowRunsHandlerWithFilter(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -486,7 +486,7 @@ func Test_getLatestWorkflowRunHandler(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -620,7 +620,7 @@ func Test_getWorkflowRunHandler(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -744,7 +744,7 @@ func Test_getWorkflowNodeRunHandler(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -886,7 +886,7 @@ func Test_postWorkflowRunHandler(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -1036,7 +1036,7 @@ func Test_postWorkflowRunAsyncFailedHandler(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -1294,7 +1294,7 @@ func Test_postWorkflowRunHandlerWithoutRightOnEnvironment(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -1435,7 +1435,7 @@ func Test_postWorkflowRunHandlerWithoutRightConditionsOnHook(t *testing.T) {
 		HookModels: map[int64]sdk.WorkflowHookModel{
 			1: sdk.WebHookModel,
 		},
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -1591,7 +1591,7 @@ func Test_postWorkflowRunHandlerHookWithMutex(t *testing.T) {
 		HookModels: map[int64]sdk.WorkflowHookModel{
 			1: sdk.WebHookModel,
 		},
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -1753,7 +1753,7 @@ func Test_postWorkflowRunHandlerHook(t *testing.T) {
 		HookModels: map[int64]sdk.WorkflowHookModel{
 			1: sdk.WebHookModel,
 		},
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -1870,7 +1870,7 @@ func Test_postWorkflowRunHandler_Forbidden(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -1933,7 +1933,7 @@ func Test_postWorkflowRunHandler_ConditionNotOK(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -2027,7 +2027,7 @@ func Test_postWorkflowRunHandler_BadPayload(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -2116,7 +2116,7 @@ func initGetWorkflowNodeRunJobTest(t *testing.T, api *API, db *gorp.DbMap) (*sdk
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -2311,7 +2311,7 @@ func Test_deleteWorkflowRunsBranchHandler(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -2457,7 +2457,7 @@ func Test_deleteWorkflowRunHandler(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -2589,7 +2589,7 @@ func Test_postWorkflowRunHandlerRestartOnlyFailed(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -2733,7 +2733,7 @@ func Test_postWorkflowRunHandlerRestartResync(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
diff --git a/engine/api/workflow_test.go b/engine/api/workflow_test.go
index d50687096..5d3840f05 100644
--- a/engine/api/workflow_test.go
+++ b/engine/api/workflow_test.go
@@ -57,7 +57,7 @@ func Test_getWorkflowsHandler(t *testing.T) {
 		Name:       "workflow1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Context: &sdk.NodeContext{
@@ -185,7 +185,7 @@ func Test_getWorkflowNotificationsConditionsHandler(t *testing.T) {
 		Name:       "test_1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Type: sdk.NodeTypePipeline,
@@ -303,7 +303,7 @@ func Test_getWorkflowHandler_CheckPermission(t *testing.T) {
 		Name:       "workflow1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Context: &sdk.NodeContext{
@@ -412,7 +412,7 @@ func Test_getWorkflowHandler_AsProvider(t *testing.T) {
 		Name:       "workflow1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Context: &sdk.NodeContext{
@@ -472,7 +472,7 @@ func Test_getWorkflowHandler_withUsage(t *testing.T) {
 		Name:       "workflow1",
 		ProjectID:  proj.ID,
 		ProjectKey: proj.Key,
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Name: "root",
 				Context: &sdk.NodeContext{
@@ -558,7 +558,7 @@ func Test_postWorkflowHandlerWithRootShouldSuccess(t *testing.T) {
 	var workflow = &sdk.Workflow{
 		Name:        "Name",
 		Description: "Description",
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Context: &sdk.NodeContext{
@@ -621,7 +621,7 @@ func Test_postWorkflowHandlerWithBadPayloadShouldFail(t *testing.T) {
 	var workflow = &sdk.Workflow{
 		Name:        "Name",
 		Description: "Description",
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Context: &sdk.NodeContext{
@@ -774,7 +774,7 @@ func Test_putWorkflowHandler(t *testing.T) {
 	var workflow = &sdk.Workflow{
 		Name:        "Name",
 		Description: "Description",
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Context: &sdk.NodeContext{
@@ -833,7 +833,7 @@ func Test_putWorkflowHandler(t *testing.T) {
 	var workflow1 = &sdk.Workflow{
 		Name:        "Name",
 		Description: "Description 2",
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Context: &sdk.NodeContext{
@@ -905,7 +905,7 @@ func Test_deleteWorkflowEventIntegrationHandler(t *testing.T) {
 	var wf = &sdk.Workflow{
 		Name:        "Name",
 		Description: "Description",
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Context: &sdk.NodeContext{
@@ -963,7 +963,7 @@ func Test_deleteWorkflowEventIntegrationHandler(t *testing.T) {
 	var workflow1 = &sdk.Workflow{
 		Name:        "Name",
 		Description: "Description 2",
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Context: &sdk.NodeContext{
@@ -1040,7 +1040,7 @@ func Test_postWorkflowHandlerWithError(t *testing.T) {
 	var workflow = &sdk.Workflow{
 		Name:        "Name",
 		Description: "Description",
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Context: &sdk.NodeContext{
@@ -1099,7 +1099,7 @@ func Test_postWorkflowRollbackHandler(t *testing.T) {
 	var wf = &sdk.Workflow{
 		Name:        "Name",
 		Description: "Description",
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Context: &sdk.NodeContext{
@@ -1139,7 +1139,7 @@ func Test_postWorkflowRollbackHandler(t *testing.T) {
 		ID:          wf.ID,
 		Name:        "Name",
 		Description: "Description 2",
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Context: &sdk.NodeContext{
@@ -1216,10 +1216,6 @@ func Test_postWorkflowRollbackHandler(t *testing.T) {
 	var wfRollback sdk.Workflow
 	test.NoError(t, json.Unmarshal(w.Body.Bytes(), &wfRollback))
 
-	if wfRollback.WorkflowData == nil {
-		t.Fatal(fmt.Errorf("workflow not found"))
-	}
-
 	test.Equal(t, int64(0), wfRollback.WorkflowData.Node.Context.ApplicationID)
 
 	assert.Equal(t, true, wfRollback.Permissions.Readable)
@@ -1301,7 +1297,7 @@ func Test_postAndDeleteWorkflowLabelHandler(t *testing.T) {
 	var wf = &sdk.Workflow{
 		Name:        name,
 		Description: "Description",
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Context: &sdk.NodeContext{
@@ -1396,7 +1392,7 @@ func Test_deleteWorkflowHandler(t *testing.T) {
 	var wkf = &sdk.Workflow{
 		Name:        "Name",
 		Description: "Description",
-		WorkflowData: &sdk.WorkflowData{
+		WorkflowData: sdk.WorkflowData{
 			Node: sdk.Node{
 				Type: sdk.NodeTypePipeline,
 				Context: &sdk.NodeContext{
@@ -1485,7 +1481,7 @@ func TestBenchmarkGetWorkflowsWithoutAPIAsAdmin(t *testing.T) {
 			ProjectID:  proj.ID,
 			ProjectKey: proj.Key,
 			Name:       sdk.RandomString(10),
-			WorkflowData: &sdk.WorkflowData{
+			WorkflowData: sdk.WorkflowData{
 				Node: sdk.Node{
 					Name: "root",
 					Context: &sdk.NodeContext{
@@ -1554,7 +1550,7 @@ func TestBenchmarkGetWorkflowsWithAPI(t *testing.T) {
 			ProjectKey: proj.Key,
 			Name:       sdk.RandomString(10),
 			Groups:     proj.ProjectGroups,
-			WorkflowData: &sdk.WorkflowData{
+			WorkflowData: sdk.WorkflowData{
 				Node: sdk.Node{
 					Name: "root",
 					Context: &sdk.NodeContext{
diff --git a/sdk/exportentities/v1/workflow_test.go b/sdk/exportentities/v1/workflow_test.go
index f6cb4756d..370513be3 100644
--- a/sdk/exportentities/v1/workflow_test.go
+++ b/sdk/exportentities/v1/workflow_test.go
@@ -1,12 +1,13 @@
 package v1_test
 
 import (
-	"github.com/ovh/cds/sdk/exportentities"
-	v1 "github.com/ovh/cds/sdk/exportentities/v1"
 	"sort"
 	"strings"
 	"testing"
 
+	"github.com/ovh/cds/sdk/exportentities"
+	v1 "github.com/ovh/cds/sdk/exportentities/v1"
+
 	"github.com/fsamin/go-dump"
 	"github.com/ovh/cds/sdk"
 	"github.com/stretchr/testify/assert"
@@ -230,7 +231,7 @@ func TestWorkflow_GetWorkflow(t *testing.T) {
 			want: sdk.Workflow{
 				Name:          "myworkflow",
 				HistoryLength: sdk.DefaultHistoryLength,
-				WorkflowData: &sdk.WorkflowData{
+				WorkflowData: sdk.WorkflowData{
 					Node: sdk.Node{
 						Name: "pipeline",
 						Type: "pipeline",
@@ -268,7 +269,7 @@ func TestWorkflow_GetWorkflow(t *testing.T) {
 				Name:          "myworkflow",
 				HistoryLength: sdk.DefaultHistoryLength,
 				Description:   "this is my description",
-				WorkflowData: &sdk.WorkflowData{
+				WorkflowData: sdk.WorkflowData{
 					Node: sdk.Node{
 						Name: "pipeline",
 						Type: "pipeline",
@@ -332,7 +333,7 @@ func TestWorkflow_GetWorkflow(t *testing.T) {
 			want: sdk.Workflow{
 				Name:          "myworkflow",
 				HistoryLength: sdk.DefaultHistoryLength,
-				WorkflowData: &sdk.WorkflowData{
+				WorkflowData: sdk.WorkflowData{
 					Node: sdk.Node{
 						Name: "root",
 						Type: "pipeline",
@@ -397,7 +398,7 @@ func TestWorkflow_GetWorkflow(t *testing.T) {
 			want: sdk.Workflow{
 				Name:          "myworkflow",
 				HistoryLength: sdk.DefaultHistoryLength,
-				WorkflowData: &sdk.WorkflowData{
+				WorkflowData: sdk.WorkflowData{
 					Node: sdk.Node{
 						Name: "root",
 						Type: "pipeline",
@@ -464,7 +465,7 @@ func TestWorkflow_GetWorkflow(t *testing.T) {
 			want: sdk.Workflow{
 				Name:          "myworkflow",
 				HistoryLength: 25,
-				WorkflowData: &sdk.WorkflowData{
+				WorkflowData: sdk.WorkflowData{
 					Node: sdk.Node{
 						Name: "root",
 						Ref:  "root",
@@ -512,7 +513,7 @@ func TestWorkflow_GetWorkflow(t *testing.T) {
 			want: sdk.Workflow{
 				Name:          "myworkflow",
 				HistoryLength: sdk.DefaultHistoryLength,
-				WorkflowData: &sdk.WorkflowData{
+				WorkflowData: sdk.WorkflowData{
 					Node: sdk.Node{
 						Name: "root",
 						Ref:  "root",
@@ -602,7 +603,7 @@ func TestWorkflow_GetWorkflow(t *testing.T) {
 			want: sdk.Workflow{
 				Name:          "myworkflow",
 				HistoryLength: sdk.DefaultHistoryLength,
-				WorkflowData: &sdk.WorkflowData{
+				WorkflowData: sdk.WorkflowData{
 					Node: sdk.Node{
 						Name: "A",
 						Ref:  "A",
@@ -733,7 +734,7 @@ func TestWorkflow_GetWorkflow(t *testing.T) {
 			want: sdk.Workflow{
 				Name:          "myworkflow",
 				HistoryLength: sdk.DefaultHistoryLength,
-				WorkflowData: &sdk.WorkflowData{
+				WorkflowData: sdk.WorkflowData{
 					Node: sdk.Node{
 						Name: "pipeline",
 						Ref:  "pipeline",
@@ -768,7 +769,7 @@ func TestWorkflow_GetWorkflow(t *testing.T) {
 			want: sdk.Workflow{
 				Name:          "myworkflow",
 				HistoryLength: sdk.DefaultHistoryLength,
-				WorkflowData: &sdk.WorkflowData{
+				WorkflowData: sdk.WorkflowData{
 					Node: sdk.Node{
 						Name: "A",
 						Ref:  "pipeline",
diff --git a/sdk/exportentities/v2/workflow_test.go b/sdk/exportentities/v2/workflow_test.go
index 883c20ce3..bd555062c 100644
--- a/sdk/exportentities/v2/workflow_test.go
+++ b/sdk/exportentities/v2/workflow_test.go
@@ -188,7 +188,7 @@ func TestWorkflow_GetWorkflow(t *testing.T) {
 			want: sdk.Workflow{
 				Name:          "myWorkflow",
 				HistoryLength: sdk.DefaultHistoryLength,
-				WorkflowData: &sdk.WorkflowData{
+				WorkflowData: sdk.WorkflowData{
 					Node: sdk.Node{
 						Name: "root",
 						Type: "pipeline",
@@ -253,7 +253,7 @@ func TestWorkflow_GetWorkflow(t *testing.T) {
 			want: sdk.Workflow{
 				Name:          "myWorkflow",
 				HistoryLength: sdk.DefaultHistoryLength,
-				WorkflowData: &sdk.WorkflowData{
+				WorkflowData: sdk.WorkflowData{
 					Node: sdk.Node{
 						Name: "root",
 						Type: "pipeline",
@@ -320,7 +320,7 @@ func TestWorkflow_GetWorkflow(t *testing.T) {
 			want: sdk.Workflow{
 				Name:          "myWorkflow",
 				HistoryLength: 25,
-				WorkflowData: &sdk.WorkflowData{
+				WorkflowData: sdk.WorkflowData{
 					Node: sdk.Node{
 						Name: "root",
 						Ref:  "root",
@@ -368,7 +368,7 @@ func TestWorkflow_GetWorkflow(t *testing.T) {
 			want: sdk.Workflow{
 				Name:          "myWorkflow",
 				HistoryLength: sdk.DefaultHistoryLength,
-				WorkflowData: &sdk.WorkflowData{
+				WorkflowData: sdk.WorkflowData{
 					Node: sdk.Node{
 						Name: "root",
 						Ref:  "root",
@@ -458,7 +458,7 @@ func TestWorkflow_GetWorkflow(t *testing.T) {
 			want: sdk.Workflow{
 				Name:          "myWorkflow",
 				HistoryLength: sdk.DefaultHistoryLength,
-				WorkflowData: &sdk.WorkflowData{
+				WorkflowData: sdk.WorkflowData{
 					Node: sdk.Node{
 						Name: "A",
 						Ref:  "A",
@@ -599,7 +599,7 @@ func TestWorkflow_GetWorkflow(t *testing.T) {
 			want: sdk.Workflow{
 				Name:          "myWorkflow",
 				HistoryLength: sdk.DefaultHistoryLength,
-				WorkflowData: &sdk.WorkflowData{
+				WorkflowData: sdk.WorkflowData{
 					Node: sdk.Node{
 						Name: "A",
 						Ref:  "pipeline",
diff --git a/sdk/workflow_node_test.go b/sdk/workflow_node_test.go
index 6440b698b..a238871f9 100644
--- a/sdk/workflow_node_test.go
+++ b/sdk/workflow_node_test.go
@@ -2,14 +2,15 @@ package sdk
 
 import (
 	"fmt"
-	"github.com/stretchr/testify/assert"
 	"sort"
 	"testing"
+
+	"github.com/stretchr/testify/assert"
 )
 
 func TestAncestorsSimple(t *testing.T) {
 	w := Workflow{
-		WorkflowData: &WorkflowData{
+		WorkflowData: WorkflowData{
 			Node: Node{
 				ID:   1,
 				Type: NodeTypePipeline,