mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2026-04-15 01:41:56 +00:00
Support for pull requests opened events from forked repositories (#5536)
Co-authored-by: Robert Kaussow <mail@thegeeklab.de>
This commit is contained in:
@@ -477,40 +477,28 @@ func (c *client) Deactivate(ctx context.Context, u *model.User, r *model.Repo, l
|
||||
}
|
||||
|
||||
func (c *client) Hook(ctx context.Context, r *http.Request) (*model.Repo, *model.Pipeline, error) {
|
||||
ev, payload, err := bb.ParsePayloadWithoutSignature(r)
|
||||
hook, err := parseHook(r, c.url)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to parse payload from webhook invocation: %w", err)
|
||||
return nil, nil, fmt.Errorf("unable to parse hook: %w", err)
|
||||
}
|
||||
|
||||
var repo *model.Repo
|
||||
var pipe *model.Pipeline
|
||||
|
||||
switch e := ev.(type) {
|
||||
case *bb.RepositoryPushEvent:
|
||||
repo = convertRepo(&e.Repository, nil, "")
|
||||
pipe = convertRepositoryPushEvent(e, c.url)
|
||||
case *bb.PullRequestEvent:
|
||||
repo = convertRepo(&e.PullRequest.Source.Repository, nil, "")
|
||||
pipe = convertPullRequestEvent(e, c.url)
|
||||
default:
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
user, repo, err := c.getUserAndRepo(ctx, repo)
|
||||
user, repo, err := c.getUserAndRepo(ctx, hook.Repo)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to get user and repo: %w", err)
|
||||
}
|
||||
|
||||
err = bb.ValidateSignature(r, payload, []byte(repo.Hash))
|
||||
err = bb.ValidateSignature(r, hook.Payload, []byte(repo.Hash))
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to validate signature on incoming webhook payload: %w", err)
|
||||
}
|
||||
|
||||
switch e := ev.(type) {
|
||||
var pipe *model.Pipeline
|
||||
|
||||
switch e := hook.Event.(type) {
|
||||
case *bb.RepositoryPushEvent:
|
||||
pipe, err = c.updatePipelineFromCommit(ctx, user, repo, pipe)
|
||||
pipe, err = c.updatePipelineFromCommit(ctx, user, repo, hook.Pipeline)
|
||||
case *bb.PullRequestEvent:
|
||||
pipe, err = c.updatePipelineFromPullRequest(ctx, user, repo, pipe, e.PullRequest.ID)
|
||||
pipe, err = c.updatePipelineFromPullRequest(ctx, user, repo, hook.Pipeline, e.PullRequest.ID)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
{
|
||||
"date": "2025-09-11T14:53:09+0300",
|
||||
"actor": {
|
||||
"emailAddress": "john.doe@example.com",
|
||||
"displayName": "EXT Doe John",
|
||||
"name": "john.doe@example.com",
|
||||
"active": true,
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/users/john.doe_example.com" }] },
|
||||
"id": 13581,
|
||||
"type": "NORMAL",
|
||||
"slug": "john.doe_example.com"
|
||||
},
|
||||
"eventKey": "pr:merged",
|
||||
"pullRequest": {
|
||||
"author": {
|
||||
"approved": false,
|
||||
"role": "AUTHOR",
|
||||
"user": {
|
||||
"emailAddress": "john.doe@example.com",
|
||||
"displayName": "EXT Doe John",
|
||||
"name": "john.doe@example.com",
|
||||
"active": true,
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/users/john.doe_example.com" }] },
|
||||
"id": 13581,
|
||||
"type": "NORMAL",
|
||||
"slug": "john.doe_example.com"
|
||||
},
|
||||
"status": "UNAPPROVED"
|
||||
},
|
||||
"description": "Updates ArgoCD to version where the CVE is patched.",
|
||||
"updatedDate": 1757591589232,
|
||||
"title": "chore(CVE-2025-55190): bump argocd",
|
||||
"version": 2,
|
||||
"reviewers": [
|
||||
{
|
||||
"approved": false,
|
||||
"role": "REVIEWER",
|
||||
"user": {
|
||||
"emailAddress": "jane.smith@contractor.com",
|
||||
"displayName": "EXT Smith Jane",
|
||||
"name": "jane.smith@contractor.com",
|
||||
"active": true,
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/users/jane.smith_contractor.com" }] },
|
||||
"id": 9374,
|
||||
"type": "NORMAL",
|
||||
"slug": "jane.smith_contractor.com"
|
||||
},
|
||||
"status": "UNAPPROVED"
|
||||
},
|
||||
{
|
||||
"approved": false,
|
||||
"role": "REVIEWER",
|
||||
"user": {
|
||||
"emailAddress": "mike.johnson@vendor.com",
|
||||
"displayName": "EXT Johnson Mike",
|
||||
"name": "mike.johnson@vendor.com",
|
||||
"active": true,
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/users/mike.johnson_vendor.com" }] },
|
||||
"id": 15107,
|
||||
"type": "NORMAL",
|
||||
"slug": "mike.johnson_vendor.com"
|
||||
},
|
||||
"status": "UNAPPROVED"
|
||||
},
|
||||
{
|
||||
"approved": true,
|
||||
"role": "REVIEWER",
|
||||
"user": {
|
||||
"emailAddress": "alex.brown@freelance.com",
|
||||
"displayName": "EXT Brown Alex",
|
||||
"name": "alex.brown@freelance.com",
|
||||
"active": true,
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/users/alex.brown_freelance.com" }] },
|
||||
"id": 13360,
|
||||
"type": "NORMAL",
|
||||
"slug": "alex.brown_freelance.com"
|
||||
},
|
||||
"lastReviewedCommit": "993203acecdb65ffe947424d0917768b0e5c3903",
|
||||
"status": "APPROVED"
|
||||
}
|
||||
],
|
||||
"toRef": {
|
||||
"latestCommit": "2bbf6d0c36db47566a934ab8f8e391e1ee54d392",
|
||||
"id": "refs/heads/master",
|
||||
"displayId": "master",
|
||||
"type": "BRANCH",
|
||||
"repository": {
|
||||
"archived": false,
|
||||
"public": false,
|
||||
"hierarchyId": "da7793ace13b18fa55a5",
|
||||
"name": "deployment-automation",
|
||||
"forkable": true,
|
||||
"project": {
|
||||
"public": false,
|
||||
"name": "devops-team",
|
||||
"description": "DevOps Team",
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/projects/DEV" }] },
|
||||
"id": 565,
|
||||
"type": "NORMAL",
|
||||
"key": "DEV"
|
||||
},
|
||||
"links": {
|
||||
"clone": [
|
||||
{
|
||||
"name": "http",
|
||||
"href": "https://bitbucket.example.com/scm/dev/deployment-automation.git"
|
||||
},
|
||||
{
|
||||
"name": "ssh",
|
||||
"href": "ssh://git@bitbucket.example.com:7999/dev/deployment-automation.git"
|
||||
}
|
||||
],
|
||||
"self": [{ "href": "https://bitbucket.example.com/projects/DEV/repos/deployment-automation/browse" }]
|
||||
},
|
||||
"id": 1684,
|
||||
"scmId": "git",
|
||||
"state": "AVAILABLE",
|
||||
"slug": "deployment-automation",
|
||||
"statusMessage": "Available"
|
||||
}
|
||||
},
|
||||
"createdDate": 1757571094582,
|
||||
"closedDate": 1757591589232,
|
||||
"draft": false,
|
||||
"closed": true,
|
||||
"fromRef": {
|
||||
"latestCommit": "993203acecdb65ffe947424d0917768b0e5c3903",
|
||||
"id": "refs/heads/PROJ-4584",
|
||||
"displayId": "PROJ-4584",
|
||||
"type": "BRANCH",
|
||||
"repository": {
|
||||
"archived": false,
|
||||
"public": false,
|
||||
"hierarchyId": "da7793ace13b18fa55a5",
|
||||
"name": "deployment-automation",
|
||||
"forkable": true,
|
||||
"project": {
|
||||
"public": false,
|
||||
"name": "devops-team",
|
||||
"description": "DevOps Team",
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/projects/DEV" }] },
|
||||
"id": 565,
|
||||
"type": "NORMAL",
|
||||
"key": "DEV"
|
||||
},
|
||||
"links": {
|
||||
"clone": [
|
||||
{
|
||||
"name": "http",
|
||||
"href": "https://bitbucket.example.com/scm/dev/deployment-automation.git"
|
||||
},
|
||||
{
|
||||
"name": "ssh",
|
||||
"href": "ssh://git@bitbucket.example.com:7999/dev/deployment-automation.git"
|
||||
}
|
||||
],
|
||||
"self": [{ "href": "https://bitbucket.example.com/projects/DEV/repos/deployment-automation/browse" }]
|
||||
},
|
||||
"id": 1684,
|
||||
"scmId": "git",
|
||||
"state": "AVAILABLE",
|
||||
"slug": "deployment-automation",
|
||||
"statusMessage": "Available"
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"self": [{ "href": "https://bitbucket.example.com/projects/DEV/repos/deployment-automation/pull-requests/111" }]
|
||||
},
|
||||
"id": 111,
|
||||
"state": "MERGED",
|
||||
"locked": false,
|
||||
"open": false,
|
||||
"properties": {
|
||||
"mergeCommit": {
|
||||
"id": "c690da9e7f6a6d90defe03d57b8802df149c4aff",
|
||||
"displayId": "c690da9e7f6"
|
||||
}
|
||||
},
|
||||
"participants": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
{
|
||||
"date": "2025-09-19T09:07:23+0300",
|
||||
"actor": {
|
||||
"emailAddress": "mike.johnson@vendor.com",
|
||||
"displayName": "EXT Johnson Mike",
|
||||
"name": "mike.johnson@vendor.com",
|
||||
"active": true,
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/users/mike.johnson_vendor.com" }] },
|
||||
"id": 15107,
|
||||
"type": "NORMAL",
|
||||
"slug": "mike.johnson_vendor.com"
|
||||
},
|
||||
"eventKey": "pr:opened",
|
||||
"pullRequest": {
|
||||
"author": {
|
||||
"approved": false,
|
||||
"role": "AUTHOR",
|
||||
"user": {
|
||||
"emailAddress": "mike.johnson@vendor.com",
|
||||
"displayName": "EXT Johnson Mike",
|
||||
"name": "mike.johnson@vendor.com",
|
||||
"active": true,
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/users/mike.johnson_vendor.com" }] },
|
||||
"id": 15107,
|
||||
"type": "NORMAL",
|
||||
"slug": "mike.johnson_vendor.com"
|
||||
},
|
||||
"status": "UNAPPROVED"
|
||||
},
|
||||
"description": "#### What?\n\nGather statistics about active repositories Woodpecker",
|
||||
"updatedDate": 1758262043663,
|
||||
"title": "feat: gather statistics about Woodpecker migration",
|
||||
"version": 0,
|
||||
"reviewers": [
|
||||
{
|
||||
"approved": false,
|
||||
"role": "REVIEWER",
|
||||
"user": {
|
||||
"emailAddress": "jane.smith@contractor.com",
|
||||
"displayName": "EXT Smith Jane",
|
||||
"name": "jane.smith@contractor.com",
|
||||
"active": true,
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/users/jane.smith_contractor.com" }] },
|
||||
"id": 9374,
|
||||
"type": "NORMAL",
|
||||
"slug": "jane.smith_contractor.com"
|
||||
},
|
||||
"status": "UNAPPROVED"
|
||||
},
|
||||
{
|
||||
"approved": false,
|
||||
"role": "REVIEWER",
|
||||
"user": {
|
||||
"emailAddress": "john.doe@example.com",
|
||||
"displayName": "EXT Doe John",
|
||||
"name": "john.doe@example.com",
|
||||
"active": true,
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/users/john.doe_example.com" }] },
|
||||
"id": 13581,
|
||||
"type": "NORMAL",
|
||||
"slug": "john.doe_example.com"
|
||||
},
|
||||
"status": "UNAPPROVED"
|
||||
},
|
||||
{
|
||||
"approved": false,
|
||||
"role": "REVIEWER",
|
||||
"user": {
|
||||
"emailAddress": "alex.brown@freelance.com",
|
||||
"displayName": "EXT Brown Alex",
|
||||
"name": "alex.brown@freelance.com",
|
||||
"active": true,
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/users/alex.brown_freelance.com" }] },
|
||||
"id": 13360,
|
||||
"type": "NORMAL",
|
||||
"slug": "alex.brown_freelance.com"
|
||||
},
|
||||
"status": "UNAPPROVED"
|
||||
}
|
||||
],
|
||||
"toRef": {
|
||||
"latestCommit": "3767a5d2d2223447d03838654baa271fc15d94df",
|
||||
"id": "refs/heads/main",
|
||||
"displayId": "main",
|
||||
"type": "BRANCH",
|
||||
"repository": {
|
||||
"hierarchyId": "618693f8805af6d8f5c7",
|
||||
"description": "Network Monitor",
|
||||
"project": {
|
||||
"public": false,
|
||||
"name": "devops-team",
|
||||
"description": "DevOps Team",
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/projects/DEV" }] },
|
||||
"id": 565,
|
||||
"type": "NORMAL",
|
||||
"key": "DEV"
|
||||
},
|
||||
"statusMessage": "Available",
|
||||
"archived": false,
|
||||
"public": false,
|
||||
"name": "network-monitor",
|
||||
"forkable": true,
|
||||
"links": {
|
||||
"clone": [
|
||||
{
|
||||
"name": "http",
|
||||
"href": "https://bitbucket.example.com/scm/dev/network-monitor.git"
|
||||
},
|
||||
{
|
||||
"name": "ssh",
|
||||
"href": "ssh://git@bitbucket.example.com:7999/dev/network-monitor.git"
|
||||
}
|
||||
],
|
||||
"self": [{ "href": "https://bitbucket.example.com/projects/DEV/repos/network-monitor/browse" }]
|
||||
},
|
||||
"id": 1079,
|
||||
"scmId": "git",
|
||||
"state": "AVAILABLE",
|
||||
"slug": "network-monitor"
|
||||
}
|
||||
},
|
||||
"createdDate": 1758262043663,
|
||||
"draft": false,
|
||||
"closed": false,
|
||||
"fromRef": {
|
||||
"latestCommit": "1c7589876bc8b5e83122b1656925d679915193d4",
|
||||
"id": "refs/heads/PROJ-4596",
|
||||
"displayId": "PROJ-4596",
|
||||
"type": "BRANCH",
|
||||
"repository": {
|
||||
"hierarchyId": "618693f8805af6d8f5c7",
|
||||
"description": "Network Monitor",
|
||||
"project": {
|
||||
"public": false,
|
||||
"name": "devops-team",
|
||||
"description": "DevOps Team",
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/projects/DEV" }] },
|
||||
"id": 565,
|
||||
"type": "NORMAL",
|
||||
"key": "DEV"
|
||||
},
|
||||
"statusMessage": "Available",
|
||||
"archived": false,
|
||||
"public": false,
|
||||
"name": "network-monitor",
|
||||
"forkable": true,
|
||||
"links": {
|
||||
"clone": [
|
||||
{
|
||||
"name": "http",
|
||||
"href": "https://bitbucket.example.com/scm/dev/network-monitor.git"
|
||||
},
|
||||
{
|
||||
"name": "ssh",
|
||||
"href": "ssh://git@bitbucket.example.com:7999/dev/network-monitor.git"
|
||||
}
|
||||
],
|
||||
"self": [{ "href": "https://bitbucket.example.com/projects/DEV/repos/network-monitor/browse" }]
|
||||
},
|
||||
"id": 1079,
|
||||
"scmId": "git",
|
||||
"state": "AVAILABLE",
|
||||
"slug": "network-monitor"
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"self": [{ "href": "https://bitbucket.example.com/projects/DEV/repos/network-monitor/pull-requests/125" }]
|
||||
},
|
||||
"id": 125,
|
||||
"state": "OPEN",
|
||||
"locked": false,
|
||||
"open": true,
|
||||
"participants": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
{
|
||||
"date": "2025-09-22T13:36:11+0300",
|
||||
"actor": {
|
||||
"emailAddress": "john.doe@example.com",
|
||||
"displayName": "EXT Doe John",
|
||||
"name": "john.doe@example.com",
|
||||
"active": true,
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/users/john.doe_example.com" }] },
|
||||
"id": 13581,
|
||||
"type": "NORMAL",
|
||||
"slug": "john.doe_example.com"
|
||||
},
|
||||
"eventKey": "pr:opened",
|
||||
"pullRequest": {
|
||||
"author": {
|
||||
"approved": false,
|
||||
"role": "AUTHOR",
|
||||
"user": {
|
||||
"emailAddress": "john.doe@example.com",
|
||||
"displayName": "EXT Doe John",
|
||||
"name": "john.doe@example.com",
|
||||
"active": true,
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/users/john.doe_example.com" }] },
|
||||
"id": 13581,
|
||||
"type": "NORMAL",
|
||||
"slug": "john.doe_example.com"
|
||||
},
|
||||
"status": "UNAPPROVED"
|
||||
},
|
||||
"updatedDate": 1758537371875,
|
||||
"title": "testing PROJ-4600",
|
||||
"version": 0,
|
||||
"reviewers": [],
|
||||
"toRef": {
|
||||
"latestCommit": "8c49fecb1363fffdf00456cedaaff6a50613725a",
|
||||
"id": "refs/heads/master",
|
||||
"displayId": "master",
|
||||
"type": "BRANCH",
|
||||
"repository": {
|
||||
"archived": false,
|
||||
"public": false,
|
||||
"hierarchyId": "da7793ace13b18fa55a5",
|
||||
"name": "deployment-automation",
|
||||
"forkable": true,
|
||||
"project": {
|
||||
"public": false,
|
||||
"name": "devops-team",
|
||||
"description": "DevOps Team",
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/projects/DEV" }] },
|
||||
"id": 565,
|
||||
"type": "NORMAL",
|
||||
"key": "DEV"
|
||||
},
|
||||
"links": {
|
||||
"clone": [
|
||||
{
|
||||
"name": "http",
|
||||
"href": "https://bitbucket.example.com/scm/dev/deployment-automation.git"
|
||||
},
|
||||
{
|
||||
"name": "ssh",
|
||||
"href": "ssh://git@bitbucket.example.com:7999/dev/deployment-automation.git"
|
||||
}
|
||||
],
|
||||
"self": [{ "href": "https://bitbucket.example.com/projects/DEV/repos/deployment-automation/browse" }]
|
||||
},
|
||||
"id": 1684,
|
||||
"scmId": "git",
|
||||
"state": "AVAILABLE",
|
||||
"slug": "deployment-automation",
|
||||
"statusMessage": "Available"
|
||||
}
|
||||
},
|
||||
"createdDate": 1758537371875,
|
||||
"draft": false,
|
||||
"closed": false,
|
||||
"fromRef": {
|
||||
"latestCommit": "716e510cecbe203618609cf103c54e040b949739",
|
||||
"id": "refs/heads/master",
|
||||
"displayId": "master",
|
||||
"type": "BRANCH",
|
||||
"repository": {
|
||||
"hierarchyId": "da7793ace13b18fa55a5",
|
||||
"origin": {
|
||||
"archived": false,
|
||||
"public": false,
|
||||
"hierarchyId": "da7793ace13b18fa55a5",
|
||||
"name": "deployment-automation",
|
||||
"forkable": true,
|
||||
"project": {
|
||||
"public": false,
|
||||
"name": "devops-team",
|
||||
"description": "DevOps Team",
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/projects/DEV" }] },
|
||||
"id": 565,
|
||||
"type": "NORMAL",
|
||||
"key": "DEV"
|
||||
},
|
||||
"links": {
|
||||
"clone": [
|
||||
{
|
||||
"name": "http",
|
||||
"href": "https://bitbucket.example.com/scm/dev/deployment-automation.git"
|
||||
},
|
||||
{
|
||||
"name": "ssh",
|
||||
"href": "ssh://git@bitbucket.example.com:7999/dev/deployment-automation.git"
|
||||
}
|
||||
],
|
||||
"self": [{ "href": "https://bitbucket.example.com/projects/DEV/repos/deployment-automation/browse" }]
|
||||
},
|
||||
"id": 1684,
|
||||
"scmId": "git",
|
||||
"state": "AVAILABLE",
|
||||
"slug": "deployment-automation",
|
||||
"statusMessage": "Available"
|
||||
},
|
||||
"project": {
|
||||
"owner": {
|
||||
"emailAddress": "john.doe@example.com",
|
||||
"displayName": "EXT Doe John",
|
||||
"name": "john.doe@example.com",
|
||||
"active": true,
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/users/john.doe_example.com" }] },
|
||||
"id": 13581,
|
||||
"type": "NORMAL",
|
||||
"slug": "john.doe_example.com"
|
||||
},
|
||||
"name": "EXT Doe John",
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/users/john.doe_example.com" }] },
|
||||
"id": 1120,
|
||||
"type": "PERSONAL",
|
||||
"key": "~JOHN.DOE_EXAMPLE.COM"
|
||||
},
|
||||
"statusMessage": "Available",
|
||||
"archived": false,
|
||||
"public": false,
|
||||
"name": "deployment-automation",
|
||||
"forkable": true,
|
||||
"links": {
|
||||
"clone": [
|
||||
{
|
||||
"name": "ssh",
|
||||
"href": "ssh://git@bitbucket.example.com:7999/~john.doe_example.com/deployment-automation.git"
|
||||
},
|
||||
{
|
||||
"name": "http",
|
||||
"href": "https://bitbucket.example.com/scm/~john.doe_example.com/deployment-automation.git"
|
||||
}
|
||||
],
|
||||
"self": [
|
||||
{ "href": "https://bitbucket.example.com/users/john.doe_example.com/repos/deployment-automation/browse" }
|
||||
]
|
||||
},
|
||||
"id": 1856,
|
||||
"scmId": "git",
|
||||
"state": "AVAILABLE",
|
||||
"slug": "deployment-automation"
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"self": [{ "href": "https://bitbucket.example.com/projects/DEV/repos/deployment-automation/pull-requests/114" }]
|
||||
},
|
||||
"id": 114,
|
||||
"state": "OPEN",
|
||||
"locked": false,
|
||||
"open": true,
|
||||
"participants": []
|
||||
}
|
||||
}
|
||||
146
server/forge/bitbucketdatacenter/fixtures/HookPush.json
Normal file
146
server/forge/bitbucketdatacenter/fixtures/HookPush.json
Normal file
@@ -0,0 +1,146 @@
|
||||
{
|
||||
"date": "2025-09-23T03:15:55+0300",
|
||||
"actor": {
|
||||
"emailAddress": "renovatebot@example.com",
|
||||
"displayName": "Renovate Bot",
|
||||
"name": "renovatebot",
|
||||
"active": true,
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/users/renovatebot" }] },
|
||||
"id": 14570,
|
||||
"type": "NORMAL",
|
||||
"slug": "renovatebot"
|
||||
},
|
||||
"toCommit": {
|
||||
"committer": {
|
||||
"emailAddress": "renovatebot@example.com",
|
||||
"displayName": "Renovate Bot",
|
||||
"name": "renovatebot",
|
||||
"active": true,
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/users/renovatebot" }] },
|
||||
"id": 14570,
|
||||
"type": "NORMAL",
|
||||
"slug": "renovatebot"
|
||||
},
|
||||
"committerTimestamp": 1758586555000,
|
||||
"author": {
|
||||
"emailAddress": "renovatebot@example.com",
|
||||
"displayName": "Renovate Bot",
|
||||
"name": "renovatebot",
|
||||
"active": true,
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/users/renovatebot" }] },
|
||||
"id": 14570,
|
||||
"type": "NORMAL",
|
||||
"slug": "renovatebot"
|
||||
},
|
||||
"authorTimestamp": 1758586555000,
|
||||
"id": "76797d54bca87db6d1e3e82ee40622c7908aa514",
|
||||
"displayId": "76797d54bca",
|
||||
"message": "chore(deps): update all",
|
||||
"parents": [
|
||||
{
|
||||
"committer": {
|
||||
"emailAddress": "john.doe@example.com",
|
||||
"name": "John Doe"
|
||||
},
|
||||
"committerTimestamp": 1757592099000,
|
||||
"author": {
|
||||
"emailAddress": "john.doe@example.com",
|
||||
"name": "John Doe"
|
||||
},
|
||||
"authorTimestamp": 1757592099000,
|
||||
"id": "8c49fecb1363fffdf00456cedaaff6a50613725a",
|
||||
"displayId": "8c49fecb136",
|
||||
"message": "chore: bump deployment automation version",
|
||||
"parents": [
|
||||
{
|
||||
"id": "c690da9e7f6a6d90defe03d57b8802df149c4aff",
|
||||
"displayId": "c690da9e7f6"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"eventKey": "repo:refs_changed",
|
||||
"changes": [
|
||||
{
|
||||
"ref": {
|
||||
"id": "refs/heads/renovate-all",
|
||||
"displayId": "renovate-all",
|
||||
"type": "BRANCH"
|
||||
},
|
||||
"fromHash": "e0e15221b987fd8296141c0faa6a79f7c86ca4ce",
|
||||
"toHash": "76797d54bca87db6d1e3e82ee40622c7908aa514",
|
||||
"refId": "refs/heads/renovate-all",
|
||||
"type": "UPDATE"
|
||||
}
|
||||
],
|
||||
"commits": [
|
||||
{
|
||||
"committer": {
|
||||
"emailAddress": "renovatebot@example.com",
|
||||
"displayName": "Renovate Bot",
|
||||
"name": "renovatebot",
|
||||
"active": true,
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/users/renovatebot" }] },
|
||||
"id": 14570,
|
||||
"type": "NORMAL",
|
||||
"slug": "renovatebot"
|
||||
},
|
||||
"committerTimestamp": 1758586555000,
|
||||
"author": {
|
||||
"emailAddress": "renovatebot@example.com",
|
||||
"displayName": "Renovate Bot",
|
||||
"name": "renovatebot",
|
||||
"active": true,
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/users/renovatebot" }] },
|
||||
"id": 14570,
|
||||
"type": "NORMAL",
|
||||
"slug": "renovatebot"
|
||||
},
|
||||
"authorTimestamp": 1758586555000,
|
||||
"id": "76797d54bca87db6d1e3e82ee40622c7908aa514",
|
||||
"displayId": "76797d54bca",
|
||||
"message": "chore(deps): update all",
|
||||
"parents": [
|
||||
{
|
||||
"id": "8c49fecb1363fffdf00456cedaaff6a50613725a",
|
||||
"displayId": "8c49fecb136"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"archived": false,
|
||||
"public": false,
|
||||
"hierarchyId": "da7793ace13b18fa55a5",
|
||||
"name": "deployment-automation",
|
||||
"forkable": true,
|
||||
"project": {
|
||||
"public": false,
|
||||
"name": "devops-team",
|
||||
"description": "DevOps Team",
|
||||
"links": { "self": [{ "href": "https://bitbucket.example.com/projects/DEV" }] },
|
||||
"id": 565,
|
||||
"type": "NORMAL",
|
||||
"key": "DEV"
|
||||
},
|
||||
"links": {
|
||||
"clone": [
|
||||
{
|
||||
"name": "http",
|
||||
"href": "https://bitbucket.example.com/scm/dev/deployment-automation.git"
|
||||
},
|
||||
{
|
||||
"name": "ssh",
|
||||
"href": "ssh://git@bitbucket.example.com:7999/dev/deployment-automation.git"
|
||||
}
|
||||
],
|
||||
"self": [{ "href": "https://bitbucket.example.com/projects/DEV/repos/deployment-automation/browse" }]
|
||||
},
|
||||
"id": 1684,
|
||||
"scmId": "git",
|
||||
"state": "AVAILABLE",
|
||||
"slug": "deployment-automation",
|
||||
"statusMessage": "Available"
|
||||
}
|
||||
}
|
||||
15
server/forge/bitbucketdatacenter/fixtures/hooks.go
Normal file
15
server/forge/bitbucketdatacenter/fixtures/hooks.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package fixtures
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed HookPullRequestOpenedFromFork.json
|
||||
var HookPullFork string
|
||||
|
||||
//go:embed HookPush.json
|
||||
var HookPush string
|
||||
|
||||
//go:embed HookPullRequestMerged.json
|
||||
var HookPullMerged string
|
||||
|
||||
//go:embed HookPullRequestOpened.json
|
||||
var HookPull string
|
||||
42
server/forge/bitbucketdatacenter/parse.go
Normal file
42
server/forge/bitbucketdatacenter/parse.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package bitbucketdatacenter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
bb "github.com/neticdk/go-bitbucket/bitbucket"
|
||||
|
||||
"go.woodpecker-ci.org/woodpecker/v3/server/model"
|
||||
)
|
||||
|
||||
type HookResult struct {
|
||||
Repo *model.Repo
|
||||
Pipeline *model.Pipeline
|
||||
Event any
|
||||
Payload []byte
|
||||
}
|
||||
|
||||
func parseHook(r *http.Request, baseURL string) (*HookResult, error) {
|
||||
ev, payload, err := bb.ParsePayloadWithoutSignature(r)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse payload from webhook invocation: %w", err)
|
||||
}
|
||||
|
||||
result := &HookResult{
|
||||
Event: ev,
|
||||
Payload: payload,
|
||||
}
|
||||
|
||||
switch e := ev.(type) {
|
||||
case *bb.RepositoryPushEvent:
|
||||
result.Repo = convertRepo(&e.Repository, nil, "")
|
||||
result.Pipeline = convertRepositoryPushEvent(e, baseURL)
|
||||
case *bb.PullRequestEvent:
|
||||
result.Repo = convertRepo(&e.PullRequest.Target.Repository, nil, "")
|
||||
result.Pipeline = convertPullRequestEvent(e, baseURL)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported webhook event type: %T", e)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
95
server/forge/bitbucketdatacenter/parse_test.go
Normal file
95
server/forge/bitbucketdatacenter/parse_test.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package bitbucketdatacenter
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
bb "github.com/neticdk/go-bitbucket/bitbucket"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"go.woodpecker-ci.org/woodpecker/v3/server/forge/bitbucketdatacenter/fixtures"
|
||||
"go.woodpecker-ci.org/woodpecker/v3/server/model"
|
||||
)
|
||||
|
||||
func Test_parseHook(t *testing.T) {
|
||||
t.Run("pull-request opened", func(t *testing.T) {
|
||||
buf := bytes.NewBufferString(fixtures.HookPull)
|
||||
req, _ := http.NewRequest(http.MethodPost, "/hook", buf)
|
||||
req.Header = http.Header{}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-Event-Key", "pr:opened")
|
||||
|
||||
result, err := parseHook(req, "https://bitbucket.example.com")
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, result)
|
||||
assert.IsType(t, &bb.PullRequestEvent{}, result.Event)
|
||||
assert.NotNil(t, result.Repo)
|
||||
assert.NotNil(t, result.Pipeline)
|
||||
assert.NotNil(t, result.Payload)
|
||||
assert.Equal(t, "DEV/network-monitor", result.Repo.FullName)
|
||||
assert.Equal(t, "1c7589876bc8b5e83122b1656925d679915193d4", result.Pipeline.Commit)
|
||||
assert.Equal(t, model.EventPull, result.Pipeline.Event)
|
||||
})
|
||||
|
||||
t.Run("pull-request opened from fork", func(t *testing.T) {
|
||||
buf := bytes.NewBufferString(fixtures.HookPullFork)
|
||||
req, _ := http.NewRequest(http.MethodPost, "/hook", buf)
|
||||
req.Header = http.Header{}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-Event-Key", "pr:opened")
|
||||
|
||||
result, err := parseHook(req, "https://bitbucket.example.com")
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, result)
|
||||
assert.IsType(t, &bb.PullRequestEvent{}, result.Event)
|
||||
assert.NotNil(t, result.Repo)
|
||||
assert.NotNil(t, result.Pipeline)
|
||||
assert.NotNil(t, result.Payload)
|
||||
assert.Equal(t, "DEV/deployment-automation", result.Repo.FullName)
|
||||
assert.Equal(t, "716e510cecbe203618609cf103c54e040b949739", result.Pipeline.Commit)
|
||||
assert.Equal(t, model.EventPull, result.Pipeline.Event)
|
||||
})
|
||||
|
||||
t.Run("push hook", func(t *testing.T) {
|
||||
buf := bytes.NewBufferString(fixtures.HookPush)
|
||||
req, _ := http.NewRequest(http.MethodPost, "/hook", buf)
|
||||
req.Header = http.Header{}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-Event-Key", "repo:refs_changed")
|
||||
|
||||
result, err := parseHook(req, "https://bitbucket.example.com")
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, result)
|
||||
assert.IsType(t, &bb.RepositoryPushEvent{}, result.Event)
|
||||
assert.NotNil(t, result.Repo)
|
||||
assert.NotNil(t, result.Pipeline)
|
||||
assert.NotNil(t, result.Payload)
|
||||
assert.Equal(t, "DEV/deployment-automation", result.Repo.FullName)
|
||||
assert.Equal(t, "76797d54bca87db6d1e3e82ee40622c7908aa514", result.Pipeline.Commit)
|
||||
assert.Equal(t, model.EventPush, result.Pipeline.Event)
|
||||
})
|
||||
|
||||
t.Run("pull-request merged", func(t *testing.T) {
|
||||
buf := bytes.NewBufferString(fixtures.HookPullMerged)
|
||||
req, _ := http.NewRequest(http.MethodPost, "/hook", buf)
|
||||
req.Header = http.Header{}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-Event-Key", "pr:merged")
|
||||
|
||||
result, err := parseHook(req, "https://bitbucket.example.com")
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, result)
|
||||
assert.IsType(t, &bb.PullRequestEvent{}, result.Event)
|
||||
assert.NotNil(t, result.Repo)
|
||||
assert.NotNil(t, result.Pipeline)
|
||||
assert.NotNil(t, result.Payload)
|
||||
assert.Equal(t, "DEV/deployment-automation", result.Repo.FullName)
|
||||
assert.Equal(t, "993203acecdb65ffe947424d0917768b0e5c3903", result.Pipeline.Commit)
|
||||
assert.Equal(t, model.EventPullClosed, result.Pipeline.Event)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user