Skip to content

fix: don't panic in GetHealth during a dry run - #6146

Open
ankit090701 wants to merge 1 commit into
nektos:masterfrom
ankit090701:fix/gethealth-dryrun-nil-panic-2607
Open

fix: don't panic in GetHealth during a dry run#6146
ankit090701 wants to merge 1 commit into
nektos:masterfrom
ankit090701:fix/gethealth-dryrun-nil-panic-2607

Conversation

@ankit090701

Copy link
Copy Markdown

Description

Any workflow with services, run with dry-run (act -n), panics with invalid memory address or nil pointer dereference (confirmed by 4 separate users on this issue, across versions 0.2.71-0.2.78, on macOS and WSL2).

Root cause

containerReference.GetHealth (pkg/container/docker_run.go) calls cr.cli.ContainerInspect(...) unconditionally. cr.cli is only ever assigned by connect(), and every pipeline that calls connect() (Create, Start, Exec, Copy, Remove) is wrapped with .IfNot(common.Dryrun) - so during a dry run, cr.cli is never set and stays nil.

GetHealth is the odd one out: it's called directly by RunContext.waitForServiceContainer (pkg/runner/run_context.go), not through one of those dry-run-gated pipelines. So as soon as a dry run with services reaches the "wait for service containers to become healthy" step, cr.cli.ContainerInspect panics on the nil client.

The fix

Add a dry-run check at the top of GetHealth that returns HealthHealthy immediately, before touching cr.cli. This mirrors two existing patterns in the same file/package:

  • GetContainerArchive already has its own if common.Dryrun(ctx) { ... } early return.
  • HostEnvironment.GetHealth (the no-Docker ExecutionsEnvironment implementation) already unconditionally returns HealthHealthy - a dry run doesn't create real containers, so reporting them as healthy is consistent with how every other dry-run codepath behaves (they no-op and report success).

waitForServiceContainer treats any non-HealthStarting result as terminal and only succeeds on HealthHealthy, so this also makes the dry-run wait loop resolve immediately instead of looping 30 times / 5 minutes.

Testing

  • Added TestDockerGetHealthDryrun (pkg/container/docker_run_test.go), which constructs a containerReference with a nil cli (matching dry run's actual state) and confirms GetHealth under a dry-run context returns HealthHealthy without panicking.
  • Verified by reverting just the docker_run.go change: the test fails with the exact panic reported in this issue (invalid memory address or nil pointer dereference, docker_run.go:175, inside GetHealth).
  • Ran go build ./... (clean) and go test ./pkg/container/.... The only other failure in that package, TestImageExistsLocally, is pre-existing and unrelated - it needs a live Docker daemon, which isn't available in the sandbox I used to verify this (no Docker-in-Docker).

Fixes #2607

containerReference.GetHealth called cr.cli.ContainerInspect
unconditionally. cr.cli is only ever set by connect(), which is called
from pipelines that are all gated with .IfNot(common.Dryrun) (Create,
Start, Exec, etc.) - so during a dry run, cr.cli stays nil.

GetHealth itself is called directly (not through one of those gated
pipelines) by RunContext.waitForServiceContainer, so any workflow with
`services` panicked with a nil pointer dereference as soon as a dry run
(`act -n`) reached the "wait for service containers to be healthy" step.

Add a dry-run check at the top of GetHealth, matching the pattern
GetContainerArchive already uses, and matching how HostEnvironment's
GetHealth already unconditionally returns HealthHealthy - a dry run
doesn't create real containers, so pretending they're healthy is
consistent with how the rest of the dry-run codepaths behave.

fixes nektos#2607

Signed-off-by: ankit090701 <ankitanku090701@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Including workflow services crashes with invalid memory address or nil pointer dereference for dry-run

1 participant