2023-06-26 02:33:18 -04:00
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package integration
import (
2023-11-18 06:37:08 -05:00
"fmt"
2024-11-03 17:03:19 -05:00
"net/http"
2023-06-26 02:33:18 -04:00
"net/url"
2023-07-18 14:14:47 -04:00
"strings"
2023-06-26 02:33:18 -04:00
"testing"
"time"
actions_model "code.gitea.io/gitea/models/actions"
2024-11-03 17:03:19 -05:00
auth_model "code.gitea.io/gitea/models/auth"
2024-03-19 03:23:40 -04:00
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
2023-06-26 02:33:18 -04:00
issues_model "code.gitea.io/gitea/models/issues"
2024-03-19 03:23:40 -04:00
repo_model "code.gitea.io/gitea/models/repo"
2023-06-26 02:33:18 -04:00
unit_model "code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
actions_module "code.gitea.io/gitea/modules/actions"
"code.gitea.io/gitea/modules/git"
2024-03-19 03:23:40 -04:00
"code.gitea.io/gitea/modules/gitrepo"
2023-11-18 06:37:08 -05:00
"code.gitea.io/gitea/modules/setting"
2024-11-03 17:03:19 -05:00
api "code.gitea.io/gitea/modules/structs"
2024-03-13 23:18:04 -04:00
"code.gitea.io/gitea/modules/test"
2024-02-11 08:06:54 -05:00
webhook_module "code.gitea.io/gitea/modules/webhook"
actions_service "code.gitea.io/gitea/services/actions"
2024-11-03 17:03:19 -05:00
issue_service "code.gitea.io/gitea/services/issue"
2023-06-26 02:33:18 -04:00
pull_service "code.gitea.io/gitea/services/pull"
2024-03-19 03:23:40 -04:00
release_service "code.gitea.io/gitea/services/release"
2023-06-26 02:33:18 -04:00
repo_service "code.gitea.io/gitea/services/repository"
files_service "code.gitea.io/gitea/services/repository/files"
2024-08-24 20:47:35 -04:00
"code.gitea.io/gitea/tests"
2023-06-26 02:33:18 -04:00
"github.com/stretchr/testify/assert"
2024-07-30 15:41:10 -04:00
"github.com/stretchr/testify/require"
2023-06-26 02:33:18 -04:00
)
2024-11-03 17:03:19 -05:00
func TestPullRequestCommitStatus ( t * testing . T ) {
onGiteaRun ( t , func ( t * testing . T , u * url . URL ) {
user2 := unittest . AssertExistsAndLoadBean ( t , & user_model . User { ID : 2 } ) // owner of the base repo
session := loginUser ( t , "user2" )
token := getTokenForLoggedInUser ( t , session , auth_model . AccessTokenScopeWriteIssue )
// prepare the repository
files := make ( [ ] * files_service . ChangeRepoFile , 0 , 10 )
for _ , onType := range [ ] string {
"opened" ,
"synchronize" ,
"labeled" ,
"unlabeled" ,
"assigned" ,
"unassigned" ,
"milestoned" ,
"demilestoned" ,
"closed" ,
"reopened" ,
} {
files = append ( files , & files_service . ChangeRepoFile {
Operation : "create" ,
TreePath : fmt . Sprintf ( ".forgejo/workflows/%s.yml" , onType ) ,
ContentReader : strings . NewReader ( fmt . Sprintf ( ` name : % [ 1 ] s
on :
pull_request :
types :
- % [ 1 ] s
jobs :
% [ 1 ] s :
runs - on : docker
steps :
- run : true
` , onType ) ) ,
} )
}
baseRepo , _ , f := tests . CreateDeclarativeRepo ( t , user2 , "repo-pull-request" ,
[ ] unit_model . Type { unit_model . TypeActions } , nil , files )
defer f ( )
baseGitRepo , err := gitrepo . OpenRepository ( db . DefaultContext , baseRepo )
require . NoError ( t , err )
defer func ( ) {
baseGitRepo . Close ( )
} ( )
2024-11-06 09:36:02 -05:00
// prepare the repository labels
labelStr := "/api/v1/repos/user2/repo-pull-request/labels"
labelsCount := 2
labels := make ( [ ] * api . Label , labelsCount )
for i := 0 ; i < labelsCount ; i ++ {
color := "abcdef"
req := NewRequestWithJSON ( t , "POST" , labelStr , & api . CreateLabelOption {
Name : fmt . Sprintf ( "label%d" , i ) ,
Color : color ,
} ) . AddTokenAuth ( token )
resp := MakeRequest ( t , req , http . StatusCreated )
labels [ i ] = new ( api . Label )
DecodeJSON ( t , resp , & labels [ i ] )
assert . Equal ( t , color , labels [ i ] . Color )
}
// create the pull request
2024-11-03 17:03:19 -05:00
testEditFileToNewBranch ( t , session , "user2" , "repo-pull-request" , "main" , "wip-something" , "README.md" , "Hello, world 1" )
testPullCreate ( t , session , "user2" , "repo-pull-request" , true , "main" , "wip-something" , "Commit status PR" )
pr := unittest . AssertExistsAndLoadBean ( t , & issues_model . PullRequest { BaseRepoID : baseRepo . ID } )
require . NoError ( t , pr . LoadIssue ( db . DefaultContext ) )
// prepare the assignees
issueURL := fmt . Sprintf ( "/api/v1/repos/%s/%s/issues/%s" , "user2" , "repo-pull-request" , fmt . Sprintf ( "%d" , pr . Issue . Index ) )
// prepare the labels
labelURL := fmt . Sprintf ( "%s/labels" , issueURL )
// prepare the milestone
milestoneStr := "/api/v1/repos/user2/repo-pull-request/milestones"
2024-11-06 09:36:02 -05:00
req := NewRequestWithJSON ( t , "POST" , milestoneStr , & api . CreateMilestoneOption {
2024-11-03 17:03:19 -05:00
Title : "mymilestone" ,
State : "open" ,
} ) . AddTokenAuth ( token )
2024-11-06 09:36:02 -05:00
resp := MakeRequest ( t , req , http . StatusCreated )
2024-11-03 17:03:19 -05:00
milestone := new ( api . Milestone )
DecodeJSON ( t , resp , & milestone )
// check that one of the status associated with the commit sha matches both
// context & state
checkCommitStatus := func ( sha , context string , state api . CommitStatusState ) bool {
commitStatuses , _ , err := git_model . GetLatestCommitStatus ( db . DefaultContext , pr . BaseRepoID , sha , db . ListOptionsAll )
require . NoError ( t , err )
for _ , commitStatus := range commitStatuses {
if state == commitStatus . State && context == commitStatus . Context {
return true
}
}
return false
}
2024-11-06 09:36:02 -05:00
assertActionRun := func ( t * testing . T , sha , onType string , action api . HookIssueAction , actionRun * actions_model . ActionRun ) {
assert . Equal ( t , fmt . Sprintf ( "%s.yml" , onType ) , actionRun . WorkflowID )
assert . Equal ( t , sha , actionRun . CommitSHA )
assert . Equal ( t , actions_module . GithubEventPullRequest , actionRun . TriggerEvent )
event , err := actionRun . GetPullRequestEventPayload ( )
require . NoError ( t , err )
assert . Equal ( t , action , event . Action )
}
type assertType func ( t * testing . T , sha , onType string , action api . HookIssueAction , actionRuns [ ] * actions_model . ActionRun )
assertActionRuns := func ( t * testing . T , sha , onType string , action api . HookIssueAction , actionRuns [ ] * actions_model . ActionRun ) {
require . Len ( t , actionRuns , 1 )
assertActionRun ( t , sha , onType , action , actionRuns [ 0 ] )
}
2024-11-03 17:03:19 -05:00
for _ , testCase := range [ ] struct {
2024-11-06 09:36:02 -05:00
onType string
jobID string
doSomething func ( )
actionRunCount int
action api . HookIssueAction
assert assertType
2024-11-03 17:03:19 -05:00
} {
{
2024-11-06 09:36:02 -05:00
onType : "opened" ,
doSomething : func ( ) { } ,
actionRunCount : 1 ,
action : api . HookIssueOpened ,
assert : assertActionRuns ,
2024-11-03 17:03:19 -05:00
} ,
{
onType : "synchronize" ,
doSomething : func ( ) {
testEditFile ( t , session , "user2" , "repo-pull-request" , "wip-something" , "README.md" , "Hello, world 2" )
} ,
2024-11-06 09:36:02 -05:00
actionRunCount : 1 ,
action : api . HookIssueSynchronized ,
assert : assertActionRuns ,
2024-11-03 17:03:19 -05:00
} ,
{
onType : "labeled" ,
doSomething : func ( ) {
req := NewRequestWithJSON ( t , "POST" , labelURL , & api . IssueLabelsOption {
2024-11-06 09:36:02 -05:00
Labels : [ ] any { labels [ 0 ] . ID , labels [ 1 ] . ID } ,
2024-11-03 17:03:19 -05:00
} ) . AddTokenAuth ( token )
MakeRequest ( t , req , http . StatusOK )
} ,
2024-11-06 09:36:02 -05:00
actionRunCount : 2 ,
action : api . HookIssueLabelUpdated ,
assert : func ( t * testing . T , sha , onType string , action api . HookIssueAction , actionRuns [ ] * actions_model . ActionRun ) {
assertActionRun ( t , sha , onType , api . HookIssueLabelUpdated , actionRuns [ 0 ] )
assertActionRun ( t , sha , onType , api . HookIssueLabelUpdated , actionRuns [ 1 ] )
} ,
2024-11-03 17:03:19 -05:00
} ,
{
onType : "unlabeled" ,
doSomething : func ( ) {
req := NewRequestWithJSON ( t , "PUT" , labelURL , & api . IssueLabelsOption {
2024-11-06 09:36:02 -05:00
Labels : [ ] any { labels [ 0 ] . ID } ,
2024-11-03 17:03:19 -05:00
} ) . AddTokenAuth ( token )
MakeRequest ( t , req , http . StatusOK )
} ,
2024-11-06 09:36:02 -05:00
actionRunCount : 3 ,
action : api . HookIssueLabelCleared ,
assert : func ( t * testing . T , sha , onType string , action api . HookIssueAction , actionRuns [ ] * actions_model . ActionRun ) {
foundPayloadWithLabels := false
knownLabels := [ ] string { "label0" , "label1" }
for _ , actionRun := range actionRuns {
assert . Equal ( t , sha , actionRun . CommitSHA )
assert . Equal ( t , actions_module . GithubEventPullRequest , actionRun . TriggerEvent )
event , err := actionRun . GetPullRequestEventPayload ( )
require . NoError ( t , err )
switch event . Action {
case api . HookIssueLabelUpdated :
assert . Equal ( t , "labeled.yml" , actionRun . WorkflowID )
assert . Equal ( t , "label0" , event . Label . Name )
require . Len ( t , event . PullRequest . Labels , 1 )
assert . Contains ( t , "label0" , event . PullRequest . Labels [ 0 ] . Name )
case api . HookIssueLabelCleared :
assert . Equal ( t , "unlabeled.yml" , actionRun . WorkflowID )
assert . Contains ( t , knownLabels , event . Label . Name )
if len ( event . PullRequest . Labels ) > 0 {
foundPayloadWithLabels = true
assert . Contains ( t , knownLabels , event . PullRequest . Labels [ 0 ] . Name )
}
default :
require . Fail ( t , fmt . Sprintf ( "unexpected action '%s'" , event . Action ) )
}
}
assert . True ( t , foundPayloadWithLabels , "expected at least one clear label payload with non empty labels" )
} ,
2024-11-03 17:03:19 -05:00
} ,
{
onType : "assigned" ,
doSomething : func ( ) {
req := NewRequestWithJSON ( t , "PATCH" , issueURL , & api . EditIssueOption {
Assignees : [ ] string { "user2" } ,
} ) . AddTokenAuth ( token )
MakeRequest ( t , req , http . StatusCreated )
} ,
2024-11-06 09:36:02 -05:00
actionRunCount : 1 ,
action : api . HookIssueAssigned ,
assert : assertActionRuns ,
2024-11-03 17:03:19 -05:00
} ,
{
onType : "unassigned" ,
doSomething : func ( ) {
req := NewRequestWithJSON ( t , "PATCH" , issueURL , & api . EditIssueOption {
Assignees : [ ] string { } ,
} ) . AddTokenAuth ( token )
MakeRequest ( t , req , http . StatusCreated )
} ,
2024-11-06 09:36:02 -05:00
actionRunCount : 1 ,
action : api . HookIssueUnassigned ,
assert : assertActionRuns ,
2024-11-03 17:03:19 -05:00
} ,
{
onType : "milestoned" ,
doSomething : func ( ) {
req := NewRequestWithJSON ( t , "PATCH" , issueURL , & api . EditIssueOption {
Milestone : & milestone . ID ,
} ) . AddTokenAuth ( token )
MakeRequest ( t , req , http . StatusCreated )
} ,
2024-11-06 09:36:02 -05:00
actionRunCount : 1 ,
action : api . HookIssueMilestoned ,
assert : assertActionRuns ,
2024-11-03 17:03:19 -05:00
} ,
{
onType : "demilestoned" ,
doSomething : func ( ) {
var zero int64
req := NewRequestWithJSON ( t , "PATCH" , issueURL , & api . EditIssueOption {
Milestone : & zero ,
} ) . AddTokenAuth ( token )
MakeRequest ( t , req , http . StatusCreated )
} ,
2024-11-06 09:36:02 -05:00
actionRunCount : 1 ,
action : api . HookIssueDemilestoned ,
assert : assertActionRuns ,
2024-11-03 17:03:19 -05:00
} ,
{
onType : "closed" ,
doSomething : func ( ) {
sha , err := baseGitRepo . GetRefCommitID ( pr . GetGitRefName ( ) )
require . NoError ( t , err )
err = issue_service . ChangeStatus ( db . DefaultContext , pr . Issue , user2 , sha , true )
require . NoError ( t , err )
} ,
2024-11-06 09:36:02 -05:00
actionRunCount : 1 ,
action : api . HookIssueClosed ,
assert : assertActionRuns ,
2024-11-03 17:03:19 -05:00
} ,
{
onType : "reopened" ,
doSomething : func ( ) {
sha , err := baseGitRepo . GetRefCommitID ( pr . GetGitRefName ( ) )
require . NoError ( t , err )
err = issue_service . ChangeStatus ( db . DefaultContext , pr . Issue , user2 , sha , false )
require . NoError ( t , err )
} ,
2024-11-06 09:36:02 -05:00
actionRunCount : 1 ,
action : api . HookIssueReOpened ,
assert : assertActionRuns ,
2024-11-03 17:03:19 -05:00
} ,
} {
t . Run ( testCase . onType , func ( t * testing . T ) {
2024-11-06 09:36:02 -05:00
defer func ( ) {
// cleanup leftovers, start from scratch
_ , err = db . DeleteByBean ( db . DefaultContext , actions_model . ActionRun { RepoID : baseRepo . ID } )
require . NoError ( t , err )
_ , err = db . DeleteByBean ( db . DefaultContext , actions_model . ActionRunJob { RepoID : baseRepo . ID } )
require . NoError ( t , err )
} ( )
2024-11-03 17:03:19 -05:00
// trigger the onType event
testCase . doSomething ( )
2024-11-06 09:36:02 -05:00
count := testCase . actionRunCount
2024-11-03 17:03:19 -05:00
context := fmt . Sprintf ( "%[1]s / %[1]s (pull_request)" , testCase . onType )
2024-11-06 09:36:02 -05:00
var actionRuns [ ] * actions_model . ActionRun
// wait for ActionRun(s) to be created
require . Eventually ( t , func ( ) bool {
actionRuns = make ( [ ] * actions_model . ActionRun , 0 )
require . NoError ( t , db . GetEngine ( db . DefaultContext ) . Where ( "repo_id=?" , baseRepo . ID ) . Find ( & actionRuns ) )
2024-11-08 18:07:18 -05:00
return len ( actionRuns ) == count
2024-11-03 17:03:19 -05:00
} , 30 * time . Second , 1 * time . Second )
2024-11-06 09:36:02 -05:00
// verify the expected ActionRuns were created
2024-11-03 17:03:19 -05:00
sha , err := baseGitRepo . GetRefCommitID ( pr . GetGitRefName ( ) )
require . NoError ( t , err )
// verify the commit status changes to CommitStatusSuccess when the job changes to StatusSuccess
assert . True ( t , checkCommitStatus ( sha , context , api . CommitStatusPending ) )
2024-11-06 09:36:02 -05:00
for _ , actionRun := range actionRuns {
// verify the expected ActionRunJob was created and is StatusWaiting
job := unittest . AssertExistsAndLoadBean ( t , & actions_model . ActionRunJob { RunID : actionRun . ID , CommitSHA : sha } )
assert . Equal ( t , actions_model . StatusWaiting , job . Status )
// change the state of the job to success
job . Status = actions_model . StatusSuccess
actions_service . CreateCommitStatus ( db . DefaultContext , job )
}
// verify the commit status changed to CommitStatusSuccess because the job(s) changed to StatusSuccess
2024-11-03 17:03:19 -05:00
assert . True ( t , checkCommitStatus ( sha , context , api . CommitStatusSuccess ) )
2024-11-06 09:36:02 -05:00
testCase . assert ( t , sha , testCase . onType , testCase . action , actionRuns )
2024-11-03 17:03:19 -05:00
} )
}
} )
}
2023-06-26 02:33:18 -04:00
func TestPullRequestTargetEvent ( t * testing . T ) {
onGiteaRun ( t , func ( t * testing . T , u * url . URL ) {
user2 := unittest . AssertExistsAndLoadBean ( t , & user_model . User { ID : 2 } ) // owner of the base repo
2023-09-13 22:59:53 -04:00
org3 := unittest . AssertExistsAndLoadBean ( t , & user_model . User { ID : 3 } ) // owner of the forked repo
2023-06-26 02:33:18 -04:00
// create the base repo
2024-08-24 20:47:35 -04:00
baseRepo , _ , f := tests . CreateDeclarativeRepo ( t , user2 , "repo-pull-request-target" ,
2024-01-12 05:53:14 -05:00
[ ] unit_model . Type { unit_model . TypeActions } , nil , nil ,
)
defer f ( )
2023-06-26 02:33:18 -04:00
// create the forked repo
2024-08-08 03:46:38 -04:00
forkedRepo , err := repo_service . ForkRepositoryAndUpdates ( git . DefaultContext , user2 , org3 , repo_service . ForkRepoOptions {
2023-06-26 02:33:18 -04:00
BaseRepo : baseRepo ,
Name : "forked-repo-pull-request-target" ,
Description : "test pull-request-target event" ,
} )
2024-07-30 15:41:10 -04:00
require . NoError ( t , err )
2023-06-26 02:33:18 -04:00
assert . NotEmpty ( t , forkedRepo )
// add workflow file to the base repo
addWorkflowToBaseResp , err := files_service . ChangeRepoFiles ( git . DefaultContext , baseRepo , user2 , & files_service . ChangeRepoFilesOptions {
Files : [ ] * files_service . ChangeRepoFile {
{
2023-07-18 14:14:47 -04:00
Operation : "create" ,
TreePath : ".gitea/workflows/pr.yml" ,
2023-08-05 02:26:06 -04:00
ContentReader : strings . NewReader ( "name: test\non:\n pull_request_target:\n paths:\n - 'file_*.txt'\njobs:\n test:\n runs-on: ubuntu-latest\n steps:\n - run: echo helloworld\n" ) ,
2023-06-26 02:33:18 -04:00
} ,
} ,
Message : "add workflow" ,
OldBranch : "main" ,
NewBranch : "main" ,
Author : & files_service . IdentityOptions {
Name : user2 . Name ,
Email : user2 . Email ,
} ,
Committer : & files_service . IdentityOptions {
Name : user2 . Name ,
Email : user2 . Email ,
} ,
Dates : & files_service . CommitDateOptions {
Author : time . Now ( ) ,
Committer : time . Now ( ) ,
} ,
} )
2024-07-30 15:41:10 -04:00
require . NoError ( t , err )
2023-06-26 02:33:18 -04:00
assert . NotEmpty ( t , addWorkflowToBaseResp )
// add a new file to the forked repo
2023-09-13 22:59:53 -04:00
addFileToForkedResp , err := files_service . ChangeRepoFiles ( git . DefaultContext , forkedRepo , org3 , & files_service . ChangeRepoFilesOptions {
2023-06-26 02:33:18 -04:00
Files : [ ] * files_service . ChangeRepoFile {
{
2023-07-18 14:14:47 -04:00
Operation : "create" ,
TreePath : "file_1.txt" ,
ContentReader : strings . NewReader ( "file1" ) ,
2023-06-26 02:33:18 -04:00
} ,
} ,
Message : "add file1" ,
OldBranch : "main" ,
NewBranch : "fork-branch-1" ,
Author : & files_service . IdentityOptions {
2023-09-13 22:59:53 -04:00
Name : org3 . Name ,
Email : org3 . Email ,
2023-06-26 02:33:18 -04:00
} ,
Committer : & files_service . IdentityOptions {
2023-09-13 22:59:53 -04:00
Name : org3 . Name ,
Email : org3 . Email ,
2023-06-26 02:33:18 -04:00
} ,
Dates : & files_service . CommitDateOptions {
Author : time . Now ( ) ,
Committer : time . Now ( ) ,
} ,
} )
2024-07-30 15:41:10 -04:00
require . NoError ( t , err )
2023-06-26 02:33:18 -04:00
assert . NotEmpty ( t , addFileToForkedResp )
// create Pull
pullIssue := & issues_model . Issue {
RepoID : baseRepo . ID ,
Title : "Test pull-request-target-event" ,
2023-09-13 22:59:53 -04:00
PosterID : org3 . ID ,
Poster : org3 ,
2023-06-26 02:33:18 -04:00
IsPull : true ,
}
pullRequest := & issues_model . PullRequest {
HeadRepoID : forkedRepo . ID ,
BaseRepoID : baseRepo . ID ,
HeadBranch : "fork-branch-1" ,
BaseBranch : "main" ,
HeadRepo : forkedRepo ,
BaseRepo : baseRepo ,
Type : issues_model . PullRequestGitea ,
}
err = pull_service . NewPullRequest ( git . DefaultContext , baseRepo , pullIssue , nil , nil , pullRequest , nil )
2024-07-30 15:41:10 -04:00
require . NoError ( t , err )
2024-02-11 08:06:54 -05:00
// if a PR "synchronized" event races the "opened" event by having the same SHA, it must be skipped. See https://codeberg.org/forgejo/forgejo/issues/2009.
assert . True ( t , actions_service . SkipPullRequestEvent ( git . DefaultContext , webhook_module . HookEventPullRequestSync , baseRepo . ID , addFileToForkedResp . Commit . SHA ) )
2023-06-26 02:33:18 -04:00
// load and compare ActionRun
2023-08-05 02:26:06 -04:00
assert . Equal ( t , 1 , unittest . GetCount ( t , & actions_model . ActionRun { RepoID : baseRepo . ID } ) )
2023-06-26 02:33:18 -04:00
actionRun := unittest . AssertExistsAndLoadBean ( t , & actions_model . ActionRun { RepoID : baseRepo . ID } )
2023-07-07 15:22:03 -04:00
assert . Equal ( t , addFileToForkedResp . Commit . SHA , actionRun . CommitSHA )
2023-06-26 02:33:18 -04:00
assert . Equal ( t , actions_module . GithubEventPullRequestTarget , actionRun . TriggerEvent )
2023-08-05 02:26:06 -04:00
// add another file whose name cannot match the specified path
2023-09-13 22:59:53 -04:00
addFileToForkedResp , err = files_service . ChangeRepoFiles ( git . DefaultContext , forkedRepo , org3 , & files_service . ChangeRepoFilesOptions {
2023-08-05 02:26:06 -04:00
Files : [ ] * files_service . ChangeRepoFile {
{
Operation : "create" ,
TreePath : "foo.txt" ,
ContentReader : strings . NewReader ( "foo" ) ,
} ,
} ,
Message : "add foo.txt" ,
OldBranch : "main" ,
NewBranch : "fork-branch-2" ,
Author : & files_service . IdentityOptions {
2023-09-13 22:59:53 -04:00
Name : org3 . Name ,
Email : org3 . Email ,
2023-08-05 02:26:06 -04:00
} ,
Committer : & files_service . IdentityOptions {
2023-09-13 22:59:53 -04:00
Name : org3 . Name ,
Email : org3 . Email ,
2023-08-05 02:26:06 -04:00
} ,
Dates : & files_service . CommitDateOptions {
Author : time . Now ( ) ,
Committer : time . Now ( ) ,
} ,
} )
2024-07-30 15:41:10 -04:00
require . NoError ( t , err )
2023-08-05 02:26:06 -04:00
assert . NotEmpty ( t , addFileToForkedResp )
// create Pull
pullIssue = & issues_model . Issue {
RepoID : baseRepo . ID ,
Title : "A mismatched path cannot trigger pull-request-target-event" ,
2023-09-13 22:59:53 -04:00
PosterID : org3 . ID ,
Poster : org3 ,
2023-08-05 02:26:06 -04:00
IsPull : true ,
}
pullRequest = & issues_model . PullRequest {
HeadRepoID : forkedRepo . ID ,
BaseRepoID : baseRepo . ID ,
HeadBranch : "fork-branch-2" ,
BaseBranch : "main" ,
HeadRepo : forkedRepo ,
BaseRepo : baseRepo ,
Type : issues_model . PullRequestGitea ,
}
err = pull_service . NewPullRequest ( git . DefaultContext , baseRepo , pullIssue , nil , nil , pullRequest , nil )
2024-07-30 15:41:10 -04:00
require . NoError ( t , err )
2023-08-05 02:26:06 -04:00
// the new pull request cannot trigger actions, so there is still only 1 record
assert . Equal ( t , 1 , unittest . GetCount ( t , & actions_model . ActionRun { RepoID : baseRepo . ID } ) )
2023-06-26 02:33:18 -04:00
} )
}
2023-11-18 06:37:08 -05:00
func TestSkipCI ( t * testing . T ) {
onGiteaRun ( t , func ( t * testing . T , u * url . URL ) {
2024-03-13 23:18:04 -04:00
session := loginUser ( t , "user2" )
2023-11-18 06:37:08 -05:00
user2 := unittest . AssertExistsAndLoadBean ( t , & user_model . User { ID : 2 } )
// create the repo
2024-08-24 20:47:35 -04:00
repo , _ , f := tests . CreateDeclarativeRepo ( t , user2 , "skip-ci" ,
2024-01-12 05:53:14 -05:00
[ ] unit_model . Type { unit_model . TypeActions } , nil ,
[ ] * files_service . ChangeRepoFile {
2023-11-18 06:37:08 -05:00
{
Operation : "create" ,
TreePath : ".gitea/workflows/pr.yml" ,
2024-03-13 23:18:04 -04:00
ContentReader : strings . NewReader ( "name: test\non:\n push:\n branches: [main]\n pull_request:\njobs:\n test:\n runs-on: ubuntu-latest\n steps:\n - run: echo helloworld\n" ) ,
2023-11-18 06:37:08 -05:00
} ,
} ,
2024-01-12 05:53:14 -05:00
)
defer f ( )
2023-11-18 06:37:08 -05:00
// a run has been created
assert . Equal ( t , 1 , unittest . GetCount ( t , & actions_model . ActionRun { RepoID : repo . ID } ) )
// add a file with a configured skip-ci string in commit message
addFileResp , err := files_service . ChangeRepoFiles ( git . DefaultContext , repo , user2 , & files_service . ChangeRepoFilesOptions {
Files : [ ] * files_service . ChangeRepoFile {
{
Operation : "create" ,
TreePath : "bar.txt" ,
ContentReader : strings . NewReader ( "bar" ) ,
} ,
} ,
Message : fmt . Sprintf ( "%s add bar" , setting . Actions . SkipWorkflowStrings [ 0 ] ) ,
OldBranch : "main" ,
NewBranch : "main" ,
Author : & files_service . IdentityOptions {
Name : user2 . Name ,
Email : user2 . Email ,
} ,
Committer : & files_service . IdentityOptions {
Name : user2 . Name ,
Email : user2 . Email ,
} ,
Dates : & files_service . CommitDateOptions {
Author : time . Now ( ) ,
Committer : time . Now ( ) ,
} ,
} )
2024-07-30 15:41:10 -04:00
require . NoError ( t , err )
2023-11-18 06:37:08 -05:00
assert . NotEmpty ( t , addFileResp )
// the commit message contains a configured skip-ci string, so there is still only 1 record
assert . Equal ( t , 1 , unittest . GetCount ( t , & actions_model . ActionRun { RepoID : repo . ID } ) )
2024-03-13 23:18:04 -04:00
// add file to new branch
addFileToBranchResp , err := files_service . ChangeRepoFiles ( git . DefaultContext , repo , user2 , & files_service . ChangeRepoFilesOptions {
Files : [ ] * files_service . ChangeRepoFile {
{
Operation : "create" ,
TreePath : "test-skip-ci" ,
ContentReader : strings . NewReader ( "test-skip-ci" ) ,
} ,
} ,
Message : "add test file" ,
OldBranch : "main" ,
NewBranch : "test-skip-ci" ,
Author : & files_service . IdentityOptions {
Name : user2 . Name ,
Email : user2 . Email ,
} ,
Committer : & files_service . IdentityOptions {
Name : user2 . Name ,
Email : user2 . Email ,
} ,
Dates : & files_service . CommitDateOptions {
Author : time . Now ( ) ,
Committer : time . Now ( ) ,
} ,
} )
2024-07-30 15:41:10 -04:00
require . NoError ( t , err )
2024-03-13 23:18:04 -04:00
assert . NotEmpty ( t , addFileToBranchResp )
resp := testPullCreate ( t , session , "user2" , "skip-ci" , true , "main" , "test-skip-ci" , "[skip ci] test-skip-ci" )
// check the redirected URL
url := test . RedirectURL ( resp )
assert . Regexp ( t , "^/user2/skip-ci/pulls/[0-9]*$" , url )
// the pr title contains a configured skip-ci string, so there is still only 1 record
assert . Equal ( t , 1 , unittest . GetCount ( t , & actions_model . ActionRun { RepoID : repo . ID } ) )
2023-11-18 06:37:08 -05:00
} )
}
2024-03-19 03:23:40 -04:00
func TestCreateDeleteRefEvent ( t * testing . T ) {
onGiteaRun ( t , func ( t * testing . T , u * url . URL ) {
user2 := unittest . AssertExistsAndLoadBean ( t , & user_model . User { ID : 2 } )
// create the repo
repo , err := repo_service . CreateRepository ( db . DefaultContext , user2 , user2 , repo_service . CreateRepoOptions {
Name : "create-delete-ref-event" ,
Description : "test create delete ref ci event" ,
AutoInit : true ,
Gitignores : "Go" ,
License : "MIT" ,
Readme : "Default" ,
DefaultBranch : "main" ,
IsPrivate : false ,
} )
2024-07-30 15:41:10 -04:00
require . NoError ( t , err )
2024-03-19 03:23:40 -04:00
assert . NotEmpty ( t , repo )
// enable actions
err = repo_service . UpdateRepositoryUnits ( db . DefaultContext , repo , [ ] repo_model . RepoUnit { {
RepoID : repo . ID ,
Type : unit_model . TypeActions ,
} } , nil )
2024-07-30 15:41:10 -04:00
require . NoError ( t , err )
2024-03-19 03:23:40 -04:00
// add workflow file to the repo
addWorkflowToBaseResp , err := files_service . ChangeRepoFiles ( git . DefaultContext , repo , user2 , & files_service . ChangeRepoFilesOptions {
Files : [ ] * files_service . ChangeRepoFile {
{
Operation : "create" ,
TreePath : ".gitea/workflows/createdelete.yml" ,
ContentReader : strings . NewReader ( "name: test\non:\n [create,delete]\njobs:\n test:\n runs-on: ubuntu-latest\n steps:\n - run: echo helloworld\n" ) ,
} ,
} ,
Message : "add workflow" ,
OldBranch : "main" ,
NewBranch : "main" ,
Author : & files_service . IdentityOptions {
Name : user2 . Name ,
Email : user2 . Email ,
} ,
Committer : & files_service . IdentityOptions {
Name : user2 . Name ,
Email : user2 . Email ,
} ,
Dates : & files_service . CommitDateOptions {
Author : time . Now ( ) ,
Committer : time . Now ( ) ,
} ,
} )
2024-07-30 15:41:10 -04:00
require . NoError ( t , err )
2024-03-19 03:23:40 -04:00
assert . NotEmpty ( t , addWorkflowToBaseResp )
// Get the commit ID of the default branch
gitRepo , err := gitrepo . OpenRepository ( git . DefaultContext , repo )
2024-07-30 15:41:10 -04:00
require . NoError ( t , err )
2024-03-19 03:23:40 -04:00
defer gitRepo . Close ( )
branch , err := git_model . GetBranch ( db . DefaultContext , repo . ID , repo . DefaultBranch )
2024-07-30 15:41:10 -04:00
require . NoError ( t , err )
2024-03-19 03:23:40 -04:00
// create a branch
err = repo_service . CreateNewBranchFromCommit ( db . DefaultContext , user2 , repo , gitRepo , branch . CommitID , "test-create-branch" )
2024-07-30 15:41:10 -04:00
require . NoError ( t , err )
2024-03-19 03:23:40 -04:00
run := unittest . AssertExistsAndLoadBean ( t , & actions_model . ActionRun {
Title : "add workflow" ,
RepoID : repo . ID ,
Event : "create" ,
Ref : "refs/heads/test-create-branch" ,
WorkflowID : "createdelete.yml" ,
CommitSHA : branch . CommitID ,
} )
assert . NotNil ( t , run )
// create a tag
err = release_service . CreateNewTag ( db . DefaultContext , user2 , repo , branch . CommitID , "test-create-tag" , "test create tag event" )
2024-07-30 15:41:10 -04:00
require . NoError ( t , err )
2024-03-19 03:23:40 -04:00
run = unittest . AssertExistsAndLoadBean ( t , & actions_model . ActionRun {
Title : "add workflow" ,
RepoID : repo . ID ,
Event : "create" ,
Ref : "refs/tags/test-create-tag" ,
WorkflowID : "createdelete.yml" ,
CommitSHA : branch . CommitID ,
} )
assert . NotNil ( t , run )
// delete the branch
err = repo_service . DeleteBranch ( db . DefaultContext , user2 , repo , gitRepo , "test-create-branch" )
2024-07-30 15:41:10 -04:00
require . NoError ( t , err )
2024-03-19 03:23:40 -04:00
run = unittest . AssertExistsAndLoadBean ( t , & actions_model . ActionRun {
Title : "add workflow" ,
RepoID : repo . ID ,
Event : "delete" ,
2024-08-19 12:25:41 -04:00
Ref : "refs/heads/main" ,
2024-03-19 03:23:40 -04:00
WorkflowID : "createdelete.yml" ,
CommitSHA : branch . CommitID ,
} )
assert . NotNil ( t , run )
// delete the tag
tag , err := repo_model . GetRelease ( db . DefaultContext , repo . ID , "test-create-tag" )
2024-07-30 15:41:10 -04:00
require . NoError ( t , err )
2024-03-19 03:23:40 -04:00
err = release_service . DeleteReleaseByID ( db . DefaultContext , repo , tag , user2 , true )
2024-07-30 15:41:10 -04:00
require . NoError ( t , err )
2024-03-19 03:23:40 -04:00
run = unittest . AssertExistsAndLoadBean ( t , & actions_model . ActionRun {
Title : "add workflow" ,
RepoID : repo . ID ,
Event : "delete" ,
2024-08-19 12:25:41 -04:00
Ref : "refs/heads/main" ,
2024-03-19 03:23:40 -04:00
WorkflowID : "createdelete.yml" ,
CommitSHA : branch . CommitID ,
} )
assert . NotNil ( t , run )
} )
}
2024-06-28 01:17:11 -04:00
func TestWorkflowDispatchEvent ( t * testing . T ) {
onGiteaRun ( t , func ( t * testing . T , u * url . URL ) {
user2 := unittest . AssertExistsAndLoadBean ( t , & user_model . User { ID : 2 } )
// create the repo
2024-08-24 20:47:35 -04:00
repo , sha , f := tests . CreateDeclarativeRepo ( t , user2 , "repo-workflow-dispatch" ,
2024-06-28 01:17:11 -04:00
[ ] unit_model . Type { unit_model . TypeActions } , nil ,
[ ] * files_service . ChangeRepoFile {
{
Operation : "create" ,
TreePath : ".gitea/workflows/dispatch.yml" ,
ContentReader : strings . NewReader (
"name: test\n" +
"on: [workflow_dispatch]\n" +
"jobs:\n" +
" test:\n" +
" runs-on: ubuntu-latest\n" +
" steps:\n" +
" - run: echo helloworld\n" ,
) ,
} ,
} ,
)
defer f ( )
gitRepo , err := gitrepo . OpenRepository ( db . DefaultContext , repo )
2024-07-30 15:41:10 -04:00
require . NoError ( t , err )
2024-06-28 01:17:11 -04:00
defer gitRepo . Close ( )
2024-06-29 23:54:31 -04:00
workflow , err := actions_service . GetWorkflowFromCommit ( gitRepo , "main" , "dispatch.yml" )
2024-07-30 15:41:10 -04:00
require . NoError ( t , err )
2024-06-29 23:54:31 -04:00
assert . Equal ( t , "refs/heads/main" , workflow . Ref )
assert . Equal ( t , sha , workflow . Commit . ID . String ( ) )
2024-06-28 01:17:11 -04:00
inputGetter := func ( key string ) string {
return ""
}
err = workflow . Dispatch ( db . DefaultContext , inputGetter , repo , user2 )
2024-07-30 15:41:10 -04:00
require . NoError ( t , err )
2024-06-28 01:17:11 -04:00
assert . Equal ( t , 1 , unittest . GetCount ( t , & actions_model . ActionRun { RepoID : repo . ID } ) )
} )
}