@@ -21,8 +21,10 @@ import (
21
21
"code.gitea.io/gitea/modules/json"
22
22
"code.gitea.io/gitea/modules/setting"
23
23
api "code.gitea.io/gitea/modules/structs"
24
+ actions_service "code.gitea.io/gitea/services/actions"
24
25
25
26
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
27
+ "connectrpc.com/connect"
26
28
"github.com/stretchr/testify/assert"
27
29
)
28
30
@@ -132,7 +134,7 @@ jobs:
132
134
133
135
apiRepo := createActionsTestRepo (t , token , "actions-jobs-with-needs" , false )
134
136
runner := newMockRunner ()
135
- runner .registerAsRepoRunner (t , user2 .Name , apiRepo .Name , "mock-runner" , []string {"ubuntu-latest" })
137
+ runner .registerAsRepoRunner (t , user2 .Name , apiRepo .Name , "mock-runner" , []string {"ubuntu-latest" }, false )
136
138
137
139
for _ , tc := range testCases {
138
140
t .Run (fmt .Sprintf ("test %s" , tc .treePath ), func (t * testing.T ) {
@@ -318,7 +320,7 @@ jobs:
318
320
319
321
apiRepo := createActionsTestRepo (t , token , "actions-jobs-outputs-with-matrix" , false )
320
322
runner := newMockRunner ()
321
- runner .registerAsRepoRunner (t , user2 .Name , apiRepo .Name , "mock-runner" , []string {"ubuntu-latest" })
323
+ runner .registerAsRepoRunner (t , user2 .Name , apiRepo .Name , "mock-runner" , []string {"ubuntu-latest" }, false )
322
324
323
325
for _ , tc := range testCases {
324
326
t .Run (fmt .Sprintf ("test %s" , tc .treePath ), func (t * testing.T ) {
@@ -363,7 +365,7 @@ func TestActionsGiteaContext(t *testing.T) {
363
365
user2APICtx := NewAPITestContext (t , baseRepo .OwnerName , baseRepo .Name , auth_model .AccessTokenScopeWriteRepository )
364
366
365
367
runner := newMockRunner ()
366
- runner .registerAsRepoRunner (t , baseRepo .OwnerName , baseRepo .Name , "mock-runner" , []string {"ubuntu-latest" })
368
+ runner .registerAsRepoRunner (t , baseRepo .OwnerName , baseRepo .Name , "mock-runner" , []string {"ubuntu-latest" }, false )
367
369
368
370
// init the workflow
369
371
wfTreePath := ".gitea/workflows/pull.yml"
@@ -437,6 +439,156 @@ jobs:
437
439
})
438
440
}
439
441
442
+ // Ephemeral
443
+ func TestActionsGiteaContextEphemeral (t * testing.T ) {
444
+ onGiteaRun (t , func (t * testing.T , u * url.URL ) {
445
+ user2 := unittest .AssertExistsAndLoadBean (t , & user_model.User {ID : 2 })
446
+ user2Session := loginUser (t , user2 .Name )
447
+ user2Token := getTokenForLoggedInUser (t , user2Session , auth_model .AccessTokenScopeWriteRepository , auth_model .AccessTokenScopeWriteUser )
448
+
449
+ apiBaseRepo := createActionsTestRepo (t , user2Token , "actions-gitea-context" , false )
450
+ baseRepo := unittest .AssertExistsAndLoadBean (t , & repo_model.Repository {ID : apiBaseRepo .ID })
451
+ user2APICtx := NewAPITestContext (t , baseRepo .OwnerName , baseRepo .Name , auth_model .AccessTokenScopeWriteRepository )
452
+
453
+ runner := newMockRunner ()
454
+ runner .registerAsRepoRunner (t , baseRepo .OwnerName , baseRepo .Name , "mock-runner" , []string {"ubuntu-latest" }, true )
455
+
456
+ // verify CleanupEphemeralRunners does not remove this runner
457
+ err := actions_service .CleanupEphemeralRunners (t .Context ())
458
+ assert .NoError (t , err )
459
+
460
+ // init the workflow
461
+ wfTreePath := ".gitea/workflows/pull.yml"
462
+ wfFileContent := `name: Pull Request
463
+ on: pull_request
464
+ jobs:
465
+ wf1-job:
466
+ runs-on: ubuntu-latest
467
+ steps:
468
+ - run: echo 'test the pull'
469
+ wf2-job:
470
+ runs-on: ubuntu-latest
471
+ steps:
472
+ - run: echo 'test the pull'
473
+ `
474
+ opts := getWorkflowCreateFileOptions (user2 , baseRepo .DefaultBranch , fmt .Sprintf ("create %s" , wfTreePath ), wfFileContent )
475
+ createWorkflowFile (t , user2Token , baseRepo .OwnerName , baseRepo .Name , wfTreePath , opts )
476
+ // user2 creates a pull request
477
+ doAPICreateFile (user2APICtx , "user2-patch.txt" , & api.CreateFileOptions {
478
+ FileOptions : api.FileOptions {
479
+ NewBranchName : "user2/patch-1" ,
480
+ Message : "create user2-patch.txt" ,
481
+ Author : api.Identity {
482
+ Name : user2 .Name ,
483
+ Email : user2 .Email ,
484
+ },
485
+ Committer : api.Identity {
486
+ Name : user2 .Name ,
487
+ Email : user2 .Email ,
488
+ },
489
+ Dates : api.CommitDateOptions {
490
+ Author : time .Now (),
491
+ Committer : time .Now (),
492
+ },
493
+ },
494
+ ContentBase64 : base64 .StdEncoding .EncodeToString ([]byte ("user2-fix" )),
495
+ })(t )
496
+ apiPull , err := doAPICreatePullRequest (user2APICtx , baseRepo .OwnerName , baseRepo .Name , baseRepo .DefaultBranch , "user2/patch-1" )(t )
497
+ assert .NoError (t , err )
498
+ task := runner .fetchTask (t )
499
+ gtCtx := task .Context .GetFields ()
500
+ actionTask := unittest .AssertExistsAndLoadBean (t , & actions_model.ActionTask {ID : task .Id })
501
+ actionRunJob := unittest .AssertExistsAndLoadBean (t , & actions_model.ActionRunJob {ID : actionTask .JobID })
502
+ actionRun := unittest .AssertExistsAndLoadBean (t , & actions_model.ActionRun {ID : actionRunJob .RunID })
503
+ assert .NoError (t , actionRun .LoadAttributes (t .Context ()))
504
+
505
+ assert .Equal (t , user2 .Name , gtCtx ["actor" ].GetStringValue ())
506
+ assert .Equal (t , setting .AppURL + "api/v1" , gtCtx ["api_url" ].GetStringValue ())
507
+ assert .Equal (t , apiPull .Base .Ref , gtCtx ["base_ref" ].GetStringValue ())
508
+ runEvent := map [string ]any {}
509
+ assert .NoError (t , json .Unmarshal ([]byte (actionRun .EventPayload ), & runEvent ))
510
+ assert .True (t , reflect .DeepEqual (gtCtx ["event" ].GetStructValue ().AsMap (), runEvent ))
511
+ assert .Equal (t , actionRun .TriggerEvent , gtCtx ["event_name" ].GetStringValue ())
512
+ assert .Equal (t , apiPull .Head .Ref , gtCtx ["head_ref" ].GetStringValue ())
513
+ assert .Equal (t , actionRunJob .JobID , gtCtx ["job" ].GetStringValue ())
514
+ assert .Equal (t , actionRun .Ref , gtCtx ["ref" ].GetStringValue ())
515
+ assert .Equal (t , (git .RefName (actionRun .Ref )).ShortName (), gtCtx ["ref_name" ].GetStringValue ())
516
+ assert .False (t , gtCtx ["ref_protected" ].GetBoolValue ())
517
+ assert .Equal (t , string ((git .RefName (actionRun .Ref )).RefType ()), gtCtx ["ref_type" ].GetStringValue ())
518
+ assert .Equal (t , actionRun .Repo .OwnerName + "/" + actionRun .Repo .Name , gtCtx ["repository" ].GetStringValue ())
519
+ assert .Equal (t , actionRun .Repo .OwnerName , gtCtx ["repository_owner" ].GetStringValue ())
520
+ assert .Equal (t , actionRun .Repo .HTMLURL (), gtCtx ["repositoryUrl" ].GetStringValue ())
521
+ assert .Equal (t , fmt .Sprint (actionRunJob .RunID ), gtCtx ["run_id" ].GetStringValue ())
522
+ assert .Equal (t , fmt .Sprint (actionRun .Index ), gtCtx ["run_number" ].GetStringValue ())
523
+ assert .Equal (t , fmt .Sprint (actionRunJob .Attempt ), gtCtx ["run_attempt" ].GetStringValue ())
524
+ assert .Equal (t , "Actions" , gtCtx ["secret_source" ].GetStringValue ())
525
+ assert .Equal (t , setting .AppURL , gtCtx ["server_url" ].GetStringValue ())
526
+ assert .Equal (t , actionRun .CommitSHA , gtCtx ["sha" ].GetStringValue ())
527
+ assert .Equal (t , actionRun .WorkflowID , gtCtx ["workflow" ].GetStringValue ())
528
+ assert .Equal (t , setting .Actions .DefaultActionsURL .URL (), gtCtx ["gitea_default_actions_url" ].GetStringValue ())
529
+ token := gtCtx ["token" ].GetStringValue ()
530
+ assert .Equal (t , actionTask .TokenLastEight , token [len (token )- 8 :])
531
+
532
+ // verify CleanupEphemeralRunners does not remove this runner
533
+ err = actions_service .CleanupEphemeralRunners (t .Context ())
534
+ assert .NoError (t , err )
535
+
536
+ resp , err := runner .client .runnerServiceClient .FetchTask (t .Context (), connect .NewRequest (& runnerv1.FetchTaskRequest {
537
+ TasksVersion : 0 ,
538
+ }))
539
+ assert .NoError (t , err )
540
+ assert .Nil (t , resp .Msg .Task )
541
+
542
+ // verify CleanupEphemeralRunners does not remove this runner
543
+ err = actions_service .CleanupEphemeralRunners (t .Context ())
544
+ assert .NoError (t , err )
545
+
546
+ runner .client .runnerServiceClient .UpdateTask (t .Context (), connect .NewRequest (& runnerv1.UpdateTaskRequest {
547
+ State : & runnerv1.TaskState {
548
+ Id : actionTask .ID ,
549
+ Result : runnerv1 .Result_RESULT_SUCCESS ,
550
+ },
551
+ }))
552
+ resp , err = runner .client .runnerServiceClient .FetchTask (t .Context (), connect .NewRequest (& runnerv1.FetchTaskRequest {
553
+ TasksVersion : 0 ,
554
+ }))
555
+ assert .Error (t , err )
556
+ assert .Nil (t , resp )
557
+
558
+ resp , err = runner .client .runnerServiceClient .FetchTask (t .Context (), connect .NewRequest (& runnerv1.FetchTaskRequest {
559
+ TasksVersion : 0 ,
560
+ }))
561
+ assert .Error (t , err )
562
+ assert .Nil (t , resp )
563
+
564
+ // create an runner that picks a job and get force cancelled
565
+ runnerToBeRemoved := newMockRunner ()
566
+ runnerToBeRemoved .registerAsRepoRunner (t , baseRepo .OwnerName , baseRepo .Name , "mock-runner-to-be-removed" , []string {"ubuntu-latest" }, true )
567
+
568
+ taskToStopAPIObj := runnerToBeRemoved .fetchTask (t )
569
+
570
+ taskToStop := unittest .AssertExistsAndLoadBean (t , & actions_model.ActionTask {ID : taskToStopAPIObj .Id })
571
+
572
+ // verify CleanupEphemeralRunners does not remove the custom crafted runner
573
+ err = actions_service .CleanupEphemeralRunners (t .Context ())
574
+ assert .NoError (t , err )
575
+
576
+ runnerToRemove := unittest .AssertExistsAndLoadBean (t , & actions_model.ActionRunner {ID : taskToStop .RunnerID })
577
+
578
+ err = actions_model .StopTask (t .Context (), taskToStop .ID , actions_model .StatusFailure )
579
+ assert .NoError (t , err )
580
+
581
+ // verify CleanupEphemeralRunners does remove the custom crafted runner
582
+ err = actions_service .CleanupEphemeralRunners (t .Context ())
583
+ assert .NoError (t , err )
584
+
585
+ unittest .AssertNotExistsBean (t , & actions_model.ActionRunner {ID : runnerToRemove .ID })
586
+
587
+ // this cleanup is required to allow further tests to pass
588
+ doAPIDeleteRepository (user2APICtx )(t )
589
+ })
590
+ }
591
+
440
592
func createActionsTestRepo (t * testing.T , authToken , repoName string , isPrivate bool ) * api.Repository {
441
593
req := NewRequestWithJSON (t , "POST" , "/api/v1/user/repos" , & api.CreateRepoOption {
442
594
Name : repoName ,
0 commit comments