8000 feat: gerrit integration (#3899) · ovh/cds@000dd3b · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Commit 000dd3b

Browse files
sguiheuxfsamin
authored andcommitted
feat: gerrit integration (#3899)
1 parent 6ec5102 commit 000dd3b

File tree

90 files changed

+9920
-555
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+9920
-555
lines changed

engine/api/api_routes.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ func (api *API) InitRouter() {
307307
r.Handle("/project/{permProjectKey}/repositories_manager", r.GET(api.getRepositoriesManagerForProjectHandler))
308308
r.Handle("/project/{permProjectKey}/repositories_manager/{name}/authorize", r.POST(api.repositoriesManagerAuthorizeHandler))
309309
r.Handle("/project/{permProjectKey}/repositories_manager/{name}/authorize/callback", r.POST(api.repositoriesManagerAuthorizeCallbackHandler))
310+
r.Handle("/project/{permProjectKey}/repositories_manager/{name}/authorize/basicauth", r.POST(api.repositoriesManagerAuthorizeBasicHandler))
310311
r.Handle("/project/{permProjectKey}/repositories_manager/{name}", r.DELETE(api.deleteRepositoriesManagerHandler))
311312
r.Handle("/project/{permProjectKey}/repositories_manager/{name}/repo", r.GET(api.getRepoFromRepositoriesManagerHandler))
312313
r.Handle("/project/{permProjectKey}/repositories_manager/{name}/repos", r.GET(api.getReposFromRepositoriesManagerHandler))
@@ -328,6 +329,7 @@ func (api *API) InitRouter() {
328329

329330
// config
330331
r.Handle("/config/user", r.GET(api.ConfigUserHandler, Auth(false)))
332+
r.Handle("/config/vcs", r.GET(api.ConfigVCShandler, NeedService()))
331333

332334
// Users
333335
r.Handle("/user", r.GET(api.getUsersHandler))

engine/api/config.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"net/http"
66

7+
"github.com/ovh/cds/engine/api/repositoriesmanager"
78
"github.com/ovh/cds/engine/service"
89
"github.com/ovh/cds/sdk"
910
)
@@ -14,3 +15,14 @@ func (api *API) ConfigUserHandler() service.Handler {
1415
return service.WriteJSON(w, map[string]string{sdk.ConfigURLAPIKey: api.Config.URL.API, sdk.ConfigURLUIKey: api.Config.URL.UI}, http.StatusOK)
1516
}
1617
}
18+
19+
// ConfigVCShandler return the configuration of vcs server
20+
func (api *API) ConfigVCShandler() service.Handler {
21+
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
22+
vcsServers, err := repositoriesmanager.LoadAll(ctx, api.mustDB(), api.Cache)
23+
if err != nil {
24+
return err
25+
}
26+
return service.WriteJSON(w, vcsServers, http.StatusOK)
27+
}
28+
}

engine/api/event/publish_workflow_run.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,38 @@ func PublishWorkflowNodeRun(db gorp.SqlExecutor, nr sdk.WorkflowNodeRun, w sdk.W
115115
}
116116
}
117117

118+
// Try to get gerrit variable
119+
var project, changeID, branch, revision, url string
120+
projectParam := sdk.ParameterFind(&nr.BuildParameters, "git.repository")
121+
if projectParam != nil {
122+
project = projectParam.Value
123+
}
124+
changeIDParam := sdk.ParameterFind(&nr.BuildParameters, "gerrit.change.id")
125+
if changeIDParam != nil {
126+
changeID = changeIDParam.Value
127+
}
128+
branchParam := sdk.ParameterFind(&nr.BuildParameters, "gerrit.change.branch")
129+
if branchParam != nil {
130+
branch = branchParam.Value
131+
}
132+
revisionParams := sdk.ParameterFind(&nr.BuildParameters, "git.hash")
133+
if revisionParams != nil {
134+
revision = revisionParams.Value
135+
}
136+
urlParams := sdk.ParameterFind(&nr.BuildParameters, "cds.ui.pipeline.run")
137+
if urlParams != nil {
138+
url = urlParams.Value
139+
}
140+
if changeID != "" && project != "" && branch != "" && revision != "" {
141+
e.GerritChange = &sdk.GerritChangeEvent{
142+
ID: changeID,
143+
DestBranch: branch,
144+
Project: project,
145+
Revision: revision,
146+
URL: url,
147+
}
148+
}
149+
118150
e.NodeName = nodeName
119151
var envName string
120152
var appName string

engine/api/pipeline/pipeline_importer.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ func Import(db gorp.SqlExecutor, store cache.Store, proj *sdk.Project, pip *sdk.
211211
msgChan <- sdk.NewMessage(sdk.MsgPipelineCreated, pip.Name)
212212
}
213213
}
214+
214215
//Reload the pipeline
215216
pip2, err := LoadPipeline(db, proj.Key, pip.Name, false)
216217
if err != nil {

engine/api/repositories_manager.go

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,14 @@ import (
2323

2424
func (api *API) getRepositoriesManagerHandler() service.Handler {
2525
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
26-
rms, err := repositoriesmanager.LoadAll(ctx, api.mustDB(), api.Cache)
26+
vcsServers, err := repositoriesmanager.LoadAll(ctx, api.mustDB(), api.Cache)
2727
if err != nil {
2828
return sdk.WrapError(err, "error")
2929
}
30+
rms := make([]string, 0, len(vcsServers))
31+
for k := range vcsServers {
32+
rms = append(rms, k)
33+
}
3034
return service.WriteJSON(w, rms, http.StatusOK)
3135
}
3236
}
@@ -69,7 +73,7 @@ func (api *API) repositoriesManagerAuthorizeHandler() service.Handler {
6973
if err != nil {
7074
return sdk.WrapError(sdk.ErrNoReposManagerAuth, "repositoriesManagerAuthorize> error with AuthorizeRedirect %s", err)
7175
}
72-
log.Info("repositoriesManagerAuthorize> [%s] RequestToken=%s; URL=%s", proj.Key, token, url)
76+
log.Debug("repositoriesManagerAuthorize> [%s] RequestToken=%s; URL=%s", proj.Key, token, url)
7377

7478
data := map[string]string{
7579
"project_key": proj.Key,
@@ -80,6 +84,12 @@ func (api *API) repositoriesManagerAuthorizeHandler() service.Handler {
8084
"username": deprecatedGetUser(ctx).Username,
8185
}
8286

87+
if token != "" {
88+
data["auth_type"] = "oauth"
89+
} else {
90+
data["auth_type"] = "basic"
91+
}
92+
8393
api.Cache.Set(cache.Key("reposmanager", "oauth", token), data)
8494
return service.WriteJSON(w, data, http.StatusOK)
8595
}
@@ -166,6 +176,73 @@ func (api *API) repositoriesManagerOAuthCallbackHandler() service.Handler {
166176
}
167177
}
168178

179+
func (api *API) repositoriesManagerAuthorizeBasicHandler() service.Handler {
180+
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
181+
vars := mux.Vars(r)
182+
projectKey := vars["permProjectKey"]
183+
rmName := vars["name"]
184+
185+
var tv map[string]interface{}
186+
if err := service.UnmarshalBody(r, &tv); err != nil {
187+
return err
188+
}
189+
190+
var username, secret string
191+
if tv["username"] != nil {
192+
username = tv["username"].(string)
193+
}
194+
if tv["secret"] != nil {
195+
secret = tv["secret"].(string)
196+
}
197+
198+
if username == "" || secret == "" {
199+
return sdk.WrapError(sdk.ErrWrongRequest, "cannot get token nor verifier from data")
200+
}
201+
202+
proj, errP := project.Load(api.mustDB(), api.Cache, projectKey, deprecatedGetUser(ctx))
203+
if errP != nil {
204+
return sdk.WrapError(errP, "cannot load project %s", projectKey)
205+
}
206+
207+
tx, errT := api.mustDB().Begin()
208+
if errT != nil {
209+
return sdk.WrapError(errT, "cannot start transaction")
210+
}
211+
defer tx.Rollback() // nolint
212+
213+
vcsServerForProject := &sdk.ProjectVCSServer{
214+
Name: rmName,
215+
Username: deprecatedGetUser(ctx).Username,
216+
Data: map[string]string{
217+
"token": username,
218+
"secret": secret,
219+
},
220+
}
221+
222+
if err := repositoriesmanager.InsertForProject(tx, proj, vcsServerForProject); err != nil {
223+
return sdk.WrapError(err, "unable to set repository manager data for project %s", projectKey)
224+
}
225+
226+
client, err := repositoriesmanager.AuthorizedClient(ctx, tx, api.Cache, vcsServerForProject)
227+
if err != nil {
228+
return sdk.WrapError(sdk.ErrNoReposManagerClientAuth, "cannot get client for project %s: %v", proj.Key, err)
229+
}
230+
231+
if _, err = client.Repos(ctx); err != nil {
232+
return sdk.WrapError(err, "unable to connect %s to %s", proj.Key, rmName)
233+
}
234+
235+
if err := tx.Commit(); err != nil {
236+
return sdk.WrapError(err, "cannot commit transaction")
237+
}
238+
239+
event.PublishAddVCSServer(proj, vcsServerForProject.Name, deprecatedGetUser(ctx))
240+
241+
return service.WriteJSON(w, proj, http.StatusOK)
242+
243+
}
244+
}
245+
169246
func (api *API) repositoriesManagerAuthorizeCallbackHandler() service.Handler {
170247
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
171248
vars := mux.Vars(r)

engine/api/repositoriesmanager/events.go

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -48,27 +48,27 @@ func processEvent(ctx context.Context, db *gorp.DbMap, event sdk.Event, store ca
4848
var c sdk.VCSAuthorizedClient
4949
var errC error
5050

51-
if event.EventType == fmt.Sprintf("%T", sdk.EventRunWorkflowNode{}) {
52-
var eventWNR sdk.EventRunWorkflowNode
51+
if event.EventType != fmt.Sprintf("%T", sdk.EventRunWorkflowNode{}) {
52+
return nil
53+
}
5354

54-
if err := mapstructure.Decode(event.Payload, &eventWNR); err != nil {
55-
return fmt.Errorf("repositoriesmanager>processEvent> Error during consumption: %v", err)
56-
}
57-
if eventWNR.RepositoryManagerName == "" {
58-
return nil
59-
}
60-
vcsServer, err := LoadForProject(db, event.ProjectKey, eventWNR.RepositoryManagerName)
61-
if err != nil {
62-
return fmt.Errorf("repositoriesmanager>processEvent> AuthorizedClient (%s, %s) > err:%s", event.ProjectKey, eventWNR.RepositoryManagerName, err)
63-
}
55+
var eventWNR sdk.EventRunWorkflowNode
6456

65-
c, errC = AuthorizedClient(ctx, db, store, vcsServer)
66-
if errC != nil {
67-
return fmt.Errorf("repositoriesmanager>processEvent> AuthorizedClient (%s, %s) > err:%s", event.ProjectKey, eventWNR.RepositoryManagerName, errC)
68-
}
69-
} else {
57+
if err := mapstructure.Decode(event.Payload, &eventWNR); err != nil {
58+
return fmt.Errorf("repositoriesmanager>processEvent> Error during consumption: %v", err)
59+
}
60+
if eventWNR.RepositoryManagerName == "" {
7061
return nil
7162
}
63+
vcsServer, err := LoadForProject(db, event.ProjectKey, eventWNR.RepositoryManagerName)
64+
if err != nil {
65+
return fmt.Errorf("repositoriesmanager>processEvent> AuthorizedClient (%s, %s) > err:%s", event.ProjectKey, eventWNR.RepositoryManagerName, err)
66+
}
67+
68+
c, errC = AuthorizedClient(ctx, db, store, vcsServer)
69+
if errC != nil {
70+
return fmt.Errorf("repositoriesmanager>processEvent> AuthorizedClient (%s, %s) > err:%s"< F438 /span>, event.ProjectKey, eventWNR.RepositoryManagerName, errC)
71+
}
7272

7373
if err := c.SetStatus(ctx, event); err != nil {
7474
RetryEvent(&event, err, store)

engine/api/repositoriesmanager/repositories_manager.go

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,30 @@ import (
2222
"github.com/ovh/cds/sdk/log"
2323
)
2424

25+
func LoadByName(ctx context.Context, db gorp.SqlExecutor, vcsName string) (sdk.VCSConfiguration, error) {
26+
var vcsServer sdk.VCSConfiguration
27+
srvs, err := services.FindByType(db, services.TypeVCS)
28+
if err != nil {
29+
return vcsServer, sdk.WrapError(err, "Unable to load services")
30+
}
31+
if _, err := services.DoJSONRequest(ctx, srvs, "GET", fmt.Sprintf("/vcs/%s", vcsName), nil, &vcsServer); err != nil {
32+
return vcsServer, sdk.WithStack(err)
33+
}
34+
return vcsServer, nil
35+
}
36+
2537
//LoadAll Load all RepositoriesManager from the database
26-
func LoadAll(ctx context.Context, db *gorp.DbMap, store cache.Store) ([]string, error) {
38+
func LoadAll(ctx context.Context, db *gorp.DbMap, store cache.Store) (map[string]sdk.VCSConfiguration, error) {
2739
srvs, err := services.FindByType(db, services.TypeVCS)
2840
if err != nil {
2941
return nil, sdk.WrapError(err, "Unable to load services")
3042
}
3143

32-
vcsServers := map[string]interface{}{}
44+
vcsServers := make(map[string]sdk.VCSConfiguration)
3345
if _, err := services.DoJSONRequest(ctx, srvs, "GET", "/vcs", nil, &vcsServers); err != nil {
3446
return nil, sdk.WithStack(err)
3547
}
36-
servers := []string{}
37-
for k := range vcsServers {
38-
servers = append(servers, k)
39-
}
40-
return servers, nil
48+
return vcsServers, nil
4149
}
4250

4351
type vcsConsumer struct {
@@ -304,17 +312,17 @@ func (c *vcsClient) Branch(ctx context.Context, fullname string, branchName stri
304312
}
305313

306314
// DefaultBranch get default branch from given repository
307-
func DefaultBranch(ctx context.Context, c sdk.VCSAuthorizedClient, fullname string) (string, error) {
315+
func DefaultBranch(ctx context.Context, c sdk.VCSAuthorizedClient, fullname string) (sdk.VCSBranch, error) {
308316
branches, err := c.Branches(ctx, fullname)
309317
if err != nil {
310-
return "", sdk.WrapError(err, "Unable to list branches on repository %s", fullname)
318+
return sdk.VCSBranch{}, sdk.WrapError(err, "Unable to list branches on repository %s", fullname)
311319
}
312320
for _, b := range branches {
313321
if b.Default {
314-
return b.DisplayID, nil
322+
return b, nil
315323
}
316324
}
317-
return "", sdk.NewErrorFrom(sdk.ErrNotFound, "unable to find default branch on repository %s (among %d branches)", fullname, len(branches))
325+
return sdk.VCSBranch{}, sdk.NewErrorFrom(sdk.ErrNotFound, "unable to find default branch on repository %s (among %d branches)", fullname, len(branches))
318326
}
319327

320328
func (c *vcsClient) Commits(ctx context.Context, fullname, branch, since, until string) ([]sdk.VCSCommit, error) {
@@ -533,9 +541,11 @@ func (c *vcsClient) GrantReadPermission(ctx context.Context, repo string) error
533541

534542
// WebhooksInfos is a set of info about webhooks
535543
type WebhooksInfos struct {
536-
WebhooksSupported bool `json:"webhooks_supported"`
537-
WebhooksDisabled bool `json:"webhooks_disabled"`
538-
Icon string `json:"webhooks_icon"`
544+
WebhooksSupported bool `json:"webhooks_supported"`
545+
WebhooksDisabled bool `json:"webhooks_disabled"`
546+
GerritHookDisabled bool `json:"gerrithook_disabled"`
547+
Icon string `json:"webhooks_icon"`
548+
Events []string `json:"events"`
539549
}
540550

541551
// GetWebhooksInfos returns webhooks_supported, webhooks_disabled, webhooks_creation_supported, webhooks_creation_disabled for a vcs server

engine/api/ui.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ func (api *API) getApplicationOverviewHandler() service.Handler {
101101

102102
// GET LAST BUILD
103103
tagFilter := make(map[string]string, 1)
104-
tagFilter["git.branch"] = defaultBranch
104+
tagFilter["git.branch"] = defaultBranch.DisplayID
105105
for _, w := range app.Usage.Workflows {
106106
runs, _, _, _, errR := workflow.LoadRuns(db, key, w.Name, 0, 5, tagFilter)
107107
if errR != nil {

engine/api/workflow/dao_data_hook.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,15 @@ func insertNodeHookData(db gorp.SqlExecutor, w *sdk.Workflow, n *sdk.Node) error
4040
Configurable: false,
4141
}
4242

43-
if model.Name == sdk.RepositoryWebHookModelName || model.Name == sdk.GitPollerModelName {
43+
if model.Name == sdk.RepositoryWebHookModelName || model.Name == sdk.GitPollerModelName || model.Name == sdk.GerritHookModelName {
4444
if n.Context.ApplicationID == 0 || w.Applications[n.Context.ApplicationID].RepositoryFullname == "" || w.Applications[n.Context.ApplicationID].VCSServer == "" {
4545
return sdk.NewErrorFrom(sdk.ErrForbidden, "cannot create a git poller or repository webhook on an application without a repository")
4646
}
47-
h.Config["vcsServer"] = sdk.WorkflowNodeHookConfigValue{
47+
h.Config[sdk.HookConfigVCSServer] = sdk.WorkflowNodeHookConfigValue{
4848
Value: w.Applications[n.Context.ApplicationID].VCSServer,
4949
Configurable: false,
5050
}
51-
h.Config["repoFullName"] = sdk.WorkflowNodeHookConfigValue{
51+
h.Config[sdk.HookConfigRepoFullName] = sdk.WorkflowNodeHookConfigValue{
5252
Value: w.Applications[n.Context.ApplicationID].RepositoryFullname,
5353
Configurable: false,
5454
}

engine/api/workflow/dao_node_run_vulnerability.go

Lines changed: 2 additions & 2 deletions
< 76C3 td data-grid-cell-id="diff-4036a72eab1028a592131d412d2cb18edb55a738b9df2630827b5f004a58a773-29-29-1" data-selected="false" role="gridcell" style="background-color:var(--bgColor-default);text-align:center" tabindex="-1" valign="top" class="focusable-grid-cell diff-line-number position-relative diff-line-number-neutral left-side">29
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ func HandleVulnerabilityReport(ctx context.Context, db gorp.SqlExecutor, cache c
2828
return sdk.WrapError(sdk.ErrNoReposManagerClientAuth, "HandleVulnerabilityReport> Cannot get repo client %s : %v", nr.VCSServer, erra)
29
}
3030

31-
var errB error
32-
defaultBranch, errB = repositoriesmanager.DefaultBranch(ctx, client, nr.VCSRepository)
31+
b, errB := repositoriesmanager.DefaultBranch(ctx, client, nr.VCSRepository)
3332
if errB != nil {
3433
return sdk.WrapError(errB, "HandleVulnerabilityReport> Unable to get default branch")
3534
}
35+
defaultBranch = b.DisplayID
3636
}
3737

3838
// Get report on the current node run if exist

0 commit comments

Comments
 (0)
0