From df0370f8bfd3563cf207098ad4c2cde4d98d371b Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 18 Jun 2026 02:55:30 +0000 Subject: [PATCH] fix: Interpolate job container.volume (#1036) Interpolate job container.volumes in GetBindsAndMounts(), matching service container volumes and other container fields (image, options). Fixes expressions like ${{ secrets.MAME }}:/path:ro being passed literally and rejected as invalid bind mounts Reviewed-on: https://gitea.com/gitea/runner/pulls/1036 Reviewed-by: Lunny Xiao --- act/runner/run_context.go | 3 +++ act/runner/run_context_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/act/runner/run_context.go b/act/runner/run_context.go index b5b78385..3630c329 100644 --- a/act/runner/run_context.go +++ b/act/runner/run_context.go @@ -189,6 +189,9 @@ func (rc *RunContext) GetBindsAndMounts() ([]string, map[string]string) { if job := rc.Run.Job(); job != nil { if container := job.Container(); container != nil { for _, v := range container.Volumes { + if rc.ExprEval != nil { + v = rc.ExprEval.Interpolate(context.Background(), v) + } if !strings.Contains(v, ":") || filepath.IsAbs(v) { // Bind anonymous volume or host file. binds = append(binds, v) diff --git a/act/runner/run_context_test.go b/act/runner/run_context_test.go index 40f4d73c..8b2563af 100644 --- a/act/runner/run_context_test.go +++ b/act/runner/run_context_test.go @@ -276,6 +276,37 @@ func TestRunContext_GetBindsAndMounts(t *testing.T) { {"MountExistingVolume", []string{"volume-id:/volume"}, "", map[string]string{"volume-id": "/volume"}}, } + t.Run("InterpolatedContainerVolumes", func(t *testing.T) { + job := &model.Job{} + err := job.RawContainer.Encode(map[string][]string{ + "volumes": {"${{ secrets.MAME }}:/root/.mame/roms:ro"}, + }) + require.NoError(t, err) + + rc := &RunContext{ + Name: "TestRCName", + Run: &model.Run{ + Workflow: &model.Workflow{ + Name: "TestWorkflowName", + }, + }, + Config: &Config{ + BindWorkdir: false, + Secrets: map[string]string{ + "MAME": "/host/mame/roms", + }, + }, + } + rc.Run.JobID = "job1" + rc.Run.Workflow.Jobs = map[string]*model.Job{"job1": job} + rc.ExprEval = rc.NewExpressionEvaluator(context.Background()) + + gotbind, gotmount := rc.GetBindsAndMounts() + assert.Contains(t, gotbind, "/host/mame/roms:/root/.mame/roms:ro") + assert.NotContains(t, gotbind, "${{ secrets.MAME }}") + assert.NotContains(t, gotmount, "${{ secrets.MAME }}") + }) + for _, testcase := range tests { t.Run(testcase.name, func(t *testing.T) { job := &model.Job{}