mirror of
https://github.com/go-gitea/gitea.git
synced 2025-11-03 13:05:22 +01:00
295 lines
12 KiB
Go
295 lines
12 KiB
Go
// 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), mergeStyle, false)
|
|
|
|
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)
|
|
}
|