c801838690
When ReplaceIssueLabels calls issue.LoadLabels it was a noop because issue.isLabelsLoaded is still set to true because of the call to issue.LoadLabels that was done at the beginning of the function.
757 lines
26 KiB
Go
757 lines
26 KiB
Go
// Copyright 2023 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package integration
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
actions_model "code.gitea.io/gitea/models/actions"
|
|
auth_model "code.gitea.io/gitea/models/auth"
|
|
"code.gitea.io/gitea/models/db"
|
|
git_model "code.gitea.io/gitea/models/git"
|
|
issues_model "code.gitea.io/gitea/models/issues"
|
|
repo_model "code.gitea.io/gitea/models/repo"
|
|
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"
|
|
"code.gitea.io/gitea/modules/gitrepo"
|
|
"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"
|
|
actions_service "code.gitea.io/gitea/services/actions"
|
|
issue_service "code.gitea.io/gitea/services/issue"
|
|
pull_service "code.gitea.io/gitea/services/pull"
|
|
release_service "code.gitea.io/gitea/services/release"
|
|
repo_service "code.gitea.io/gitea/services/repository"
|
|
files_service "code.gitea.io/gitea/services/repository/files"
|
|
"code.gitea.io/gitea/tests"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
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()
|
|
}()
|
|
|
|
// 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
|
|
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"
|
|
req := NewRequestWithJSON(t, "POST", milestoneStr, &api.CreateMilestoneOption{
|
|
Title: "mymilestone",
|
|
State: "open",
|
|
}).AddTokenAuth(token)
|
|
resp := MakeRequest(t, req, http.StatusCreated)
|
|
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
|
|
}
|
|
|
|
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])
|
|
}
|
|
|
|
for _, testCase := range []struct {
|
|
onType string
|
|
jobID string
|
|
doSomething func()
|
|
actionRunCount int
|
|
action api.HookIssueAction
|
|
assert assertType
|
|
}{
|
|
{
|
|
onType: "opened",
|
|
doSomething: func() {},
|
|
actionRunCount: 1,
|
|
action: api.HookIssueOpened,
|
|
assert: assertActionRuns,
|
|
},
|
|
{
|
|
onType: "synchronize",
|
|
doSomething: func() {
|
|
testEditFile(t, session, "user2", "repo-pull-request", "wip-something", "README.md", "Hello, world 2")
|
|
},
|
|
actionRunCount: 1,
|
|
action: api.HookIssueSynchronized,
|
|
assert: assertActionRuns,
|
|
},
|
|
{
|
|
onType: "labeled",
|
|
doSomething: func() {
|
|
req := NewRequestWithJSON(t, "POST", labelURL, &api.IssueLabelsOption{
|
|
Labels: []any{labels[0].ID, labels[1].ID},
|
|
}).AddTokenAuth(token)
|
|
MakeRequest(t, req, http.StatusOK)
|
|
},
|
|
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])
|
|
},
|
|
},
|
|
{
|
|
onType: "unlabeled",
|
|
doSomething: func() {
|
|
req := NewRequestWithJSON(t, "PUT", labelURL, &api.IssueLabelsOption{
|
|
Labels: []any{labels[0].ID},
|
|
}).AddTokenAuth(token)
|
|
MakeRequest(t, req, http.StatusOK)
|
|
},
|
|
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")
|
|
},
|
|
},
|
|
{
|
|
onType: "assigned",
|
|
doSomething: func() {
|
|
req := NewRequestWithJSON(t, "PATCH", issueURL, &api.EditIssueOption{
|
|
Assignees: []string{"user2"},
|
|
}).AddTokenAuth(token)
|
|
MakeRequest(t, req, http.StatusCreated)
|
|
},
|
|
actionRunCount: 1,
|
|
action: api.HookIssueAssigned,
|
|
assert: assertActionRuns,
|
|
},
|
|
{
|
|
onType: "unassigned",
|
|
doSomething: func() {
|
|
req := NewRequestWithJSON(t, "PATCH", issueURL, &api.EditIssueOption{
|
|
Assignees: []string{},
|
|
}).AddTokenAuth(token)
|
|
MakeRequest(t, req, http.StatusCreated)
|
|
},
|
|
actionRunCount: 1,
|
|
action: api.HookIssueUnassigned,
|
|
assert: assertActionRuns,
|
|
},
|
|
{
|
|
onType: "milestoned",
|
|
doSomething: func() {
|
|
req := NewRequestWithJSON(t, "PATCH", issueURL, &api.EditIssueOption{
|
|
Milestone: &milestone.ID,
|
|
}).AddTokenAuth(token)
|
|
MakeRequest(t, req, http.StatusCreated)
|
|
},
|
|
actionRunCount: 1,
|
|
action: api.HookIssueMilestoned,
|
|
assert: assertActionRuns,
|
|
},
|
|
{
|
|
onType: "demilestoned",
|
|
doSomething: func() {
|
|
var zero int64
|
|
req := NewRequestWithJSON(t, "PATCH", issueURL, &api.EditIssueOption{
|
|
Milestone: &zero,
|
|
}).AddTokenAuth(token)
|
|
MakeRequest(t, req, http.StatusCreated)
|
|
},
|
|
actionRunCount: 1,
|
|
action: api.HookIssueDemilestoned,
|
|
assert: assertActionRuns,
|
|
},
|
|
{
|
|
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)
|
|
},
|
|
actionRunCount: 1,
|
|
action: api.HookIssueClosed,
|
|
assert: assertActionRuns,
|
|
},
|
|
{
|
|
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)
|
|
},
|
|
actionRunCount: 1,
|
|
action: api.HookIssueReOpened,
|
|
assert: assertActionRuns,
|
|
},
|
|
} {
|
|
t.Run(testCase.onType, func(t *testing.T) {
|
|
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)
|
|
}()
|
|
|
|
// trigger the onType event
|
|
testCase.doSomething()
|
|
count := testCase.actionRunCount
|
|
context := fmt.Sprintf("%[1]s / %[1]s (pull_request)", testCase.onType)
|
|
|
|
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))
|
|
return assert.Len(t, actionRuns, count)
|
|
}, 30*time.Second, 1*time.Second)
|
|
|
|
// verify the expected ActionRuns were created
|
|
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))
|
|
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
|
|
assert.True(t, checkCommitStatus(sha, context, api.CommitStatusSuccess))
|
|
|
|
testCase.assert(t, sha, testCase.onType, testCase.action, actionRuns)
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
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
|
|
org3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}) // owner of the forked repo
|
|
|
|
// create the base repo
|
|
baseRepo, _, f := tests.CreateDeclarativeRepo(t, user2, "repo-pull-request-target",
|
|
[]unit_model.Type{unit_model.TypeActions}, nil, nil,
|
|
)
|
|
defer f()
|
|
|
|
// create the forked repo
|
|
forkedRepo, err := repo_service.ForkRepositoryAndUpdates(git.DefaultContext, user2, org3, repo_service.ForkRepoOptions{
|
|
BaseRepo: baseRepo,
|
|
Name: "forked-repo-pull-request-target",
|
|
Description: "test pull-request-target event",
|
|
})
|
|
require.NoError(t, err)
|
|
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{
|
|
{
|
|
Operation: "create",
|
|
TreePath: ".gitea/workflows/pr.yml",
|
|
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"),
|
|
},
|
|
},
|
|
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(),
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
assert.NotEmpty(t, addWorkflowToBaseResp)
|
|
|
|
// add a new file to the forked repo
|
|
addFileToForkedResp, err := files_service.ChangeRepoFiles(git.DefaultContext, forkedRepo, org3, &files_service.ChangeRepoFilesOptions{
|
|
Files: []*files_service.ChangeRepoFile{
|
|
{
|
|
Operation: "create",
|
|
TreePath: "file_1.txt",
|
|
ContentReader: strings.NewReader("file1"),
|
|
},
|
|
},
|
|
Message: "add file1",
|
|
OldBranch: "main",
|
|
NewBranch: "fork-branch-1",
|
|
Author: &files_service.IdentityOptions{
|
|
Name: org3.Name,
|
|
Email: org3.Email,
|
|
},
|
|
Committer: &files_service.IdentityOptions{
|
|
Name: org3.Name,
|
|
Email: org3.Email,
|
|
},
|
|
Dates: &files_service.CommitDateOptions{
|
|
Author: time.Now(),
|
|
Committer: time.Now(),
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
assert.NotEmpty(t, addFileToForkedResp)
|
|
|
|
// create Pull
|
|
pullIssue := &issues_model.Issue{
|
|
RepoID: baseRepo.ID,
|
|
Title: "Test pull-request-target-event",
|
|
PosterID: org3.ID,
|
|
Poster: org3,
|
|
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)
|
|
require.NoError(t, err)
|
|
// 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))
|
|
|
|
// load and compare ActionRun
|
|
assert.Equal(t, 1, unittest.GetCount(t, &actions_model.ActionRun{RepoID: baseRepo.ID}))
|
|
actionRun := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{RepoID: baseRepo.ID})
|
|
assert.Equal(t, addFileToForkedResp.Commit.SHA, actionRun.CommitSHA)
|
|
assert.Equal(t, actions_module.GithubEventPullRequestTarget, actionRun.TriggerEvent)
|
|
|
|
// add another file whose name cannot match the specified path
|
|
addFileToForkedResp, err = files_service.ChangeRepoFiles(git.DefaultContext, forkedRepo, org3, &files_service.ChangeRepoFilesOptions{
|
|
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{
|
|
Name: org3.Name,
|
|
Email: org3.Email,
|
|
},
|
|
Committer: &files_service.IdentityOptions{
|
|
Name: org3.Name,
|
|
Email: org3.Email,
|
|
},
|
|
Dates: &files_service.CommitDateOptions{
|
|
Author: time.Now(),
|
|
Committer: time.Now(),
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
assert.NotEmpty(t, addFileToForkedResp)
|
|
|
|
// create Pull
|
|
pullIssue = &issues_model.Issue{
|
|
RepoID: baseRepo.ID,
|
|
Title: "A mismatched path cannot trigger pull-request-target-event",
|
|
PosterID: org3.ID,
|
|
Poster: org3,
|
|
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)
|
|
require.NoError(t, err)
|
|
|
|
// 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}))
|
|
})
|
|
}
|
|
|
|
func TestSkipCI(t *testing.T) {
|
|
onGiteaRun(t, func(t *testing.T, u *url.URL) {
|
|
session := loginUser(t, "user2")
|
|
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
|
|
|
// create the repo
|
|
repo, _, f := tests.CreateDeclarativeRepo(t, user2, "skip-ci",
|
|
[]unit_model.Type{unit_model.TypeActions}, nil,
|
|
[]*files_service.ChangeRepoFile{
|
|
{
|
|
Operation: "create",
|
|
TreePath: ".gitea/workflows/pr.yml",
|
|
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"),
|
|
},
|
|
},
|
|
)
|
|
defer f()
|
|
|
|
// 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(),
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
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}))
|
|
|
|
// 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(),
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
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}))
|
|
})
|
|
}
|
|
|
|
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,
|
|
})
|
|
require.NoError(t, err)
|
|
assert.NotEmpty(t, repo)
|
|
|
|
// enable actions
|
|
err = repo_service.UpdateRepositoryUnits(db.DefaultContext, repo, []repo_model.RepoUnit{{
|
|
RepoID: repo.ID,
|
|
Type: unit_model.TypeActions,
|
|
}}, nil)
|
|
require.NoError(t, err)
|
|
|
|
// 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(),
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
assert.NotEmpty(t, addWorkflowToBaseResp)
|
|
|
|
// Get the commit ID of the default branch
|
|
gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo)
|
|
require.NoError(t, err)
|
|
defer gitRepo.Close()
|
|
branch, err := git_model.GetBranch(db.DefaultContext, repo.ID, repo.DefaultBranch)
|
|
require.NoError(t, err)
|
|
|
|
// create a branch
|
|
err = repo_service.CreateNewBranchFromCommit(db.DefaultContext, user2, repo, gitRepo, branch.CommitID, "test-create-branch")
|
|
require.NoError(t, err)
|
|
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")
|
|
require.NoError(t, err)
|
|
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")
|
|
require.NoError(t, err)
|
|
run = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{
|
|
Title: "add workflow",
|
|
RepoID: repo.ID,
|
|
Event: "delete",
|
|
Ref: "refs/heads/main",
|
|
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")
|
|
require.NoError(t, err)
|
|
err = release_service.DeleteReleaseByID(db.DefaultContext, repo, tag, user2, true)
|
|
require.NoError(t, err)
|
|
run = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{
|
|
Title: "add workflow",
|
|
RepoID: repo.ID,
|
|
Event: "delete",
|
|
Ref: "refs/heads/main",
|
|
WorkflowID: "createdelete.yml",
|
|
CommitSHA: branch.CommitID,
|
|
})
|
|
assert.NotNil(t, run)
|
|
})
|
|
}
|
|
|
|
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
|
|
repo, sha, f := tests.CreateDeclarativeRepo(t, user2, "repo-workflow-dispatch",
|
|
[]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)
|
|
require.NoError(t, err)
|
|
defer gitRepo.Close()
|
|
|
|
workflow, err := actions_service.GetWorkflowFromCommit(gitRepo, "main", "dispatch.yml")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "refs/heads/main", workflow.Ref)
|
|
assert.Equal(t, sha, workflow.Commit.ID.String())
|
|
|
|
inputGetter := func(key string) string {
|
|
return ""
|
|
}
|
|
|
|
err = workflow.Dispatch(db.DefaultContext, inputGetter, repo, user2)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, 1, unittest.GetCount(t, &actions_model.ActionRun{RepoID: repo.ID}))
|
|
})
|
|
}
|