From 08ea952e47834510857f2a7d57f9c6b73e70611f Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sun, 11 Feb 2024 08:17:47 +0100 Subject: [PATCH 1/9] Refresh token on hook --- server/api/hook.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/server/api/hook.go b/server/api/hook.go index 91abc39714..5c92ccbbeb 100644 --- a/server/api/hook.go +++ b/server/api/hook.go @@ -27,6 +27,7 @@ import ( "github.com/rs/zerolog/log" "go.woodpecker-ci.org/woodpecker/v2/server" + forge2 "go.woodpecker-ci.org/woodpecker/v2/server/forge" "go.woodpecker-ci.org/woodpecker/v2/server/forge/types" "go.woodpecker-ci.org/woodpecker/v2/server/model" "go.woodpecker-ci.org/woodpecker/v2/server/pipeline" @@ -160,6 +161,13 @@ func PostHook(c *gin.Context) { return } + user, err := _store.GetUser(repo.UserID) + if err != nil { + handleDBError(c, err) + return + } + forge2.Refresh(c, forge, _store, user) + // // 3. Check if the webhook is a valid and authorized one // From fb5759a9513100c9e643207fde6f17c31c674c2c Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sun, 11 Feb 2024 08:32:21 +0100 Subject: [PATCH 2/9] correct link --- server/api/pipeline.go | 11 +++++------ server/cron/cron.go | 4 ++-- server/forge/bitbucket/bitbucket.go | 11 +++++++++-- server/forge/bitbucket/internal/client.go | 8 ++++---- server/forge/bitbucket/internal/types.go | 7 ++++++- server/forge/forge.go | 2 +- server/forge/gitea/gitea.go | 11 +++++++---- server/forge/github/github.go | 9 ++++++--- server/forge/gitlab/gitlab.go | 13 ++++++++----- server/model/commit.go | 6 ++++++ 10 files changed, 54 insertions(+), 28 deletions(-) create mode 100644 server/model/commit.go diff --git a/server/api/pipeline.go b/server/api/pipeline.go index b5ed9a11b1..a190f54d5c 100644 --- a/server/api/pipeline.go +++ b/server/api/pipeline.go @@ -61,9 +61,9 @@ func CreatePipeline(c *gin.Context) { lastCommit, _ := server.Config.Services.Forge.BranchHead(c, user, repo, opts.Branch) - tmpBuild := createTmpPipeline(model.EventManual, lastCommit, repo, user, &opts) + tmpPipeline := createTmpPipeline(model.EventManual, lastCommit, repo, user, &opts) - pl, err := pipeline.Create(c, _store, repo, tmpBuild) + pl, err := pipeline.Create(c, _store, repo, tmpPipeline) if err != nil { handlePipelineErr(c, err) } 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, repo *model.Repo, user *model.User, opts *model.PipelineOptions) *model.Pipeline { return &model.Pipeline{ Event: event, - Commit: commitSHA, + Commit: commit.SHA, Branch: opts.Branch, Timestamp: time.Now().UTC().Unix(), @@ -87,8 +87,7 @@ func createTmpPipeline(event model.WebhookEvent, commitSHA string, repo *model.R Author: user.Login, Email: user.Email, - // TODO: Generate proper URL to commit - ForgeURL: repo.ForgeURL, + ForgeURL: commit.ForgeURL, } } diff --git a/server/cron/cron.go b/server/cron/cron.go index ac3ae33bf7..bce8374d52 100644 --- a/server/cron/cron.go +++ b/server/cron/cron.go @@ -133,12 +133,12 @@ func CreatePipeline(ctx context.Context, store store.Store, f forge.Forge, cron return repo, &model.Pipeline{ Event: model.EventCron, - Commit: commit, + Commit: commit.SHA, Ref: "refs/heads/" + cron.Branch, Branch: cron.Branch, Message: cron.Name, Timestamp: cron.NextExec, Sender: cron.Name, - ForgeURL: repo.ForgeURL, + ForgeURL: commit.ForgeURL, }, nil } diff --git a/server/forge/bitbucket/bitbucket.go b/server/forge/bitbucket/bitbucket.go index 9247de60cb..13b0d43e52 100644 --- a/server/forge/bitbucket/bitbucket.go +++ b/server/forge/bitbucket/bitbucket.go @@ -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 -func (c *config) BranchHead(ctx context.Context, u *model.User, r *model.Repo, branch string) (string, error) { - return c.newClient(ctx, u).GetBranchHead(r.Owner, r.Name, branch) +func (c *config) BranchHead(ctx context.Context, u *model.User, r *model.Repo, branch string) (*model.Commit, error) { + 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. diff --git a/server/forge/bitbucket/internal/client.go b/server/forge/bitbucket/internal/client.go index c7ca81b010..779029ca9c 100644 --- a/server/forge/bitbucket/internal/client.go +++ b/server/forge/bitbucket/internal/client.go @@ -198,17 +198,17 @@ func (c *Client) ListBranches(owner, name string, opts *ListOpts) ([]*Branch, er 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) uri := fmt.Sprintf(pathBranchCommits, c.base, owner, name, branch) _, err := c.do(uri, get, nil, out) if err != nil { - return "", err + return nil, err } 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) { diff --git a/server/forge/bitbucket/internal/types.go b/server/forge/bitbucket/internal/types.go index fa3376a74d..e9d7ecc87b 100644 --- a/server/forge/bitbucket/internal/types.go +++ b/server/forge/bitbucket/internal/types.go @@ -282,7 +282,12 @@ type CommitsResp 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 { diff --git a/server/forge/forge.go b/server/forge/forge.go index a9f163bb55..a6fb65e3b6 100644 --- a/server/forge/forge.go +++ b/server/forge/forge.go @@ -78,7 +78,7 @@ type Forge interface { 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(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(ctx context.Context, u *model.User, r *model.Repo, p *model.ListOptions) ([]*model.PullRequest, error) diff --git a/server/forge/gitea/gitea.go b/server/forge/gitea/gitea.go index 30673e4d31..f378e97838 100644 --- a/server/forge/gitea/gitea.go +++ b/server/forge/gitea/gitea.go @@ -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 -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) client, err := c.newClientToken(ctx, token) if err != nil { - return "", err + return nil, err } b, _, err := client.GetRepoBranch(r.Owner, r.Name, branch) 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) { diff --git a/server/forge/github/github.go b/server/forge/github/github.go index fb89a74484..a05e6b3ab9 100644 --- a/server/forge/github/github.go +++ b/server/forge/github/github.go @@ -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 -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) b, _, err := c.newClientToken(ctx, token).Repositories.GetBranch(ctx, r.Owner, r.Name, branch, 1) 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 diff --git a/server/forge/gitlab/gitlab.go b/server/forge/gitlab/gitlab.go index eb13aedce8..8a59c08b1f 100644 --- a/server/forge/gitlab/gitlab.go +++ b/server/forge/gitlab/gitlab.go @@ -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 -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) client, err := newClient(g.url, token, g.SkipVerify) if err != nil { - return "", err + return nil, err } _repo, err := g.getProject(ctx, client, r.ForgeRemoteID, r.Owner, r.Name) if err != nil { - return "", err + return nil, err } b, _, err := client.Branches.GetBranch(_repo.ID, branch, gitlab.WithContext(ctx)) 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 diff --git a/server/model/commit.go b/server/model/commit.go new file mode 100644 index 0000000000..2de74fc44b --- /dev/null +++ b/server/model/commit.go @@ -0,0 +1,6 @@ +package model + +type Commit struct { + SHA string + ForgeURL string +} From 545b5405a74a654752775d283988bdae19754cbf Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sun, 11 Feb 2024 09:20:02 +0100 Subject: [PATCH 3/9] rename vars --- server/api/hook.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/api/hook.go b/server/api/hook.go index 5c92ccbbeb..4318ae480a 100644 --- a/server/api/hook.go +++ b/server/api/hook.go @@ -27,7 +27,7 @@ import ( "github.com/rs/zerolog/log" "go.woodpecker-ci.org/woodpecker/v2/server" - forge2 "go.woodpecker-ci.org/woodpecker/v2/server/forge" + "go.woodpecker-ci.org/woodpecker/v2/server/forge" "go.woodpecker-ci.org/woodpecker/v2/server/forge/types" "go.woodpecker-ci.org/woodpecker/v2/server/model" "go.woodpecker-ci.org/woodpecker/v2/server/pipeline" @@ -104,13 +104,13 @@ func BlockTilQueueHasRunningItem(c *gin.Context) { // @Param hook body object true "the webhook payload; forge is automatically detected" func PostHook(c *gin.Context) { _store := store.FromContext(c) - forge := server.Config.Services.Forge + _forge := server.Config.Services.Forge // // 1. Parse webhook // - tmpRepo, tmpPipeline, err := forge.Hook(c, c.Request) + tmpRepo, tmpPipeline, err := _forge.Hook(c, c.Request) if err != nil { if errors.Is(err, &types.ErrIgnoreEvent{}) { msg := fmt.Sprintf("forge driver: %s", err) @@ -166,7 +166,7 @@ func PostHook(c *gin.Context) { handleDBError(c, err) return } - forge2.Refresh(c, forge, _store, user) + forge.Refresh(c, _forge, _store, user) // // 3. Check if the webhook is a valid and authorized one From 45f1fa95a1f83d324a836fdecc60f54885e25912 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sun, 11 Feb 2024 09:59:59 +0100 Subject: [PATCH 4/9] generate --- server/forge/mocks/forge.go | 14 ++++++++------ server/store/mocks/store.go | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/server/forge/mocks/forge.go b/server/forge/mocks/forge.go index 6fe891fd81..5d46271307 100644 --- a/server/forge/mocks/forge.go +++ b/server/forge/mocks/forge.go @@ -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 @@ -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 -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) if len(ret) == 0 { panic("no return value specified for BranchHead") } - var r0 string + var r0 *model.Commit 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) } - 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) } 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 { diff --git a/server/store/mocks/store.go b/server/store/mocks/store.go index f4c60c593d..aa33159251 100644 --- a/server/store/mocks/store.go +++ b/server/store/mocks/store.go @@ -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 From ec17c0e13702efd87b3520e19785c5751938f88d Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sun, 11 Feb 2024 10:03:17 +0100 Subject: [PATCH 5/9] update id --- pipeline/frontend/yaml/linter/schema/schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pipeline/frontend/yaml/linter/schema/schema.json b/pipeline/frontend/yaml/linter/schema/schema.json index a6315710b8..41d69de627 100644 --- a/pipeline/frontend/yaml/linter/schema/schema.json +++ b/pipeline/frontend/yaml/linter/schema/schema.json @@ -1,7 +1,7 @@ { "title": "Woodpecker CI configuration file", "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://woodpecker-ci.org/schema/woodpecker.json", + "$id": "https://raw.githubusercontent.com/woodpecker-ci/woodpecker/main/pipeline/frontend/yaml/linter/schema/schema.json", "description": "Schema of a Woodpecker pipeline file. Read more: https://woodpecker-ci.org/docs/usage/workflow-syntax", "type": "object", "required": ["steps"], From 6b4b314ee9c92f9491127176a6df6fb86959d5de Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sun, 11 Feb 2024 10:03:36 +0100 Subject: [PATCH 6/9] Revert "update id" This reverts commit ec17c0e13702efd87b3520e19785c5751938f88d. --- pipeline/frontend/yaml/linter/schema/schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pipeline/frontend/yaml/linter/schema/schema.json b/pipeline/frontend/yaml/linter/schema/schema.json index 41d69de627..a6315710b8 100644 --- a/pipeline/frontend/yaml/linter/schema/schema.json +++ b/pipeline/frontend/yaml/linter/schema/schema.json @@ -1,7 +1,7 @@ { "title": "Woodpecker CI configuration file", "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://raw.githubusercontent.com/woodpecker-ci/woodpecker/main/pipeline/frontend/yaml/linter/schema/schema.json", + "$id": "https://woodpecker-ci.org/schema/woodpecker.json", "description": "Schema of a Woodpecker pipeline file. Read more: https://woodpecker-ci.org/docs/usage/workflow-syntax", "type": "object", "required": ["steps"], From f0a1b326a8da0f2666c20e91705cb6f8c2482686 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sun, 11 Feb 2024 10:15:29 +0100 Subject: [PATCH 7/9] fix lint --- server/api/pipeline.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/api/pipeline.go b/server/api/pipeline.go index a190f54d5c..5fbfaa09b3 100644 --- a/server/api/pipeline.go +++ b/server/api/pipeline.go @@ -61,7 +61,7 @@ func CreatePipeline(c *gin.Context) { lastCommit, _ := server.Config.Services.Forge.BranchHead(c, user, repo, opts.Branch) - tmpPipeline := createTmpPipeline(model.EventManual, lastCommit, repo, user, &opts) + tmpPipeline := createTmpPipeline(model.EventManual, lastCommit, user, &opts) pl, err := pipeline.Create(c, _store, repo, tmpPipeline) if err != nil { @@ -71,7 +71,7 @@ func CreatePipeline(c *gin.Context) { } } -func createTmpPipeline(event model.WebhookEvent, commit *model.Commit, 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{ Event: event, Commit: commit.SHA, From 77f338eb550bf41e19934eb8c74c49290f87d4ee Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sun, 11 Feb 2024 10:22:14 +0100 Subject: [PATCH 8/9] fix tests --- server/cron/cron_test.go | 6 +++++- server/forge/bitbucket/bitbucket_test.go | 3 ++- server/forge/bitbucket/fixtures/handler.go | 7 ++++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/server/cron/cron_test.go b/server/cron/cron_test.go index 450831bdb9..8f96a44b21 100644 --- a/server/cron/cron_test.go +++ b/server/cron/cron_test.go @@ -47,7 +47,10 @@ func TestCreateBuild(t *testing.T) { // mock things store.On("GetRepo", mock.Anything).Return(repo1, 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{ + SHA: "sha1", + ForgeURL: "https://example.com/sha1", + }, nil) _, pipeline, err := CreatePipeline(ctx, store, forge, &model.Cron{ Name: "test", @@ -60,6 +63,7 @@ func TestCreateBuild(t *testing.T) { Ref: "refs/heads/default", Message: "test", Sender: "test", + ForgeURL: "https://example.com/sha1", }, pipeline) } diff --git a/server/forge/bitbucket/bitbucket_test.go b/server/forge/bitbucket/bitbucket_test.go index 2afde47894..8488cc6aa2 100644 --- a/server/forge/bitbucket/bitbucket_test.go +++ b/server/forge/bitbucket/bitbucket_test.go @@ -184,7 +184,8 @@ func Test_bitbucket(t *testing.T) { g.It("Should return the details", func() { branchHead, err := c.BranchHead(ctx, fakeUser, fakeRepo, "branch_name") 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() { _, err := c.BranchHead(ctx, fakeUser, fakeRepo, "branch_not_found") diff --git a/server/forge/bitbucket/fixtures/handler.go b/server/forge/bitbucket/fixtures/handler.go index dd586fd12e..a2a42d8aa5 100644 --- a/server/forge/bitbucket/fixtures/handler.go +++ b/server/forge/bitbucket/fixtures/handler.go @@ -268,7 +268,12 @@ const branchCommitsPayload = ` { "values": [ { - "hash": "branch_head_name" + "hash": "branch_head_name", + "links": { + "html": { + "href": "https://bitbucket.org/commitlink" + } + } }, { "hash": "random1" From 4b8224587b0ee8e5f9cff246cae365ed4eab8467 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sun, 11 Feb 2024 10:33:30 +0100 Subject: [PATCH 9/9] fix lint --- server/cron/cron_test.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/server/cron/cron_test.go b/server/cron/cron_test.go index 8f96a44b21..0b170cfe98 100644 --- a/server/cron/cron_test.go +++ b/server/cron/cron_test.go @@ -48,8 +48,8 @@ func TestCreateBuild(t *testing.T) { store.On("GetRepo", mock.Anything).Return(repo1, nil) store.On("GetUser", mock.Anything).Return(creator, nil) forge.On("BranchHead", mock.Anything, creator, repo1, "default").Return(&model.Commit{ - SHA: "sha1", ForgeURL: "https://example.com/sha1", + SHA: "sha1", }, nil) _, pipeline, err := CreatePipeline(ctx, store, forge, &model.Cron{ @@ -57,13 +57,13 @@ func TestCreateBuild(t *testing.T) { }) assert.NoError(t, err) assert.EqualValues(t, &model.Pipeline{ - Event: "cron", - Commit: "sha1", - Branch: "default", - Ref: "refs/heads/default", - Message: "test", - Sender: "test", + Branch: "default", + Commit: "sha1", + Event: "cron", ForgeURL: "https://example.com/sha1", + Message: "test", + Ref: "refs/heads/default", + Sender: "test", }, pipeline) }