Reload repo on hook (#5324)

This commit is contained in:
qwerty287 2025-07-18 16:37:51 +03:00 committed by GitHub
parent 8fc936356c
commit 5a33134814
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 197 additions and 12 deletions

View file

@ -398,8 +398,23 @@ func (c *config) PullRequests(ctx context.Context, u *model.User, r *model.Repo,
// Hook parses the incoming Bitbucket hook and returns the Repository and
// Pipeline details. If the hook is unsupported nil values are returned.
func (c *config) Hook(_ context.Context, req *http.Request) (*model.Repo, *model.Pipeline, error) {
return parseHook(req)
func (c *config) Hook(ctx context.Context, req *http.Request) (*model.Repo, *model.Pipeline, error) {
repo, pl, err := parseHook(req)
if err != nil {
return nil, nil, err
}
u, err := common.RepoUserForgeID(ctx, repo.ForgeRemoteID)
if err != nil {
return nil, nil, err
}
repo, err = c.Repo(ctx, u, repo.ForgeRemoteID, repo.Owner, repo.Name)
if err != nil {
return nil, nil, err
}
return repo, pl, nil
}
// OrgMembership returns if user is member of organization and if user

View file

@ -23,11 +23,14 @@ import (
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"go.woodpecker-ci.org/woodpecker/v3/server/forge/bitbucket/fixtures"
"go.woodpecker-ci.org/woodpecker/v3/server/forge/bitbucket/internal"
"go.woodpecker-ci.org/woodpecker/v3/server/forge/types"
"go.woodpecker-ci.org/woodpecker/v3/server/model"
"go.woodpecker-ci.org/woodpecker/v3/server/store"
mocks_store "go.woodpecker-ci.org/woodpecker/v3/server/store/mocks"
)
func TestNew(t *testing.T) {
@ -203,9 +206,15 @@ func TestBitbucket(t *testing.T) {
req.Header = http.Header{}
req.Header.Set(hookEvent, hookPush)
mockStore := mocks_store.NewStore(t)
ctx = store.InjectToContext(ctx, mockStore)
mockStore.On("GetUser", mock.Anything).Return(fakeUser, nil)
mockStore.On("GetRepoForgeID", mock.Anything).Return(fakeRepoFromHook, nil)
r, b, err := c.Hook(ctx, req)
assert.NoError(t, err)
assert.Equal(t, "martinherren1984/publictestrepo", r.FullName)
assert.Equal(t, "master", r.Branch)
assert.Equal(t, "c14c1bb05dfb1fdcdf06b31485fff61b0ea44277", b.Commit)
}
@ -269,6 +278,13 @@ var (
FullName: "test_name/hook_empty",
}
fakeRepoFromHook = &model.Repo{
Owner: "martinherren1984",
Name: "publictestrepo",
FullName: "martinherren1984/publictestrepo",
UserID: 1,
}
fakePipeline = &model.Pipeline{
Commit: "9ecad50",
}

View file

@ -90,6 +90,8 @@ func getRepo(c *gin.Context) {
c.String(http.StatusNotFound, "")
case "permission_read", "permission_write", "permission_admin":
c.String(http.StatusOK, fmt.Sprintf(permissionRepoPayload, c.Param("name")))
case "{898477b2-a080-4089-b385-597a783db392}":
c.String(http.StatusOK, repoPayloadFromHook)
default:
c.String(http.StatusOK, repoPayload)
}
@ -227,6 +229,137 @@ const permissionRepoPayload = `
}
`
const repoPayloadFromHook = `
{
"type": "repository",
"full_name": "martinherren1984/publictestrepo",
"links": {
"self": {
"href": "https://api.bitbucket.org/2.0/repositories/martinherren1984/publictestrepo"
},
"html": {
"href": "https://bitbucket.org/martinherren1984/publictestrepo"
},
"avatar": {
"href": "https://bytebucket.org/ravatar/%7B898477b2-a080-4089-b385-597a783db392%7D?ts=default"
},
"pullrequests": {
"href": "https://api.bitbucket.org/2.0/repositories/martinherren1984/publictestrepo/pullrequests"
},
"commits": {
"href": "https://api.bitbucket.org/2.0/repositories/martinherren1984/publictestrepo/commits"
},
"forks": {
"href": "https://api.bitbucket.org/2.0/repositories/martinherren1984/publictestrepo/forks"
},
"watchers": {
"href": "https://api.bitbucket.org/2.0/repositories/martinherren1984/publictestrepo/watchers"
},
"branches": {
"href": "https://api.bitbucket.org/2.0/repositories/martinherren1984/publictestrepo/refs/branches"
},
"tags": {
"href": "https://api.bitbucket.org/2.0/repositories/martinherren1984/publictestrepo/refs/tags"
},
"downloads": {
"href": "https://api.bitbucket.org/2.0/repositories/martinherren1984/publictestrepo/downloads"
},
"source": {
"href": "https://api.bitbucket.org/2.0/repositories/martinherren1984/publictestrepo/src"
},
"clone": [
{
"name": "https",
"href": "https://bitbucket.org/martinherren1984/publictestrepo.git"
},
{
"name": "ssh",
"href": "git@bitbucket.org:martinherren1984/publictestrepo.git"
}
],
"hooks": {
"href": "https://api.bitbucket.org/2.0/repositories/martinherren1984/publictestrepo/hooks"
}
},
"name": "PublicTestRepo",
"slug": "publictestrepo",
"description": "",
"scm": "git",
"website": null,
"owner": {
"display_name": "Martin Herren",
"links": {
"self": {
"href": "https://api.bitbucket.org/2.0/users/%7Bc5a0d676-fd27-4bd4-ac69-a7540d7b495b%7D"
},
"avatar": {
"href": "https://secure.gravatar.com/avatar/37de364488b2ec474b5458ca86442bbb?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FMH-2.png"
},
"html": {
"href": "https://bitbucket.org/%7Bc5a0d676-fd27-4bd4-ac69-a7540d7b495b%7D/"
}
},
"type": "user",
"uuid": "{c5a0d676-fd27-4bd4-ac69-a7540d7b495b}",
"account_id": "5cf8e3a9678ca90f8e7cc8a8",
"nickname": "Martin Herren"
},
"workspace": {
"type": "workspace",
"uuid": "{c5a0d676-fd27-4bd4-ac69-a7540d7b495b}",
"name": "Martin Herren",
"slug": "martinherren1984",
"links": {
"avatar": {
"href": "https://bitbucket.org/workspaces/martinherren1984/avatar/?ts=1658761964"
},
"html": {
"href": "https://bitbucket.org/martinherren1984/"
},
"self": {
"href": "https://api.bitbucket.org/2.0/workspaces/martinherren1984"
}
}
},
"is_private": false,
"project": {
"type": "project",
"key": "PUB",
"uuid": "{2cede481-f59e-49ec-88d0-a85629b7925d}",
"name": "PublicTestProject",
"links": {
"self": {
"href": "https://api.bitbucket.org/2.0/workspaces/martinherren1984/projects/PUB"
},
"html": {
"href": "https://bitbucket.org/martinherren1984/workspace/projects/PUB"
},
"avatar": {
"href": "https://bitbucket.org/martinherren1984/workspace/projects/PUB/avatar/32?ts=1658768453"
}
}
},
"fork_policy": "allow_forks",
"created_on": "2022-07-25T17:01:20.950706+00:00",
"updated_on": "2022-09-07T20:19:30.622886+00:00",
"size": 85955,
"language": "",
"uuid": "{898477b2-a080-4089-b385-597a783db392}",
"mainbranch": {
"name": "master",
"type": "branch"
},
"override_settings": {
"default_merge_strategy": true,
"branching_model": true
},
"parent": null,
"enforced_signed_commits": null,
"has_issues": false,
"has_wiki": false
}
`
const repoHookPayload = `
{
"pagelen": 10,

View file

@ -16,6 +16,7 @@ package common
import (
"context"
"errors"
"net"
"net/url"
"strings"
@ -49,18 +50,38 @@ func UserToken(ctx context.Context, r *model.Repo, u *model.User) string {
return u.AccessToken
}
_store, ok := store.TryFromContext(ctx)
if !ok {
log.Error().Msg("could not get store from context")
return ""
}
if r == nil {
log.Error().Msg("cannot get user token by empty repo")
return ""
}
user, err := _store.GetUser(r.UserID)
user, err := RepoUser(ctx, r)
if err != nil {
log.Error().Err(err).Msg("could not get repo user")
return ""
}
return user.AccessToken
}
func RepoUser(ctx context.Context, r *model.Repo) (*model.User, error) {
_store, ok := store.TryFromContext(ctx)
if !ok {
return nil, errors.New("could not get store from context")
}
if r == nil {
log.Error().Msg("cannot get user token by empty repo")
return nil, errors.New("cannot get user token by empty repo")
}
user, err := _store.GetUser(r.UserID)
if err != nil {
return nil, err
}
return user, nil
}
func RepoUserForgeID(ctx context.Context, repoForgeID model.ForgeRemoteID) (*model.User, error) {
_store, ok := store.TryFromContext(ctx)
if !ok {
return nil, errors.New("could not get store from context")
}
r, err := _store.GetRepoForgeID(repoForgeID)
if err != nil {
return nil, err
}
return RepoUser(ctx, r)
}