<commit_before>package workflow_test

import (
	"context"
	"testing"
	"time"

	"github.com/go-gorp/gorp"
	"github.com/stretchr/testify/assert"

	"github.com/ovh/cds/engine/api/bootstrap"
	"github.com/ovh/cds/engine/api/group"
	"github.com/ovh/cds/engine/api/integration"
	"github.com/ovh/cds/engine/api/permission"
	"github.com/ovh/cds/engine/api/pipeline"
	"github.com/ovh/cds/engine/api/plugin"
	"github.com/ovh/cds/engine/api/project"
	"github.com/ovh/cds/engine/api/test"
	"github.com/ovh/cds/engine/api/test/assets"
	"github.com/ovh/cds/engine/api/workermodel"
	"github.com/ovh/cds/engine/api/workflow"
	"github.com/ovh/cds/sdk"
)

func TestManualRun1(t *testing.T) {
	db, cache, end := test.SetupPG(t, bootstrap.InitiliazeDB)
	defer end()
	u, _ := assets.InsertAdminUser(db)
	key := sdk.RandomString(10)
	proj := assets.InsertTestProject(t, db, cache, key, key, u)
	ctx := context.Background()

	//First pipeline
	pip := sdk.Pipeline{
		ProjectID:  proj.ID,
		ProjectKey: proj.Key,
		Name:       "pip1",
	}
	test.NoError(t, pipeline.InsertPipeline(db, cache, proj, &pip, u))

	s := sdk.NewStage("stage 1")
	s.Enabled = true
	s.PipelineID = pip.ID
	pipeline.InsertStage(db, s)
	j := &sdk.Job{
		Enabled: true,
		Action: sdk.Action{
			Enabled: true,
		},
	}
	pipeline.InsertJob(db, j, s.ID, &pip)
	s.Jobs = append(s.Jobs, *j)

	pip.Stages = append(pip.Stages, *s)

	//Second pipeline
	pip2 := sdk.Pipeline{
		ProjectID:  proj.ID,
		ProjectKey: proj.Key,
		Name:       "pip2",
	}
	test.NoError(t, pipeline.InsertPipeline(db, cache, proj, &pip2, u))
	s = sdk.NewStage("stage 1")
	s.Enabled = true
	s.PipelineID = pip2.ID
	pipeline.InsertStage(db, s)
	j = &sdk.Job{
		Enabled: true,
		Action: sdk.Action{
			Enabled: true,
		},
	}
	pipeline.InsertJob(db, j, s.ID, &pip2)
	s.Jobs = append(s.Jobs, *j)

	proj, _ = project.LoadByID(db, cache, proj.ID, u, project.LoadOptions.WithApplications, project.LoadOptions.WithPipelines, project.LoadOptions.WithEnvironments, project.LoadOptions.WithGroups)

	w := sdk.Workflow{
		Name:       "test_1",
		ProjectID:  proj.ID,
		ProjectKey: proj.Key,
		WorkflowData: &sdk.WorkflowData{
			Node: sdk.Node{
				Name: "node1",
				Ref:  "node1",
				Type: sdk.NodeTypePipeline,
				Context: &sdk.NodeContext{
					PipelineID: pip.ID,
				},
				Triggers: []sdk.NodeTrigger{
					{
						ChildNode: sdk.Node{
							Name: "node2",
							Ref:  "node2",
							Type: sdk.NodeTypePipeline,
							Context: &sdk.NodeContext{
								PipelineID: pip.ID,
							},
						},
					},
				},
			},
		},
	}

	test.NoError(t, workflow.Insert(db, cache, &w, proj, u))

	w1, err := workflow.Load(context.TODO(), db, cache, proj, "test_1", u, workflow.LoadOptions{
		DeepPipeline: true,
	})
	test.NoError(t, err)

	wr, errWR := workflow.CreateRun(db, w1, nil, u)
	assert.NoError(t, errWR)
	wr.Workflow = *w1
	_, errS := workflow.StartWorkflowRun(context.TODO(), db, cache, proj, wr, &sdk.WorkflowRunPostHandlerOption{
		Manual: &sdk.WorkflowNodeRunManual{
			User: *u,
			Payload: map[string]string{
				"git.branch": "master",
			},
		},
	}, u, nil)
	test.NoError(t, errS)

	wr2, errWR := workflow.CreateRun(db, w1, nil, u)
	assert.NoError(t, errWR)
	wr2.Workflow = *w1
	_, errS = workflow.StartWorkflowRun(context.TODO(), db, cache, proj, wr2, &sdk.WorkflowRunPostHandlerOption{
		Manual: &sdk.WorkflowNodeRunManual{
			User: *u,
		},
	}, u, nil)
	test.NoError(t, errS)

	//LoadLastRun
	lastrun, err := workflow.LoadLastRun(db, proj.Key, "test_1", workflow.LoadRunOptions{})
	test.NoError(t, err)
	assert.Equal(t, int64(2), lastrun.Number)

	//TestLoadNodeRun
	nodeRun, err := workflow.LoadNodeRun(db, proj.Key, "test_1", 2, lastrun.WorkflowNodeRuns[w1.WorkflowData.Node.ID][0].ID, workflow.LoadRunOptions{WithArtifacts: true})
	test.NoError(t, err)

	//don't want to compare queueSeconds attributes and spawn infos attributes
	nodeRun.Stages[0].RunJobs[0].QueuedSeconds = 0
	lastrun.WorkflowNodeRuns[w1.WorkflowData.Node.ID][0].Stages[0].RunJobs[0].QueuedSeconds = 0
	nodeRun.Stages[0].RunJobs[0].SpawnInfos = nil
	lastrun.WorkflowNodeRuns[w1.WorkflowData.Node.ID][0].Stages[0].RunJobs[0].SpawnInfos = nil

	test.Equal(t, lastrun.WorkflowNodeRuns[w1.WorkflowData.Node.ID][0], nodeRun)

	//TestLoadNodeJobRun
	filter := workflow.NewQueueFilter()
	filter.Rights = permission.PermissionReadExecute
	jobs, err := workflow.LoadNodeJobRunQueueByGroups(ctx, db, cache, filter, append(u.Groups, proj.ProjectGroups[0].Group))
	test.NoError(t, err)
	test.Equal(t, 2, len(jobs))

	//TestprocessWorkflowRun
	_, errS = workflow.StartWorkflowRun(context.TODO(), db, cache, proj, wr2, &sdk.WorkflowRunPostHandlerOption{
		Manual: &sdk.WorkflowNodeRunManual{
			User: *u,
		},
		FromNodeIDs: []int64{wr2.Workflow.WorkflowData.Node.ID},
	}, u, nil)
	test.NoError(t, errS)

	//TestLoadRuns
	runs, offset, limit, count, err := workflow.LoadRuns(db, proj.Key, w1.Name, 0, 50, nil)
	test.NoError(t, err)
	assert.Equal(t, 0, offset)
	assert.Equal(t, 50, limit)
	assert.Equal(t, 2, count)
	assert.Len(t, runs, 2)

	//TestLoadRunByID
	_, err = workflow.LoadRunByIDAndProjectKey(db, proj.Key, wr2.ID, workflow.LoadRunOptions{})
	test.NoError(t, err)
}

func TestManualRun2(t *testing.T) {
	db, cache, end := test.SetupPG(t, bootstrap.InitiliazeDB)
	defer end()
	u, _ := assets.InsertAdminUser(db)
	key := sdk.RandomString(10)
	proj := assets.InsertTestProject(t, db, cache, key, key, u)
	ctx := context.Background()

	//First pipeline
	pip := sdk.Pipeline{
		ProjectID:  proj.ID,
		ProjectKey: proj.Key,
		Name:       "pip1",
	}
	test.NoError(t, pipeline.InsertPipeline(db, cache, proj, &pip, u))

	s := sdk.NewStage("stage 1")
	s.Enabled = true
	s.PipelineID = pip.ID
	pipeline.InsertStage(db, s)
	j := &sdk.Job{
		Enabled: true,
		Action: sdk.Action{
			Enabled: true,
		},
	}
	pipeline.InsertJob(db, j, s.ID, &pip)
	s.Jobs = append(s.Jobs, *j)

	pip.Stages = append(pip.Stages, *s)

	//Second pipeline
	pip2 := sdk.Pipeline{
		ProjectID:  proj.ID,
		ProjectKey: proj.Key,
		Name:       "pip2",
	}
	test.NoError(t, pipeline.InsertPipeline(db, cache, proj, &pip2, u))
	s = sdk.NewStage("stage 1")
	s.Enabled = true
	s.PipelineID = pip2.ID
	pipeline.InsertStage(db, s)
	j = &sdk.Job{
		Enabled: true,
		Action: sdk.Action{
			Enabled: true,
		},
	}
	pipeline.InsertJob(db, j, s.ID, &pip2)
	s.Jobs = append(s.Jobs, *j)

	proj, _ = project.LoadByID(db, cache, proj.ID, u, project.LoadOptions.WithApplications, project.LoadOptions.WithPipelines, project.LoadOptions.WithEnvironments, project.LoadOptions.WithGroups)

	w := sdk.Workflow{
		Name:       "test_1",
		ProjectID:  proj.ID,
		ProjectKey: proj.Key,
		WorkflowData: &sdk.WorkflowData{
			Node: sdk.Node{
				Name: "node1",
				Ref:  "node1",
				Type: sdk.NodeTypePipeline,
				Context: &sdk.NodeContext{
					PipelineID: pip.ID,
				},
				Triggers: []sdk.NodeTrigger{
					{
						ChildNode: sdk.Node{
							Name: "node2",
							Ref:  "node2",
							Type: sdk.NodeTypePipeline,
							Context: &sdk.NodeContext{
								PipelineID: pip.ID,
							},
						},
					},
				},
			},
		},
	}

	test.NoError(t, workflow.Insert(db, cache, &w, proj, u))

	w1, err := workflow.Load(context.TODO(), db, cache, proj, "test_1", u, workflow.LoadOptions{
		DeepPipeline: true,
	})
	test.NoError(t, err)

	wr, errWR := workflow.CreateRun(db, w1, nil, u)
	assert.NoError(t, errWR)
	wr.Workflow = *w1
	_, errS := workflow.StartWorkflowRun(context.TODO(), db, cache, proj, wr, &sdk.WorkflowRunPostHandlerOption{
		Manual: &sdk.WorkflowNodeRunManual{User: *u},
	}, u, nil)
	test.NoError(t, errS)

	wr2, errWR := workflow.CreateRun(db, w1, nil, u)
	assert.NoError(t, errWR)
	wr2.Workflow = *w1
	_, errS = workflow.StartWorkflowRun(context.TODO(), db, cache, proj, wr2, &sdk.WorkflowRunPostHandlerOption{
		Manual: &sdk.WorkflowNodeRunManual{User: *u},
	}, u, nil)
	test.NoError(t, errS)

	_, errS = workflow.StartWorkflowRun(context.TODO(), db, cache, proj, wr, &sdk.WorkflowRunPostHandlerOption{
		Manual:      &sdk.WorkflowNodeRunManual{User: *u},
		FromNodeIDs: []int64{wr.Workflow.WorkflowData.Node.ID},
	}, u, nil)
	test.NoError(t, errS)

	filter := workflow.NewQueueFilter()
	filter.Rights = permission.PermissionReadExecute
	jobs, err := workflow.LoadNodeJobRunQueueByGroups(ctx, db, cache, filter, append(u.Groups, proj.ProjectGroups[0].Group))
	test.NoError(t, err)

	assert.Len(t, jobs, 3)
}

func TestManualRun3(t *testing.T) {
	db, cache, end := test.SetupPG(t, bootstrap.InitiliazeDB)
	defer end()
	u, _ := assets.InsertAdminUser(db)
	key := sdk.RandomString(10)
	proj := assets.InsertTestProject(t, db, cache, key, key, u)

	ctx := context.Background()

	test.NoError(t, project.AddKeyPair(db, proj, "key", u))

	g0 := sdk.Group{Name: "g0"}
	g1 := sdk.Group{Name: "g1"}
	for _, g := range []sdk.Group{g0, g1} {
		oldg, _ := group.LoadGroup(db, g.Name)
		if oldg != nil {
			test.NoError(t, group.DeleteGroupAndDependencies(db, oldg))
		}
	}

	test.NoError(t, group.InsertGroup(db, &g0))
	test.NoError(t, group.InsertGroup(db, &g1))

	test.NoError(t, group.InsertGroupInProject(db, proj.ID, g0.ID, permission.PermissionReadWriteExecute))
	test.NoError(t, group.InsertGroupInProject(db, proj.ID, g1.ID, permission.PermissionReadWriteExecute))

	g, err := group.LoadGroup(db, "shared.infra")
	if err != nil {
		t.Fatalf("Error getting group : %s", err)
	}

	modelIntegration := sdk.IntegrationModel{
		Name:       sdk.RandomString(10),
		Deployment: true,
	}
	test.NoError(t, integration.InsertModel(db, &modelIntegration))
	t.Logf("### Integration model %s created with id: %d\n", modelIntegration.Name, modelIntegration.ID)

	projInt := sdk.ProjectIntegration{
		Config: sdk.IntegrationConfig{
			"test": sdk.IntegrationConfigValue{
				Description: "here is a test",
				Type:        sdk.IntegrationConfigTypeString,
				Value:       "test",
			},
		},
		Name:               sdk.RandomString(10),
		ProjectID:          proj.ID,
		Model:              modelIntegration,
		IntegrationModelID: modelIntegration.ID,
	}
	test.NoError(t, integration.InsertIntegration(db, &projInt))
	t.Logf("### Integration %s created with id: %d\n", projInt.Name, projInt.ID)

	p := sdk.GRPCPlugin{
		Author:             "unitTest",
		Description:        "desc",
		Name:               sdk.RandomString(10),
		Type:               sdk.GRPCPluginDeploymentIntegration,
		IntegrationModelID: &modelIntegration.ID,
		Integration:        modelIntegration.Name,
		Binaries: []sdk.GRPCPluginBinary{
			{
				OS:   "linux",
				Arch: "adm64",
				Name: "blabla",
			},
		},
	}

	test.NoError(t, plugin.Insert(db, &p))
	assert.NotEqual(t, 0, p.ID)

	model, _ := workermodel.LoadByNameAndGroupID(db, "TestManualRun", g.ID)
	if model == nil {
		model = &sdk.Model{
			Name:    "TestManualRun",
			GroupID: g.ID,
			Type:    sdk.Docker,
			ModelDocker: sdk.ModelDocker{
				Image: "buildpack-deps:jessie",
			},
			RegisteredCapabilities: sdk.RequirementList{
				{
					Name:  "capa1",
					Type:  sdk.BinaryRequirement,
					Value: "1",
				},
			},
		}

		if err := workermodel.Insert(db, model); err != nil {
			t.Fatalf("Error inserting model : %s", err)
		}
	}

	//First pipeline
	pip := sdk.Pipeline{
		ProjectID:  proj.ID,
		ProjectKey: proj.Key,
		Name:       "pip1",
	}
	test.NoError(t, pipeline.InsertPipeline(db, cache, proj, &pip, u))

	// one pipeline with two stages
	s := sdk.NewStage("stage1-pipeline1")
	s2 := sdk.NewStage("stage2-pipeline1")
	s.Enabled = true
	s2.Enabled = true
	s.PipelineID = pip.ID
	s2.PipelineID = pip.ID
	test.NoError(t, pipeline.InsertStage(db, s))
	test.NoError(t, pipeline.InsertStage(db, s2))
	j := &sdk.Job{
		Enabled: true,
		Action: sdk.Action{
			Enabled:      true,
			Name:         "job10",
			Requirements: []sdk.Requirement{{Name: "TestManualRun", Value: "TestManualRun", Type: sdk.ModelRequirement}},
		},
	}
	j2 := &sdk.Job{
		Enabled: true,
		Action: sdk.Action{
			Enabled: true,
			Name:    "job11",
		},
	}
	test.NoError(t, pipeline.InsertJob(db, j, s.ID, &pip))
	test.NoError(t, pipeline.InsertJob(db, j2, s2.ID, &pip))
	s.Jobs = append(s.Jobs, *j)
	s2.Jobs = append(s.Jobs, *j2)

	pip.Stages = append(pip.Stages, *s)
	pip.Stages = append(pip.Stages, *s2)

	//Second pipeline
	pip2 := sdk.Pipeline{
		ProjectID:  proj.ID,
		ProjectKey: proj.Key,
		Name:       "pip2",
	}
	test.NoError(t, pipeline.InsertPipeline(db, cache, proj, &pip2, u))
	s = sdk.NewStage("stage1-pipeline2")
	s.Enabled = true
	s.PipelineID = pip2.ID
	pipeline.InsertStage(db, s)
	j = &sdk.Job{
		Enabled: true,
		Action: sdk.Action{
			Enabled:      true,
			Name:         "job20",
			Requirements: []sdk.Requirement{{Name: "fooNameService", Value: "valueService", Type: sdk.ServiceRequirement}},
		},
	}
	pipeline.InsertJob(db, j, s.ID, &pip2)
	s.Jobs = append(s.Jobs, *j)

	w := sdk.Workflow{
		Name:       "test_1",
		ProjectID:  proj.ID,
		ProjectKey: proj.Key,
		WorkflowData: &sdk.WorkflowData{
			Node: sdk.Node{
				Name: "node1",
				Ref:  "node1",
				Type: sdk.NodeTypePipeline,
				Context: &sdk.NodeContext{
					PipelineID:           pip.ID,
					ProjectIntegrationID: projInt.ID,
				},
				Groups: []sdk.GroupPermission{
					{
						Group:      g0,
						Permission: 777,
					},
				},
				Triggers: []sdk.NodeTrigger{
					{
						ChildNode: sdk.Node{
							Name: "node2",
							Ref:  "node2",
							Type: sdk.NodeTypePipeline,
							Context: &sdk.NodeContext{
								PipelineID: pip2.ID,
							},
							Groups: []sdk.GroupPermission{
								{
									Group:      g1,
									Permission: 777,
								},
							},
						},
					},
				},
			},
		},
	}

	proj, _ = project.LoadByID(db, cache, proj.ID, u, project.LoadOptions.WithApplications, project.LoadOptions.WithPipelines, project.LoadOptions.WithEnvironments, project.LoadOptions.WithGroups, project.LoadOptions.WithVariablesWithClearPassword, project.LoadOptions.WithKeys, project.LoadOptions.WithIntegrations)

	test.NoError(t, workflow.Insert(db, cache, &w, proj, u))

	w1, err := workflow.Load(context.TODO(), db, cache, proj, "test_1", u, workflow.LoadOptions{
		DeepPipeline: true,
	})
	test.NoError(t, err)

	wr, errWR := workflow.CreateRun(db, w1, nil, u)
	assert.NoError(t, errWR)
	wr.Workflow = *w1
	_, errS := workflow.StartWorkflowRun(context.TODO(), db, cache, proj, wr, &sdk.WorkflowRunPostHandlerOption{
		Manual: &sdk.WorkflowNodeRunManual{User: *u},
	}, u, nil)
	test.NoError(t, errS)

	filter := workflow.NewQueueFilter()
	// test nil since/until
	_, err = workflow.CountNodeJobRunQueueByGroups(ctx, db, cache, filter, append(u.Groups, proj.ProjectGroups[0].Group))
	test.NoError(t, err)

	// queue should be empty with since 0,0 until 0,0
	t0 := time.Unix(0, 0)
	t1 := time.Unix(0, 0)

	filter.Since = &t0
	filter.Until = &t1

	countAlreadyInQueueNone, err := workflow.CountNodeJobRunQueueByGroups(ctx, db, cache, filter, append(u.Groups, proj.ProjectGroups[0].Group))
	test.NoError(t, err)
	assert.Equal(t, 0, int(countAlreadyInQueueNone.Count))

queueRun:
	filter3 := workflow.NewQueueFilter()
	filter3.Rights = permission.PermissionReadExecute

	var jobs []sdk.WorkflowNodeJobRun
	// this group must return nothing (execGroups)
	jobs, err = workflow.LoadNodeJobRunQueueByGroups(ctx, db, cache, filter, append(u.Groups, proj.ProjectGroups[0].Group))
	test.NoError(t, err)
	assert.Equal(t, 0, len(jobs))
<commit_msg>test(api): fix manual run (#4661)<commit_after>package workflow_test

import (
	"context"
	"testing"
	"time"

	"github.com/go-gorp/gorp"
	"github.com/stretchr/testify/assert"

	"github.com/ovh/cds/engine/api/bootstrap"
	"github.com/ovh/cds/engine/api/group"
	"github.com/ovh/cds/engine/api/integration"
	"github.com/ovh/cds/engine/api/permission"
	"github.com/ovh/cds/engine/api/pipeline"
	"github.com/ovh/cds/engine/api/plugin"
	"github.com/ovh/cds/engine/api/project"
	"github.com/ovh/cds/engine/api/test"
	"github.com/ovh/cds/engine/api/test/assets"
	"github.com/ovh/cds/engine/api/workermodel"
	"github.com/ovh/cds/engine/api/workflow"
	"github.com/ovh/cds/sdk"
)

func TestManualRun1(t *testing.T) {
	db, cache, end := test.SetupPG(t, bootstrap.InitiliazeDB)
	defer end()
	u, _ := assets.InsertAdminUser(db)
	key := sdk.RandomString(10)
	proj := assets.InsertTestProject(t, db, cache, key, key, u)
	ctx := context.Background()

	//First pipeline
	pip := sdk.Pipeline{
		ProjectID:  proj.ID,
		ProjectKey: proj.Key,
		Name:       "pip1",
	}
	test.NoError(t, pipeline.InsertPipeline(db, cache, proj, &pip, u))

	s := sdk.NewStage("stage 1")
	s.Enabled = true
	s.PipelineID = pip.ID
	pipeline.InsertStage(db, s)
	j := &sdk.Job{
		Enabled: true,
		Action: sdk.Action{
			Enabled: true,
		},
	}
	pipeline.InsertJob(db, j, s.ID, &pip)
	s.Jobs = append(s.Jobs, *j)

	pip.Stages = append(pip.Stages, *s)

	//Second pipeline
	pip2 := sdk.Pipeline{
		ProjectID:  proj.ID,
		ProjectKey: proj.Key,
		Name:       "pip2",
	}
	test.NoError(t, pipeline.InsertPipeline(db, cache, proj, &pip2, u))
	s = sdk.NewStage("stage 1")
	s.Enabled = true
	s.PipelineID = pip2.ID
	pipeline.InsertStage(db, s)
	j = &sdk.Job{
		Enabled: true,
		Action: sdk.Action{
			Enabled: true,
		},
	}
	pipeline.InsertJob(db, j, s.ID, &pip2)
	s.Jobs = append(s.Jobs, *j)

	proj, _ = project.LoadByID(db, cache, proj.ID, u, project.LoadOptions.WithApplications, project.LoadOptions.WithPipelines, project.LoadOptions.WithEnvironments, project.LoadOptions.WithGroups)

	w := sdk.Workflow{
		Name:       "test_1",
		ProjectID:  proj.ID,
		ProjectKey: proj.Key,
		WorkflowData: &sdk.WorkflowData{
			Node: sdk.Node{
				Name: "node1",
				Ref:  "node1",
				Type: sdk.NodeTypePipeline,
				Context: &sdk.NodeContext{
					PipelineID: pip.ID,
				},
				Triggers: []sdk.NodeTrigger{
					{
						ChildNode: sdk.Node{
							Name: "node2",
							Ref:  "node2",
							Type: sdk.NodeTypePipeline,
							Context: &sdk.NodeContext{
								PipelineID: pip.ID,
							},
						},
					},
				},
			},
		},
	}

	test.NoError(t, workflow.Insert(db, cache, &w, proj, u))

	w1, err := workflow.Load(context.TODO(), db, cache, proj, "test_1", u, workflow.LoadOptions{
		DeepPipeline: true,
	})
	test.NoError(t, err)

	wr, errWR := workflow.CreateRun(db, w1, nil, u)
	assert.NoError(t, errWR)
	wr.Workflow = *w1
	_, errS := workflow.StartWorkflowRun(context.TODO(), db, cache, proj, wr, &sdk.WorkflowRunPostHandlerOption{
		Manual: &sdk.WorkflowNodeRunManual{
			User: *u,
			Payload: map[string]string{
				"git.branch": "master",
			},
		},
	}, u, nil)
	test.NoError(t, errS)

	wr2, errWR := workflow.CreateRun(db, w1, nil, u)
	assert.NoError(t, errWR)
	wr2.Workflow = *w1
	_, errS = workflow.StartWorkflowRun(context.TODO(), db, cache, proj, wr2, &sdk.WorkflowRunPostHandlerOption{
		Manual: &sdk.WorkflowNodeRunManual{
			User: *u,
		},
	}, u, nil)
	test.NoError(t, errS)

	//LoadLastRun
	lastrun, err := workflow.LoadLastRun(db, proj.Key, "test_1", workflow.LoadRunOptions{})
	test.NoError(t, err)
	assert.Equal(t, int64(2), lastrun.Number)

	//TestLoadNodeRun
	nodeRun, err := workflow.LoadNodeRun(db, proj.Key, "test_1", 2, lastrun.WorkflowNodeRuns[w1.WorkflowData.Node.ID][0].ID, workflow.LoadRunOptions{WithArtifacts: true})
	test.NoError(t, err)

	//don't want to compare queueSeconds attributes and spawn infos attributes
	nodeRun.Stages[0].RunJobs[0].QueuedSeconds = 0
	lastrun.WorkflowNodeRuns[w1.WorkflowData.Node.ID][0].Stages[0].RunJobs[0].QueuedSeconds = 0
	nodeRun.Stages[0].RunJobs[0].SpawnInfos = nil
	lastrun.WorkflowNodeRuns[w1.WorkflowData.Node.ID][0].Stages[0].RunJobs[0].SpawnInfos = nil

	test.Equal(t, lastrun.WorkflowNodeRuns[w1.WorkflowData.Node.ID][0], nodeRun)

	//TestLoadNodeJobRun
	filter := workflow.NewQueueFilter()
	filter.Rights = permission.PermissionReadExecute
	jobs, err := workflow.LoadNodeJobRunQueueByGroups(ctx, db, cache, filter, append(u.Groups, proj.ProjectGroups[0].Group))
	test.NoError(t, err)
	test.Equal(t, 2, len(jobs))

	//TestprocessWorkflowRun
	_, errS = workflow.StartWorkflowRun(context.TODO(), db, cache, proj, wr2, &sdk.WorkflowRunPostHandlerOption{
		Manual: &sdk.WorkflowNodeRunManual{
			User: *u,
		},
		FromNodeIDs: []int64{wr2.Workflow.WorkflowData.Node.ID},
	}, u, nil)
	test.NoError(t, errS)

	//TestLoadRuns
	runs, offset, limit, count, err := workflow.LoadRuns(db, proj.Key, w1.Name, 0, 50, nil)
	test.NoError(t, err)
	assert.Equal(t, 0, offset)
	assert.Equal(t, 50, limit)
	assert.Equal(t, 2, count)
	assert.Len(t, runs, 2)

	//TestLoadRunByID
	_, err = workflow.LoadRunByIDAndProjectKey(db, proj.Key, wr2.ID, workflow.LoadRunOptions{})
	test.NoError(t, err)
}

func TestManualRun2(t *testing.T) {
	db, cache, end := test.SetupPG(t, bootstrap.InitiliazeDB)
	defer end()
	u, _ := assets.InsertAdminUser(db)
	key := sdk.RandomString(10)
	proj := assets.InsertTestProject(t, db, cache, key, key, u)
	ctx := context.Background()

	//First pipeline
	pip := sdk.Pipeline{
		ProjectID:  proj.ID,
		ProjectKey: proj.Key,
		Name:       "pip1",
	}
	test.NoError(t, pipeline.InsertPipeline(db, cache, proj, &pip, u))

	s := sdk.NewStage("stage 1")
	s.Enabled = true
	s.PipelineID = pip.ID
	pipeline.InsertStage(db, s)
	j := &sdk.Job{
		Enabled: true,
		Action: sdk.Action{
			Enabled: true,
		},
	}
	pipeline.InsertJob(db, j, s.ID, &pip)
	s.Jobs = append(s.Jobs, *j)

	pip.Stages = append(pip.Stages, *s)

	//Second pipeline
	pip2 := sdk.Pipeline{
		ProjectID:  proj.ID,
		ProjectKey: proj.Key,
		Name:       "pip2",
	}
	test.NoError(t, pipeline.InsertPipeline(db, cache, proj, &pip2, u))
	s = sdk.NewStage("stage 1")
	s.Enabled = true
	s.PipelineID = pip2.ID
	pipeline.InsertStage(db, s)
	j = &sdk.Job{
		Enabled: true,
		Action: sdk.Action{
			Enabled: true,
		},
	}
	pipeline.InsertJob(db, j, s.ID, &pip2)
	s.Jobs = append(s.Jobs, *j)

	proj, _ = project.LoadByID(db, cache, proj.ID, u, project.LoadOptions.WithApplications, project.LoadOptions.WithPipelines, project.LoadOptions.WithEnvironments, project.LoadOptions.WithGroups)

	w := sdk.Workflow{
		Name:       "test_1",
		ProjectID:  proj.ID,
		ProjectKey: proj.Key,
		WorkflowData: &sdk.WorkflowData{
			Node: sdk.Node{
				Name: "node1",
				Ref:  "node1",
				Type: sdk.NodeTypePipeline,
				Context: &sdk.NodeContext{
					PipelineID: pip.ID,
				},
				Triggers: []sdk.NodeTrigger{
					{
						ChildNode: sdk.Node{
							Name: "node2",
							Ref:  "node2",
							Type: sdk.NodeTypePipeline,
							Context: &sdk.NodeContext{
								PipelineID: pip.ID,
							},
						},
					},
				},
			},
		},
	}

	test.NoError(t, workflow.Insert(db, cache, &w, proj, u))

	w1, err := workflow.Load(context.TODO(), db, cache, proj, "test_1", u, workflow.LoadOptions{
		DeepPipeline: true,
	})
	test.NoError(t, err)

	wr, errWR := workflow.CreateRun(db, w1, nil, u)
	assert.NoError(t, errWR)
	wr.Workflow = *w1
	_, errS := workflow.StartWorkflowRun(context.TODO(), db, cache, proj, wr, &sdk.WorkflowRunPostHandlerOption{
		Manual: &sdk.WorkflowNodeRunManual{User: *u},
	}, u, nil)
	test.NoError(t, errS)

	wr2, errWR := workflow.CreateRun(db, w1, nil, u)
	assert.NoError(t, errWR)
	wr2.Workflow = *w1
	_, errS = workflow.StartWorkflowRun(context.TODO(), db, cache, proj, wr2, &sdk.WorkflowRunPostHandlerOption{
		Manual: &sdk.WorkflowNodeRunManual{User: *u},
	}, u, nil)
	test.NoError(t, errS)

	_, errS = workflow.StartWorkflowRun(context.TODO(), db, cache, proj, wr, &sdk.WorkflowRunPostHandlerOption{
		Manual:      &sdk.WorkflowNodeRunManual{User: *u},
		FromNodeIDs: []int64{wr.Workflow.WorkflowData.Node.ID},
	}, u, nil)
	test.NoError(t, errS)

	filter := workflow.NewQueueFilter()
	filter.Rights = permission.PermissionReadExecute
	jobs, err := workflow.LoadNodeJobRunQueueByGroups(ctx, db, cache, filter, append(u.Groups, proj.ProjectGroups[0].Group))
	test.NoError(t, err)

	assert.Len(t, jobs, 3)
}

func TestManualRun3(t *testing.T) {
	db, cache, end := test.SetupPG(t, bootstrap.InitiliazeDB)
	defer end()
	u, _ := assets.InsertAdminUser(db)
	key := sdk.RandomString(10)
	proj := assets.InsertTestProject(t, db, cache, key, key, u)

	ctx := context.Background()

	test.NoError(t, project.AddKeyPair(db, proj, "key", u))

	g0 := sdk.Group{Name: "g0"}
	g1 := sdk.Group{Name: "g1"}
	for _, g := range []sdk.Group{g0, g1} {
		oldg, _ := group.LoadGroup(db, g.Name)
		if oldg != nil {
			test.NoError(t, group.DeleteGroupAndDependencies(db, oldg))
		}
	}

	test.NoError(t, group.InsertGroup(db, &g0))
	test.NoError(t, group.InsertGroup(db, &g1))

	test.NoError(t, group.InsertGroupInProject(db, proj.ID, g0.ID, permission.PermissionReadWriteExecute))
	test.NoError(t, group.InsertGroupInProject(db, proj.ID, g1.ID, permission.PermissionReadWriteExecute))

	g, err := group.LoadGroup(db, "shared.infra")
	if err != nil {
		t.Fatalf("Error getting group : %s", err)
	}

	modelIntegration := sdk.IntegrationModel{
		Name:       sdk.RandomString(10),
		Deployment: true,
	}
	test.NoError(t, integration.InsertModel(db, &modelIntegration))
	t.Logf("### Integration model %s created with id: %d\n", modelIntegration.Name, modelIntegration.ID)

	projInt := sdk.ProjectIntegration{
		Config: sdk.IntegrationConfig{
			"test": sdk.IntegrationConfigValue{
				Description: "here is a test",
				Type:        sdk.IntegrationConfigTypeString,
				Value:       "test",
			},
		},
		Name:               sdk.RandomString(10),
		ProjectID:          proj.ID,
		Model:              modelIntegration,
		IntegrationModelID: modelIntegration.ID,
	}
	test.NoError(t, integration.InsertIntegration(db, &projInt))
	t.Logf("### Integration %s created with id: %d\n", projInt.Name, projInt.ID)

	p := sdk.GRPCPlugin{
		Author:             "unitTest",
		Description:        "desc",
		Name:               sdk.RandomString(10),
		Type:               sdk.GRPCPluginDeploymentIntegration,
		IntegrationModelID: &modelIntegration.ID,
		Integration:        modelIntegration.Name,
		Binaries: []sdk.GRPCPluginBinary{
			{
				OS:   "linux",
				Arch: "adm64",
				Name: "blabla",
			},
		},
	}

	test.NoError(t, plugin.Insert(db, &p))
	assert.NotEqual(t, 0, p.ID)

	model, _ := workermodel.LoadByNameAndGroupID(db, "TestManualRun", g.ID)
	if model == nil {
		model = &sdk.Model{
			Name:    "TestManualRun",
			GroupID: g.ID,
			Type:    sdk.Docker,
			ModelDocker: sdk.ModelDocker{
				Image: "buildpack-deps:jessie",
			},
			RegisteredCapabilities: sdk.RequirementList{
				{
					Name:  "capa1",
					Type:  sdk.BinaryRequirement,
					Value: "1",
				},
			},
		}

		if err := workermodel.Insert(db, model); err != nil {
			t.Fatalf("Error inserting model : %s", err)
		}
	}

	//First pipeline
	pip := sdk.Pipeline{
		ProjectID:  proj.ID,
		ProjectKey: proj.Key,
		Name:       "pip1",
	}
	test.NoError(t, pipeline.InsertPipeline(db, cache, proj, &pip, u))

	// one pipeline with two stages
	s := sdk.NewStage("stage1-pipeline1")
	s2 := sdk.NewStage("stage2-pipeline1")
	s.Enabled = true
	s2.Enabled = true
	s.PipelineID = pip.ID
	s2.PipelineID = pip.ID
	test.NoError(t, pipeline.InsertStage(db, s))
	test.NoError(t, pipeline.InsertStage(db, s2))
	j := &sdk.Job{
		Enabled: true,
		Action: sdk.Action{
			Enabled:      true,
			Name:         "job10",
			Requirements: []sdk.Requirement{{Name: "TestManualRun", Value: "TestManualRun", Type: sdk.ModelRequirement}},
		},
	}
	j2 := &sdk.Job{
		Enabled: true,
		Action: sdk.Action{
			Enabled: true,
			Name:    "job11",
		},
	}
	test.NoError(t, pipeline.InsertJob(db, j, s.ID, &pip))
	test.NoError(t, pipeline.InsertJob(db, j2, s2.ID, &pip))
	s.Jobs = append(s.Jobs, *j)
	s2.Jobs = append(s.Jobs, *j2)

	pip.Stages = append(pip.Stages, *s)
	pip.Stages = append(pip.Stages, *s2)

	//Second pipeline
	pip2 := sdk.Pipeline{
		ProjectID:  proj.ID,
		ProjectKey: proj.Key,
		Name:       "pip2",
	}
	test.NoError(t, pipeline.InsertPipeline(db, cache, proj, &pip2, u))
	s = sdk.NewStage("stage1-pipeline2")
	s.Enabled = true
	s.PipelineID = pip2.ID
	pipeline.InsertStage(db, s)
	j = &sdk.Job{
		Enabled: true,
		Action: sdk.Action{
			Enabled:      true,
			Name:         "job20",
			Requirements: []sdk.Requirement{{Name: "fooNameService", Value: "valueService", Type: sdk.ServiceRequirement}},
		},
	}
	pipeline.InsertJob(db, j, s.ID, &pip2)
	s.Jobs = append(s.Jobs, *j)

	w := sdk.Workflow{
		Name:       "test_1",
		ProjectID:  proj.ID,
		ProjectKey: proj.Key,
		WorkflowData: &sdk.WorkflowData{
			Node: sdk.Node{
				Name: "node1",
				Ref:  "node1",
				Type: sdk.NodeTypePipeline,
				Context: &sdk.NodeContext{
					PipelineID:           pip.ID,
					ProjectIntegrationID: projInt.ID,
				},
				Groups: []sdk.GroupPermission{
					{
						Group:      g0,
						Permission: 777,
					},
				},
				Triggers: []sdk.NodeTrigger{
					{
						ChildNode: sdk.Node{
							Name: "node2",
							Ref:  "node2",
							Type: sdk.NodeTypePipeline,
							Context: &sdk.NodeContext{
								PipelineID: pip2.ID,
							},
							Groups: []sdk.GroupPermission{
								{
									Group:      g1,
									Permission: 777,
								},
							},
						},
					},
				},
			},
		},
	}

	proj, _ = project.LoadByID(db, cache, proj.ID, u, project.LoadOptions.WithApplications, project.LoadOptions.WithPipelines, project.LoadOptions.WithEnvironments, project.LoadOptions.WithGroups, project.LoadOptions.WithVariablesWithClearPassword, project.LoadOptions.WithKeys, project.LoadOptions.WithIntegrations)

	test.NoError(t, workflow.Insert(db, cache, &w, proj, u))

	w1, err := workflow.Load(context.TODO(), db, cache, proj, "test_1", u, workflow.LoadOptions{
		DeepPipeline: true,
	})
	test.NoError(t, err)

	wr, errWR := workflow.CreateRun(db, w1, nil, u)
	assert.NoError(t, errWR)
	wr.Workflow = *w1
	_, errS := workflow.StartWorkflowRun(context.TODO(), db, cache, proj, wr, &sdk.WorkflowRunPostHandlerOption{
		Manual: &sdk.WorkflowNodeRunManual{User: *u},
	}, u, nil)
	test.NoError(t, errS)

	filter := workflow.NewQueueFilter()
	// test nil since/until
	_, err = workflow.CountNodeJobRunQueueByGroups(ctx, db, cache, filter, append(u.Groups, proj.ProjectGroups[0].Group, g0, g1))
	test.NoError(t, err)

	// queue should be empty with since 0,0 until 0,0
	t0 := time.Unix(0, 0)
	t1 := time.Unix(0, 0)

	filter.Since = &t0
	filter.Until = &t1

	countAlreadyInQueueNone, err := workflow.CountNodeJobRunQueueByGroups(ctx, db, cache, filter, append(u.Groups, proj.ProjectGroups[0].Group, g0, g1))
	test.NoError(t, err)
	assert.Equal(t, 0, int(countAlreadyInQueueNone.Count))

queueRun:
	filter3 := workflow.NewQueueFilter()
	filter3.Rights = permission.PermissionReadExecute

	var jobs []sdk.WorkflowNodeJobRun
	// this group must return nothing (execGroups)
	jobs, err = workflow.LoadNodeJobRunQueueByGroups(ctx, db, cache, filter, append(u.Groups, proj.ProjectGroups[0].Group, g0, g1))
	test.NoError(t, err)
	assert.Equal(t, 0, len(jobs))

{'fraction_non_alphanumeric': 0.15675887777123798, 'fraction_numerical': 0.012294813942842195, 'mean_word_length': 3.714505934946817, 'pattern_counts': {'":': 4, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3299470', 'n_tokens_mistral': 13356, 'n_tokens_neox': 11899, 'n_words': 2250}