Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf85cd7a

Browse files
GiteaBotZettat123wxiaoguang
authored
Fix actions schedule update issue (#35767) (#35774)
Backport#35767 by@Zettat123Fix#34472Add integration tests for actions schedule update.---------Co-authored-by: Zettat123 <zettat123@gmail.com>Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
1 parentcf644d5 commitf85cd7a

File tree

2 files changed

+302
-12
lines changed

2 files changed

+302
-12
lines changed

‎services/actions/notifier_helper.go‎

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -236,12 +236,12 @@ func notify(ctx context.Context, input *notifyInput) error {
236236
}
237237

238238
ifshouldDetectSchedules {
239-
iferr:=handleSchedules(ctx,schedules,commit,input,ref.String());err!=nil {
239+
iferr:=handleSchedules(ctx,schedules,commit,input,ref);err!=nil {
240240
returnerr
241241
}
242242
}
243243

244-
returnhandleWorkflows(ctx,detectedWorkflows,commit,input,ref.String())
244+
returnhandleWorkflows(ctx,detectedWorkflows,commit,input,ref)
245245
}
246246

247247
funcskipWorkflows(ctx context.Context,input*notifyInput,commit*git.Commit)bool {
@@ -293,7 +293,7 @@ func handleWorkflows(
293293
detectedWorkflows []*actions_module.DetectedWorkflow,
294294
commit*git.Commit,
295295
input*notifyInput,
296-
refstring,
296+
refgit.RefName,
297297
)error {
298298
iflen(detectedWorkflows)==0 {
299299
log.Trace("repo %s with commit %s couldn't find workflows",input.Repo.RepoPath(),commit.ID)
@@ -329,7 +329,7 @@ func handleWorkflows(
329329
WorkflowID:dwf.EntryName,
330330
TriggerUserID:input.Doer.ID,
331331
TriggerUser:input.Doer,
332-
Ref:ref,
332+
Ref:ref.String(),
333333
CommitSHA:commit.ID.String(),
334334
IsForkPullRequest:isForkPullRequest,
335335
Event:input.Event,
@@ -500,13 +500,9 @@ func handleSchedules(
500500
detectedWorkflows []*actions_module.DetectedWorkflow,
501501
commit*git.Commit,
502502
input*notifyInput,
503-
refstring,
503+
refgit.RefName,
504504
)error {
505-
branch,err:=commit.GetBranchName()
506-
iferr!=nil {
507-
returnerr
508-
}
509-
ifbranch!=input.Repo.DefaultBranch {
505+
ifref.BranchName()!=input.Repo.DefaultBranch {
510506
log.Trace("commit branch is not default branch in repo")
511507
returnnil
512508
}
@@ -552,7 +548,7 @@ func handleSchedules(
552548
WorkflowID:dwf.EntryName,
553549
TriggerUserID:user_model.ActionsUserID,
554550
TriggerUser:user_model.NewActionsUser(),
555-
Ref:ref,
551+
Ref:ref.String(),
556552
CommitSHA:commit.ID.String(),
557553
Event:input.Event,
558554
EventPayload:string(p),
@@ -614,5 +610,5 @@ func DetectAndHandleSchedules(ctx context.Context, repo *repo_model.Repository)
614610
// so we use action user as the Doer of the notifyInput
615611
notifyInput:=newNotifyInputForSchedules(repo)
616612

617-
returnhandleSchedules(ctx,scheduleWorkflows,commit,notifyInput,repo.DefaultBranch)
613+
returnhandleSchedules(ctx,scheduleWorkflows,commit,notifyInput,git.RefNameFromBranch(repo.DefaultBranch))
618614
}
Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package integration
5+
6+
import (
7+
"net/url"
8+
"strconv"
9+
"strings"
10+
"testing"
11+
12+
actions_model"code.gitea.io/gitea/models/actions"
13+
auth_model"code.gitea.io/gitea/models/auth"
14+
git_model"code.gitea.io/gitea/models/git"
15+
issues_model"code.gitea.io/gitea/models/issues"
16+
repo_model"code.gitea.io/gitea/models/repo"
17+
unit_model"code.gitea.io/gitea/models/unit"
18+
"code.gitea.io/gitea/models/unittest"
19+
user_model"code.gitea.io/gitea/models/user"
20+
"code.gitea.io/gitea/modules/migration"
21+
api"code.gitea.io/gitea/modules/structs"
22+
"code.gitea.io/gitea/modules/util"
23+
mirror_service"code.gitea.io/gitea/services/mirror"
24+
repo_service"code.gitea.io/gitea/services/repository"
25+
files_service"code.gitea.io/gitea/services/repository/files"
26+
27+
"github.com/stretchr/testify/assert"
28+
)
29+
30+
funcTestScheduleUpdate(t*testing.T) {
31+
t.Run("Push",testScheduleUpdatePush)
32+
t.Run("PullMerge",testScheduleUpdatePullMerge)
33+
t.Run("DisableAndEnableActionsUnit",testScheduleUpdateDisableAndEnableActionsUnit)
34+
t.Run("ArchiveAndUnarchive",testScheduleUpdateArchiveAndUnarchive)
35+
t.Run("MirrorSync",testScheduleUpdateMirrorSync)
36+
}
37+
38+
functestScheduleUpdatePush(t*testing.T) {
39+
doTestScheduleUpdate(t,func(t*testing.T,u*url.URL,testContextAPITestContext,user*user_model.User,repo*repo_model.Repository) (commitID,expectedSpecstring) {
40+
newCron:="30 5 * * 1,3"
41+
pushScheduleChange(t,u,repo,newCron)
42+
branch,err:=git_model.GetBranch(t.Context(),repo.ID,repo.DefaultBranch)
43+
assert.NoError(t,err)
44+
returnbranch.CommitID,newCron
45+
})
46+
}
47+
48+
functestScheduleUpdatePullMerge(t*testing.T) {
49+
newBranchName:="feat1"
50+
workflowTreePath:=".gitea/workflows/actions-schedule.yml"
51+
workflowContent:=`name: actions-schedule
52+
on:
53+
schedule:
54+
- cron: '@every 2m' # update to 2m
55+
jobs:
56+
job:
57+
runs-on: ubuntu-latest
58+
steps:
59+
- run: echo 'schedule workflow'
60+
`
61+
62+
mergeStyles:= []repo_model.MergeStyle{
63+
repo_model.MergeStyleMerge,
64+
repo_model.MergeStyleRebase,
65+
repo_model.MergeStyleRebaseMerge,
66+
repo_model.MergeStyleSquash,
67+
repo_model.MergeStyleFastForwardOnly,
68+
}
69+
70+
for_,mergeStyle:=rangemergeStyles {
71+
t.Run(string(mergeStyle),func(t*testing.T) {
72+
doTestScheduleUpdate(t,func(t*testing.T,u*url.URL,testContextAPITestContext,user*user_model.User,repo*repo_model.Repository) (commitID,expectedSpecstring) {
73+
// update workflow file
74+
_,err:=files_service.ChangeRepoFiles(t.Context(),repo,user,&files_service.ChangeRepoFilesOptions{
75+
NewBranch:newBranchName,
76+
Files: []*files_service.ChangeRepoFile{
77+
{
78+
Operation:"update",
79+
TreePath:workflowTreePath,
80+
ContentReader:strings.NewReader(workflowContent),
81+
},
82+
},
83+
Message:"update workflow schedule",
84+
})
85+
assert.NoError(t,err)
86+
87+
// create pull request
88+
apiPull,err:=doAPICreatePullRequest(testContext,repo.OwnerName,repo.Name,repo.DefaultBranch,newBranchName)(t)
89+
assert.NoError(t,err)
90+
91+
// merge pull request
92+
testPullMerge(t,testContext.Session,repo.OwnerName,repo.Name,strconv.FormatInt(apiPull.Index,10),mergeStyle,false)
93+
94+
pull:=unittest.AssertExistsAndLoadBean(t,&issues_model.PullRequest{ID:apiPull.ID})
95+
returnpull.MergedCommitID,"@every 2m"
96+
})
97+
})
98+
}
99+
100+
t.Run(string(repo_model.MergeStyleManuallyMerged),func(t*testing.T) {
101+
doTestScheduleUpdate(t,func(t*testing.T,u*url.URL,testContextAPITestContext,user*user_model.User,repo*repo_model.Repository) (commitID,expectedSpecstring) {
102+
// enable manual-merge
103+
doAPIEditRepository(testContext,&api.EditRepoOption{
104+
HasPullRequests:util.ToPointer(true),
105+
AllowManualMerge:util.ToPointer(true),
106+
})(t)
107+
108+
// update workflow file
109+
fileResp,err:=files_service.ChangeRepoFiles(t.Context(),repo,user,&files_service.ChangeRepoFilesOptions{
110+
NewBranch:newBranchName,
111+
Files: []*files_service.ChangeRepoFile{
112+
{
113+
Operation:"update",
114+
TreePath:workflowTreePath,
115+
ContentReader:strings.NewReader(workflowContent),
116+
},
117+
},
118+
Message:"update workflow schedule",
119+
})
120+
assert.NoError(t,err)
121+
122+
// merge and push
123+
dstPath:=t.TempDir()
124+
u.Path=repo.FullName()+".git"
125+
u.User=url.UserPassword(repo.OwnerName,userPassword)
126+
doGitClone(dstPath,u)(t)
127+
doGitMerge(dstPath,"origin/"+newBranchName)(t)
128+
doGitPushTestRepository(dstPath,"origin",repo.DefaultBranch)(t)
129+
130+
// create pull request
131+
apiPull,err:=doAPICreatePullRequest(testContext,repo.OwnerName,repo.Name,repo.DefaultBranch,newBranchName)(t)
132+
assert.NoError(t,err)
133+
134+
// merge pull request manually
135+
doAPIManuallyMergePullRequest(testContext,repo.OwnerName,repo.Name,fileResp.Commit.SHA,apiPull.Index)(t)
136+
137+
pull:=unittest.AssertExistsAndLoadBean(t,&issues_model.PullRequest{ID:apiPull.ID})
138+
assert.Equal(t,issues_model.PullRequestStatusManuallyMerged,pull.Status)
139+
returnpull.MergedCommitID,"@every 2m"
140+
})
141+
})
142+
}
143+
144+
functestScheduleUpdateMirrorSync(t*testing.T) {
145+
doTestScheduleUpdate(t,func(t*testing.T,u*url.URL,testContextAPITestContext,user*user_model.User,repo*repo_model.Repository) (commitID,expectedSpecstring) {
146+
// create mirror repo
147+
opts:= migration.MigrateOptions{
148+
RepoName:"actions-schedule-mirror",
149+
Description:"Test mirror for actions-schedule",
150+
Private:false,
151+
Mirror:true,
152+
CloneAddr:repo.CloneLinkGeneral(t.Context()).HTTPS,
153+
}
154+
mirrorRepo,err:=repo_service.CreateRepositoryDirectly(t.Context(),user,user, repo_service.CreateRepoOptions{
155+
Name:opts.RepoName,
156+
Description:opts.Description,
157+
IsPrivate:opts.Private,
158+
IsMirror:opts.Mirror,
159+
DefaultBranch:repo.DefaultBranch,
160+
Status:repo_model.RepositoryBeingMigrated,
161+
},false)
162+
assert.NoError(t,err)
163+
assert.True(t,mirrorRepo.IsMirror)
164+
mirrorRepo,err=repo_service.MigrateRepositoryGitData(t.Context(),user,mirrorRepo,opts,nil)
165+
assert.NoError(t,err)
166+
mirrorContext:=NewAPITestContext(t,user.Name,mirrorRepo.Name,auth_model.AccessTokenScopeWriteRepository)
167+
168+
// enable actions unit for mirror repo
169+
assert.False(t,mirrorRepo.UnitEnabled(t.Context(),unit_model.TypeActions))
170+
doAPIEditRepository(mirrorContext,&api.EditRepoOption{
171+
HasActions:util.ToPointer(true),
172+
})(t)
173+
actionSchedule:=unittest.AssertExistsAndLoadBean(t,&actions_model.ActionSchedule{RepoID:mirrorRepo.ID})
174+
scheduleSpec:=unittest.AssertExistsAndLoadBean(t,&actions_model.ActionScheduleSpec{RepoID:mirrorRepo.ID,ScheduleID:actionSchedule.ID})
175+
assert.Equal(t,"@every 1m",scheduleSpec.Spec)
176+
177+
// update remote repo
178+
newCron:="30 5,17 * * 2,4"
179+
pushScheduleChange(t,u,repo,newCron)
180+
repoDefaultBranch,err:=git_model.GetBranch(t.Context(),repo.ID,repo.DefaultBranch)
181+
assert.NoError(t,err)
182+
183+
// sync
184+
ok:=mirror_service.SyncPullMirror(t.Context(),mirrorRepo.ID)
185+
assert.True(t,ok)
186+
mirrorRepoDefaultBranch,err:=git_model.GetBranch(t.Context(),mirrorRepo.ID,mirrorRepo.DefaultBranch)
187+
assert.NoError(t,err)
188+
assert.Equal(t,repoDefaultBranch.CommitID,mirrorRepoDefaultBranch.CommitID)
189+
190+
// check updated schedule
191+
actionSchedule=unittest.AssertExistsAndLoadBean(t,&actions_model.ActionSchedule{RepoID:mirrorRepo.ID})
192+
scheduleSpec=unittest.AssertExistsAndLoadBean(t,&actions_model.ActionScheduleSpec{RepoID:mirrorRepo.ID,ScheduleID:actionSchedule.ID})
193+
assert.Equal(t,newCron,scheduleSpec.Spec)
194+
195+
returnrepoDefaultBranch.CommitID,newCron
196+
})
197+
}
198+
199+
functestScheduleUpdateArchiveAndUnarchive(t*testing.T) {
200+
doTestScheduleUpdate(t,func(t*testing.T,u*url.URL,testContextAPITestContext,user*user_model.User,repo*repo_model.Repository) (commitID,expectedSpecstring) {
201+
doAPIEditRepository(testContext,&api.EditRepoOption{
202+
Archived:util.ToPointer(true),
203+
})(t)
204+
assert.Zero(t,unittest.GetCount(t,&actions_model.ActionSchedule{RepoID:repo.ID}))
205+
doAPIEditRepository(testContext,&api.EditRepoOption{
206+
Archived:util.ToPointer(false),
207+
})(t)
208+
branch,err:=git_model.GetBranch(t.Context(),repo.ID,repo.DefaultBranch)
209+
assert.NoError(t,err)
210+
returnbranch.CommitID,"@every 1m"
211+
})
212+
}
213+
214+
functestScheduleUpdateDisableAndEnableActionsUnit(t*testing.T) {
215+
doTestScheduleUpdate(t,func(t*testing.T,u*url.URL,testContextAPITestContext,user*user_model.User,repo*repo_model.Repository) (commitID,expectedSpecstring) {
216+
doAPIEditRepository(testContext,&api.EditRepoOption{
217+
HasActions:util.ToPointer(false),
218+
})(t)
219+
assert.Zero(t,unittest.GetCount(t,&actions_model.ActionSchedule{RepoID:repo.ID}))
220+
doAPIEditRepository(testContext,&api.EditRepoOption{
221+
HasActions:util.ToPointer(true),
222+
})(t)
223+
branch,err:=git_model.GetBranch(t.Context(),repo.ID,repo.DefaultBranch)
224+
assert.NoError(t,err)
225+
returnbranch.CommitID,"@every 1m"
226+
})
227+
}
228+
229+
typescheduleUpdateTriggerfunc(t*testing.T,u*url.URL,testContextAPITestContext,user*user_model.User,repo*repo_model.Repository) (commitID,expectedSpecstring)
230+
231+
funcdoTestScheduleUpdate(t*testing.T,updateTriggerscheduleUpdateTrigger) {
232+
onGiteaRun(t,func(t*testing.T,u*url.URL) {
233+
user2:=unittest.AssertExistsAndLoadBean(t,&user_model.User{ID:2})
234+
session:=loginUser(t,user2.Name)
235+
token:=getTokenForLoggedInUser(t,session,auth_model.AccessTokenScopeWriteRepository,auth_model.AccessTokenScopeWriteUser)
236+
237+
apiRepo:=createActionsTestRepo(t,token,"actions-schedule",false)
238+
repo:=unittest.AssertExistsAndLoadBean(t,&repo_model.Repository{ID:apiRepo.ID})
239+
assert.NoError(t,repo.LoadAttributes(t.Context()))
240+
httpContext:=NewAPITestContext(t,user2.Name,repo.Name,auth_model.AccessTokenScopeWriteRepository)
241+
deferdoAPIDeleteRepository(httpContext)(t)
242+
243+
wfTreePath:=".gitea/workflows/actions-schedule.yml"
244+
wfFileContent:=`name: actions-schedule
245+
on:
246+
schedule:
247+
- cron: '@every 1m'
248+
jobs:
249+
job:
250+
runs-on: ubuntu-latest
251+
steps:
252+
- run: echo 'schedule workflow'
253+
`
254+
255+
opts1:=getWorkflowCreateFileOptions(user2,repo.DefaultBranch,"create "+wfTreePath,wfFileContent)
256+
apiFileResp:=createWorkflowFile(t,token,user2.Name,repo.Name,wfTreePath,opts1)
257+
258+
actionSchedule:=unittest.AssertExistsAndLoadBean(t,&actions_model.ActionSchedule{RepoID:repo.ID,CommitSHA:apiFileResp.Commit.SHA})
259+
scheduleSpec:=unittest.AssertExistsAndLoadBean(t,&actions_model.ActionScheduleSpec{RepoID:repo.ID,ScheduleID:actionSchedule.ID})
260+
assert.Equal(t,"@every 1m",scheduleSpec.Spec)
261+
262+
commitID,expectedSpec:=updateTrigger(t,u,httpContext,user2,repo)
263+
264+
actionSchedule=unittest.AssertExistsAndLoadBean(t,&actions_model.ActionSchedule{RepoID:repo.ID,CommitSHA:commitID})
265+
scheduleSpec=unittest.AssertExistsAndLoadBean(t,&actions_model.ActionScheduleSpec{RepoID:repo.ID,ScheduleID:actionSchedule.ID})
266+
assert.Equal(t,expectedSpec,scheduleSpec.Spec)
267+
})
268+
}
269+
270+
funcpushScheduleChange(t*testing.T,u*url.URL,repo*repo_model.Repository,newCronstring) {
271+
workflowTreePath:=".gitea/workflows/actions-schedule.yml"
272+
workflowContent:=`name: actions-schedule
273+
on:
274+
schedule:
275+
- cron: '`+newCron+`'
276+
jobs:
277+
job:
278+
runs-on: ubuntu-latest
279+
steps:
280+
- run: echo 'schedule workflow'
281+
`
282+
283+
dstPath:=t.TempDir()
284+
u.Path=repo.FullName()+".git"
285+
u.User=url.UserPassword(repo.OwnerName,userPassword)
286+
doGitClone(dstPath,u)(t)
287+
doGitCheckoutWriteFileCommit(localGitAddCommitOptions{
288+
LocalRepoPath:dstPath,
289+
CheckoutBranch:repo.DefaultBranch,
290+
TreeFilePath:workflowTreePath,
291+
TreeFileContent:workflowContent,
292+
})(t)
293+
doGitPushTestRepository(dstPath,"origin",repo.DefaultBranch)(t)
294+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp