Skip to content

Commit 7c5b8ef

Browse files
committed
feat(api,vcs): use new vcs
Signed-off-by: Yvonnick Esnault <yvonnick.esnault@corp.ovh.com>
1 parent 61326b0 commit 7c5b8ef

28 files changed

+500
-241
lines changed

engine/api/project/dao.go

+26-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/ovh/cds/engine/api/group"
1717
"github.com/ovh/cds/engine/api/keys"
1818
"github.com/ovh/cds/engine/api/repositoriesmanager"
19+
"github.com/ovh/cds/engine/api/vcs"
1920
"github.com/ovh/cds/engine/cache"
2021
"github.com/ovh/cds/engine/gorpmapper"
2122
"github.com/ovh/cds/sdk"
@@ -314,11 +315,34 @@ func unwrap(ctx context.Context, db gorp.SqlExecutor, p *dbProject, opts []LoadO
314315
end()
315316
}
316317

317-
vcsServers, err := repositoriesmanager.LoadAllProjectVCSServerLinksByProjectID(ctx, db, p.ID)
318+
vcsProjects, err := vcs.LoadAllVCSByProject(ctx, db, p.Key)
318319
if err != nil {
319320
return nil, err
320321
}
321-
proj.VCSServers = vcsServers
322+
323+
proj.VCSServers = vcsProjects
324+
325+
// DEPRECATED VCS
326+
vcsServersDeprecated, err := repositoriesmanager.LoadAllProjectVCSServerLinksByProjectID(ctx, db, p.ID)
327+
if err != nil {
328+
return nil, err
329+
}
330+
331+
for _, vcsDeprecated := range vcsServersDeprecated {
332+
var found bool
333+
for _, v := range vcsProjects {
334+
if vcsDeprecated.Name == v.Name {
335+
found = true
336+
break
337+
}
338+
}
339+
if !found {
340+
toadd := sdk.VCSProject{
341+
Name: vcsDeprecated.Name,
342+
}
343+
proj.VCSServers = append(proj.VCSServers, toadd)
344+
}
345+
}
322346

323347
return &proj, nil
324348
}

engine/api/repositoriesmanager/repositories_manager.go

+34-11
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package repositoriesmanager
33
import (
44
"context"
55
"encoding/base64"
6+
"encoding/json"
67
"fmt"
78
"io"
89
"net/http"
@@ -23,16 +24,22 @@ import (
2324
"github.com/ovh/cds/sdk/telemetry"
2425
)
2526

26-
func LoadByName(ctx context.Context, db gorp.SqlExecutor, vcsName string) (sdk.VCSConfiguration, error) {
27+
func (c *vcsClient) IsGerrit(ctx context.Context, db gorp.SqlExecutor) (bool, error) {
28+
if c.vcsProject != nil {
29+
return c.vcsProject.Type == "gerrit", nil
30+
}
31+
32+
// DEPRECATED VCS
2733
var vcsServer sdk.VCSConfiguration
2834
srvs, err := services.LoadAllByType(ctx, db, sdk.TypeVCS)
2935
if err != nil {
30-
return vcsServer, sdk.WrapError(err, "Unable to load services")
36+
return false, sdk.WrapError(err, "Unable to load services")
3137
}
32-
if _, _, err := services.NewClient(db, srvs).DoJSONRequest(ctx, "GET", fmt.Sprintf("/vcs/%s", vcsName), nil, &vcsServer); err != nil {
33-
return vcsServer, sdk.WithStack(err)
38+
if _, _, err := services.NewClient(db, srvs).DoJSONRequest(ctx, "GET", fmt.Sprintf("/vcs/%s", c.name), nil, &vcsServer); err != nil {
39+
return false, sdk.WrapError(err, "error on requesting vcs service")
3440
}
35-
return vcsServer, nil
41+
42+
return vcsServer.Type == "gerrit", nil
3643
}
3744

3845
//LoadAll Load all RepositoriesManager from the database
@@ -241,10 +248,20 @@ func deprecatedAuthorizedClient(ctx context.Context, db gorpmapper.SqlExecutorWi
241248

242249
func (c *vcsClient) doJSONRequest(ctx context.Context, method, path string, in interface{}, out interface{}) (int, error) {
243250
headers, code, err := services.NewClient(c.db, c.srvs).DoJSONRequest(ctx, method, path, in, out, func(req *http.Request) {
244-
req.Header.Set(sdk.HeaderXAccessToken, base64.StdEncoding.EncodeToString([]byte(c.token)))
245-
req.Header.Set(sdk.HeaderXAccessTokenSecret, base64.StdEncoding.EncodeToString([]byte(c.secret)))
246-
if c.created != 0 {
247-
req.Header.Set(sdk.HeaderXAccessTokenCreated, base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%d", c.created))))
251+
if c.vcsProject != nil {
252+
log.Debug(ctx, "requesting vcs via vcs project")
253+
btes, err := json.Marshal(c.vcsProject)
254+
if err != nil {
255+
log.Error(ctx, "invalid vcs project conf. err: %v", err)
256+
}
257+
req.Header.Set(sdk.HeaderXVCSProjectConf, base64.StdEncoding.EncodeToString(btes))
258+
} else {
259+
log.Debug(ctx, "requesting vcs via vcs oauth2")
260+
req.Header.Set(sdk.HeaderXAccessToken, base64.StdEncoding.EncodeToString([]byte(c.token)))
261+
req.Header.Set(sdk.HeaderXAccessTokenSecret, base64.StdEncoding.EncodeToString([]byte(c.secret)))
262+
if c.created != 0 {
263+
req.Header.Set(sdk.HeaderXAccessTokenCreated, base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%d", c.created))))
264+
}
248265
}
249266
})
250267

@@ -274,8 +291,14 @@ func (c *vcsClient) doJSONRequest(ctx context.Context, method, path string, in i
274291

275292
func (c *vcsClient) postBinary(ctx context.Context, path string, fileLength int, r io.Reader, out interface{}) (int, error) {
276293
return services.PostBinary(ctx, c.srvs, path, r, out, func(req *http.Request) {
277-
req.Header.Set(sdk.HeaderXAccessToken, base64.StdEncoding.EncodeToString([]byte(c.token)))
278-
req.Header.Set(sdk.HeaderXAccessTokenSecret, base64.StdEncoding.EncodeToString([]byte(c.secret)))
294+
if c.vcsProject != nil {
295+
if token, ok := c.vcsProject.Auth["token"]; ok {
296+
req.Header.Set(sdk.HeaderXVCSProjectConf, base64.StdEncoding.EncodeToString([]byte(token)))
297+
}
298+
} else {
299+
req.Header.Set(sdk.HeaderXAccessToken, base64.StdEncoding.EncodeToString([]byte(c.token)))
300+
req.Header.Set(sdk.HeaderXAccessTokenSecret, base64.StdEncoding.EncodeToString([]byte(c.secret)))
301+
}
279302
req.Header.Set("Content-Type", "application/octet-stream")
280303
req.Header.Set("Content-Length", strconv.Itoa(fileLength))
281304
})

engine/api/v2_project.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ func (api *API) getVCSProjectHandler() ([]service.RbacChecker, service.Handler)
154154
}
155155
defer tx.Rollback() // nolint
156156

157-
vcsProject, err := vcs.LoadVCSByProject(context.Background(), tx, pKey, vcsProjectName, gorpmapping.GetOptions.WithDecryption)
157+
vcsProject, err := vcs.LoadVCSByProject(context.Background(), tx, pKey, vcsProjectName)
158158
if err != nil {
159159
return err
160160
}

engine/api/workflow/workflow_run_event.go

+19-18
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,19 @@ loopNotif:
9393
repoFullName := wr.Workflow.Applications[node.Context.ApplicationID].RepositoryFullname
9494

9595
//Get the RepositoriesManager Client
96+
log.Info(ctx, "######## SendVCSEvent: AAAA")
9697
if e.vcsClient == nil {
98+
log.Info(ctx, "######## SendVCSEvent: BBBBB")
9799
var err error
98100
e.vcsClient, err = repositoriesmanager.AuthorizedClient(ctx, tx, store, proj.Key, vcsServerName)
99101
if err != nil {
100-
return err
102+
log.Info(ctx, "######## SendVCSEvent: CCCC")
103+
return sdk.WrapError(err, "can't get AuthorizedClient for %v/%v", proj.Key, vcsServerName)
101104
}
105+
log.Info(ctx, "######## SendVCSEvent: DDDDD")
102106
}
103107

108+
log.Info(ctx, "######## SendVCSEvent: EEEEE")
104109
ref := nodeRun.VCSHash
105110
if nodeRun.VCSTag != "" {
106111
ref = nodeRun.VCSTag
@@ -111,7 +116,7 @@ loopNotif:
111116
var err error
112117
statuses, err = e.vcsClient.ListStatuses(ctx, repoFullName, ref)
113118
if err != nil {
114-
return err
119+
return sdk.WrapError(err, "can't ListStatuses for %v with vcs %v/%v", repoFullName, proj.Key, vcsServerName)
115120
}
116121
e.commitsStatuses[ref] = statuses
117122
}
@@ -129,7 +134,7 @@ loopNotif:
129134

130135
if statusFound == nil || statusFound.State == "" {
131136
if err := e.sendVCSEventStatus(ctx, tx, store, proj.Key, wr, &nodeRun, notif, vcsServerName); err != nil {
132-
return err
137+
return sdk.WrapError(err, "can't sendVCSEventStatus vcs %v/%v", proj.Key, vcsServerName)
133138
}
134139
} else {
135140
skipStatus := false
@@ -154,7 +159,7 @@ loopNotif:
154159

155160
if !skipStatus {
156161
if err := e.sendVCSEventStatus(ctx, tx, store, proj.Key, wr, &nodeRun, notif, vcsServerName); err != nil {
157-
return err
162+
return sdk.WrapError(err, "can't sendVCSEventStatus vcs %v/%v", proj.Key, vcsServerName)
158163
}
159164
}
160165
}
@@ -163,7 +168,7 @@ loopNotif:
163168
return nil
164169
}
165170
if err := e.sendVCSPullRequestComment(ctx, tx, wr, &nodeRun, notif, vcsServerName); err != nil {
166-
return err
171+
return sdk.WrapError(err, "can't sendVCSPullRequestComment vcs %v/%v", proj.Key, vcsServerName)
167172
}
168173

169174
if err := tx.Commit(); err != nil {
@@ -237,12 +242,11 @@ func (e *VCSEventMessenger) sendVCSEventStatus(ctx context.Context, db gorp.SqlE
237242
}
238243

239244
// Check if it's a gerrit or not
240-
vcsConf, err := repositoriesmanager.LoadByName(ctx, db, vcsServerName)
245+
isGerrit, err := e.vcsClient.IsGerrit(ctx, db)
241246
if err != nil {
242247
return err
243248
}
244-
245-
if vcsConf.Type == "gerrit" {
249+
if isGerrit {
246250
// Get gerrit variable
247251
var project, changeID, branch, revision, url string
248252
projectParam := sdk.ParameterFind(nodeRun.BuildParameters, "git.repository")
@@ -275,7 +279,6 @@ func (e *VCSEventMessenger) sendVCSEventStatus(ctx context.Context, db gorp.SqlE
275279
URL: url,
276280
}
277281
}
278-
279282
}
280283

281284
payload, _ := json.Marshal(eventWNR)
@@ -329,12 +332,6 @@ func (e *VCSEventMessenger) sendVCSPullRequestComment(ctx context.Context, db go
329332
return err
330333
}
331334

332-
// Check if it's a gerrit or not
333-
vcsConf, err := repositoriesmanager.LoadByName(ctx, db, vcsServerName)
334-
if err != nil {
335-
return err
336-
}
337-
338335
var changeID string
339336
changeIDParam := sdk.ParameterFind(nodeRun.BuildParameters, "gerrit.change.id")
340337
if changeIDParam != nil {
@@ -350,13 +347,17 @@ func (e *VCSEventMessenger) sendVCSPullRequestComment(ctx context.Context, db go
350347
reqComment := sdk.VCSPullRequestCommentRequest{Message: report}
351348
reqComment.Revision = revision
352349

353-
// If we are on Gerrit
354-
if changeID != "" && vcsConf.Type == "gerrit" {
350+
isGerrit, err := e.vcsClient.IsGerrit(ctx, db)
351+
if err != nil {
352+
return err
353+
}
354+
355+
if changeID != "" && isGerrit {
355356
reqComment.ChangeID = changeID
356357
if err := e.vcsClient.PullRequestComment(ctx, app.RepositoryFullname, reqComment); err != nil {
357358
return err
358359
}
359-
} else if vcsConf.Type != "gerrit" {
360+
} else if !isGerrit {
360361
//Check if this branch and this commit is a pullrequest
361362
prs, err := e.vcsClient.PullRequests(ctx, app.RepositoryFullname)
362363
if err != nil {

engine/api/workflow_event.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func (api *API) WorkflowSendEvent(ctx context.Context, proj sdk.Project, report
6161
event.PublishWorkflowNodeRun(ctx, *nr, wr.Workflow, eventsNotif)
6262
e := &workflow.VCSEventMessenger{}
6363
if err := e.SendVCSEvent(ctx, db, api.Cache, proj, *wr, wnr); err != nil {
64-
log.Warn(ctx, "WorkflowSendEvent> Cannot send vcs notification")
64+
log.Warn(ctx, "WorkflowSendEvent> Cannot send vcs notification err:%v", err)
6565
}
6666
}
6767

engine/api/workflow_queue_test.go

-3
Original file line numberDiff line numberDiff line change
@@ -1171,9 +1171,6 @@ func TestInsertNewCodeCoverageReport(t *testing.T) {
11711171
}))
11721172
u.Groups = append(u.Groups, proj.ProjectGroups[0].Group)
11731173

1174-
// Add repo manager
1175-
proj.VCSServers = make([]sdk.ProjectVCSServerLink, 0, 1)
1176-
11771174
vcsServer := sdk.ProjectVCSServerLink{
11781175
ProjectID: proj.ID,
11791176
Name: "repoManServ",

engine/vcs/bitbucketcloud/bitbucketcloud.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,17 @@ type bitbucketcloudConsumer struct {
3636
}
3737

3838
//New creates a new GithubConsumer
39-
func New(ClientID, ClientSecret, apiURL, uiURL, proxyURL string, store cache.Store, disableStatus, disableStatusDetail bool) sdk.VCSServer {
39+
func New(apiURL, uiURL, proxyURL string, store cache.Store) sdk.VCSServer {
40+
return &bitbucketcloudConsumer{
41+
Cache: store,
42+
apiURL: apiURL,
43+
uiURL: uiURL,
44+
proxyURL: proxyURL,
45+
}
46+
}
47+
48+
// DEPRECATED VCS
49+
func NewDeprecated(ClientID, ClientSecret, apiURL, uiURL, proxyURL string, store cache.Store, disableStatus, disableStatusDetail bool) sdk.VCSServer {
4050
return &bitbucketcloudConsumer{
4151
ClientID: ClientID,
4252
ClientSecret: ClientSecret,

engine/vcs/bitbucketcloud/bitbucketcloud_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func getNewConsumer(t *testing.T) sdk.VCSServer {
4444
t.Fatalf("Unable to init cache (%s): %v", redisHost, err)
4545
}
4646

47-
bbConsumer := New(clientID, clientSecret, "http://localhost", "", "", cache, true, true)
47+
bbConsumer := NewDeprecated(clientID, clientSecret, "http://localhost", "", "", cache, true, true)
4848
return bbConsumer
4949
}
5050

@@ -66,7 +66,7 @@ func getNewAuthorizedClient(t *testing.T) sdk.VCSAuthorizedClient {
6666
t.Fatalf("Unable to init cache (%s): %v", redisHost, err)
6767
}
6868

69-
bbConsumer := New(clientID, clientSecret, "http://localhost", "", "", cache, true, true)
69+
bbConsumer := NewDeprecated(clientID, clientSecret, "http://localhost", "", "", cache, true, true)
7070
vcsAuth := sdk.VCSAuth{
7171
AccessToken: currentAccessToken,
7272
AccessTokenSecret: currentRefreshToken,

engine/vcs/bitbucketcloud/oauth_consumer.go

+25-49
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"fmt"
66
"net/url"
7-
"time"
87

98
"github.com/rockbears/log"
109

@@ -92,62 +91,39 @@ func (consumer *bitbucketcloudConsumer) RefreshToken(ctx context.Context, refres
9291
return resp.AccessToken, resp.RefreshToken, nil
9392
}
9493

95-
//keep client in memory
96-
var instancesAuthorizedClient = map[string]*bitbucketcloudClient{}
97-
9894
//GetAuthorized returns an authorized client
9995
func (consumer *bitbucketcloudConsumer) GetAuthorizedClient(ctx context.Context, vcsAuth sdk.VCSAuth) (sdk.VCSAuthorizedClient, error) {
100-
token := vcsAuth.PersonalAccessTokens
101-
if vcsAuth.PersonalAccessTokens == "" { // DEPRECATED
102-
token = vcsAuth.AccessToken
103-
}
104-
105-
createdTime := time.Unix(vcsAuth.AccessTokenCreated, 0)
106-
107-
c, ok := instancesAuthorizedClient[token]
108-
if createdTime.Add(2 * time.Hour).Before(time.Now()) {
109-
if ok {
110-
delete(instancesAuthorizedClient, token)
111-
}
112-
var newAccessToken string
113-
if vcsAuth.AccessToken != "" { // DEPRECATED
114-
var err error
115-
newAccessToken, _, err = consumer.RefreshToken(ctx, vcsAuth.AccessTokenSecret)
116-
if err != nil {
117-
return nil, sdk.WrapError(err, "cannot refresh token")
118-
}
119-
}
120-
121-
c = &bitbucketcloudClient{
122-
PersonalAccessToken: vcsAuth.PersonalAccessTokens,
123-
ClientID: consumer.ClientID, // DEPRECATED
124-
OAuthToken: newAccessToken, // DEPRECATED
125-
RefreshToken: vcsAuth.AccessTokenSecret, // DEPRECATED
96+
if vcsAuth.VCSProject != nil {
97+
c := &bitbucketcloudClient{
98+
PersonalAccessToken: vcsAuth.VCSProject.Auth["token"],
12699
Cache: consumer.Cache,
127100
apiURL: consumer.apiURL,
128101
uiURL: consumer.uiURL,
129-
DisableStatus: consumer.disableStatus,
130-
DisableStatusDetail: consumer.disableStatusDetail,
131-
proxyURL: consumer.proxyURL,
132102
}
133-
instancesAuthorizedClient[newAccessToken] = c
134-
} else {
135-
if !ok {
136-
c = &bitbucketcloudClient{
137-
PersonalAccessToken: vcsAuth.PersonalAccessTokens,
138-
ClientID: consumer.ClientID, // DEPRECATED
139-
OAuthToken: vcsAuth.AccessToken, // DEPRECATED
140-
RefreshToken: vcsAuth.AccessTokenSecret, // DEPRECATED
141-
Cache: consumer.Cache,
142-
apiURL: consumer.apiURL,
143-
uiURL: consumer.uiURL,
144-
DisableStatus: consumer.disableStatus,
145-
DisableStatusDetail: consumer.disableStatusDetail,
146-
proxyURL: consumer.proxyURL,
147-
}
148-
instancesAuthorizedClient[token] = c
103+
return c, nil
104+
}
105+
106+
// DEPRECATED VCS
107+
var newAccessToken string
108+
if vcsAuth.AccessToken != "" {
109+
var err error
110+
newAccessToken, _, err = consumer.RefreshToken(ctx, vcsAuth.AccessTokenSecret)
111+
if err != nil {
112+
return nil, sdk.WrapError(err, "cannot refresh token")
149113
}
150114
}
151115

116+
c := &bitbucketcloudClient{
117+
ClientID: consumer.ClientID,
118+
OAuthToken: newAccessToken,
119+
RefreshToken: vcsAuth.AccessTokenSecret,
120+
Cache: consumer.Cache,
121+
apiURL: consumer.apiURL,
122+
uiURL: consumer.uiURL,
123+
DisableStatus: consumer.disableStatus,
124+
DisableStatusDetail: consumer.disableStatusDetail,
125+
proxyURL: consumer.proxyURL,
126+
}
127+
152128
return c, nil
153129
}

0 commit comments

Comments
 (0)