mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2025-01-03 14:18:42 +00:00
Set correct link for commit (#3368)
Closes https://github.com/woodpecker-ci/woodpecker/issues/2657 Closes https://github.com/woodpecker-ci/woodpecker/issues/906
This commit is contained in:
parent
894ab51215
commit
e1521ef460
16 changed files with 92 additions and 46 deletions
|
@ -27,6 +27,7 @@ import (
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
"go.woodpecker-ci.org/woodpecker/v2/server"
|
"go.woodpecker-ci.org/woodpecker/v2/server"
|
||||||
|
"go.woodpecker-ci.org/woodpecker/v2/server/forge"
|
||||||
"go.woodpecker-ci.org/woodpecker/v2/server/forge/types"
|
"go.woodpecker-ci.org/woodpecker/v2/server/forge/types"
|
||||||
"go.woodpecker-ci.org/woodpecker/v2/server/model"
|
"go.woodpecker-ci.org/woodpecker/v2/server/model"
|
||||||
"go.woodpecker-ci.org/woodpecker/v2/server/pipeline"
|
"go.woodpecker-ci.org/woodpecker/v2/server/pipeline"
|
||||||
|
@ -103,13 +104,13 @@ func BlockTilQueueHasRunningItem(c *gin.Context) {
|
||||||
// @Param hook body object true "the webhook payload; forge is automatically detected"
|
// @Param hook body object true "the webhook payload; forge is automatically detected"
|
||||||
func PostHook(c *gin.Context) {
|
func PostHook(c *gin.Context) {
|
||||||
_store := store.FromContext(c)
|
_store := store.FromContext(c)
|
||||||
forge := server.Config.Services.Forge
|
_forge := server.Config.Services.Forge
|
||||||
|
|
||||||
//
|
//
|
||||||
// 1. Parse webhook
|
// 1. Parse webhook
|
||||||
//
|
//
|
||||||
|
|
||||||
tmpRepo, tmpPipeline, err := forge.Hook(c, c.Request)
|
tmpRepo, tmpPipeline, err := _forge.Hook(c, c.Request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, &types.ErrIgnoreEvent{}) {
|
if errors.Is(err, &types.ErrIgnoreEvent{}) {
|
||||||
msg := fmt.Sprintf("forge driver: %s", err)
|
msg := fmt.Sprintf("forge driver: %s", err)
|
||||||
|
@ -160,6 +161,13 @@ func PostHook(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user, err := _store.GetUser(repo.UserID)
|
||||||
|
if err != nil {
|
||||||
|
handleDBError(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
forge.Refresh(c, _forge, _store, user)
|
||||||
|
|
||||||
//
|
//
|
||||||
// 3. Check if the webhook is a valid and authorized one
|
// 3. Check if the webhook is a valid and authorized one
|
||||||
//
|
//
|
||||||
|
|
|
@ -61,9 +61,9 @@ func CreatePipeline(c *gin.Context) {
|
||||||
|
|
||||||
lastCommit, _ := server.Config.Services.Forge.BranchHead(c, user, repo, opts.Branch)
|
lastCommit, _ := server.Config.Services.Forge.BranchHead(c, user, repo, opts.Branch)
|
||||||
|
|
||||||
tmpBuild := createTmpPipeline(model.EventManual, lastCommit, repo, user, &opts)
|
tmpPipeline := createTmpPipeline(model.EventManual, lastCommit, user, &opts)
|
||||||
|
|
||||||
pl, err := pipeline.Create(c, _store, repo, tmpBuild)
|
pl, err := pipeline.Create(c, _store, repo, tmpPipeline)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handlePipelineErr(c, err)
|
handlePipelineErr(c, err)
|
||||||
} else {
|
} else {
|
||||||
|
@ -71,10 +71,10 @@ func CreatePipeline(c *gin.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTmpPipeline(event model.WebhookEvent, commitSHA string, repo *model.Repo, user *model.User, opts *model.PipelineOptions) *model.Pipeline {
|
func createTmpPipeline(event model.WebhookEvent, commit *model.Commit, user *model.User, opts *model.PipelineOptions) *model.Pipeline {
|
||||||
return &model.Pipeline{
|
return &model.Pipeline{
|
||||||
Event: event,
|
Event: event,
|
||||||
Commit: commitSHA,
|
Commit: commit.SHA,
|
||||||
Branch: opts.Branch,
|
Branch: opts.Branch,
|
||||||
Timestamp: time.Now().UTC().Unix(),
|
Timestamp: time.Now().UTC().Unix(),
|
||||||
|
|
||||||
|
@ -87,8 +87,7 @@ func createTmpPipeline(event model.WebhookEvent, commitSHA string, repo *model.R
|
||||||
Author: user.Login,
|
Author: user.Login,
|
||||||
Email: user.Email,
|
Email: user.Email,
|
||||||
|
|
||||||
// TODO: Generate proper URL to commit
|
ForgeURL: commit.ForgeURL,
|
||||||
ForgeURL: repo.ForgeURL,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -133,12 +133,12 @@ func CreatePipeline(ctx context.Context, store store.Store, f forge.Forge, cron
|
||||||
|
|
||||||
return repo, &model.Pipeline{
|
return repo, &model.Pipeline{
|
||||||
Event: model.EventCron,
|
Event: model.EventCron,
|
||||||
Commit: commit,
|
Commit: commit.SHA,
|
||||||
Ref: "refs/heads/" + cron.Branch,
|
Ref: "refs/heads/" + cron.Branch,
|
||||||
Branch: cron.Branch,
|
Branch: cron.Branch,
|
||||||
Message: cron.Name,
|
Message: cron.Name,
|
||||||
Timestamp: cron.NextExec,
|
Timestamp: cron.NextExec,
|
||||||
Sender: cron.Name,
|
Sender: cron.Name,
|
||||||
ForgeURL: repo.ForgeURL,
|
ForgeURL: commit.ForgeURL,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,18 +47,22 @@ func TestCreateBuild(t *testing.T) {
|
||||||
// mock things
|
// mock things
|
||||||
store.On("GetRepo", mock.Anything).Return(repo1, nil)
|
store.On("GetRepo", mock.Anything).Return(repo1, nil)
|
||||||
store.On("GetUser", mock.Anything).Return(creator, nil)
|
store.On("GetUser", mock.Anything).Return(creator, nil)
|
||||||
forge.On("BranchHead", mock.Anything, creator, repo1, "default").Return("sha1", nil)
|
forge.On("BranchHead", mock.Anything, creator, repo1, "default").Return(&model.Commit{
|
||||||
|
ForgeURL: "https://example.com/sha1",
|
||||||
|
SHA: "sha1",
|
||||||
|
}, nil)
|
||||||
|
|
||||||
_, pipeline, err := CreatePipeline(ctx, store, forge, &model.Cron{
|
_, pipeline, err := CreatePipeline(ctx, store, forge, &model.Cron{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, &model.Pipeline{
|
assert.EqualValues(t, &model.Pipeline{
|
||||||
Event: "cron",
|
|
||||||
Commit: "sha1",
|
|
||||||
Branch: "default",
|
Branch: "default",
|
||||||
Ref: "refs/heads/default",
|
Commit: "sha1",
|
||||||
|
Event: "cron",
|
||||||
|
ForgeURL: "https://example.com/sha1",
|
||||||
Message: "test",
|
Message: "test",
|
||||||
|
Ref: "refs/heads/default",
|
||||||
Sender: "test",
|
Sender: "test",
|
||||||
}, pipeline)
|
}, pipeline)
|
||||||
}
|
}
|
||||||
|
|
|
@ -363,8 +363,15 @@ func (c *config) Branches(ctx context.Context, u *model.User, r *model.Repo, p *
|
||||||
}
|
}
|
||||||
|
|
||||||
// BranchHead returns the sha of the head (latest commit) of the specified branch
|
// BranchHead returns the sha of the head (latest commit) of the specified branch
|
||||||
func (c *config) BranchHead(ctx context.Context, u *model.User, r *model.Repo, branch string) (string, error) {
|
func (c *config) BranchHead(ctx context.Context, u *model.User, r *model.Repo, branch string) (*model.Commit, error) {
|
||||||
return c.newClient(ctx, u).GetBranchHead(r.Owner, r.Name, branch)
|
commit, err := c.newClient(ctx, u).GetBranchHead(r.Owner, r.Name, branch)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &model.Commit{
|
||||||
|
SHA: commit.Hash,
|
||||||
|
ForgeURL: commit.Links.HTML.Href,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PullRequests returns the pull requests of the named repository.
|
// PullRequests returns the pull requests of the named repository.
|
||||||
|
|
|
@ -184,7 +184,8 @@ func Test_bitbucket(t *testing.T) {
|
||||||
g.It("Should return the details", func() {
|
g.It("Should return the details", func() {
|
||||||
branchHead, err := c.BranchHead(ctx, fakeUser, fakeRepo, "branch_name")
|
branchHead, err := c.BranchHead(ctx, fakeUser, fakeRepo, "branch_name")
|
||||||
g.Assert(err).IsNil()
|
g.Assert(err).IsNil()
|
||||||
g.Assert(branchHead).Equal("branch_head_name")
|
g.Assert(branchHead.SHA).Equal("branch_head_name")
|
||||||
|
g.Assert(branchHead.ForgeURL).Equal("https://bitbucket.org/commitlink")
|
||||||
})
|
})
|
||||||
g.It("Should handle not found errors", func() {
|
g.It("Should handle not found errors", func() {
|
||||||
_, err := c.BranchHead(ctx, fakeUser, fakeRepo, "branch_not_found")
|
_, err := c.BranchHead(ctx, fakeUser, fakeRepo, "branch_not_found")
|
||||||
|
|
|
@ -268,7 +268,12 @@ const branchCommitsPayload = `
|
||||||
{
|
{
|
||||||
"values": [
|
"values": [
|
||||||
{
|
{
|
||||||
"hash": "branch_head_name"
|
"hash": "branch_head_name",
|
||||||
|
"links": {
|
||||||
|
"html": {
|
||||||
|
"href": "https://bitbucket.org/commitlink"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"hash": "random1"
|
"hash": "random1"
|
||||||
|
|
|
@ -198,17 +198,17 @@ func (c *Client) ListBranches(owner, name string, opts *ListOpts) ([]*Branch, er
|
||||||
return out.Values, err
|
return out.Values, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetBranchHead(owner, name, branch string) (string, error) {
|
func (c *Client) GetBranchHead(owner, name, branch string) (*Commit, error) {
|
||||||
out := new(CommitsResp)
|
out := new(CommitsResp)
|
||||||
uri := fmt.Sprintf(pathBranchCommits, c.base, owner, name, branch)
|
uri := fmt.Sprintf(pathBranchCommits, c.base, owner, name, branch)
|
||||||
_, err := c.do(uri, get, nil, out)
|
_, err := c.do(uri, get, nil, out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(out.Values) == 0 {
|
if len(out.Values) == 0 {
|
||||||
return "", fmt.Errorf("no commits in branch %s", branch)
|
return nil, fmt.Errorf("no commits in branch %s", branch)
|
||||||
}
|
}
|
||||||
return out.Values[0].Hash, nil
|
return out.Values[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetUserWorkspaceMembership(workspace, user string) (string, error) {
|
func (c *Client) GetUserWorkspaceMembership(workspace, user string) (string, error) {
|
||||||
|
|
|
@ -283,6 +283,11 @@ type CommitsResp struct {
|
||||||
|
|
||||||
type Commit struct {
|
type Commit struct {
|
||||||
Hash string `json:"hash"`
|
Hash string `json:"hash"`
|
||||||
|
Links struct {
|
||||||
|
HTML struct {
|
||||||
|
Href string `json:"href"`
|
||||||
|
} `json:"html"`
|
||||||
|
} `json:"links"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DirResp struct {
|
type DirResp struct {
|
||||||
|
|
|
@ -78,7 +78,7 @@ type Forge interface {
|
||||||
Branches(ctx context.Context, u *model.User, r *model.Repo, p *model.ListOptions) ([]string, error)
|
Branches(ctx context.Context, u *model.User, r *model.Repo, p *model.ListOptions) ([]string, error)
|
||||||
|
|
||||||
// BranchHead returns the sha of the head (latest commit) of the specified branch
|
// BranchHead returns the sha of the head (latest commit) of the specified branch
|
||||||
BranchHead(ctx context.Context, u *model.User, r *model.Repo, branch string) (string, error)
|
BranchHead(ctx context.Context, u *model.User, r *model.Repo, branch string) (*model.Commit, error)
|
||||||
|
|
||||||
// PullRequests returns all pull requests for the named repository.
|
// PullRequests returns all pull requests for the named repository.
|
||||||
PullRequests(ctx context.Context, u *model.User, r *model.Repo, p *model.ListOptions) ([]*model.PullRequest, error)
|
PullRequests(ctx context.Context, u *model.User, r *model.Repo, p *model.ListOptions) ([]*model.PullRequest, error)
|
||||||
|
|
|
@ -463,18 +463,21 @@ func (c *Gitea) Branches(ctx context.Context, u *model.User, r *model.Repo, p *m
|
||||||
}
|
}
|
||||||
|
|
||||||
// BranchHead returns the sha of the head (latest commit) of the specified branch
|
// BranchHead returns the sha of the head (latest commit) of the specified branch
|
||||||
func (c *Gitea) BranchHead(ctx context.Context, u *model.User, r *model.Repo, branch string) (string, error) {
|
func (c *Gitea) BranchHead(ctx context.Context, u *model.User, r *model.Repo, branch string) (*model.Commit, error) {
|
||||||
token := common.UserToken(ctx, r, u)
|
token := common.UserToken(ctx, r, u)
|
||||||
client, err := c.newClientToken(ctx, token)
|
client, err := c.newClientToken(ctx, token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
b, _, err := client.GetRepoBranch(r.Owner, r.Name, branch)
|
b, _, err := client.GetRepoBranch(r.Owner, r.Name, branch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
return b.Commit.ID, nil
|
return &model.Commit{
|
||||||
|
SHA: b.Commit.ID,
|
||||||
|
ForgeURL: b.Commit.URL,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Gitea) PullRequests(ctx context.Context, u *model.User, r *model.Repo, p *model.ListOptions) ([]*model.PullRequest, error) {
|
func (c *Gitea) PullRequests(ctx context.Context, u *model.User, r *model.Repo, p *model.ListOptions) ([]*model.PullRequest, error) {
|
||||||
|
|
|
@ -565,13 +565,16 @@ func (c *client) Branches(ctx context.Context, u *model.User, r *model.Repo, p *
|
||||||
}
|
}
|
||||||
|
|
||||||
// BranchHead returns the sha of the head (latest commit) of the specified branch
|
// BranchHead returns the sha of the head (latest commit) of the specified branch
|
||||||
func (c *client) BranchHead(ctx context.Context, u *model.User, r *model.Repo, branch string) (string, error) {
|
func (c *client) BranchHead(ctx context.Context, u *model.User, r *model.Repo, branch string) (*model.Commit, error) {
|
||||||
token := common.UserToken(ctx, r, u)
|
token := common.UserToken(ctx, r, u)
|
||||||
b, _, err := c.newClientToken(ctx, token).Repositories.GetBranch(ctx, r.Owner, r.Name, branch, 1)
|
b, _, err := c.newClientToken(ctx, token).Repositories.GetBranch(ctx, r.Owner, r.Name, branch, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
return b.GetCommit().GetSHA(), nil
|
return &model.Commit{
|
||||||
|
SHA: b.GetCommit().GetSHA(),
|
||||||
|
ForgeURL: b.GetCommit().GetHTMLURL(),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hook parses the post-commit hook from the Request body
|
// Hook parses the post-commit hook from the Request body
|
||||||
|
|
|
@ -607,24 +607,27 @@ func (g *GitLab) Branches(ctx context.Context, user *model.User, repo *model.Rep
|
||||||
}
|
}
|
||||||
|
|
||||||
// BranchHead returns the sha of the head (latest commit) of the specified branch
|
// BranchHead returns the sha of the head (latest commit) of the specified branch
|
||||||
func (g *GitLab) BranchHead(ctx context.Context, u *model.User, r *model.Repo, branch string) (string, error) {
|
func (g *GitLab) BranchHead(ctx context.Context, u *model.User, r *model.Repo, branch string) (*model.Commit, error) {
|
||||||
token := common.UserToken(ctx, r, u)
|
token := common.UserToken(ctx, r, u)
|
||||||
client, err := newClient(g.url, token, g.SkipVerify)
|
client, err := newClient(g.url, token, g.SkipVerify)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
_repo, err := g.getProject(ctx, client, r.ForgeRemoteID, r.Owner, r.Name)
|
_repo, err := g.getProject(ctx, client, r.ForgeRemoteID, r.Owner, r.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
b, _, err := client.Branches.GetBranch(_repo.ID, branch, gitlab.WithContext(ctx))
|
b, _, err := client.Branches.GetBranch(_repo.ID, branch, gitlab.WithContext(ctx))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.Commit.ID, nil
|
return &model.Commit{
|
||||||
|
SHA: b.Commit.ID,
|
||||||
|
ForgeURL: b.Commit.WebURL,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hook parses the post-commit hook from the Request body
|
// Hook parses the post-commit hook from the Request body
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Code generated by mockery v2.40.1. DO NOT EDIT.
|
// Code generated by mockery v2.40.3. DO NOT EDIT.
|
||||||
|
|
||||||
package mocks
|
package mocks
|
||||||
|
|
||||||
|
@ -66,22 +66,24 @@ func (_m *Forge) Auth(ctx context.Context, token string, secret string) (string,
|
||||||
}
|
}
|
||||||
|
|
||||||
// BranchHead provides a mock function with given fields: ctx, u, r, branch
|
// BranchHead provides a mock function with given fields: ctx, u, r, branch
|
||||||
func (_m *Forge) BranchHead(ctx context.Context, u *model.User, r *model.Repo, branch string) (string, error) {
|
func (_m *Forge) BranchHead(ctx context.Context, u *model.User, r *model.Repo, branch string) (*model.Commit, error) {
|
||||||
ret := _m.Called(ctx, u, r, branch)
|
ret := _m.Called(ctx, u, r, branch)
|
||||||
|
|
||||||
if len(ret) == 0 {
|
if len(ret) == 0 {
|
||||||
panic("no return value specified for BranchHead")
|
panic("no return value specified for BranchHead")
|
||||||
}
|
}
|
||||||
|
|
||||||
var r0 string
|
var r0 *model.Commit
|
||||||
var r1 error
|
var r1 error
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, *model.User, *model.Repo, string) (string, error)); ok {
|
if rf, ok := ret.Get(0).(func(context.Context, *model.User, *model.Repo, string) (*model.Commit, error)); ok {
|
||||||
return rf(ctx, u, r, branch)
|
return rf(ctx, u, r, branch)
|
||||||
}
|
}
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, *model.User, *model.Repo, string) string); ok {
|
if rf, ok := ret.Get(0).(func(context.Context, *model.User, *model.Repo, string) *model.Commit); ok {
|
||||||
r0 = rf(ctx, u, r, branch)
|
r0 = rf(ctx, u, r, branch)
|
||||||
} else {
|
} else {
|
||||||
r0 = ret.Get(0).(string)
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*model.Commit)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if rf, ok := ret.Get(1).(func(context.Context, *model.User, *model.Repo, string) error); ok {
|
if rf, ok := ret.Get(1).(func(context.Context, *model.User, *model.Repo, string) error); ok {
|
||||||
|
|
6
server/model/commit.go
Normal file
6
server/model/commit.go
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
package model
|
||||||
|
|
||||||
|
type Commit struct {
|
||||||
|
SHA string
|
||||||
|
ForgeURL string
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// Code generated by mockery v2.40.1. DO NOT EDIT.
|
// Code generated by mockery v2.40.3. DO NOT EDIT.
|
||||||
|
|
||||||
package mocks
|
package mocks
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue