Skip to content

Commit

Permalink
feat (api): receive hook from repository manager (#1586)
Browse files Browse the repository at this point in the history
  • Loading branch information
sguiheux authored and fsamin committed Nov 28, 2017
1 parent be28c8b commit f90cd50
Show file tree
Hide file tree
Showing 12 changed files with 1,355 additions and 124 deletions.
3 changes: 2 additions & 1 deletion engine/api/api_routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ func (api *API) InitRouter() {
r.Handle("/project/{key}/workflows/{permWorkflowName}", r.GET(api.getWorkflowHandler), r.PUT(api.putWorkflowHandler), r.DELETE(api.deleteWorkflowHandler))
r.Handle("/project/{key}/workflows/{permWorkflowName}/groups", r.POST(api.postWorkflowGroupHandler))
r.Handle("/project/{key}/workflows/{permWorkflowName}/groups/{groupName}", r.PUT(api.putWorkflowGroupHandler), r.DELETE(api.deleteWorkflowGroupHandler))
r.Handle("/project/{key}/workflow/{permWorkflowName}/node/{nodeID}/hook/model", r.GET(api.getWorkflowHookModelsHandler))

// Workflows run
r.Handle("/project/{key}/workflows/{permWorkflowName}/runs", r.GET(api.getWorkflowRunsHandler), r.POSTEXECUTE(api.postWorkflowRunHandler, AllowServices(true)))
r.Handle("/project/{key}/workflows/{permWorkflowName}/runs/latest", r.GET(api.getLatestWorkflowRunHandler))
Expand Down Expand Up @@ -346,7 +348,6 @@ func (api *API) InitRouter() {

// Workflows
r.Handle("/workflow/hook", r.GET(api.getWorkflowHooksHandler, NeedService()))
r.Handle("/workflow/hook/model", r.GET(api.getWorkflowHookModelsHandler))
r.Handle("/workflow/hook/model/{model}", r.GET(api.getWorkflowHookModelHandler), r.POST(api.postWorkflowHookModelHandler, NeedAdmin(true)), r.PUT(api.putWorkflowHookModelHandler, NeedAdmin(true)))

// SSE
Expand Down
2 changes: 1 addition & 1 deletion engine/api/workflow/dao_hook_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ var (
DefaultConfig: sdk.WorkflowNodeHookConfig{
"method": {
Value: "POST",
Configurable: true,
Configurable: false,
},
},
}
Expand Down
60 changes: 60 additions & 0 deletions engine/api/workflow_hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (

"github.com/gorilla/mux"

"github.com/ovh/cds/engine/api/project"
"github.com/ovh/cds/engine/api/repositoriesmanager"
"github.com/ovh/cds/engine/api/workflow"
"github.com/ovh/cds/sdk"
)
Expand All @@ -23,10 +25,68 @@ func (api *API) getWorkflowHooksHandler() Handler {

func (api *API) getWorkflowHookModelsHandler() Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
vars := mux.Vars(r)
key := vars["key"]
workflowName := vars["permWorkflowName"]
nodeID, errN := requestVarInt(r, "nodeID")
if errN != nil {
return sdk.WrapError(errN, "getWorkflowHookModelsHandler")
}

p, errP := project.Load(api.mustDB(), api.Cache, key, getUser(ctx))
if errP != nil {
return sdk.WrapError(errP, "getWorkflowHookModelsHandler > project.Load")
}

wf, errW := workflow.Load(api.mustDB(), api.Cache, key, workflowName, getUser(ctx))
if errW != nil {
return sdk.WrapError(errW, "getWorkflowHookModelsHandler > workflow.Load")
}

node := wf.GetNode(nodeID)
if node == nil {
return sdk.WrapError(sdk.ErrWorkflowNodeNotFound, "getWorkflowHookModelsHandler")
}

m, err := workflow.LoadHookModels(api.mustDB())
if err != nil {
return sdk.WrapError(err, "getWorkflowHookModelsHandler")
}

// Post processing on repositoryWebHook
hasRepoManager := false
repoWebHookEnable := false
if node.Context.Application != nil && node.Context.Application.RepositoryFullname != "" {
hasRepoManager = true
}
if hasRepoManager {
// Call VCS to know if repository allows webhook and get the configuration fields
vcsServer := repositoriesmanager.GetProjectVCSServer(p, node.Context.Application.VCSServer)
if vcsServer != nil {
client, errclient := repositoriesmanager.AuthorizedClient(api.mustDB(), api.Cache, vcsServer)
if errclient != nil {
return sdk.WrapError(errclient, "getWorkflowHookModelsHandler> Cannot get vcs client")
}
webHookInfo, errWH := repositoriesmanager.GetWebhooksInfos(client)
if errWH != nil {
return sdk.WrapError(errWH, "getWorkflowHookModelsHandler> Cannot get vcs web hook info")
}
repoWebHookEnable = webHookInfo.WebhooksSupported && !webHookInfo.WebhooksDisabled

}
}

if !repoWebHookEnable {
var indexToDelete int
for i := range m {
if m[i].Name == workflow.RepositoryWebHookModel.Name {
indexToDelete = i
break
}
}
m = append(m[0:indexToDelete], m[indexToDelete+1:]...)
}

return WriteJSON(w, r, m, http.StatusOK)
}
}
Expand Down
89 changes: 85 additions & 4 deletions engine/api/workflow_hook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ package api

import (
"encoding/json"
"fmt"
"net/http/httptest"
"testing"

"github.com/stretchr/testify/assert"

"github.com/ovh/cds/engine/api/application"
"github.com/ovh/cds/engine/api/group"
"github.com/ovh/cds/engine/api/pipeline"
"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/workflow"
Expand All @@ -15,14 +20,48 @@ import (

func Test_getWorkflowHookModelsHandlerAsLambdaUser(t *testing.T) {
api, _, _ := newTestAPI(t)
db := api.mustDB()
cache := api.Cache
test.NoError(t, workflow.CreateBuiltinWorkflowHookModels(api.mustDB()))
user, passUser := assets.InsertLambdaUser(api.mustDB())
u, passUser := assets.InsertLambdaUser(api.mustDB())

proj := assets.InsertTestProject(t, db, cache, sdk.RandomString(10), sdk.RandomString(10), u)
test.NoError(t, group.InsertUserInGroup(db, proj.ProjectGroups[0].Group.ID, u.ID, true))

pip := sdk.Pipeline{
ProjectID: proj.ID,
ProjectKey: proj.Key,
Name: sdk.RandomString(10),
Type: sdk.BuildPipeline,
}

test.NoError(t, pipeline.InsertPipeline(db, proj, &pip, u))
test.NoError(t, group.InsertGroupInPipeline(db, pip.ID, proj.ProjectGroups[0].Group.ID, 7))

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

w := sdk.Workflow{
Name: sdk.RandomString(10),
ProjectID: proj.ID,
ProjectKey: proj.Key,
Root: &sdk.WorkflowNode{
Pipeline: pip,
},
}

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

//Prepare request
vars := map[string]string{}
vars["key"] = proj.Key
vars["permWorkflowName"] = w.Name
vars["nodeID"] = fmt.Sprintf("%d", w.Root.ID)

uri := api.Router.GetRoute("GET", api.getWorkflowHookModelsHandler, vars)
test.NotEmpty(t, uri)
req := assets.NewAuthentifiedRequest(t, user, passUser, "GET", uri, nil)
req := assets.NewAuthentifiedRequest(t, u, passUser, "GET", uri, nil)

//Do the request
rec := httptest.NewRecorder()
Expand All @@ -32,16 +71,58 @@ func Test_getWorkflowHookModelsHandlerAsLambdaUser(t *testing.T) {
//Check result
models := []sdk.WorkflowHookModel{}
test.NoError(t, json.Unmarshal(rec.Body.Bytes(), &models))
assert.Len(t, models, 4, "")
assert.Len(t, models, 3, "")
}

func Test_getWorkflowHookModelsHandlerAsAdminUser(t *testing.T) {
api, _, _ := newTestAPI(t)
db := api.mustDB()
cache := api.Cache
test.NoError(t, workflow.CreateBuiltinWorkflowHookModels(api.mustDB()))
admin, passAdmin := assets.InsertAdminUser(api.mustDB())

proj := assets.InsertTestProject(t, db, cache, sdk.RandomString(10), sdk.RandomString(10), admin)

pip := sdk.Pipeline{
ProjectID: proj.ID,
ProjectKey: proj.Key,
Name: sdk.RandomString(10),
Type: sdk.BuildPipeline,
}

test.NoError(t, pipeline.InsertPipeline(db, proj, &pip, admin))

app := sdk.Application{
Name: sdk.RandomString(10),
ProjectKey: proj.Key,
ProjectID: proj.ID,
RepositoryFullname: "ovh/cds",
}
test.NoError(t, application.Insert(db, cache, proj, &app, admin))

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

w := sdk.Workflow{
Name: sdk.RandomString(10),
ProjectID: proj.ID,
ProjectKey: proj.Key,
Root: &sdk.WorkflowNode{
Pipeline: pip,
Context: &sdk.WorkflowNodeContext{
Application: &app,
},
},
}

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

//Prepare request
vars := map[string]string{}
vars["key"] = proj.Key
vars["permWorkflowName"] = w.Name
vars["nodeID"] = fmt.Sprintf("%d", w.Root.ID)

uri := api.Router.GetRoute("GET", api.getWorkflowHookModelsHandler, vars)
test.NotEmpty(t, uri)
req := assets.NewAuthentifiedRequest(t, admin, passAdmin, "GET", uri, nil)
Expand All @@ -54,7 +135,7 @@ func Test_getWorkflowHookModelsHandlerAsAdminUser(t *testing.T) {
//Check result
models := []sdk.WorkflowHookModel{}
test.NoError(t, json.Unmarshal(rec.Body.Bytes(), &models))
assert.Len(t, models, 4, "")
assert.Len(t, models, 3, "")
}

func Test_getWorkflowHookModelHandler(t *testing.T) {
Expand Down
Loading

0 comments on commit f90cd50

Please sign in to comment.