@ -4,10 +4,22 @@
package integration
package integration
import (
import (
"context"
"fmt"
"io"
"net/http"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"strings"
"testing"
"testing"
auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/json"
api "code.gitea.io/gitea/modules/structs"
webhook_module "code.gitea.io/gitea/modules/webhook"
"code.gitea.io/gitea/tests"
"code.gitea.io/gitea/tests"
"github.com/PuerkitoBio/goquery"
"github.com/PuerkitoBio/goquery"
@ -39,3 +51,514 @@ func TestNewWebHookLink(t *testing.T) {
} )
} )
}
}
}
}
func testAPICreateWebhookForRepo ( t * testing . T , session * TestSession , userName , repoName , url , event string ) {
token := getTokenForLoggedInUser ( t , session , auth_model . AccessTokenScopeAll )
req := NewRequestWithJSON ( t , "POST" , "/api/v1/repos/" + userName + "/" + repoName + "/hooks" , api . CreateHookOption {
Type : "gitea" ,
Config : api . CreateHookOptionConfig {
"content_type" : "json" ,
"url" : url ,
} ,
Events : [ ] string { event } ,
Active : true ,
} ) . AddTokenAuth ( token )
MakeRequest ( t , req , http . StatusCreated )
}
func testAPICreateWebhookForOrg ( t * testing . T , session * TestSession , userName , url , event string ) {
token := getTokenForLoggedInUser ( t , session , auth_model . AccessTokenScopeAll )
req := NewRequestWithJSON ( t , "POST" , "/api/v1/orgs/" + userName + "/hooks" , api . CreateHookOption {
Type : "gitea" ,
Config : api . CreateHookOptionConfig {
"content_type" : "json" ,
"url" : url ,
} ,
Events : [ ] string { event } ,
Active : true ,
} ) . AddTokenAuth ( token )
MakeRequest ( t , req , http . StatusCreated )
}
type mockWebhookProvider struct {
server * httptest . Server
}
func newMockWebhookProvider ( callback func ( r * http . Request ) , status int ) * mockWebhookProvider {
m := & mockWebhookProvider { }
m . server = httptest . NewServer ( http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
callback ( r )
w . WriteHeader ( status )
} ) )
return m
}
func ( m * mockWebhookProvider ) URL ( ) string {
if m . server == nil {
return ""
}
return m . server . URL
}
// Close closes the mock webhook http server
func ( m * mockWebhookProvider ) Close ( ) {
if m . server != nil {
m . server . Close ( )
m . server = nil
}
}
func Test_WebhookCreate ( t * testing . T ) {
var payloads [ ] api . CreatePayload
var triggeredEvent string
provider := newMockWebhookProvider ( func ( r * http . Request ) {
content , _ := io . ReadAll ( r . Body )
var payload api . CreatePayload
err := json . Unmarshal ( content , & payload )
assert . NoError ( t , err )
payloads = append ( payloads , payload )
triggeredEvent = string ( webhook_module . HookEventCreate )
} , http . StatusOK )
defer provider . Close ( )
onGiteaRun ( t , func ( t * testing . T , giteaURL * url . URL ) {
// 1. create a new webhook with special webhook for repo1
session := loginUser ( t , "user2" )
testAPICreateWebhookForRepo ( t , session , "user2" , "repo1" , provider . URL ( ) , "create" )
// 2. trigger the webhook
testAPICreateBranch ( t , session , "user2" , "repo1" , "master" , "master2" , http . StatusCreated )
// 3. validate the webhook is triggered
assert . Len ( t , payloads , 1 )
assert . EqualValues ( t , string ( webhook_module . HookEventCreate ) , triggeredEvent )
assert . EqualValues ( t , "repo1" , payloads [ 0 ] . Repo . Name )
assert . EqualValues ( t , "user2/repo1" , payloads [ 0 ] . Repo . FullName )
assert . EqualValues ( t , "master2" , payloads [ 0 ] . Ref )
assert . EqualValues ( t , "branch" , payloads [ 0 ] . RefType )
} )
}
func Test_WebhookDelete ( t * testing . T ) {
var payloads [ ] api . DeletePayload
var triggeredEvent string
provider := newMockWebhookProvider ( func ( r * http . Request ) {
content , _ := io . ReadAll ( r . Body )
var payload api . DeletePayload
err := json . Unmarshal ( content , & payload )
assert . NoError ( t , err )
payloads = append ( payloads , payload )
triggeredEvent = "delete"
} , http . StatusOK )
defer provider . Close ( )
onGiteaRun ( t , func ( t * testing . T , giteaURL * url . URL ) {
// 1. create a new webhook with special webhook for repo1
session := loginUser ( t , "user2" )
testAPICreateWebhookForRepo ( t , session , "user2" , "repo1" , provider . URL ( ) , "delete" )
// 2. trigger the webhook
testAPICreateBranch ( t , session , "user2" , "repo1" , "master" , "master2" , http . StatusCreated )
testAPIDeleteBranch ( t , "master2" , http . StatusNoContent )
// 3. validate the webhook is triggered
assert . EqualValues ( t , "delete" , triggeredEvent )
assert . Len ( t , payloads , 1 )
assert . EqualValues ( t , "repo1" , payloads [ 0 ] . Repo . Name )
assert . EqualValues ( t , "user2/repo1" , payloads [ 0 ] . Repo . FullName )
assert . EqualValues ( t , "master2" , payloads [ 0 ] . Ref )
assert . EqualValues ( t , "branch" , payloads [ 0 ] . RefType )
} )
}
func Test_WebhookFork ( t * testing . T ) {
var payloads [ ] api . ForkPayload
var triggeredEvent string
provider := newMockWebhookProvider ( func ( r * http . Request ) {
content , _ := io . ReadAll ( r . Body )
var payload api . ForkPayload
err := json . Unmarshal ( content , & payload )
assert . NoError ( t , err )
payloads = append ( payloads , payload )
triggeredEvent = "fork"
} , http . StatusOK )
defer provider . Close ( )
onGiteaRun ( t , func ( t * testing . T , giteaURL * url . URL ) {
// 1. create a new webhook with special webhook for repo1
session := loginUser ( t , "user1" )
testAPICreateWebhookForRepo ( t , session , "user2" , "repo1" , provider . URL ( ) , "fork" )
// 2. trigger the webhook
testRepoFork ( t , session , "user2" , "repo1" , "user1" , "repo1-fork" , "master" )
// 3. validate the webhook is triggered
assert . EqualValues ( t , "fork" , triggeredEvent )
assert . Len ( t , payloads , 1 )
assert . EqualValues ( t , "repo1-fork" , payloads [ 0 ] . Repo . Name )
assert . EqualValues ( t , "user1/repo1-fork" , payloads [ 0 ] . Repo . FullName )
assert . EqualValues ( t , "repo1" , payloads [ 0 ] . Forkee . Name )
assert . EqualValues ( t , "user2/repo1" , payloads [ 0 ] . Forkee . FullName )
} )
}
func Test_WebhookIssueComment ( t * testing . T ) {
var payloads [ ] api . IssueCommentPayload
var triggeredEvent string
provider := newMockWebhookProvider ( func ( r * http . Request ) {
content , _ := io . ReadAll ( r . Body )
var payload api . IssueCommentPayload
err := json . Unmarshal ( content , & payload )
assert . NoError ( t , err )
payloads = append ( payloads , payload )
triggeredEvent = "issue_comment"
} , http . StatusOK )
defer provider . Close ( )
onGiteaRun ( t , func ( t * testing . T , giteaURL * url . URL ) {
// 1. create a new webhook with special webhook for repo1
session := loginUser ( t , "user2" )
testAPICreateWebhookForRepo ( t , session , "user2" , "repo1" , provider . URL ( ) , "issue_comment" )
// 2. trigger the webhook
issueURL := testNewIssue ( t , session , "user2" , "repo1" , "Title2" , "Description2" )
testIssueAddComment ( t , session , issueURL , "issue title2 comment1" , "" )
// 3. validate the webhook is triggered
assert . EqualValues ( t , "issue_comment" , triggeredEvent )
assert . Len ( t , payloads , 1 )
assert . EqualValues ( t , "created" , payloads [ 0 ] . Action )
assert . EqualValues ( t , "repo1" , payloads [ 0 ] . Issue . Repo . Name )
assert . EqualValues ( t , "user2/repo1" , payloads [ 0 ] . Issue . Repo . FullName )
assert . EqualValues ( t , "Title2" , payloads [ 0 ] . Issue . Title )
assert . EqualValues ( t , "Description2" , payloads [ 0 ] . Issue . Body )
assert . EqualValues ( t , "issue title2 comment1" , payloads [ 0 ] . Comment . Body )
} )
}
func Test_WebhookRelease ( t * testing . T ) {
var payloads [ ] api . ReleasePayload
var triggeredEvent string
provider := newMockWebhookProvider ( func ( r * http . Request ) {
content , _ := io . ReadAll ( r . Body )
var payload api . ReleasePayload
err := json . Unmarshal ( content , & payload )
assert . NoError ( t , err )
payloads = append ( payloads , payload )
triggeredEvent = "release"
} , http . StatusOK )
defer provider . Close ( )
onGiteaRun ( t , func ( t * testing . T , giteaURL * url . URL ) {
// 1. create a new webhook with special webhook for repo1
session := loginUser ( t , "user2" )
testAPICreateWebhookForRepo ( t , session , "user2" , "repo1" , provider . URL ( ) , "release" )
// 2. trigger the webhook
createNewRelease ( t , session , "/user2/repo1" , "v0.0.99" , "v0.0.99" , false , false )
// 3. validate the webhook is triggered
assert . EqualValues ( t , "release" , triggeredEvent )
assert . Len ( t , payloads , 1 )
assert . EqualValues ( t , "repo1" , payloads [ 0 ] . Repository . Name )
assert . EqualValues ( t , "user2/repo1" , payloads [ 0 ] . Repository . FullName )
assert . EqualValues ( t , "v0.0.99" , payloads [ 0 ] . Release . TagName )
assert . False ( t , payloads [ 0 ] . Release . IsDraft )
assert . False ( t , payloads [ 0 ] . Release . IsPrerelease )
} )
}
func Test_WebhookPush ( t * testing . T ) {
var payloads [ ] api . PushPayload
var triggeredEvent string
provider := newMockWebhookProvider ( func ( r * http . Request ) {
content , _ := io . ReadAll ( r . Body )
var payload api . PushPayload
err := json . Unmarshal ( content , & payload )
assert . NoError ( t , err )
payloads = append ( payloads , payload )
triggeredEvent = "push"
} , http . StatusOK )
defer provider . Close ( )
onGiteaRun ( t , func ( t * testing . T , giteaURL * url . URL ) {
// 1. create a new webhook with special webhook for repo1
session := loginUser ( t , "user2" )
testAPICreateWebhookForRepo ( t , session , "user2" , "repo1" , provider . URL ( ) , "push" )
// 2. trigger the webhook
testCreateFile ( t , session , "user2" , "repo1" , "master" , "test_webhook_push.md" , "# a test file for webhook push" )
// 3. validate the webhook is triggered
assert . EqualValues ( t , "push" , triggeredEvent )
assert . Len ( t , payloads , 1 )
assert . EqualValues ( t , "repo1" , payloads [ 0 ] . Repo . Name )
assert . EqualValues ( t , "user2/repo1" , payloads [ 0 ] . Repo . FullName )
assert . Len ( t , payloads [ 0 ] . Commits , 1 )
assert . EqualValues ( t , [ ] string { "test_webhook_push.md" } , payloads [ 0 ] . Commits [ 0 ] . Added )
} )
}
func Test_WebhookIssue ( t * testing . T ) {
var payloads [ ] api . IssuePayload
var triggeredEvent string
provider := newMockWebhookProvider ( func ( r * http . Request ) {
content , _ := io . ReadAll ( r . Body )
var payload api . IssuePayload
err := json . Unmarshal ( content , & payload )
assert . NoError ( t , err )
payloads = append ( payloads , payload )
triggeredEvent = "issues"
} , http . StatusOK )
defer provider . Close ( )
onGiteaRun ( t , func ( t * testing . T , giteaURL * url . URL ) {
// 1. create a new webhook with special webhook for repo1
session := loginUser ( t , "user2" )
testAPICreateWebhookForRepo ( t , session , "user2" , "repo1" , provider . URL ( ) , "issues" )
// 2. trigger the webhook
testNewIssue ( t , session , "user2" , "repo1" , "Title1" , "Description1" )
// 3. validate the webhook is triggered
assert . EqualValues ( t , "issues" , triggeredEvent )
assert . Len ( t , payloads , 1 )
assert . EqualValues ( t , "opened" , payloads [ 0 ] . Action )
assert . EqualValues ( t , "repo1" , payloads [ 0 ] . Issue . Repo . Name )
assert . EqualValues ( t , "user2/repo1" , payloads [ 0 ] . Issue . Repo . FullName )
assert . EqualValues ( t , "Title1" , payloads [ 0 ] . Issue . Title )
assert . EqualValues ( t , "Description1" , payloads [ 0 ] . Issue . Body )
} )
}
func Test_WebhookPullRequest ( t * testing . T ) {
var payloads [ ] api . PullRequestPayload
var triggeredEvent string
provider := newMockWebhookProvider ( func ( r * http . Request ) {
content , _ := io . ReadAll ( r . Body )
var payload api . PullRequestPayload
err := json . Unmarshal ( content , & payload )
assert . NoError ( t , err )
payloads = append ( payloads , payload )
triggeredEvent = "pull_request"
} , http . StatusOK )
defer provider . Close ( )
onGiteaRun ( t , func ( t * testing . T , giteaURL * url . URL ) {
// 1. create a new webhook with special webhook for repo1
session := loginUser ( t , "user2" )
testAPICreateWebhookForRepo ( t , session , "user2" , "repo1" , provider . URL ( ) , "pull_request" )
testAPICreateBranch ( t , session , "user2" , "repo1" , "master" , "master2" , http . StatusCreated )
// 2. trigger the webhook
repo1 := unittest . AssertExistsAndLoadBean ( t , & repo . Repository { ID : 1 } )
testCreatePullToDefaultBranch ( t , session , repo1 , repo1 , "master2" , "first pull request" )
// 3. validate the webhook is triggered
assert . EqualValues ( t , "pull_request" , triggeredEvent )
assert . Len ( t , payloads , 1 )
assert . EqualValues ( t , "repo1" , payloads [ 0 ] . PullRequest . Base . Repository . Name )
assert . EqualValues ( t , "user2/repo1" , payloads [ 0 ] . PullRequest . Base . Repository . FullName )
assert . EqualValues ( t , "repo1" , payloads [ 0 ] . PullRequest . Head . Repository . Name )
assert . EqualValues ( t , "user2/repo1" , payloads [ 0 ] . PullRequest . Head . Repository . FullName )
assert . EqualValues ( t , 0 , payloads [ 0 ] . PullRequest . Additions )
} )
}
func Test_WebhookPullRequestComment ( t * testing . T ) {
var payloads [ ] api . IssueCommentPayload
var triggeredEvent string
provider := newMockWebhookProvider ( func ( r * http . Request ) {
content , _ := io . ReadAll ( r . Body )
var payload api . IssueCommentPayload
err := json . Unmarshal ( content , & payload )
assert . NoError ( t , err )
payloads = append ( payloads , payload )
triggeredEvent = "pull_request_comment"
} , http . StatusOK )
defer provider . Close ( )
onGiteaRun ( t , func ( t * testing . T , giteaURL * url . URL ) {
// 1. create a new webhook with special webhook for repo1
session := loginUser ( t , "user2" )
testAPICreateWebhookForRepo ( t , session , "user2" , "repo1" , provider . URL ( ) , "pull_request_comment" )
// 2. trigger the webhook
testAPICreateBranch ( t , session , "user2" , "repo1" , "master" , "master2" , http . StatusCreated )
repo1 := unittest . AssertExistsAndLoadBean ( t , & repo . Repository { ID : 1 } )
prID := testCreatePullToDefaultBranch ( t , session , repo1 , repo1 , "master2" , "first pull request" )
testIssueAddComment ( t , session , "/user2/repo1/pulls/" + prID , "pull title2 comment1" , "" )
// 3. validate the webhook is triggered
assert . EqualValues ( t , "pull_request_comment" , triggeredEvent )
assert . Len ( t , payloads , 1 )
assert . EqualValues ( t , "created" , payloads [ 0 ] . Action )
assert . EqualValues ( t , "repo1" , payloads [ 0 ] . Issue . Repo . Name )
assert . EqualValues ( t , "user2/repo1" , payloads [ 0 ] . Issue . Repo . FullName )
assert . EqualValues ( t , "first pull request" , payloads [ 0 ] . Issue . Title )
assert . EqualValues ( t , "" , payloads [ 0 ] . Issue . Body )
assert . EqualValues ( t , "pull title2 comment1" , payloads [ 0 ] . Comment . Body )
} )
}
func Test_WebhookWiki ( t * testing . T ) {
var payloads [ ] api . WikiPayload
var triggeredEvent string
provider := newMockWebhookProvider ( func ( r * http . Request ) {
content , _ := io . ReadAll ( r . Body )
var payload api . WikiPayload
err := json . Unmarshal ( content , & payload )
assert . NoError ( t , err )
payloads = append ( payloads , payload )
triggeredEvent = "wiki"
} , http . StatusOK )
defer provider . Close ( )
onGiteaRun ( t , func ( t * testing . T , giteaURL * url . URL ) {
// 1. create a new webhook with special webhook for repo1
session := loginUser ( t , "user2" )
testAPICreateWebhookForRepo ( t , session , "user2" , "repo1" , provider . URL ( ) , "wiki" )
// 2. trigger the webhook
testAPICreateWikiPage ( t , session , "user2" , "repo1" , "Test Wiki Page" , http . StatusCreated )
// 3. validate the webhook is triggered
assert . EqualValues ( t , "wiki" , triggeredEvent )
assert . Len ( t , payloads , 1 )
assert . EqualValues ( t , "created" , payloads [ 0 ] . Action )
assert . EqualValues ( t , "repo1" , payloads [ 0 ] . Repository . Name )
assert . EqualValues ( t , "user2/repo1" , payloads [ 0 ] . Repository . FullName )
assert . EqualValues ( t , "Test-Wiki-Page" , payloads [ 0 ] . Page )
} )
}
func Test_WebhookRepository ( t * testing . T ) {
var payloads [ ] api . RepositoryPayload
var triggeredEvent string
provider := newMockWebhookProvider ( func ( r * http . Request ) {
content , _ := io . ReadAll ( r . Body )
var payload api . RepositoryPayload
err := json . Unmarshal ( content , & payload )
assert . NoError ( t , err )
payloads = append ( payloads , payload )
triggeredEvent = "repository"
} , http . StatusOK )
defer provider . Close ( )
onGiteaRun ( t , func ( t * testing . T , giteaURL * url . URL ) {
// 1. create a new webhook with special webhook for repo1
session := loginUser ( t , "user1" )
testAPICreateWebhookForOrg ( t , session , "org3" , provider . URL ( ) , "repository" )
// 2. trigger the webhook
testAPIOrgCreateRepo ( t , session , "org3" , "repo_new" , http . StatusCreated )
// 3. validate the webhook is triggered
assert . EqualValues ( t , "repository" , triggeredEvent )
assert . Len ( t , payloads , 1 )
assert . EqualValues ( t , "created" , payloads [ 0 ] . Action )
assert . EqualValues ( t , "org3" , payloads [ 0 ] . Organization . UserName )
assert . EqualValues ( t , "repo_new" , payloads [ 0 ] . Repository . Name )
assert . EqualValues ( t , "org3/repo_new" , payloads [ 0 ] . Repository . FullName )
} )
}
func Test_WebhookPackage ( t * testing . T ) {
var payloads [ ] api . PackagePayload
var triggeredEvent string
provider := newMockWebhookProvider ( func ( r * http . Request ) {
content , _ := io . ReadAll ( r . Body )
var payload api . PackagePayload
err := json . Unmarshal ( content , & payload )
assert . NoError ( t , err )
payloads = append ( payloads , payload )
triggeredEvent = "package"
} , http . StatusOK )
defer provider . Close ( )
onGiteaRun ( t , func ( t * testing . T , giteaURL * url . URL ) {
// 1. create a new webhook with special webhook for repo1
session := loginUser ( t , "user1" )
testAPICreateWebhookForOrg ( t , session , "org3" , provider . URL ( ) , "package" )
// 2. trigger the webhook
token := getTokenForLoggedInUser ( t , session , auth_model . AccessTokenScopeAll )
url := fmt . Sprintf ( "/api/packages/%s/generic/%s/%s" , "org3" , "gitea" , "v1.24.0" )
req := NewRequestWithBody ( t , "PUT" , url + "/gitea" , strings . NewReader ( "This is a dummy file" ) ) .
AddTokenAuth ( token )
MakeRequest ( t , req , http . StatusCreated )
// 3. validate the webhook is triggered
assert . EqualValues ( t , "package" , triggeredEvent )
assert . Len ( t , payloads , 1 )
assert . EqualValues ( t , "created" , payloads [ 0 ] . Action )
assert . EqualValues ( t , "gitea" , payloads [ 0 ] . Package . Name )
assert . EqualValues ( t , "generic" , payloads [ 0 ] . Package . Type )
assert . EqualValues ( t , "org3" , payloads [ 0 ] . Organization . UserName )
assert . EqualValues ( t , "v1.24.0" , payloads [ 0 ] . Package . Version )
} )
}
func Test_WebhookStatus ( t * testing . T ) {
var payloads [ ] api . CommitStatusPayload
var triggeredEvent string
provider := newMockWebhookProvider ( func ( r * http . Request ) {
assert . Contains ( t , r . Header [ "X-Github-Event-Type" ] , "status" , "X-GitHub-Event-Type should contain status" )
assert . Contains ( t , r . Header [ "X-Gitea-Event-Type" ] , "status" , "X-Gitea-Event-Type should contain status" )
assert . Contains ( t , r . Header [ "X-Gogs-Event-Type" ] , "status" , "X-Gogs-Event-Type should contain status" )
content , _ := io . ReadAll ( r . Body )
var payload api . CommitStatusPayload
err := json . Unmarshal ( content , & payload )
assert . NoError ( t , err )
payloads = append ( payloads , payload )
triggeredEvent = "status"
} , http . StatusOK )
defer provider . Close ( )
onGiteaRun ( t , func ( t * testing . T , giteaURL * url . URL ) {
// 1. create a new webhook with special webhook for repo1
session := loginUser ( t , "user2" )
testAPICreateWebhookForRepo ( t , session , "user2" , "repo1" , provider . URL ( ) , "status" )
repo1 := unittest . AssertExistsAndLoadBean ( t , & repo . Repository { ID : 1 } )
gitRepo1 , err := gitrepo . OpenRepository ( context . Background ( ) , repo1 )
assert . NoError ( t , err )
commitID , err := gitRepo1 . GetBranchCommitID ( repo1 . DefaultBranch )
assert . NoError ( t , err )
// 2. trigger the webhook
testCtx := NewAPITestContext ( t , "user2" , "repo1" , auth_model . AccessTokenScopeAll )
// update a status for a commit via API
doAPICreateCommitStatus ( testCtx , commitID , api . CreateStatusOption {
State : api . CommitStatusSuccess ,
TargetURL : "http://test.ci/" ,
Description : "" ,
Context : "testci" ,
} ) ( t )
// 3. validate the webhook is triggered
assert . EqualValues ( t , "status" , triggeredEvent )
assert . Len ( t , payloads , 1 )
assert . EqualValues ( t , commitID , payloads [ 0 ] . Commit . ID )
assert . EqualValues ( t , "repo1" , payloads [ 0 ] . Repo . Name )
assert . EqualValues ( t , "user2/repo1" , payloads [ 0 ] . Repo . FullName )
assert . EqualValues ( t , "testci" , payloads [ 0 ] . Context )
assert . EqualValues ( t , commitID , payloads [ 0 ] . SHA )
} )
}