From 1d74ae636a07ec3df70f3a25d8bc05b890824a20 Mon Sep 17 00:00:00 2001 From: silverwind Date: Thu, 9 Jul 2026 15:08:59 +0000 Subject: [PATCH] fix: skip service containers with an empty image (#1074) GitHub Actions skips services whose image evaluates to an empty string, enabling conditional services via expressions like `image: ${{ matrix.image || '' }}`. Here such a service failed the job at `docker create`. Skip them before container creation, using GitHub's log message verbatim, and add a regression test. Reviewed-on: https://gitea.com/gitea/runner/pulls/1074 Reviewed-by: Nicolas Co-authored-by: silverwind --- act/runner/run_context.go | 9 ++++++++- act/runner/runner_test.go | 1 + act/runner/testdata/services-empty-image/push.yml | 10 ++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 act/runner/testdata/services-empty-image/push.yml diff --git a/act/runner/run_context.go b/act/runner/run_context.go index 68998801..5fdfeb41 100644 --- a/act/runner/run_context.go +++ b/act/runner/run_context.go @@ -379,6 +379,13 @@ func (rc *RunContext) startJobContainer() common.Executor { // add service containers for serviceID, spec := range rc.Run.Job().Services { + // GitHub compatibility: skip services whose image evaluates to an + // empty string, enabling conditional services via expressions + serviceImage := rc.ExprEval.Interpolate(ctx, spec.Image) + if serviceImage == "" { + logger.Infof("The service '%s' will not be started because the container definition has an empty image.", serviceID) + continue + } // interpolate env interpolatedEnvs := make(map[string]string, len(spec.Env)) for k, v := range spec.Env { @@ -417,7 +424,7 @@ func (rc *RunContext) startJobContainer() common.Executor { c := container.NewContainer(&container.NewContainerInput{ Name: serviceContainerName, WorkingDir: ext.ToContainerPath(rc.Config.Workdir), - Image: rc.ExprEval.Interpolate(ctx, spec.Image), + Image: serviceImage, Username: username, Password: password, Cmd: interpolatedCmd, diff --git a/act/runner/runner_test.go b/act/runner/runner_test.go index 92425818..61244f4b 100644 --- a/act/runner/runner_test.go +++ b/act/runner/runner_test.go @@ -303,6 +303,7 @@ func TestRunEvent(t *testing.T) { // services {workdir, "services", "push", "", platforms, secrets}, {workdir, "services-with-container", "push", "", platforms, secrets}, + {workdir, "services-empty-image", "push", "", platforms, secrets}, // local remote action overrides {workdir, "local-remote-action-overrides", "push", "", platforms, secrets}, diff --git a/act/runner/testdata/services-empty-image/push.yml b/act/runner/testdata/services-empty-image/push.yml new file mode 100644 index 00000000..b7c7082e --- /dev/null +++ b/act/runner/testdata/services-empty-image/push.yml @@ -0,0 +1,10 @@ +name: services-empty-image +on: push +jobs: + test: + runs-on: ubuntu-latest + services: + db: + image: ${{ false && 'postgres:16' || '' }} + steps: + - run: echo "empty-image service was skipped"