diff --git a/models/actions/run.go b/models/actions/run.go index 8194c07940..1551032f07 100644 --- a/models/actions/run.go +++ b/models/actions/run.go @@ -208,6 +208,30 @@ func (run *ActionRun) SetDefaultConcurrencyGroup() { )) } +func (run *ActionRun) FindOuterWorkflowCall(ctx context.Context, innerCall *ActionRunJob) (*ActionRunJob, error) { + allJobs, err := GetRunJobsByRunID(ctx, run.ID) + if err != nil { + return nil, fmt.Errorf("failure to get run jobs: %w", err) + } + if innerCall.workflowPayloadDecoded == nil || innerCall.workflowPayloadDecoded.Metadata.WorkflowCallParent == "" { + return nil, errors.New("invalid state for FindOuterWorkflowCall") + } + parent := innerCall.workflowPayloadDecoded.Metadata.WorkflowCallParent + for _, job := range allJobs { + if job.ID == innerCall.ID { + continue + } + swf, err := job.DecodeWorkflowPayload() + if err != nil { + return nil, err + } + if swf.Metadata.WorkflowCallID == parent { + return job, nil + } + } + return nil, fmt.Errorf("no workflow call with ID %s found in run %d", parent, run.ID) +} + func actionsCountOpenCacheKey(repoID int64) string { return fmt.Sprintf("Actions:CountOpenActionRuns:%d", repoID) } diff --git a/models/actions/run_test.go b/models/actions/run_test.go index 3a169dd56a..a0fdfddbd6 100644 --- a/models/actions/run_test.go +++ b/models/actions/run_test.go @@ -272,3 +272,58 @@ jobs: // Expect job with an incomplete runs-on to be StatusBlocked: assert.Equal(t, StatusBlocked, job.Status) } + +func TestActionRun_FindOuterWorkflowCall(t *testing.T) { + require.NoError(t, unittest.PrepareTestDatabase()) + + pullRequestPosterID := int64(4) + repoID := int64(10) + pullRequestID := int64(2) + run := &ActionRun{ + RepoID: repoID, + PullRequestID: pullRequestID, + PullRequestPosterID: pullRequestPosterID, + } + + workflowRaw := []byte(` +jobs: + outer-job: + uses: ./.forgejo/workflows/reusable.yml +`) + workflows, err := jobparser.Parse(workflowRaw, false, + jobparser.WithJobOutputs(map[string]map[string]string{}), + jobparser.ExpandLocalReusableWorkflows(func(job *jobparser.Job, path string) ([]byte, error) { + return []byte(` +on: + workflow_call: +jobs: + inner-job-1: + runs-on: debian + steps: [] + inner-job-2: + runs-on: debian + steps: [] +`), nil + })) + require.NoError(t, err) + require.NoError(t, InsertRun(t.Context(), run, workflows)) + + jobs, err := db.Find[ActionRunJob](t.Context(), FindRunJobOptions{RunID: run.ID}) + require.NoError(t, err) + require.Len(t, jobs, 3) + + for _, j := range jobs { + t.Run(j.Name, func(t *testing.T) { + _, err := j.DecodeWorkflowPayload() + require.NoError(t, err) + outer, err := run.FindOuterWorkflowCall(t.Context(), j) + if j.Name == "outer-job" { + require.ErrorContains(t, err, "invalid state for FindOuterWorkflowCall") + } else { + require.NoError(t, err) + require.NotNil(t, outer) + assert.Equal(t, "outer-job", outer.Name) + } + }) + } +} diff --git a/models/secret/secret.go b/models/secret/secret.go index 0a5db17690..b19199c177 100644 --- a/models/secret/secret.go +++ b/models/secret/secret.go @@ -8,9 +8,7 @@ import ( "fmt" "strings" - actions_model "forgejo.org/models/actions" "forgejo.org/models/db" - actions_module "forgejo.org/modules/actions" "forgejo.org/modules/keying" "forgejo.org/modules/log" "forgejo.org/modules/timeutil" @@ -120,28 +118,17 @@ func (s *Secret) SetSecret(data string) { s.Data = keying.ActionSecret.Encrypt([]byte(data), keying.ColumnAndID("data", s.ID)) } -func GetSecretsOfTask(ctx context.Context, task *actions_model.ActionTask) (map[string]string, error) { +func FetchActionSecrets(ctx context.Context, ownerID, repoID int64) (map[string]string, error) { secrets := map[string]string{} - secrets["GITHUB_TOKEN"] = task.Token - secrets["GITEA_TOKEN"] = task.Token - secrets["FORGEJO_TOKEN"] = task.Token - - if task.Job.Run.IsForkPullRequest && task.Job.Run.TriggerEvent != actions_module.GithubEventPullRequestTarget { - // ignore secrets for fork pull request, except GITHUB_TOKEN, GITEA_TOKEN and FORGEJO_TOKEN which are automatically generated. - // for the tasks triggered by pull_request_target event, they could access the secrets because they will run in the context of the base branch - // see the documentation: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target - return secrets, nil - } - - ownerSecrets, err := db.Find[Secret](ctx, FindSecretsOptions{OwnerID: task.Job.Run.Repo.OwnerID}) + ownerSecrets, err := db.Find[Secret](ctx, FindSecretsOptions{OwnerID: ownerID}) if err != nil { - log.Error("find secrets of owner %v: %v", task.Job.Run.Repo.OwnerID, err) + log.Error("find secrets of owner %v: %v", ownerID, err) return nil, err } - repoSecrets, err := db.Find[Secret](ctx, FindSecretsOptions{RepoID: task.Job.Run.RepoID}) + repoSecrets, err := db.Find[Secret](ctx, FindSecretsOptions{RepoID: repoID}) if err != nil { - log.Error("find secrets of repo %v: %v", task.Job.Run.RepoID, err) + log.Error("find secrets of repo %v: %v", repoID, err) return nil, err } diff --git a/models/secret/secret_test.go b/models/secret/secret_test.go index 76b673f2fe..50120ecfa3 100644 --- a/models/secret/secret_test.go +++ b/models/secret/secret_test.go @@ -6,8 +6,6 @@ package secret import ( "testing" - "forgejo.org/models/actions" - "forgejo.org/models/repo" "forgejo.org/models/unittest" "forgejo.org/modules/keying" "forgejo.org/modules/util" @@ -85,17 +83,8 @@ func TestInsertEncryptedSecret(t *testing.T) { }) }) - t.Run("Get secrets", func(t *testing.T) { - secrets, err := GetSecretsOfTask(t.Context(), &actions.ActionTask{ - Job: &actions.ActionRunJob{ - Run: &actions.ActionRun{ - RepoID: 1, - Repo: &repo.Repository{ - OwnerID: 2, - }, - }, - }, - }) + t.Run("FetchActionSecrets", func(t *testing.T) { + secrets, err := FetchActionSecrets(t.Context(), 2, 1) require.NoError(t, err) assert.Equal(t, "some owner secret", secrets["OWNER_SECRET"]) assert.Equal(t, "some repository secret", secrets["REPO_SECRET"]) diff --git a/services/actions/TestGetSecretsOfJob/action_run.yml b/services/actions/TestGetSecretsOfJob/action_run.yml new file mode 100644 index 0000000000..0bf311292f --- /dev/null +++ b/services/actions/TestGetSecretsOfJob/action_run.yml @@ -0,0 +1,94 @@ +# Supporting data for Case 600 +- + id: 900 + title: "running" + owner_id: 2 + repo_id: 63 + workflow_id: "running.yaml" + index: 4 + trigger_event: "push" + is_fork_pull_request: false + +# Supporting data for Case 601 +- + id: 901 + title: "running" + owner_id: 2 + repo_id: 63 + workflow_id: "running.yaml" + index: 5 + trigger_event: "pull_request_target" + is_fork_pull_request: false + +# Supporting data for Case 602 +- + id: 902 + title: "running" + owner_id: 2 + repo_id: 63 + workflow_id: "running.yaml" + index: 6 + trigger_event: "pull_request_target" + is_fork_pull_request: true + +# Supporting data for Case 603 +- + id: 903 + title: "running" + owner_id: 2 + repo_id: 63 + workflow_id: "running.yaml" + index: 7 + trigger_event: "pull_request" + is_fork_pull_request: false + +# Supporting data for Case 604 +- + id: 904 + title: "running" + owner_id: 2 + repo_id: 63 + workflow_id: "running.yaml" + index: 8 + trigger_event: "pull_request" + is_fork_pull_request: true + +# Supporting data for Case 605 +- + id: 905 + title: "running" + owner_id: 2 + repo_id: 63 + workflow_id: "running.yaml" + index: 9 + trigger_event: "pull_request" + is_fork_pull_request: false + +# Supporting data for Case 607 +- + id: 906 + title: "running" + owner_id: 2 + repo_id: 63 + workflow_id: "running.yaml" + index: 10 + trigger_event: "pull_request" + is_fork_pull_request: false + +# Supporting data for Case 610 +- + id: 907 + title: "running" + owner_id: 2 + repo_id: 63 + ref: "refs/heads/main" + workflow_id: "running.yaml" + index: 11 + trigger_event: "workflow_dispatch" + is_fork_pull_request: false + event_payload: | + { + "inputs": { + "some_wd_input": "some_wd_input_value" + } + } diff --git a/services/actions/TestGetSecretsOfJob/action_run_job.yml b/services/actions/TestGetSecretsOfJob/action_run_job.yml new file mode 100644 index 0000000000..a1bad9fe98 --- /dev/null +++ b/services/actions/TestGetSecretsOfJob/action_run_job.yml @@ -0,0 +1,192 @@ +# Case 600 -- on:push workflow with some secrets +- + id: 600 + run_id: 900 + workflow_payload: | + "on": + push: + jobs: + produce-artifacts: + name: produce-artifacts + runs-on: docker + steps: + - run: echo "OK!" + +# Case 601 -- on: pull_request_target workflow, local PR (not fork) +- + id: 601 + run_id: 901 + workflow_payload: | + "on": + pull_request_target: + jobs: + produce-artifacts: + name: produce-artifacts + runs-on: docker + steps: + - run: echo "OK!" + +# Case 602 -- on: pull_request_target workflow, fork PR +- + id: 602 + run_id: 902 + workflow_payload: | + "on": + pull_request_target: + jobs: + produce-artifacts: + name: produce-artifacts + runs-on: docker + steps: + - run: echo "OK!" + +# Case 603 -- on: pull_request workflow, local PR (not fork) +- + id: 603 + run_id: 903 + workflow_payload: | + "on": + pull_request: + jobs: + produce-artifacts: + name: produce-artifacts + runs-on: docker + steps: + - run: echo "OK!" + +# Case 604 -- on: pull_request workflow, fork PR +- + id: 604 + run_id: 904 + workflow_payload: | + "on": + pull_request: + jobs: + produce-artifacts: + name: produce-artifacts + runs-on: docker + steps: + - run: echo "OK!" + +# Case 605 -- workflow call inner job, inherit secrets, 606 is the outer job +- + id: 605 + run_id: 905 + workflow_payload: | + "on": + pull_request_target: + jobs: + produce-artifacts: + name: produce-artifacts + runs-on: docker + steps: + - run: echo "OK!" + __metadata: + workflow_call_parent: b5a9f46f1f2513d7777fde50b169d323a6519e349cc175484c947ac315a209ed +- + id: 606 + run_id: 905 + workflow_payload: | + "on": + pull_request_target: + jobs: + invoke-reusable: + uses: ./.forgejo/workflows/produce.yml + secrets: inherit + __metadata: + workflow_call_id: b5a9f46f1f2513d7777fde50b169d323a6519e349cc175484c947ac315a209ed + +# Case 607 -- workflow call two layer inner job, inherit secrets, 607->608->609 +- + id: 607 + run_id: 906 + workflow_payload: | + "on": + workflow_call: + jobs: + produce-artifacts: + name: produce-artifacts + runs-on: docker + steps: + - run: echo "OK!" + __metadata: + workflow_call_parent: b5a9f46f1f2513d7777fde50b169d323a6519e349cc175484c947ac315a209ed +- + id: 608 + run_id: 906 + workflow_payload: | + "on": + workflow_call: + jobs: + invoke-reusable: + uses: ./.forgejo/workflows/produce-specific.yml + secrets: inherit + __metadata: + workflow_call_id: b5a9f46f1f2513d7777fde50b169d323a6519e349cc175484c947ac315a209ed + workflow_call_parent: 1976193ec4c48a92ba58816b34116272f5b3a612b91494956e5b53ee70b8714f +- + id: 609 + run_id: 906 + workflow_payload: | + "on": + pull_request: + jobs: + invoke-reusable: + uses: ./.forgejo/workflows/produce.yml + secrets: + secret_1: ${{ secrets.secret_1 }} -- but are you sure? + __metadata: + workflow_call_id: 1976193ec4c48a92ba58816b34116272f5b3a612b91494956e5b53ee70b8714f + +# Case 610 -- workflow call specifically defined secrets, 611 is the outer job, 612 is another job in the same workflow +- + id: 610 + run_id: 907 + workflow_payload: | + "on": + workflow_call: + jobs: + produce-artifacts: + name: produce-artifacts + runs-on: docker + steps: + - run: echo "OK!" + __metadata: + workflow_call_parent: b5a9f46f1f2513d7777fde50b169d323a6519e349cc175484c947ac315a209ed +- + id: 611 + run_id: 907 + needs: '["provide-outputs"]' + workflow_payload: | + "on": + workflow_dispatch: + jobs: + invoke-reusable: + uses: ./.forgejo/workflows/produce-specific.yml + secrets: + forgejo: context forgejo = ${{ forgejo.ref }} + inputs: context inputs = ${{ inputs.some_wd_input }} + matrix: context matrix = ${{ matrix.some-dimension }} + needs: context needs = ${{ needs.provide-outputs.outputs.some-output }} + secrets: context secrets = ${{ secrets.secret_1 }} + strategy: context strategy = ${{ strategy.fail-fast }} + vars: context vars = ${{ vars.repo_var }} + strategy: + fail-fast: false + matrix: + some-dimension: + - some-dimension-value + __metadata: + workflow_call_id: b5a9f46f1f2513d7777fde50b169d323a6519e349cc175484c947ac315a209ed +- + id: 612 + run_id: 907 + job_id: provide-outputs + status: 1 # success + workflow_payload: | + "on": + workflow_dispatch: + jobs: + provide-outputs: + steps: [] + task_id: 100 diff --git a/services/actions/TestGetSecretsOfJob/action_task_output.yml b/services/actions/TestGetSecretsOfJob/action_task_output.yml new file mode 100644 index 0000000000..6f33d22d29 --- /dev/null +++ b/services/actions/TestGetSecretsOfJob/action_task_output.yml @@ -0,0 +1,6 @@ +# Supporting data for Case 610 +- + id: 100 + task_id: 100 + output_key: some-output + output_value: 'abcdefghijklmnopqrstuvwxyz' diff --git a/services/actions/TestGetSecretsOfJob/action_variable.yml b/services/actions/TestGetSecretsOfJob/action_variable.yml new file mode 100644 index 0000000000..859f90ae34 --- /dev/null +++ b/services/actions/TestGetSecretsOfJob/action_variable.yml @@ -0,0 +1,22 @@ +# Case w/ action_run_job.id = 601 +- + id: 1001 + name: REPO_VAR + owner_id: 0 + repo_id: 63 + data: "this is a repo variable" + created_unix: 1737000000 +- + id: 1002 + name: ORG_VAR + owner_id: 2 + repo_id: 0 + data: "this is an org variable" + created_unix: 1737000000 +- + id: 1003 + name: GLOBAL_VAR + owner_id: 0 + repo_id: 0 + data: "this is a global variable" + created_unix: 1737000000 diff --git a/services/actions/secret.go b/services/actions/secret.go new file mode 100644 index 0000000000..b62547ce70 --- /dev/null +++ b/services/actions/secret.go @@ -0,0 +1,145 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: GPL-3.0-or-later + +package actions + +import ( + "context" + "errors" + "fmt" + + actions_model "forgejo.org/models/actions" + secret_model "forgejo.org/models/secret" + actions_module "forgejo.org/modules/actions" + "forgejo.org/modules/json" + "forgejo.org/modules/structs" + + "code.forgejo.org/forgejo/runner/v12/act/jobparser" +) + +func getSecretsOfTask(ctx context.Context, task *actions_model.ActionTask) (map[string]string, error) { + secrets, err := getSecretsOfJob(ctx, task.Job) + secrets["GITHUB_TOKEN"] = task.Token + secrets["GITEA_TOKEN"] = task.Token + secrets["FORGEJO_TOKEN"] = task.Token + return secrets, err +} + +func getSecretsOfJob(ctx context.Context, job *actions_model.ActionRunJob) (map[string]string, error) { + isInnerWorkflowCall, err := job.IsWorkflowCallInnerJob() + if err != nil { + return nil, err + } + + err = job.LoadRun(ctx) + if err != nil { + return nil, fmt.Errorf("failure to load job run: %w", err) + } + + if isInnerWorkflowCall { + return getSecretsOfInnerWorkflowCall(ctx, job) + } + + if job.Run.IsForkPullRequest && job.Run.TriggerEvent != actions_module.GithubEventPullRequestTarget { + // ignore secrets for fork pull request, except GITHUB_TOKEN, GITEA_TOKEN and FORGEJO_TOKEN which are automatically generated. + // for the tasks triggered by pull_request_target event, they could access the secrets because they will run in the context of the base branch + // see the documentation: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target + return map[string]string{}, nil + } + + err = job.Run.LoadRepo(ctx) + if err != nil { + return nil, err + } + + jobSecrets, err := secret_model.FetchActionSecrets(ctx, job.Run.Repo.OwnerID, job.Run.RepoID) + if err != nil { + // Don't return error details, just in case they contain confidential details and error reaches a user; + // FetchActionSecrets logs all errors to the server log. + return nil, errors.New("failure to fetch secrets") + } + return jobSecrets, nil +} + +func getSecretsOfInnerWorkflowCall(ctx context.Context, job *actions_model.ActionRunJob) (map[string]string, error) { + // Workflow calls can have two different behaviours -- they can either have `secrets: inherit` in which case we get + // the secrets of the caller and pass them in, or, they can have `secrets: { ... }` with key-values that need to be + // evaluated in the context of the parent (that is, `${{ secret.example_secret }}` would reference `example_secret` + // from the caller's secrets). + // + // In either case, we need the caller job's secrets, and we need the caller job's workflow definition to find out + // how they wanted secrets defined for this workflow call. + outerWorkflowCall, err := job.Run.FindOuterWorkflowCall(ctx, job) + if err != nil { + return nil, fmt.Errorf("failure to find outer workflow call: %w", err) + } + outerSecrets, err := getSecretsOfJob(ctx, outerWorkflowCall) + if err != nil { + return nil, err + } + + outerWorkflowPayload, err := outerWorkflowCall.DecodeWorkflowPayload() + if err != nil { + return nil, err + } + _, outerJob := outerWorkflowPayload.Job() + if outerJob.InheritSecrets() { + return outerSecrets, nil + } + + // Gather all the data that is needed to perform an expression evaluation of the parent job's secrets context: + err = outerWorkflowCall.LoadRun(ctx) + if err != nil { + return nil, fmt.Errorf("failure to load job's run: %w", err) + } + err = outerWorkflowCall.Run.LoadRepo(ctx) + if err != nil { + return nil, fmt.Errorf("failure to load run's repo: %w", err) + } + githubContext := generateGiteaContextForRun(outerWorkflowCall.Run) + taskNeeds, err := FindTaskNeeds(ctx, outerWorkflowCall) + if err != nil { + return nil, fmt.Errorf("failure evaluating 'needs' for job: %w", err) + } + needs := make([]string, 0, len(taskNeeds)) + jobResults := make(map[string]string, len(taskNeeds)) + jobOutputs := make(map[string]map[string]string, len(taskNeeds)) + for jobID, n := range taskNeeds { + needs = append(needs, jobID) + jobResults[jobID] = n.Result.String() + jobOutputs[jobID] = n.Outputs + } + vars, err := actions_model.GetVariablesOfRun(ctx, job.Run) + if err != nil { + return nil, fmt.Errorf("failure evaluating 'vars' for run: %w", err) + } + + var inputs map[string]any + if outerWorkflowCall.Run.TriggerEvent == actions_module.GithubEventWorkflowDispatch { + // workflow_dispatch inputs are stored in the event payload + var dispatchPayload *structs.WorkflowDispatchPayload + err := json.Unmarshal([]byte(outerWorkflowCall.Run.EventPayload), &dispatchPayload) + if err != nil { + return nil, fmt.Errorf("failure reading workflow dispatch payload: %w", err) + } + // transition from map[string]string to map[string]any... + inputs = make(map[string]any, len(dispatchPayload.Inputs)) + for k, v := range dispatchPayload.Inputs { + inputs[k] = v + } + } + + jobSecrets := jobparser.EvaluateWorkflowCallSecrets(&jobparser.EvaluateWorkflowCallSecretsArgs{ + CallerWorkflow: outerWorkflowPayload, + CallerSecrets: outerSecrets, + + GitCtx: githubContext, + Vars: vars, + Needs: needs, + JobResults: jobResults, + JobOutputs: jobOutputs, + JobInputs: inputs, + }) + + return jobSecrets, nil +} diff --git a/services/actions/secret_test.go b/services/actions/secret_test.go new file mode 100644 index 0000000000..107cde1a4d --- /dev/null +++ b/services/actions/secret_test.go @@ -0,0 +1,108 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: GPL-3.0-or-later + +package actions + +import ( + "testing" + + actions_model "forgejo.org/models/actions" + secret_model "forgejo.org/models/secret" + "forgejo.org/models/unittest" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestGetSecretsOfJob(t *testing.T) { + tests := []struct { + name string + runJobID int64 + secrets map[string]string + }{ + { + name: "push run", + runJobID: 600, + secrets: map[string]string{ + "SECRET_1": "the sky is blue", + "SECRET_2": "the ocean is also blue", + }, + }, + { + name: "on: pull_request_target workflow, local PR (not fork)", + runJobID: 601, + secrets: map[string]string{ + "SECRET_1": "the sky is blue", + "SECRET_2": "the ocean is also blue", + }, + }, + { + name: "on: pull_request_target workflow, fork PR", + runJobID: 602, + secrets: map[string]string{ + "SECRET_1": "the sky is blue", + "SECRET_2": "the ocean is also blue", + }, + }, + { + name: "on: pull_request workflow, local PR (not fork)", + runJobID: 603, + secrets: map[string]string{ + "SECRET_1": "the sky is blue", + "SECRET_2": "the ocean is also blue", + }, + }, + { + name: "on: pull_request workflow, fork PR", + runJobID: 604, + secrets: map[string]string{}, + }, + { + name: "workflow call inner job, inherit secrets", + runJobID: 605, + secrets: map[string]string{ + "SECRET_1": "the sky is blue", + "SECRET_2": "the ocean is also blue", + }, + }, + { + name: "workflow call two layer inner job, inherit secrets", + runJobID: 607, + secrets: map[string]string{ + // Even though we're 'inherit' in this case, we're inheriting from the parent call which is a subset + // (and modification) of the secrets -- so shouldn't see SECRET_2. + "SECRET_1": "the sky is blue -- but are you sure?", + }, + }, + { + name: "workflow call inner job, defined secrets", + runJobID: 610, + secrets: map[string]string{ + "FORGEJO": "context forgejo = refs/heads/main", + "INPUTS": "context inputs = some_wd_input_value", + "MATRIX": "context matrix = some-dimension-value", + "NEEDS": "context needs = abcdefghijklmnopqrstuvwxyz", + "SECRETS": "context secrets = the sky is blue", + "STRATEGY": "context strategy = false", + "VARS": "context vars = this is a repo variable", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + defer unittest.OverrideFixtures("services/actions/TestGetSecretsOfJob")() + require.NoError(t, unittest.PrepareTestDatabase()) + + // Due to encryption, more maintainable to do this rather than create secrets in fixture data + _, err := secret_model.InsertEncryptedSecret(t.Context(), 2, 0, "secret_1", "the sky is blue") + require.NoError(t, err) + _, err = secret_model.InsertEncryptedSecret(t.Context(), 0, 63, "secret_2", "the ocean is also blue") + require.NoError(t, err) + + runJob := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunJob{ID: tt.runJobID}) + actualSecrets, err := getSecretsOfJob(t.Context(), runJob) + require.NoError(t, err) + assert.Equal(t, tt.secrets, actualSecrets) + }) + } +} diff --git a/services/actions/task.go b/services/actions/task.go index 277c2f6ca0..1de054346a 100644 --- a/services/actions/task.go +++ b/services/actions/task.go @@ -10,7 +10,6 @@ import ( actions_model "forgejo.org/models/actions" "forgejo.org/models/db" - secret_model "forgejo.org/models/secret" "forgejo.org/modules/timeutil" "forgejo.org/modules/util" @@ -39,7 +38,7 @@ func PickTask(ctx context.Context, runner *actions_model.ActionRunner) (*runnerv } job = t.Job - secrets, err := secret_model.GetSecretsOfTask(ctx, t) + secrets, err := getSecretsOfTask(ctx, t) if err != nil { return fmt.Errorf("GetSecretsOfTask: %w", err) }