Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

fix(api): workflow node commits history #6083

Merged
merged 4 commits into from
Feb 10, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion engine/api/repositoriesmanager/repositories_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ func (c *vcsClient) doJSONRequest(ctx context.Context, method, path string, in i
})

if code >= 400 {
log.Warn(ctx, "repositories manager %s HTTP %s %s error %s", c.name, method, path, code)
log.Warn(ctx, "repositories manager %s HTTP %s %s error %d", c.name, method, path, code)
switch code {
case http.StatusUnauthorized:
err = sdk.NewError(sdk.ErrNoReposManagerClientAuth, err)
Expand Down
4 changes: 2 additions & 2 deletions engine/api/workflow/dao_node_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -728,11 +728,11 @@ func PreviousNodeRunVCSInfos(ctx context.Context, db gorp.SqlExecutor, projectKe
queryPrevious := `
SELECT workflow_node_run.vcs_branch, workflow_node_run.vcs_tag, workflow_node_run.vcs_hash, workflow_node_run.vcs_repository, workflow_node_run.num
FROM workflow_node_run
JOIN w_node ON w_node.name = workflow_node_run.workflow_node_name AND w_node.name = $1 AND w_node.workflow_id = $2
JOIN w_node ON w_node.id = workflow_node_run.workflow_node_id AND w_node.name = $1 AND w_node.workflow_id = $2
JOIN w_node_context ON w_node_context.node_id = w_node.id
WHERE workflow_node_run.vcs_hash IS NOT NULL
AND workflow_node_run.num < $3
AND w_node_context.application_id = $4
AND w_node_context.application_id = $4
`

argPrevious := []interface{}{nodeName, wf.ID, current.BuildNumber, appID}
Expand Down
288 changes: 288 additions & 0 deletions engine/api/workflow/dao_node_run_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,288 @@
package workflow_test

import (
"bytes"
"context"
"encoding/json"
"io"
"net/http"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v2"

"github.com/ovh/cds/engine/api/application"
"github.com/ovh/cds/engine/api/authentication"
"github.com/ovh/cds/engine/api/bootstrap"
"github.com/ovh/cds/engine/api/event"
"github.com/ovh/cds/engine/api/pipeline"
"github.com/ovh/cds/engine/api/project"
"github.com/ovh/cds/engine/api/repositoriesmanager"
"github.com/ovh/cds/engine/api/services"
"github.com/ovh/cds/engine/api/test"
"github.com/ovh/cds/engine/api/test/assets"
"github.com/ovh/cds/engine/api/workflow"
"github.com/ovh/cds/sdk"
"github.com/ovh/cds/sdk/exportentities"
)

func TestCommitListWorkflowRun(t *testing.T) {
db, cache := test.SetupPG(t, bootstrap.InitiliazeDB)

_ = event.Initialize(context.TODO(), db.DbMap, cache, nil)

mockVCSSservice, _ := assets.InsertService(t, db, "TestManualRunBuildParameterMultiApplication", sdk.TypeVCS)
defer func() {
services.Delete(db, mockVCSSservice) // nolint
}()

services.HTTPClient = mock(
func(r *http.Request) (*http.Response, error) {
body := new(bytes.Buffer)
w := new(http.Response)
enc := json.NewEncoder(body)
w.Body = io.NopCloser(body)

switch r.URL.String() {
// NEED get REPO
case "/vcs/github/repos/sguiheux/demo":
repo := sdk.VCSRepo{
URL: "https",
Name: "demo",
ID: "123",
Fullname: "sguiheux/demo",
Slug: "sguiheux",
HTTPCloneURL: "https://github.com/sguiheux/demo.git",
SSHCloneURL: "git://github.com/sguiheux/demo.git",
}
if err := enc.Encode(repo); err != nil {
return writeError(w, err)
}
case "/vcs/github/repos/sguiheux/demo2":
repo := sdk.VCSRepo{
URL: "https",
Name: "demo",
ID: "123",
Fullname: "sguiheux/demo2",
Slug: "sguiheux",
HTTPCloneURL: "https://github.com/sguiheux/demo2.git",
SSHCloneURL: "git://github.com/sguiheux/demo2.git",
}
if err := enc.Encode(repo); err != nil {
return writeError(w, err)
}
// Default payload on workflow insert
case "/vcs/github/repos/sguiheux/demo/branches/?branch=&default=true":
b := sdk.VCSBranch{
Default: true,
DisplayID: "master",
LatestCommit: "mylastcommit",
}
if err := enc.Encode([]sdk.VCSBranch{b}); err != nil {
return writeError(w, err)
}
case "/vcs/github/repos/sguiheux/demo2/branches/?branch=&default=true":
b := sdk.VCSBranch{
Default: true,
DisplayID: "master",
LatestCommit: "mylastcommit2",
}
if err := enc.Encode([]sdk.VCSBranch{b}); err != nil {
return writeError(w, err)
}
// NEED GET BRANCH TO GET LATEST COMMIT
case "/vcs/github/repos/sguiheux/demo/branches/?branch=master&default=false":
b := sdk.VCSBranch{
Default: false,
DisplayID: "master",
LatestCommit: "mylastcommit",
}
if err := enc.Encode(b); err != nil {
return writeError(w, err)
}
case "/vcs/github/repos/sguiheux/demo2/branches/?branch=master&default=false":
b := sdk.VCSBranch{
Default: false,
DisplayID: "master",
LatestCommit: "mylastcommit2",
}
if err := enc.Encode(b); err != nil {
return writeError(w, err)
}
// NEED GET COMMIT TO GET AUTHOR AND MESSAGE
case "/vcs/github/repos/sguiheux/demo/commits/mylastcommit":
c := sdk.VCSCommit{
Author: sdk.VCSAuthor{
Name: "test",
Email: "[email protected]",
},
Hash: "mylastcommit",
Message: "super commit",
Timestamp: time.Now().Unix(),
}
if err := enc.Encode(c); err != nil {
return writeError(w, err)
}
case "/vcs/github/repos/sguiheux/demo2/commits/mylastcommit2":
c := sdk.VCSCommit{
Author: sdk.VCSAuthor{
Name: "test",
Email: "[email protected]",
},
Hash: "mylastcommit2",
Message: "super commit2",
Timestamp: time.Now().Unix(),
}
if err := enc.Encode(c); err != nil {
return writeError(w, err)
}
default:
t.Fatalf("UNKNOWN ROUTE: %s", r.URL.String())
}

return w, nil
},
)

u, _ := assets.InsertAdminUser(t, db)
consumer, _ := authentication.LoadConsumerByTypeAndUserID(context.TODO(), db, sdk.ConsumerLocal, u.ID, authentication.LoadConsumerOptions.WithAuthentifiedUser)

key := sdk.RandomString(10)
proj := assets.InsertTestProject(t, db, cache, key, key)
vcsServer := sdk.ProjectVCSServerLink{
ProjectID: proj.ID,
Name: "github",
}
vcsServer.Set("token", "foo")
vcsServer.Set("secret", "bar")
assert.NoError(t, repositoriesmanager.InsertProjectVCSServerLink(context.TODO(), db, &vcsServer))

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

s := sdk.NewStage("stage 1")
s.Enabled = true
s.PipelineID = pip.ID
test.NoError(t, pipeline.InsertStage(db, s))

// Add application
appS := `version: v1.0
name: blabla
vcs_server: github
repo: sguiheux/demo
vcs_ssh_key: proj-blabla
`
var eapp = new(exportentities.Application)
assert.NoError(t, yaml.Unmarshal([]byte(appS), eapp))
app, _, _, globalError := application.ParseAndImport(context.TODO(), db, cache, *proj, eapp, application.ImportOptions{Force: true}, nil, u)
assert.NoError(t, globalError)

// Add application2
appS2 := `version: v1.0
name: blabla2
vcs_server: github
repo: sguiheux/demo2
vcs_ssh_key: proj-blabla
`
var eapp2 = new(exportentities.Application)
assert.NoError(t, yaml.Unmarshal([]byte(appS2), eapp2))
app2, _, _, globalError := application.ParseAndImport(context.TODO(), db, cache, *proj, eapp2, application.ImportOptions{Force: true}, nil, u)
assert.NoError(t, globalError)

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

w := sdk.Workflow{
Name: "test_commits_list",
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,
ApplicationID: app.ID,
},
},
},
HistoryLength: 2,
PurgeTags: []string{"git.branch"},
}

w2 := sdk.Workflow{
Name: "test_commits_list_second",
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,
ApplicationID: app2.ID,
},
},
},
HistoryLength: 2,
PurgeTags: []string{"git.branch"},
}

test.NoError(t, workflow.Insert(context.TODO(), db, cache, *proj, &w))
test.NoError(t, workflow.Insert(context.TODO(), db, cache, *proj, &w2))

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

wr, errWR := workflow.CreateRun(db.DbMap, w1, sdk.WorkflowRunPostHandlerOption{AuthConsumerID: consumer.ID})
require.NoError(t, errWR)
wr.Workflow = *w1
_, errWr := workflow.StartWorkflowRun(context.TODO(), db, cache, *proj, wr, &sdk.WorkflowRunPostHandlerOption{
Manual: &sdk.WorkflowNodeRunManual{
Username: u.Username,
Payload: map[string]string{
"git.branch": "master",
"git.author": "test",
},
},
}, *consumer, nil)
test.NoError(t, errWr)

wr2, errWR := workflow.CreateRun(db.DbMap, w2t, sdk.WorkflowRunPostHandlerOption{AuthConsumerID: consumer.ID})
require.NoError(t, errWR)
wr2.Workflow = *w2t
_, errWr2 := workflow.StartWorkflowRun(context.TODO(), db, cache, *proj, wr2, &sdk.WorkflowRunPostHandlerOption{
Manual: &sdk.WorkflowNodeRunManual{
Username: u.Username,
Payload: map[string]string{
"git.branch": "master",
"git.author": "test",
},
},
}, *consumer, nil)
test.NoError(t, errWr2)

current2 := sdk.BuildNumberAndHash{BuildNumber: 10000}
r2, err := workflow.PreviousNodeRunVCSInfos(context.Background(), db, proj.Key, *w2t, "node1", current2, app2.ID, 0)
require.NoError(t, err)
require.NotEmpty(t, r2.Branch)
t.Logf("key:%s w2t:%d current:%v app2.ID:%d", proj.Key, w1.ID, current2.Hash, app2.ID)
require.Equal(t, "mylastcommit2", r2.Hash)

current := sdk.BuildNumberAndHash{BuildNumber: 10000}
r, err := workflow.PreviousNodeRunVCSInfos(context.Background(), db, proj.Key, *w1, "node1", current, app.ID, 0)
require.NoError(t, err)
require.NotEmpty(t, r.Branch)
t.Logf("key:%s w1:%d current:%v app.ID:%d", proj.Key, w1.ID, current.Hash, app.ID)
require.Equal(t, "mylastcommit", r.Hash)
}