Skip to content

Commit c679d54

Browse files
authored
fix(api): workflow node commits history (#6083)
1 parent f260e1e commit c679d54

File tree

3 files changed

+291
-2
lines changed

3 files changed

+291
-2
lines changed

engine/api/repositoriesmanager/repositories_manager.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ func (c *vcsClient) doJSONRequest(ctx context.Context, method, path string, in i
224224
})
225225

226226
if code >= 400 {
227-
log.Warn(ctx, "repositories manager %s HTTP %s %s error %s", c.name, method, path, code)
227+
log.Warn(ctx, "repositories manager %s HTTP %s %s error %d", c.name, method, path, code)
228228
switch code {
229229
case http.StatusUnauthorized:
230230
err = sdk.NewError(sdk.ErrNoReposManagerClientAuth, err)

engine/api/workflow/dao_node_run.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -731,8 +731,9 @@ func PreviousNodeRunVCSInfos(ctx context.Context, db gorp.SqlExecutor, projectKe
731731
JOIN w_node ON w_node.name = workflow_node_run.workflow_node_name AND w_node.name = $1 AND w_node.workflow_id = $2
732732
JOIN w_node_context ON w_node_context.node_id = w_node.id
733733
WHERE workflow_node_run.vcs_hash IS NOT NULL
734+
AND workflow_node_run.workflow_id = $2
734735
AND workflow_node_run.num < $3
735-
AND w_node_context.application_id = $4
736+
AND w_node_context.application_id = $4
736737
`
737738

738739
argPrevious := []interface{}{nodeName, wf.ID, current.BuildNumber, appID}
+288
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
package workflow_test
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"encoding/json"
7+
"io"
8+
"net/http"
9+
"testing"
10+
"time"
11+
12+
"github.com/stretchr/testify/assert"
13+
"github.com/stretchr/testify/require"
14+
"gopkg.in/yaml.v2"
15+
16+
"github.com/ovh/cds/engine/api/application"
17+
"github.com/ovh/cds/engine/api/authentication"
18+
"github.com/ovh/cds/engine/api/bootstrap"
19+
"github.com/ovh/cds/engine/api/event"
20+
"github.com/ovh/cds/engine/api/pipeline"
21+
"github.com/ovh/cds/engine/api/project"
22+
"github.com/ovh/cds/engine/api/repositoriesmanager"
23+
"github.com/ovh/cds/engine/api/services"
24+
"github.com/ovh/cds/engine/api/test"
25+
"github.com/ovh/cds/engine/api/test/assets"
26+
"github.com/ovh/cds/engine/api/workflow"
27+
"github.com/ovh/cds/sdk"
28+
"github.com/ovh/cds/sdk/exportentities"
29+
)
30+
31+
func TestCommitListWorkflowRun(t *testing.T) {
32+
db, cache := test.SetupPG(t, bootstrap.InitiliazeDB)
33+
34+
_ = event.Initialize(context.TODO(), db.DbMap, cache, nil)
35+
36+
mockVCSSservice, _ := assets.InsertService(t, db, "TestManualRunBuildParameterMultiApplication", sdk.TypeVCS)
37+
defer func() {
38+
services.Delete(db, mockVCSSservice) // nolint
39+
}()
40+
41+
services.HTTPClient = mock(
42+
func(r *http.Request) (*http.Response, error) {
43+
body := new(bytes.Buffer)
44+
w := new(http.Response)
45+
enc := json.NewEncoder(body)
46+
w.Body = io.NopCloser(body)
47+
48+
switch r.URL.String() {
49+
// NEED get REPO
50+
case "/vcs/github/repos/sguiheux/demo":
51+
repo := sdk.VCSRepo{
52+
URL: "https",
53+
Name: "demo",
54+
ID: "123",
55+
Fullname: "sguiheux/demo",
56+
Slug: "sguiheux",
57+
HTTPCloneURL: "https://github.com/sguiheux/demo.git",
58+
SSHCloneURL: "git://github.com/sguiheux/demo.git",
59+
}
60+
if err := enc.Encode(repo); err != nil {
61+
return writeError(w, err)
62+
}
63+
case "/vcs/github/repos/sguiheux/demo2":
64+
repo := sdk.VCSRepo{
65+
URL: "https",
66+
Name: "demo",
67+
ID: "123",
68+
Fullname: "sguiheux/demo2",
69+
Slug: "sguiheux",
70+
HTTPCloneURL: "https://github.com/sguiheux/demo2.git",
71+
SSHCloneURL: "git://github.com/sguiheux/demo2.git",
72+
}
73+
if err := enc.Encode(repo); err != nil {
74+
return writeError(w, err)
75+
}
76+
// Default payload on workflow insert
77+
case "/vcs/github/repos/sguiheux/demo/branches/?branch=&default=true":
78+
b := sdk.VCSBranch{
79+
Default: true,
80+
DisplayID: "master",
81+
LatestCommit: "mylastcommit",
82+
}
83+
if err := enc.Encode([]sdk.VCSBranch{b}); err != nil {
84+
return writeError(w, err)
85+
}
86+
case "/vcs/github/repos/sguiheux/demo2/branches/?branch=&default=true":
87+
b := sdk.VCSBranch{
88+
Default: true,
89+
DisplayID: "master",
90+
LatestCommit: "mylastcommit2",
91+
}
92+
if err := enc.Encode([]sdk.VCSBranch{b}); err != nil {
93+
return writeError(w, err)
94+
}
95+
// NEED GET BRANCH TO GET LATEST COMMIT
96+
case "/vcs/github/repos/sguiheux/demo/branches/?branch=master&default=false":
97+
b := sdk.VCSBranch{
98+
Default: false,
99+
DisplayID: "master",
100+
LatestCommit: "mylastcommit",
101+
}
102+
if err := enc.Encode(b); err != nil {
103+
return writeError(w, err)
104+
}
105+
case "/vcs/github/repos/sguiheux/demo2/branches/?branch=master&default=false":
106+
b := sdk.VCSBranch{
107+
Default: false,
108+
DisplayID: "master",
109+
LatestCommit: "mylastcommit2",
110+
}
111+
if err := enc.Encode(b); err != nil {
112+
return writeError(w, err)
113+
}
114+
// NEED GET COMMIT TO GET AUTHOR AND MESSAGE
115+
case "/vcs/github/repos/sguiheux/demo/commits/mylastcommit":
116+
c := sdk.VCSCommit{
117+
Author: sdk.VCSAuthor{
118+
Name: "test",
119+
120+
},
121+
Hash: "mylastcommit",
122+
Message: "super commit",
123+
Timestamp: time.Now().Unix(),
124+
}
125+
if err := enc.Encode(c); err != nil {
126+
return writeError(w, err)
127+
}
128+
case "/vcs/github/repos/sguiheux/demo2/commits/mylastcommit2":
129+
c := sdk.VCSCommit{
130+
Author: sdk.VCSAuthor{
131+
Name: "test",
132+
133+
},
134+
Hash: "mylastcommit2",
135+
Message: "super commit2",
136+
Timestamp: time.Now().Unix(),
137+
}
138+
if err := enc.Encode(c); err != nil {
139+
return writeError(w, err)
140+
}
141+
default:
142+
t.Fatalf("UNKNOWN ROUTE: %s", r.URL.String())
143+
}
144+
145+
return w, nil
146+
},
147+
)
148+
149+
u, _ := assets.InsertAdminUser(t, db)
150+
consumer, _ := authentication.LoadConsumerByTypeAndUserID(context.TODO(), db, sdk.ConsumerLocal, u.ID, authentication.LoadConsumerOptions.WithAuthentifiedUser)
151+
152+
key := sdk.RandomString(10)
153+
proj := assets.InsertTestProject(t, db, cache, key, key)
154+
vcsServer := sdk.ProjectVCSServerLink{
155+
ProjectID: proj.ID,
156+
Name: "github",
157+
}
158+
vcsServer.Set("token", "foo")
159+
vcsServer.Set("secret", "bar")
160+
assert.NoError(t, repositoriesmanager.InsertProjectVCSServerLink(context.TODO(), db, &vcsServer))
161+
162+
//First pipeline
163+
pip := sdk.Pipeline{
164+
ProjectID: proj.ID,
165+
ProjectKey: proj.Key,
166+
Name: "pip1",
167+
}
168+
test.NoError(t, pipeline.InsertPipeline(db, &pip))
169+
170+
s := sdk.NewStage("stage 1")
171+
s.Enabled = true
172+
s.PipelineID = pip.ID
173+
test.NoError(t, pipeline.InsertStage(db, s))
174+
175+
// Add application
176+
appS := `version: v1.0
177+
name: blabla
178+
vcs_server: github
179+
repo: sguiheux/demo
180+
vcs_ssh_key: proj-blabla
181+
`
182+
var eapp = new(exportentities.Application)
183+
assert.NoError(t, yaml.Unmarshal([]byte(appS), eapp))
184+
app, _, _, globalError := application.ParseAndImport(context.TODO(), db, cache, *proj, eapp, application.ImportOptions{Force: true}, nil, u)
185+
assert.NoError(t, globalError)
186+
187+
// Add application2
188+
appS2 := `version: v1.0
189+
name: blabla2
190+
vcs_server: github
191+
repo: sguiheux/demo2
192+
vcs_ssh_key: proj-blabla
193+
`
194+
var eapp2 = new(exportentities.Application)
195+
assert.NoError(t, yaml.Unmarshal([]byte(appS2), eapp2))
196+
app2, _, _, globalError := application.ParseAndImport(context.TODO(), db, cache, *proj, eapp2, application.ImportOptions{Force: true}, nil, u)
197+
assert.NoError(t, globalError)
198+
199+
proj, _ = project.LoadByID(db, proj.ID, project.LoadOptions.WithApplications, project.LoadOptions.WithPipelines, project.LoadOptions.WithEnvironments, project.LoadOptions.WithGroups)
200+
201+
w := sdk.Workflow{
202+
Name: "test_commits_list",
203+
ProjectID: proj.ID,
204+
ProjectKey: proj.Key,
205+
WorkflowData: sdk.WorkflowData{
206+
Node: sdk.Node{
207+
Name: "node1",
208+
Ref: "node1",
209+
Type: sdk.NodeTypePipeline,
210+
Context: &sdk.NodeContext{
211+
PipelineID: pip.ID,
212+
ApplicationID: app.ID,
213+
},
214+
},
215+
},
216+
HistoryLength: 2,
217+
PurgeTags: []string{"git.branch"},
218+
}
219+
220+
w2 := sdk.Workflow{
221+
Name: "test_commits_list_second",
222+
ProjectID: proj.ID,
223+
ProjectKey: proj.Key,
224+
WorkflowData: sdk.WorkflowData{
225+
Node: sdk.Node{
226+
Name: "node1",
227+
Ref: "node1",
228+
Type: sdk.NodeTypePipeline,
229+
Context: &sdk.NodeContext{
230+
PipelineID: pip.ID,
231+
ApplicationID: app2.ID,
232+
},
233+
},
234+
},
235+
HistoryLength: 2,
236+
PurgeTags: []string{"git.branch"},
237+
}
238+
239+
test.NoError(t, workflow.Insert(context.TODO(), db, cache, *proj, &w))
240+
test.NoError(t, workflow.Insert(context.TODO(), db, cache, *proj, &w2))
241+
242+
w1, err := workflow.Load(context.TODO(), db, cache, *proj, "test_commits_list", workflow.LoadOptions{DeepPipeline: true})
243+
test.NoError(t, err)
244+
w2t, err := workflow.Load(context.TODO(), db, cache, *proj, "test_commits_list_second", workflow.LoadOptions{DeepPipeline: true})
245+
test.NoError(t, err)
246+
247+
wr, errWR := workflow.CreateRun(db.DbMap, w1, sdk.WorkflowRunPostHandlerOption{AuthConsumerID: consumer.ID})
248+
require.NoError(t, errWR)
249+
wr.Workflow = *w1
250+
_, errWr := workflow.StartWorkflowRun(context.TODO(), db, cache, *proj, wr, &sdk.WorkflowRunPostHandlerOption{
251+
Manual: &sdk.WorkflowNodeRunManual{
252+
Username: u.Username,
253+
Payload: map[string]string{
254+
"git.branch": "master",
255+
"git.author": "test",
256+
},
257+
},
258+
}, *consumer, nil)
259+
test.NoError(t, errWr)
260+
261+
wr2, errWR := workflow.CreateRun(db.DbMap, w2t, sdk.WorkflowRunPostHandlerOption{AuthConsumerID: consumer.ID})
262+
require.NoError(t, errWR)
263+
wr2.Workflow = *w2t
264+
_, errWr2 := workflow.StartWorkflowRun(context.TODO(), db, cache, *proj, wr2, &sdk.WorkflowRunPostHandlerOption{
265+
Manual: &sdk.WorkflowNodeRunManual{
266+
Username: u.Username,
267+
Payload: map[string]string{
268+
"git.branch": "master",
269+
"git.author": "test",
270+
},
271+
},
272+
}, *consumer, nil)
273+
test.NoError(t, errWr2)
274+
275+
current2 := sdk.BuildNumberAndHash{BuildNumber: 10000}
276+
r2, err := workflow.PreviousNodeRunVCSInfos(context.Background(), db, proj.Key, *w2t, "node1", current2, app2.ID, 0)
277+
require.NoError(t, err)
278+
require.NotEmpty(t, r2.Branch)
279+
t.Logf("key:%s w2t:%d current:%v app2.ID:%d", proj.Key, w1.ID, current2.Hash, app2.ID)
280+
require.Equal(t, "mylastcommit2", r2.Hash)
281+
282+
current := sdk.BuildNumberAndHash{BuildNumber: 10000}
283+
r, err := workflow.PreviousNodeRunVCSInfos(context.Background(), db, proj.Key, *w1, "node1", current, app.ID, 0)
284+
require.NoError(t, err)
285+
require.NotEmpty(t, r.Branch)
286+
t.Logf("key:%s w1:%d current:%v app.ID:%d", proj.Key, w1.ID, current.Hash, app.ID)
287+
require.Equal(t, "mylastcommit", r.Hash)
288+
}

0 commit comments

Comments
 (0)