From d35f5158bcfd9c111fae69f6eb590665f647070c Mon Sep 17 00:00:00 2001 From: Anbraten Date: Wed, 27 Oct 2021 02:47:55 +0200 Subject: [PATCH] Add repo branches endpoint (#481) * add repo branches endpoint * add branches func to remotes --- server/api/repo.go | 14 +++++++++++ server/remote/bitbucket/bitbucket.go | 6 +++++ .../remote/bitbucketserver/bitbucketserver.go | 6 +++++ server/remote/coding/coding.go | 6 +++++ server/remote/gitea/gitea.go | 19 +++++++++++++++ server/remote/github/github.go | 16 +++++++++++++ server/remote/gitlab/gitlab.go | 24 +++++++++++++++++++ server/remote/gogs/gogs.go | 6 +++++ server/remote/mocks/remote.go | 23 ++++++++++++++++++ server/remote/remote.go | 3 +++ server/router/api.go | 2 ++ 11 files changed, 125 insertions(+) diff --git a/server/api/repo.go b/server/api/repo.go index fcc823f9b..158627d75 100644 --- a/server/api/repo.go +++ b/server/api/repo.go @@ -170,6 +170,20 @@ func GetRepoPermissions(c *gin.Context) { c.JSON(http.StatusOK, perm) } +func GetRepoBranches(c *gin.Context) { + repo := session.Repo(c) + user := session.User(c) + r := remote.FromContext(c) + + branches, err := r.Branches(c, user, repo) + if err != nil { + c.AbortWithError(http.StatusInternalServerError, err) + return + } + + c.JSON(http.StatusOK, branches) +} + func DeleteRepo(c *gin.Context) { remove, _ := strconv.ParseBool(c.Query("remove")) r := remote.FromContext(c) diff --git a/server/remote/bitbucket/bitbucket.go b/server/remote/bitbucket/bitbucket.go index 42df8ec2c..f3886cb7a 100644 --- a/server/remote/bitbucket/bitbucket.go +++ b/server/remote/bitbucket/bitbucket.go @@ -275,6 +275,12 @@ func (c *config) Netrc(u *model.User, r *model.Repo) (*model.Netrc, error) { }, nil } +// Branches returns the names of all branches for the named repository. +func (c *config) Branches(ctx context.Context, u *model.User, r *model.Repo) ([]string, error) { + // TODO: fetch all branches + return []string{r.Branch}, nil +} + // Hook parses the incoming Bitbucket hook and returns the Repository and // Build details. If the hook is unsupported nil values are returned. func (c *config) Hook(req *http.Request) (*model.Repo, *model.Build, error) { diff --git a/server/remote/bitbucketserver/bitbucketserver.go b/server/remote/bitbucketserver/bitbucketserver.go index be0691f41..6f5466b75 100644 --- a/server/remote/bitbucketserver/bitbucketserver.go +++ b/server/remote/bitbucketserver/bitbucketserver.go @@ -225,6 +225,12 @@ func (c *Config) Activate(ctx context.Context, u *model.User, r *model.Repo, lin return client.CreateHook(r.Owner, r.Name, link) } +// Branches returns the names of all branches for the named repository. +func (c *Config) Branches(ctx context.Context, u *model.User, r *model.Repo) ([]string, error) { + // TODO: fetch all branches + return []string{r.Branch}, nil +} + func (c *Config) Deactivate(ctx context.Context, u *model.User, r *model.Repo, link string) error { client := internal.NewClientWithToken(ctx, c.URL, c.Consumer, u.Token) return client.DeleteHook(r.Owner, r.Name, link) diff --git a/server/remote/coding/coding.go b/server/remote/coding/coding.go index 19c143b81..6b92d7343 100644 --- a/server/remote/coding/coding.go +++ b/server/remote/coding/coding.go @@ -276,6 +276,12 @@ func (c *Coding) Deactivate(ctx context.Context, u *model.User, r *model.Repo, l return c.newClient(ctx, u).RemoveWebhook(r.Owner, r.Name, link) } +// Branches returns the names of all branches for the named repository. +func (c *Coding) Branches(ctx context.Context, u *model.User, r *model.Repo) ([]string, error) { + // TODO: fetch all branches + return []string{r.Branch}, nil +} + // Hook parses the post-commit hook from the Request body and returns the // required data in a standard format. func (c *Coding) Hook(r *http.Request) (*model.Repo, *model.Build, error) { diff --git a/server/remote/gitea/gitea.go b/server/remote/gitea/gitea.go index 31b81728a..0d7bded2f 100644 --- a/server/remote/gitea/gitea.go +++ b/server/remote/gitea/gitea.go @@ -424,6 +424,25 @@ func (c *Gitea) Deactivate(ctx context.Context, u *model.User, r *model.Repo, li return nil } +// Branches returns the names of all branches for the named repository. +func (c *Gitea) Branches(ctx context.Context, u *model.User, r *model.Repo) ([]string, error) { + client, err := c.newClientToken(ctx, u.Token) + if err != nil { + return nil, err + } + + giteaBranches, _, err := client.ListRepoBranches(r.Owner, r.Name, gitea.ListRepoBranchesOptions{}) + if err != nil { + return nil, err + } + + branches := make([]string, 0) + for _, branch := range giteaBranches { + branches = append(branches, branch.Name) + } + return branches, nil +} + // Hook parses the incoming Gitea hook and returns the Repository and Build // details. If the hook is unsupported nil values are returned. func (c *Gitea) Hook(r *http.Request) (*model.Repo, *model.Build, error) { diff --git a/server/remote/github/github.go b/server/remote/github/github.go index 25ed77900..5ebf73448 100644 --- a/server/remote/github/github.go +++ b/server/remote/github/github.go @@ -505,6 +505,22 @@ func (c *client) Activate(ctx context.Context, u *model.User, r *model.Repo, lin return err } +// Branches returns the names of all branches for the named repository. +func (c *client) Branches(ctx context.Context, u *model.User, r *model.Repo) ([]string, error) { + client := c.newClientToken(ctx, u.Token) + + githubBranches, _, err := client.Repositories.ListBranches(ctx, r.Owner, r.Name, &github.BranchListOptions{}) + if err != nil { + return nil, err + } + + branches := make([]string, 0) + for _, branch := range githubBranches { + branches = append(branches, *branch.Name) + } + return branches, nil +} + // Hook parses the post-commit hook from the Request body // and returns the required data in a standard format. func (c *client) Hook(r *http.Request) (*model.Repo, *model.Build, error) { diff --git a/server/remote/gitlab/gitlab.go b/server/remote/gitlab/gitlab.go index 109f23f66..1ffb800e5 100644 --- a/server/remote/gitlab/gitlab.go +++ b/server/remote/gitlab/gitlab.go @@ -434,6 +434,30 @@ func (g *Gitlab) Deactivate(ctx context.Context, user *model.User, repo *model.R return err } +// Branches returns the names of all branches for the named repository. +func (g *Gitlab) Branches(ctx context.Context, user *model.User, repo *model.Repo) ([]string, error) { + client, err := newClient(g.URL, user.Token, g.SkipVerify) + if err != nil { + return nil, err + } + + repo_, err := g.getProject(ctx, client, repo.Owner, repo.Name) + if err != nil { + return nil, err + } + + gitlabBranches, _, err := client.Branches.ListBranches(repo_.ID, &gitlab.ListBranchesOptions{}, gitlab.WithContext(ctx)) + if err != nil { + return nil, err + } + + branches := make([]string, 0) + for _, branch := range gitlabBranches { + branches = append(branches, branch.Name) + } + return branches, nil +} + // Hook parses the post-commit hook from the Request body // and returns the required data in a standard format. func (g *Gitlab) Hook(req *http.Request) (*model.Repo, *model.Build, error) { diff --git a/server/remote/gogs/gogs.go b/server/remote/gogs/gogs.go index 1df26de62..2608ed708 100644 --- a/server/remote/gogs/gogs.go +++ b/server/remote/gogs/gogs.go @@ -256,6 +256,12 @@ func (c *client) Deactivate(ctx context.Context, u *model.User, r *model.Repo, l return nil } +// Branches returns the names of all branches for the named repository. +func (c *client) Branches(ctx context.Context, u *model.User, r *model.Repo) ([]string, error) { + // TODO: fetch all branches + return []string{r.Branch}, nil +} + // Hook parses the incoming Gogs hook and returns the Repository and Build // details. If the hook is unsupported nil values are returned. func (c *client) Hook(r *http.Request) (*model.Repo, *model.Build, error) { diff --git a/server/remote/mocks/remote.go b/server/remote/mocks/remote.go index 4329443b7..061f13321 100644 --- a/server/remote/mocks/remote.go +++ b/server/remote/mocks/remote.go @@ -52,6 +52,29 @@ func (_m *Remote) Auth(ctx context.Context, token string, secret string) (string return r0, r1 } +// Branches provides a mock function with given fields: ctx, u, r +func (_m *Remote) Branches(ctx context.Context, u *model.User, r *model.Repo) ([]string, error) { + ret := _m.Called(ctx, u, r) + + var r0 []string + if rf, ok := ret.Get(0).(func(context.Context, *model.User, *model.Repo) []string); ok { + r0 = rf(ctx, u, r) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]string) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *model.User, *model.Repo) error); ok { + r1 = rf(ctx, u, r) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // Deactivate provides a mock function with given fields: ctx, u, r, link func (_m *Remote) Deactivate(ctx context.Context, u *model.User, r *model.Repo, link string) error { ret := _m.Called(ctx, u, r, link) diff --git a/server/remote/remote.go b/server/remote/remote.go index b3dc06b72..020290d30 100644 --- a/server/remote/remote.go +++ b/server/remote/remote.go @@ -70,6 +70,9 @@ type Remote interface { // post-commit hooks matching the given link. Deactivate(ctx context.Context, u *model.User, r *model.Repo, link string) error + // Branches returns the names of all branches for the named repository. + Branches(ctx context.Context, u *model.User, r *model.Repo) ([]string, error) + // Hook parses the post-commit hook from the Request body and returns the // required data in a standard format. Hook(r *http.Request) (*model.Repo, *model.Build, error) diff --git a/server/router/api.go b/server/router/api.go index 99ead7d30..e88c0a551 100644 --- a/server/router/api.go +++ b/server/router/api.go @@ -57,6 +57,8 @@ func apiRoutes(e *gin.Engine) { repo.POST("", session.MustRepoAdmin(), api.PostRepo) repo.GET("", api.GetRepo) + repo.GET("/branches", api.GetRepoBranches) + repo.GET("/builds", api.GetBuilds) repo.GET("/builds/:number", api.GetBuild)