mirror of
https://github.com/go-gitea/gitea
synced 2025-08-25 19:08:28 +00:00
Prevent duplicate actions email (#35215)
Trying to prevent duplicate action emails by adding an extra check on job status. --------- Signed-off-by: NorthRealm <155140859+NorthRealm@users.noreply.github.com> Co-authored-by: Christopher Homberger <christopher.homberger@web.de>
This commit is contained in:
@@ -12,6 +12,7 @@ import (
|
||||
"path"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/repo"
|
||||
@@ -24,7 +25,9 @@ import (
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
webhook_module "code.gitea.io/gitea/modules/webhook"
|
||||
"code.gitea.io/gitea/services/actions"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
@@ -1102,45 +1105,465 @@ type workflowRunWebhook struct {
|
||||
}
|
||||
|
||||
func Test_WebhookWorkflowRun(t *testing.T) {
|
||||
webhookData := &workflowRunWebhook{}
|
||||
provider := newMockWebhookProvider(func(r *http.Request) {
|
||||
assert.Contains(t, r.Header["X-Github-Event-Type"], "workflow_run", "X-GitHub-Event-Type should contain workflow_run")
|
||||
assert.Contains(t, r.Header["X-Gitea-Event-Type"], "workflow_run", "X-Gitea-Event-Type should contain workflow_run")
|
||||
assert.Contains(t, r.Header["X-Gogs-Event-Type"], "workflow_run", "X-Gogs-Event-Type should contain workflow_run")
|
||||
content, _ := io.ReadAll(r.Body)
|
||||
var payload api.WorkflowRunPayload
|
||||
err := json.Unmarshal(content, &payload)
|
||||
assert.NoError(t, err)
|
||||
webhookData.payloads = append(webhookData.payloads, payload)
|
||||
webhookData.triggeredEvent = "workflow_run"
|
||||
}, http.StatusOK)
|
||||
defer provider.Close()
|
||||
webhookData.URL = provider.URL()
|
||||
|
||||
tests := []struct {
|
||||
testCases := []struct {
|
||||
name string
|
||||
callback func(t *testing.T, webhookData *workflowRunWebhook)
|
||||
testFunc func(t *testing.T, webhookData *workflowRunWebhook)
|
||||
}{
|
||||
{
|
||||
name: "WorkflowRun",
|
||||
callback: testWebhookWorkflowRun,
|
||||
testFunc: testWebhookWorkflowRun,
|
||||
},
|
||||
{
|
||||
name: "WorkflowRunDepthLimit",
|
||||
callback: testWebhookWorkflowRunDepthLimit,
|
||||
testFunc: testWebhookWorkflowRunDepthLimit,
|
||||
},
|
||||
{
|
||||
name: "WorkflowRunEvents",
|
||||
testFunc: testWorkflowRunEvents,
|
||||
},
|
||||
{
|
||||
name: "WorkflowRunEventsOnRerun",
|
||||
testFunc: testWorkflowRunEventsOnRerun,
|
||||
},
|
||||
{
|
||||
name: "WorkflowRunEventsOnCancellingAbandonedRunAllJobsAbandoned",
|
||||
testFunc: func(t *testing.T, webhookData *workflowRunWebhook) {
|
||||
testWorkflowRunEventsOnCancellingAbandonedRun(t, webhookData, true)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "WorkflowRunEventsOnCancellingAbandonedRunPartiallyAbandoned",
|
||||
testFunc: func(t *testing.T, webhookData *workflowRunWebhook) {
|
||||
testWorkflowRunEventsOnCancellingAbandonedRun(t, webhookData, false)
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
webhookData.payloads = nil
|
||||
webhookData.triggeredEvent = ""
|
||||
for _, obj := range testCases {
|
||||
t.Run(obj.name, func(t *testing.T) {
|
||||
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
||||
test.callback(t, webhookData)
|
||||
webhookData := &workflowRunWebhook{}
|
||||
provider := newMockWebhookProvider(func(r *http.Request) {
|
||||
assert.Contains(t, r.Header["X-Github-Event-Type"], "workflow_run", "X-GitHub-Event-Type should contain workflow_run")
|
||||
assert.Contains(t, r.Header["X-Gitea-Event-Type"], "workflow_run", "X-Gitea-Event-Type should contain workflow_run")
|
||||
assert.Contains(t, r.Header["X-Gogs-Event-Type"], "workflow_run", "X-Gogs-Event-Type should contain workflow_run")
|
||||
content, _ := io.ReadAll(r.Body)
|
||||
var payload api.WorkflowRunPayload
|
||||
err := json.Unmarshal(content, &payload)
|
||||
assert.NoError(t, err)
|
||||
webhookData.payloads = append(webhookData.payloads, payload)
|
||||
webhookData.triggeredEvent = "workflow_run"
|
||||
}, http.StatusOK)
|
||||
defer provider.Close()
|
||||
webhookData.URL = provider.URL()
|
||||
webhookData.payloads = nil
|
||||
webhookData.triggeredEvent = ""
|
||||
obj.testFunc(t, webhookData)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testWorkflowRunEvents(t *testing.T, webhookData *workflowRunWebhook) {
|
||||
// 1. create a new webhook with special webhook for repo1
|
||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
session := loginUser(t, "user2")
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||
|
||||
testAPICreateWebhookForRepo(t, session, "user2", "repo1", webhookData.URL, "workflow_run")
|
||||
|
||||
repo1 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 1})
|
||||
|
||||
gitRepo1, err := gitrepo.OpenRepository(t.Context(), repo1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// 2.2 trigger the webhooks
|
||||
|
||||
// add workflow file to the repo
|
||||
// init the workflow
|
||||
wfTreePath := ".gitea/workflows/push.yml"
|
||||
wfFileContent := `on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test2:
|
||||
needs: [test]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test3:
|
||||
needs: [test, test2]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test4:
|
||||
needs: [test, test2, test3]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test5:
|
||||
needs: [test, test2, test4]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test6:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04, ubuntu-22.04, ubuntu-24.04]
|
||||
needs: [test, test2, test3]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test7:
|
||||
needs: test6
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test8:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test9:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04, ubuntu-22.04, ubuntu-24.04, ubuntu-25.04, windows-2022, windows-2025, macos-13, macos-14, macos-15]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test10:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0`
|
||||
opts := getWorkflowCreateFileOptions(user2, repo1.DefaultBranch, "create "+wfTreePath, wfFileContent)
|
||||
createWorkflowFile(t, token, "user2", "repo1", wfTreePath, opts)
|
||||
|
||||
commitID, err := gitRepo1.GetBranchCommitID(repo1.DefaultBranch)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// 3. validate the webhook is triggered
|
||||
assert.Equal(t, "workflow_run", webhookData.triggeredEvent)
|
||||
assert.Len(t, webhookData.payloads, 1)
|
||||
assert.Equal(t, "requested", webhookData.payloads[0].Action)
|
||||
assert.Equal(t, "queued", webhookData.payloads[0].WorkflowRun.Status)
|
||||
assert.Equal(t, repo1.DefaultBranch, webhookData.payloads[0].WorkflowRun.HeadBranch)
|
||||
assert.Equal(t, commitID, webhookData.payloads[0].WorkflowRun.HeadSha)
|
||||
assert.Equal(t, "repo1", webhookData.payloads[0].Repo.Name)
|
||||
assert.Equal(t, "user2/repo1", webhookData.payloads[0].Repo.FullName)
|
||||
|
||||
// Call cancel ui api
|
||||
// Only a web UI API exists for cancelling workflow runs, so use the UI endpoint.
|
||||
cancelURL := fmt.Sprintf("/user2/repo1/actions/runs/%d/cancel", webhookData.payloads[0].WorkflowRun.RunNumber)
|
||||
req := NewRequestWithValues(t, "POST", cancelURL, map[string]string{
|
||||
"_csrf": GetUserCSRFToken(t, session),
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
assert.Len(t, webhookData.payloads, 2)
|
||||
|
||||
// 4. Validate the second webhook payload
|
||||
assert.Equal(t, "workflow_run", webhookData.triggeredEvent)
|
||||
assert.Equal(t, "completed", webhookData.payloads[1].Action)
|
||||
assert.Equal(t, "push", webhookData.payloads[1].WorkflowRun.Event)
|
||||
assert.Equal(t, "completed", webhookData.payloads[1].WorkflowRun.Status)
|
||||
assert.Equal(t, repo1.DefaultBranch, webhookData.payloads[1].WorkflowRun.HeadBranch)
|
||||
assert.Equal(t, commitID, webhookData.payloads[1].WorkflowRun.HeadSha)
|
||||
assert.Equal(t, "repo1", webhookData.payloads[1].Repo.Name)
|
||||
assert.Equal(t, "user2/repo1", webhookData.payloads[1].Repo.FullName)
|
||||
}
|
||||
|
||||
func testWorkflowRunEventsOnRerun(t *testing.T, webhookData *workflowRunWebhook) {
|
||||
// 1. create a new webhook with special webhook for repo1
|
||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
session := loginUser(t, "user2")
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||
|
||||
runners := make([]*mockRunner, 2)
|
||||
for i := range runners {
|
||||
runners[i] = newMockRunner()
|
||||
runners[i].registerAsRepoRunner(t, "user2", "repo1", fmt.Sprintf("mock-runner-%d", i), []string{"ubuntu-latest"}, false)
|
||||
}
|
||||
|
||||
testAPICreateWebhookForRepo(t, session, "user2", "repo1", webhookData.URL, "workflow_run")
|
||||
|
||||
repo1 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 1})
|
||||
|
||||
gitRepo1, err := gitrepo.OpenRepository(t.Context(), repo1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// 2.2 trigger the webhooks
|
||||
|
||||
// add workflow file to the repo
|
||||
// init the workflow
|
||||
wfTreePath := ".gitea/workflows/push.yml"
|
||||
wfFileContent := `on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test2:
|
||||
needs: [test]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test3:
|
||||
needs: [test, test2]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test4:
|
||||
needs: [test, test2, test3]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test5:
|
||||
needs: [test, test2, test4]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test6:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04, ubuntu-22.04, ubuntu-24.04]
|
||||
needs: [test, test2, test3]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test7:
|
||||
needs: test6
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test8:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test9:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04, ubuntu-22.04, ubuntu-24.04, ubuntu-25.04, windows-2022, windows-2025, macos-13, macos-14, macos-15]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test10:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0`
|
||||
opts := getWorkflowCreateFileOptions(user2, repo1.DefaultBranch, "create "+wfTreePath, wfFileContent)
|
||||
createWorkflowFile(t, token, "user2", "repo1", wfTreePath, opts)
|
||||
|
||||
commitID, err := gitRepo1.GetBranchCommitID(repo1.DefaultBranch)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// 3. validate the webhook is triggered
|
||||
assert.Equal(t, "workflow_run", webhookData.triggeredEvent)
|
||||
assert.Len(t, webhookData.payloads, 1)
|
||||
assert.Equal(t, "requested", webhookData.payloads[0].Action)
|
||||
assert.Equal(t, "queued", webhookData.payloads[0].WorkflowRun.Status)
|
||||
assert.Equal(t, repo1.DefaultBranch, webhookData.payloads[0].WorkflowRun.HeadBranch)
|
||||
assert.Equal(t, commitID, webhookData.payloads[0].WorkflowRun.HeadSha)
|
||||
assert.Equal(t, "repo1", webhookData.payloads[0].Repo.Name)
|
||||
assert.Equal(t, "user2/repo1", webhookData.payloads[0].Repo.FullName)
|
||||
|
||||
for _, runner := range runners {
|
||||
task := runner.fetchTask(t)
|
||||
runner.execTask(t, task, &mockTaskOutcome{
|
||||
result: runnerv1.Result_RESULT_SUCCESS,
|
||||
})
|
||||
}
|
||||
|
||||
// Call cancel ui api
|
||||
// Only a web UI API exists for cancelling workflow runs, so use the UI endpoint.
|
||||
cancelURL := fmt.Sprintf("/user2/repo1/actions/runs/%d/cancel", webhookData.payloads[0].WorkflowRun.RunNumber)
|
||||
req := NewRequestWithValues(t, "POST", cancelURL, map[string]string{
|
||||
"_csrf": GetUserCSRFToken(t, session),
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
assert.Len(t, webhookData.payloads, 2)
|
||||
|
||||
// 4. Validate the second webhook payload
|
||||
assert.Equal(t, "workflow_run", webhookData.triggeredEvent)
|
||||
assert.Equal(t, "completed", webhookData.payloads[1].Action)
|
||||
assert.Equal(t, "push", webhookData.payloads[1].WorkflowRun.Event)
|
||||
assert.Equal(t, "completed", webhookData.payloads[1].WorkflowRun.Status)
|
||||
assert.Equal(t, repo1.DefaultBranch, webhookData.payloads[1].WorkflowRun.HeadBranch)
|
||||
assert.Equal(t, commitID, webhookData.payloads[1].WorkflowRun.HeadSha)
|
||||
assert.Equal(t, "repo1", webhookData.payloads[1].Repo.Name)
|
||||
assert.Equal(t, "user2/repo1", webhookData.payloads[1].Repo.FullName)
|
||||
|
||||
// Call rerun ui api
|
||||
// Only a web UI API exists for cancelling workflow runs, so use the UI endpoint.
|
||||
rerunURL := fmt.Sprintf("/user2/repo1/actions/runs/%d/rerun", webhookData.payloads[0].WorkflowRun.RunNumber)
|
||||
req = NewRequestWithValues(t, "POST", rerunURL, map[string]string{
|
||||
"_csrf": GetUserCSRFToken(t, session),
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
assert.Len(t, webhookData.payloads, 3)
|
||||
}
|
||||
|
||||
func testWorkflowRunEventsOnCancellingAbandonedRun(t *testing.T, webhookData *workflowRunWebhook, allJobsAbandoned bool) {
|
||||
defer test.MockVariableValue(&setting.Actions.AbandonedJobTimeout, 0*time.Nanosecond)()
|
||||
|
||||
// 1. create a new webhook with special webhook for repo1
|
||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
session := loginUser(t, "user2")
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
|
||||
|
||||
repoName := "test-workflow-run-cancelling-abandoned-run"
|
||||
testRepo := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: createActionsTestRepo(t, token, repoName, false).ID})
|
||||
|
||||
runners := make([]*mockRunner, 2)
|
||||
for i := range runners {
|
||||
runners[i] = newMockRunner()
|
||||
runners[i].registerAsRepoRunner(t, "user2", repoName,
|
||||
fmt.Sprintf("mock-runner-%d", i), []string{"ubuntu-latest"}, false)
|
||||
}
|
||||
|
||||
testAPICreateWebhookForRepo(t, session, "user2", repoName, webhookData.URL, "workflow_run")
|
||||
|
||||
ctx := t.Context()
|
||||
gitRepo, err := gitrepo.OpenRepository(ctx, testRepo)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// 2.2 trigger the webhooks
|
||||
|
||||
// add workflow file to the repo
|
||||
// init the workflow
|
||||
wfilename := "push.yml"
|
||||
wfTreePath := ".gitea/workflows/" + wfilename
|
||||
wfFileContent := `on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test2:
|
||||
needs: [test]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test3:
|
||||
needs: [test, test2]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test4:
|
||||
needs: [test, test2, test3]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test5:
|
||||
needs: [test, test2, test4]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test6:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04, ubuntu-22.04, ubuntu-24.04]
|
||||
needs: [test, test2, test3]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test7:
|
||||
needs: test6
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test8:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test9:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04, ubuntu-22.04, ubuntu-24.04, ubuntu-25.04, windows-2022, windows-2025, macos-13, macos-14, macos-15]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
test10:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0`
|
||||
|
||||
opts := getWorkflowCreateFileOptions(user2, testRepo.DefaultBranch, "create "+wfTreePath, wfFileContent)
|
||||
createWorkflowFile(t, token, "user2", repoName, wfTreePath, opts)
|
||||
|
||||
commitID, err := gitRepo.GetBranchCommitID(testRepo.DefaultBranch)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// 3. validate the webhook is triggered
|
||||
assert.Equal(t, "workflow_run", webhookData.triggeredEvent)
|
||||
assert.Len(t, webhookData.payloads, 1)
|
||||
assert.Equal(t, "requested", webhookData.payloads[0].Action)
|
||||
assert.Equal(t, "queued", webhookData.payloads[0].WorkflowRun.Status)
|
||||
assert.Equal(t, testRepo.DefaultBranch, webhookData.payloads[0].WorkflowRun.HeadBranch)
|
||||
assert.Equal(t, commitID, webhookData.payloads[0].WorkflowRun.HeadSha)
|
||||
assert.Equal(t, repoName, webhookData.payloads[0].Repo.Name)
|
||||
assert.Equal(t, "user2/"+repoName, webhookData.payloads[0].Repo.FullName)
|
||||
|
||||
if !allJobsAbandoned {
|
||||
for _, runner := range runners {
|
||||
task := runner.fetchTask(t)
|
||||
runner.execTask(t, task, &mockTaskOutcome{
|
||||
result: runnerv1.Result_RESULT_SUCCESS,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Add this sleep to ensure the func can find the tasks by timestamp.
|
||||
time.Sleep(time.Second)
|
||||
|
||||
err = actions.CancelAbandonedJobs(ctx)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, webhookData.payloads, 2)
|
||||
assert.Equal(t, "completed", webhookData.payloads[1].Action)
|
||||
assert.Equal(t, "completed", webhookData.payloads[1].WorkflowRun.Status)
|
||||
assert.Equal(t, testRepo.DefaultBranch, webhookData.payloads[1].WorkflowRun.HeadBranch)
|
||||
assert.Equal(t, commitID, webhookData.payloads[1].WorkflowRun.HeadSha)
|
||||
assert.Equal(t, repoName, webhookData.payloads[1].Repo.Name)
|
||||
assert.Equal(t, "user2/"+repoName, webhookData.payloads[1].Repo.FullName)
|
||||
}
|
||||
|
||||
func testWebhookWorkflowRun(t *testing.T, webhookData *workflowRunWebhook) {
|
||||
// 1. create a new webhook with special webhook for repo1
|
||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
|
Reference in New Issue
Block a user