mirror of https://github.com/go-gitea/gitea.git
2 changed files with 304 additions and 12 deletions
@ -0,0 +1,296 @@
@@ -0,0 +1,296 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package integration |
||||
|
||||
import ( |
||||
"net/url" |
||||
"strconv" |
||||
"strings" |
||||
"testing" |
||||
|
||||
actions_model "code.gitea.io/gitea/models/actions" |
||||
auth_model "code.gitea.io/gitea/models/auth" |
||||
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" |
||||
"code.gitea.io/gitea/modules/migration" |
||||
api "code.gitea.io/gitea/modules/structs" |
||||
"code.gitea.io/gitea/modules/util" |
||||
mirror_service "code.gitea.io/gitea/services/mirror" |
||||
repo_service "code.gitea.io/gitea/services/repository" |
||||
files_service "code.gitea.io/gitea/services/repository/files" |
||||
|
||||
"github.com/stretchr/testify/assert" |
||||
) |
||||
|
||||
func TestScheduleUpdate(t *testing.T) { |
||||
t.Run("Push", testScheduleUpdatePush) |
||||
t.Run("PullMerge", testScheduleUpdatePullMerge) |
||||
t.Run("DisableAndEnableActionsUnit", testScheduleUpdateDisableAndEnableActionsUnit) |
||||
t.Run("ArchiveAndUnarchive", testScheduleUpdateArchiveAndUnarchive) |
||||
t.Run("MirrorSync", testScheduleUpdateMirrorSync) |
||||
} |
||||
|
||||
func testScheduleUpdatePush(t *testing.T) { |
||||
doTestScheduleUpdate(t, func(t *testing.T, u *url.URL, testContext APITestContext, user *user_model.User, repo *repo_model.Repository) (commitID, expectedSpec string) { |
||||
newCron := "30 5 * * 1,3" |
||||
pushScheduleChange(t, u, repo, newCron) |
||||
branch, err := git_model.GetBranch(t.Context(), repo.ID, repo.DefaultBranch) |
||||
assert.NoError(t, err) |
||||
return branch.CommitID, newCron |
||||
}) |
||||
} |
||||
|
||||
func testScheduleUpdatePullMerge(t *testing.T) { |
||||
newBranchName := "feat1" |
||||
workflowTreePath := ".gitea/workflows/actions-schedule.yml" |
||||
workflowContent := `name: actions-schedule |
||||
on: |
||||
schedule: |
||||
- cron: '@every 2m' # update to 2m |
||||
jobs: |
||||
job: |
||||
runs-on: ubuntu-latest |
||||
steps: |
||||
- run: echo 'schedule workflow' |
||||
` |
||||
|
||||
mergeStyles := []repo_model.MergeStyle{ |
||||
repo_model.MergeStyleMerge, |
||||
repo_model.MergeStyleRebase, |
||||
repo_model.MergeStyleRebaseMerge, |
||||
repo_model.MergeStyleSquash, |
||||
repo_model.MergeStyleFastForwardOnly, |
||||
} |
||||
|
||||
for _, mergeStyle := range mergeStyles { |
||||
t.Run(string(mergeStyle), func(t *testing.T) { |
||||
doTestScheduleUpdate(t, func(t *testing.T, u *url.URL, testContext APITestContext, user *user_model.User, repo *repo_model.Repository) (commitID, expectedSpec string) { |
||||
// update workflow file
|
||||
_, err := files_service.ChangeRepoFiles(t.Context(), repo, user, &files_service.ChangeRepoFilesOptions{ |
||||
NewBranch: newBranchName, |
||||
Files: []*files_service.ChangeRepoFile{ |
||||
{ |
||||
Operation: "update", |
||||
TreePath: workflowTreePath, |
||||
ContentReader: strings.NewReader(workflowContent), |
||||
}, |
||||
}, |
||||
Message: "update workflow schedule", |
||||
}) |
||||
assert.NoError(t, err) |
||||
|
||||
// create pull request
|
||||
apiPull, err := doAPICreatePullRequest(testContext, repo.OwnerName, repo.Name, repo.DefaultBranch, newBranchName)(t) |
||||
assert.NoError(t, err) |
||||
|
||||
// merge pull request
|
||||
testPullMerge(t, testContext.Session, repo.OwnerName, repo.Name, strconv.FormatInt(apiPull.Index, 10), MergeOptions{ |
||||
Style: mergeStyle, |
||||
}) |
||||
|
||||
pull := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: apiPull.ID}) |
||||
return pull.MergedCommitID, "@every 2m" |
||||
}) |
||||
}) |
||||
} |
||||
|
||||
t.Run(string(repo_model.MergeStyleManuallyMerged), func(t *testing.T) { |
||||
doTestScheduleUpdate(t, func(t *testing.T, u *url.URL, testContext APITestContext, user *user_model.User, repo *repo_model.Repository) (commitID, expectedSpec string) { |
||||
// enable manual-merge
|
||||
doAPIEditRepository(testContext, &api.EditRepoOption{ |
||||
HasPullRequests: util.ToPointer(true), |
||||
AllowManualMerge: util.ToPointer(true), |
||||
})(t) |
||||
|
||||
// update workflow file
|
||||
fileResp, err := files_service.ChangeRepoFiles(t.Context(), repo, user, &files_service.ChangeRepoFilesOptions{ |
||||
NewBranch: newBranchName, |
||||
Files: []*files_service.ChangeRepoFile{ |
||||
{ |
||||
Operation: "update", |
||||
TreePath: workflowTreePath, |
||||
ContentReader: strings.NewReader(workflowContent), |
||||
}, |
||||
}, |
||||
Message: "update workflow schedule", |
||||
}) |
||||
assert.NoError(t, err) |
||||
|
||||
// merge and push
|
||||
dstPath := t.TempDir() |
||||
u.Path = repo.FullName() + ".git" |
||||
u.User = url.UserPassword(repo.OwnerName, userPassword) |
||||
doGitClone(dstPath, u)(t) |
||||
doGitMerge(dstPath, "origin/"+newBranchName)(t) |
||||
doGitPushTestRepository(dstPath, "origin", repo.DefaultBranch)(t) |
||||
|
||||
// create pull request
|
||||
apiPull, err := doAPICreatePullRequest(testContext, repo.OwnerName, repo.Name, repo.DefaultBranch, newBranchName)(t) |
||||
assert.NoError(t, err) |
||||
|
||||
// merge pull request manually
|
||||
doAPIManuallyMergePullRequest(testContext, repo.OwnerName, repo.Name, fileResp.Commit.SHA, apiPull.Index)(t) |
||||
|
||||
pull := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: apiPull.ID}) |
||||
assert.Equal(t, issues_model.PullRequestStatusManuallyMerged, pull.Status) |
||||
return pull.MergedCommitID, "@every 2m" |
||||
}) |
||||
}) |
||||
} |
||||
|
||||
func testScheduleUpdateMirrorSync(t *testing.T) { |
||||
doTestScheduleUpdate(t, func(t *testing.T, u *url.URL, testContext APITestContext, user *user_model.User, repo *repo_model.Repository) (commitID, expectedSpec string) { |
||||
// create mirror repo
|
||||
opts := migration.MigrateOptions{ |
||||
RepoName: "actions-schedule-mirror", |
||||
Description: "Test mirror for actions-schedule", |
||||
Private: false, |
||||
Mirror: true, |
||||
CloneAddr: repo.CloneLinkGeneral(t.Context()).HTTPS, |
||||
} |
||||
mirrorRepo, err := repo_service.CreateRepositoryDirectly(t.Context(), user, user, repo_service.CreateRepoOptions{ |
||||
Name: opts.RepoName, |
||||
Description: opts.Description, |
||||
IsPrivate: opts.Private, |
||||
IsMirror: opts.Mirror, |
||||
DefaultBranch: repo.DefaultBranch, |
||||
Status: repo_model.RepositoryBeingMigrated, |
||||
}, false) |
||||
assert.NoError(t, err) |
||||
assert.True(t, mirrorRepo.IsMirror) |
||||
mirrorRepo, err = repo_service.MigrateRepositoryGitData(t.Context(), user, mirrorRepo, opts, nil) |
||||
assert.NoError(t, err) |
||||
mirrorContext := NewAPITestContext(t, user.Name, mirrorRepo.Name, auth_model.AccessTokenScopeWriteRepository) |
||||
|
||||
// enable actions unit for mirror repo
|
||||
assert.False(t, mirrorRepo.UnitEnabled(t.Context(), unit_model.TypeActions)) |
||||
doAPIEditRepository(mirrorContext, &api.EditRepoOption{ |
||||
HasActions: util.ToPointer(true), |
||||
})(t) |
||||
actionSchedule := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionSchedule{RepoID: mirrorRepo.ID}) |
||||
scheduleSpec := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionScheduleSpec{RepoID: mirrorRepo.ID, ScheduleID: actionSchedule.ID}) |
||||
assert.Equal(t, "@every 1m", scheduleSpec.Spec) |
||||
|
||||
// update remote repo
|
||||
newCron := "30 5,17 * * 2,4" |
||||
pushScheduleChange(t, u, repo, newCron) |
||||
repoDefaultBranch, err := git_model.GetBranch(t.Context(), repo.ID, repo.DefaultBranch) |
||||
assert.NoError(t, err) |
||||
|
||||
// sync
|
||||
ok := mirror_service.SyncPullMirror(t.Context(), mirrorRepo.ID) |
||||
assert.True(t, ok) |
||||
mirrorRepoDefaultBranch, err := git_model.GetBranch(t.Context(), mirrorRepo.ID, mirrorRepo.DefaultBranch) |
||||
assert.NoError(t, err) |
||||
assert.Equal(t, repoDefaultBranch.CommitID, mirrorRepoDefaultBranch.CommitID) |
||||
|
||||
// check updated schedule
|
||||
actionSchedule = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionSchedule{RepoID: mirrorRepo.ID}) |
||||
scheduleSpec = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionScheduleSpec{RepoID: mirrorRepo.ID, ScheduleID: actionSchedule.ID}) |
||||
assert.Equal(t, newCron, scheduleSpec.Spec) |
||||
|
||||
return repoDefaultBranch.CommitID, newCron |
||||
}) |
||||
} |
||||
|
||||
func testScheduleUpdateArchiveAndUnarchive(t *testing.T) { |
||||
doTestScheduleUpdate(t, func(t *testing.T, u *url.URL, testContext APITestContext, user *user_model.User, repo *repo_model.Repository) (commitID, expectedSpec string) { |
||||
doAPIEditRepository(testContext, &api.EditRepoOption{ |
||||
Archived: util.ToPointer(true), |
||||
})(t) |
||||
assert.Zero(t, unittest.GetCount(t, &actions_model.ActionSchedule{RepoID: repo.ID})) |
||||
doAPIEditRepository(testContext, &api.EditRepoOption{ |
||||
Archived: util.ToPointer(false), |
||||
})(t) |
||||
branch, err := git_model.GetBranch(t.Context(), repo.ID, repo.DefaultBranch) |
||||
assert.NoError(t, err) |
||||
return branch.CommitID, "@every 1m" |
||||
}) |
||||
} |
||||
|
||||
func testScheduleUpdateDisableAndEnableActionsUnit(t *testing.T) { |
||||
doTestScheduleUpdate(t, func(t *testing.T, u *url.URL, testContext APITestContext, user *user_model.User, repo *repo_model.Repository) (commitID, expectedSpec string) { |
||||
doAPIEditRepository(testContext, &api.EditRepoOption{ |
||||
HasActions: util.ToPointer(false), |
||||
})(t) |
||||
assert.Zero(t, unittest.GetCount(t, &actions_model.ActionSchedule{RepoID: repo.ID})) |
||||
doAPIEditRepository(testContext, &api.EditRepoOption{ |
||||
HasActions: util.ToPointer(true), |
||||
})(t) |
||||
branch, err := git_model.GetBranch(t.Context(), repo.ID, repo.DefaultBranch) |
||||
assert.NoError(t, err) |
||||
return branch.CommitID, "@every 1m" |
||||
}) |
||||
} |
||||
|
||||
type scheduleUpdateTrigger func(t *testing.T, u *url.URL, testContext APITestContext, user *user_model.User, repo *repo_model.Repository) (commitID, expectedSpec string) |
||||
|
||||
func doTestScheduleUpdate(t *testing.T, updateTrigger scheduleUpdateTrigger) { |
||||
onGiteaRun(t, func(t *testing.T, u *url.URL) { |
||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) |
||||
session := loginUser(t, user2.Name) |
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) |
||||
|
||||
apiRepo := createActionsTestRepo(t, token, "actions-schedule", false) |
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID}) |
||||
assert.NoError(t, repo.LoadAttributes(t.Context())) |
||||
httpContext := NewAPITestContext(t, user2.Name, repo.Name, auth_model.AccessTokenScopeWriteRepository) |
||||
defer doAPIDeleteRepository(httpContext)(t) |
||||
|
||||
wfTreePath := ".gitea/workflows/actions-schedule.yml" |
||||
wfFileContent := `name: actions-schedule |
||||
on: |
||||
schedule: |
||||
- cron: '@every 1m' |
||||
jobs: |
||||
job: |
||||
runs-on: ubuntu-latest |
||||
steps: |
||||
- run: echo 'schedule workflow' |
||||
` |
||||
|
||||
opts1 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create "+wfTreePath, wfFileContent) |
||||
apiFileResp := createWorkflowFile(t, token, user2.Name, repo.Name, wfTreePath, opts1) |
||||
|
||||
actionSchedule := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionSchedule{RepoID: repo.ID, CommitSHA: apiFileResp.Commit.SHA}) |
||||
scheduleSpec := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionScheduleSpec{RepoID: repo.ID, ScheduleID: actionSchedule.ID}) |
||||
assert.Equal(t, "@every 1m", scheduleSpec.Spec) |
||||
|
||||
commitID, expectedSpec := updateTrigger(t, u, httpContext, user2, repo) |
||||
|
||||
actionSchedule = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionSchedule{RepoID: repo.ID, CommitSHA: commitID}) |
||||
scheduleSpec = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionScheduleSpec{RepoID: repo.ID, ScheduleID: actionSchedule.ID}) |
||||
assert.Equal(t, expectedSpec, scheduleSpec.Spec) |
||||
}) |
||||
} |
||||
|
||||
func pushScheduleChange(t *testing.T, u *url.URL, repo *repo_model.Repository, newCron string) { |
||||
workflowTreePath := ".gitea/workflows/actions-schedule.yml" |
||||
workflowContent := `name: actions-schedule |
||||
on: |
||||
schedule: |
||||
- cron: '` + newCron + `' |
||||
jobs: |
||||
job: |
||||
runs-on: ubuntu-latest |
||||
steps: |
||||
- run: echo 'schedule workflow' |
||||
` |
||||
|
||||
dstPath := t.TempDir() |
||||
u.Path = repo.FullName() + ".git" |
||||
u.User = url.UserPassword(repo.OwnerName, userPassword) |
||||
doGitClone(dstPath, u)(t) |
||||
doGitCheckoutWriteFileCommit(localGitAddCommitOptions{ |
||||
LocalRepoPath: dstPath, |
||||
CheckoutBranch: repo.DefaultBranch, |
||||
TreeFilePath: workflowTreePath, |
||||
TreeFileContent: workflowContent, |
||||
})(t) |
||||
doGitPushTestRepository(dstPath, "origin", repo.DefaultBranch)(t) |
||||
} |
||||
Loading…
Reference in new issue