Skip to content

Commit

Permalink
gateway: add default_branch in projectresponse and /projects/{project…
Browse files Browse the repository at this point in the history
…ref}/refreshremoterepo api to refresh repo info
  • Loading branch information
alessandro-sorint committed Aug 5, 2022
1 parent ceea616 commit 5fa27c8
Show file tree
Hide file tree
Showing 15 changed files with 194 additions and 20 deletions.
11 changes: 6 additions & 5 deletions internal/gitsources/gitea/gitea.go
Original file line number Diff line number Diff line change
Expand Up @@ -420,11 +420,12 @@ func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {

func fromGiteaRepo(rr *gitea.Repository) *gitsource.RepoInfo {
return &gitsource.RepoInfo{
ID: strconv.FormatInt(rr.ID, 10),
Path: path.Join(rr.Owner.UserName, rr.Name),
HTMLURL: rr.HTMLURL,
SSHCloneURL: rr.SSHURL,
HTTPCloneURL: rr.CloneURL,
ID: strconv.FormatInt(rr.ID, 10),
Path: path.Join(rr.Owner.UserName, rr.Name),
HTMLURL: rr.HTMLURL,
SSHCloneURL: rr.SSHURL,
HTTPCloneURL: rr.CloneURL,
DefaultBranch: rr.DefaultBranch,
}
}

Expand Down
11 changes: 6 additions & 5 deletions internal/gitsources/github/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,11 +423,12 @@ func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {

func fromGithubRepo(rr *github.Repository) *gitsource.RepoInfo {
return &gitsource.RepoInfo{
ID: strconv.FormatInt(*rr.ID, 10),
Path: path.Join(*rr.Owner.Login, *rr.Name),
HTMLURL: *rr.HTMLURL,
SSHCloneURL: *rr.SSHURL,
HTTPCloneURL: *rr.CloneURL,
ID: strconv.FormatInt(*rr.ID, 10),
Path: path.Join(*rr.Owner.Login, *rr.Name),
HTMLURL: *rr.HTMLURL,
SSHCloneURL: *rr.SSHURL,
HTTPCloneURL: *rr.CloneURL,
DefaultBranch: *rr.DefaultBranch,
}
}

Expand Down
11 changes: 6 additions & 5 deletions internal/gitsources/gitlab/gitlab.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,11 +297,12 @@ func (c *Client) ListUserRepos() ([]*gitsource.RepoInfo, error) {

func fromGitlabRepo(rr *gitlab.Project) *gitsource.RepoInfo {
return &gitsource.RepoInfo{
ID: strconv.Itoa(rr.ID),
Path: rr.PathWithNamespace,
HTMLURL: rr.WebURL,
SSHCloneURL: rr.SSHURLToRepo,
HTTPCloneURL: rr.HTTPURLToRepo,
ID: strconv.Itoa(rr.ID),
Path: rr.PathWithNamespace,
HTMLURL: rr.WebURL,
SSHCloneURL: rr.SSHURLToRepo,
HTTPCloneURL: rr.HTTPURLToRepo,
DefaultBranch: rr.DefaultBranch,
}
}

Expand Down
11 changes: 6 additions & 5 deletions internal/gitsources/gitsource.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,12 @@ type Oauth2Source interface {
}

type RepoInfo struct {
ID string
Path string
HTMLURL string
SSHCloneURL string
HTTPCloneURL string
ID string
Path string
HTMLURL string
SSHCloneURL string
HTTPCloneURL string
DefaultBranch string
}

type UserInfo struct {
Expand Down
3 changes: 3 additions & 0 deletions internal/services/configstore/action/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ type CreateUpdateProjectRequest struct {
SSHPrivateKey string
SkipSSHHostKeyCheck bool
PassVarsToForkedPR bool
DefaultBranch string
}

func (h *ActionHandler) CreateProject(ctx context.Context, req *CreateUpdateProjectRequest) (*types.Project, error) {
Expand Down Expand Up @@ -162,6 +163,7 @@ func (h *ActionHandler) CreateProject(ctx context.Context, req *CreateUpdateProj
project.SSHPrivateKey = req.SSHPrivateKey
project.SkipSSHHostKeyCheck = req.SkipSSHHostKeyCheck
project.PassVarsToForkedPR = req.PassVarsToForkedPR
project.DefaultBranch = req.DefaultBranch

// generate the Secret and the WebhookSecret
// TODO(sgotti) move this to the gateway?
Expand Down Expand Up @@ -271,6 +273,7 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, curProjectRef string,
project.SSHPrivateKey = req.SSHPrivateKey
project.SkipSSHHostKeyCheck = req.SkipSSHHostKeyCheck
project.PassVarsToForkedPR = req.PassVarsToForkedPR
project.DefaultBranch = req.DefaultBranch

if err := h.d.UpdateProject(tx, project); err != nil {
return errors.WithStack(err)
Expand Down
2 changes: 2 additions & 0 deletions internal/services/configstore/api/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ func (h *CreateProjectHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
SSHPrivateKey: req.SSHPrivateKey,
SkipSSHHostKeyCheck: req.SkipSSHHostKeyCheck,
PassVarsToForkedPR: req.PassVarsToForkedPR,
DefaultBranch: req.DefaultBranch,
}

project, err := h.ah.CreateProject(ctx, areq)
Expand Down Expand Up @@ -240,6 +241,7 @@ func (h *UpdateProjectHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
SSHPrivateKey: req.SSHPrivateKey,
SkipSSHHostKeyCheck: req.SkipSSHHostKeyCheck,
PassVarsToForkedPR: req.PassVarsToForkedPR,
DefaultBranch: req.DefaultBranch,
}

project, err := h.ah.UpdateProject(ctx, projectRef, areq)
Expand Down
44 changes: 44 additions & 0 deletions internal/services/gateway/action/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ func (h *ActionHandler) CreateProject(ctx context.Context, req *CreateProjectReq
SSHPrivateKey: string(privateKey),
SkipSSHHostKeyCheck: req.SkipSSHHostKeyCheck,
PassVarsToForkedPR: req.PassVarsToForkedPR,
DefaultBranch: repo.DefaultBranch,
}

h.log.Info().Msgf("creating project")
Expand Down Expand Up @@ -169,6 +170,8 @@ type UpdateProjectRequest struct {

Visibility *cstypes.Visibility
PassVarsToForkedPR *bool

DefaultBranch *string
}

func (h *ActionHandler) UpdateProject(ctx context.Context, projectRef string, req *UpdateProjectRequest) (*csapitypes.Project, error) {
Expand Down Expand Up @@ -197,6 +200,9 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, projectRef string, re
if req.PassVarsToForkedPR != nil {
p.PassVarsToForkedPR = *req.PassVarsToForkedPR
}
if req.DefaultBranch != nil {
p.DefaultBranch = *req.DefaultBranch
}

creq := &csapitypes.CreateUpdateProjectRequest{
Name: p.Name,
Expand All @@ -210,6 +216,7 @@ func (h *ActionHandler) UpdateProject(ctx context.Context, projectRef string, re
SSHPrivateKey: p.SSHPrivateKey,
SkipSSHHostKeyCheck: p.SkipSSHHostKeyCheck,
PassVarsToForkedPR: p.PassVarsToForkedPR,
DefaultBranch: p.DefaultBranch,
}

h.log.Info().Msgf("updating project")
Expand Down Expand Up @@ -584,3 +591,40 @@ func (h *ActionHandler) getRemoteRepoAccessData(ctx context.Context, linkedAccou

return user, rs, la, nil
}

func (h *ActionHandler) GetRepoInfo(ctx context.Context, repoPath string, remoteSourceRef string) (*gitsource.RepoInfo, error) {
curUserID := common.CurrentUserID(ctx)
gitSource, _, _, err := h.GetGitSourceByRemoteSourceRef(ctx, remoteSourceRef, curUserID)
if err != nil {
return nil, util.NewAPIError(util.KindFromRemoteError(err), errors.Wrapf(err, "failed to get remote source %q", remoteSourceRef))
}

repo, err := gitSource.GetRepoInfo(repoPath)
if err != nil {
return nil, util.NewAPIError(util.KindFromRemoteError(err), errors.Wrapf(err, "failed to get repository info from gitsource %q", repoPath))
}

return repo, nil
}

func (h *ActionHandler) RefreshRemoteRepositoryInfo(ctx context.Context, projectRef string) (*csapitypes.Project, error) {
project, err := h.GetProject(ctx, projectRef)
if err != nil {
return nil, util.NewAPIError(util.KindFromRemoteError(err), errors.Wrapf(err, "failed to get project %q", projectRef))
}

repoInfo, err := h.GetRepoInfo(ctx, project.RepositoryPath, project.RemoteSourceID)
if err != nil {
return nil, util.NewAPIError(util.KindFromRemoteError(err), errors.Wrapf(err, "failed to get repo info %q", project.RepositoryPath))
}

areq := &UpdateProjectRequest{
DefaultBranch: &repoInfo.DefaultBranch,
}
project, err = h.UpdateProject(ctx, projectRef, areq)
if err != nil {
return nil, util.NewAPIError(util.KindFromRemoteError(err), errors.Wrapf(err, "failed to update project %q", projectRef))
}

return project, nil
}
30 changes: 30 additions & 0 deletions internal/services/gateway/action/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -1027,3 +1027,33 @@ func (h *ActionHandler) GetUserGitSource(ctx context.Context, remoteSourceRef, u

return gitSource, rs, la, nil
}

func (h *ActionHandler) GetGitSourceByRemoteSourceRef(ctx context.Context, remoteSourceRef, userID string) (gitsource.GitSource, *cstypes.RemoteSource, *cstypes.LinkedAccount, error) {
rs, _, err := h.configstoreClient.GetRemoteSource(ctx, remoteSourceRef)
if err != nil {
return nil, nil, nil, util.NewAPIError(util.KindFromRemoteError(err), errors.Wrapf(err, "failed to get remote source %q", remoteSourceRef))
}

linkedAccounts, _, err := h.configstoreClient.GetUserLinkedAccounts(ctx, userID)
if err != nil {
return nil, nil, nil, util.NewAPIError(util.KindFromRemoteError(err), errors.Wrapf(err, "failed to get linked accounts for user %q", userID))
}

var la *cstypes.LinkedAccount
for _, v := range linkedAccounts {
if v.RemoteSourceID == rs.ID {
la = v
break
}
}
if la == nil {
return nil, nil, nil, errors.Errorf("user doesn't have a linked account for remote source %q", rs.Name)
}

gitSource, err := h.GetGitSource(ctx, rs, la.RemoteUserName, la)
if err != nil {
return nil, nil, nil, util.NewAPIError(util.ErrInternal, errors.Wrapf(err, "failed to create gitea client"))
}

return gitSource, rs, la, nil
}
31 changes: 31 additions & 0 deletions internal/services/gateway/api/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ func createProjectResponse(r *csapitypes.Project) *gwapitypes.ProjectResponse {
Visibility: gwapitypes.Visibility(r.Visibility),
GlobalVisibility: string(r.GlobalVisibility),
PassVarsToForkedPR: r.PassVarsToForkedPR,
DefaultBranch: r.DefaultBranch,
}

return res
Expand Down Expand Up @@ -284,3 +285,33 @@ func (h *ProjectCreateRunHandler) ServeHTTP(w http.ResponseWriter, r *http.Reque
h.log.Err(err).Send()
}
}

type RefreshRemoteRepositoryInfoHandler struct {
log zerolog.Logger
ah *action.ActionHandler
}

func NewRefreshRemoteRepositoryInfoHandler(log zerolog.Logger, ah *action.ActionHandler) *RefreshRemoteRepositoryInfoHandler {
return &RefreshRemoteRepositoryInfoHandler{log: log, ah: ah}
}

func (h *RefreshRemoteRepositoryInfoHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
vars := mux.Vars(r)
projectRef, err := url.PathUnescape(vars["projectref"])
if err != nil {
util.HTTPError(w, util.NewAPIError(util.ErrBadRequest, err))
return
}

project, err := h.ah.RefreshRemoteRepositoryInfo(ctx, projectRef)
if util.HTTPError(w, err) {
h.log.Err(err).Send()
return
}

res := createProjectResponse(project)
if err := util.HTTPResponse(w, http.StatusCreated, res); err != nil {
h.log.Err(err).Send()
}
}
2 changes: 2 additions & 0 deletions internal/services/gateway/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ func (g *Gateway) Run(ctx context.Context) error {
projectReconfigHandler := api.NewProjectReconfigHandler(g.log, g.ah)
projectUpdateRepoLinkedAccountHandler := api.NewProjectUpdateRepoLinkedAccountHandler(g.log, g.ah)
projectCreateRunHandler := api.NewProjectCreateRunHandler(g.log, g.ah)
refreshRemoteRepositoryInfoHandler := api.NewRefreshRemoteRepositoryInfoHandler(g.log, g.ah)

secretHandler := api.NewSecretHandler(g.log, g.ah)
createSecretHandler := api.NewCreateSecretHandler(g.log, g.ah)
Expand Down Expand Up @@ -263,6 +264,7 @@ func (g *Gateway) Run(ctx context.Context) error {
apirouter.Handle("/projects/{projectref}/runs/{runnumber}/tasks/{taskid}/actions", authForcedHandler(projectRunTaskActionsHandler)).Methods("PUT")
apirouter.Handle("/projects/{projectref}/runs/{runnumber}/tasks/{taskid}/logs", authOptionalHandler(projectRunLogsHandler)).Methods("GET")
apirouter.Handle("/projects/{projectref}/runs/{runnumber}/tasks/{taskid}/logs", authForcedHandler(projectRunLogsDeleteHandler)).Methods("DELETE")
apirouter.Handle("/projects/{projectref}/refreshremoterepo", authForcedHandler(refreshRemoteRepositoryInfoHandler)).Methods("PUT")

apirouter.Handle("/projectgroups/{projectgroupref}/secrets", authForcedHandler(secretHandler)).Methods("GET")
apirouter.Handle("/projects/{projectref}/secrets", authForcedHandler(secretHandler)).Methods("GET")
Expand Down
1 change: 1 addition & 0 deletions services/configstore/api/types/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type CreateUpdateProjectRequest struct {
SSHPrivateKey string
SkipSSHHostKeyCheck bool
PassVarsToForkedPR bool
DefaultBranch string
}

// Project augments cstypes.Project with dynamic data
Expand Down
2 changes: 2 additions & 0 deletions services/configstore/types/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ type Project struct {
WebhookSecret string `json:"webhook_secret,omitempty"`

PassVarsToForkedPR bool `json:"pass_vars_to_forked_pr,omitempty"`

DefaultBranch string `json:"default_branch,omitempty"`
}

func NewProject() *Project {
Expand Down
1 change: 1 addition & 0 deletions services/gateway/api/types/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type ProjectResponse struct {
Visibility Visibility `json:"visibility,omitempty"`
GlobalVisibility string `json:"global_visibility,omitempty"`
PassVarsToForkedPR bool `json:"pass_vars_to_forked_pr,omitempty"`
DefaultBranch string `json:"default_branch,omitempty"`
}

type ProjectCreateRunRequest struct {
Expand Down
6 changes: 6 additions & 0 deletions services/gateway/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -637,3 +637,9 @@ func (c *Client) GetUserOrgs(ctx context.Context) ([]*gwapitypes.UserOrgsRespons
resp, err := c.getParsedResponse(ctx, "GET", "/user/orgs", nil, jsonContent, nil, &userOrgs)
return userOrgs, resp, errors.WithStack(err)
}

func (c *Client) RefreshRemoteRepo(ctx context.Context, projectRef string) (*gwapitypes.ProjectResponse, *http.Response, error) {
project := new(gwapitypes.ProjectResponse)
resp, err := c.getParsedResponse(ctx, "PUT", path.Join("/projects", url.PathEscape(projectRef), "/refreshremoterepo"), nil, jsonContent, nil, project)
return project, resp, err
}
48 changes: 48 additions & 0 deletions tests/setup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2204,3 +2204,51 @@ func TestTaskTimeout(t *testing.T) {
})
}
}

func TestRefreshRemoteRepositoryInfo(t *testing.T) {
dir, err := ioutil.TempDir("", "agola")
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
defer os.RemoveAll(dir)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

tgitea, c := setup(ctx, t, dir, true)
defer shutdownGitea(tgitea)

giteaAPIURL := fmt.Sprintf("http://%s:%s", tgitea.HTTPListenAddress, tgitea.HTTPPort)

giteaToken, token := createLinkedAccount(ctx, t, tgitea, c)

giteaClient := gitea.NewClient(giteaAPIURL, giteaToken)
gwClient := gwclient.NewClient(c.Gateway.APIExposedURL, token)

giteaRepo, project := createProject(ctx, t, giteaClient, gwClient)

if project.DefaultBranch != "master" {
t.Fatalf("expected DefaultBranch master got: %s", project.DefaultBranch)
}

_, err = giteaClient.EditRepo(giteaRepo.Owner.UserName, giteaRepo.Name, gitea.EditRepoOption{DefaultBranch: util.StringP("testbranch")})
if err != nil {
t.Fatalf("unexpected err: %v", err)
}

project, _, err = gwClient.RefreshRemoteRepo(ctx, project.ID)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
if project.DefaultBranch != "testbranch" {
t.Fatalf("expected DefaultBranch testbranch got: %s", project.DefaultBranch)
}

p, _, err := gwClient.GetProject(ctx, project.ID)
if err != nil {
t.Fatalf("unexpected err: %v", err)
}
if diff := cmp.Diff(project, p); diff != "" {
t.Fatalf("projects mismatch (-expected +got):\n%s", diff)
}
}

0 comments on commit 5fa27c8

Please sign in to comment.