[REVIEW DRAFT] Windows container PATH fix (do not merge) + proposed upstream issue/PR#1
Closed
bugale wants to merge 1 commit into
Closed
[REVIEW DRAFT] Windows container PATH fix (do not merge) + proposed upstream issue/PR#1bugale wants to merge 1 commit into
bugale wants to merge 1 commit into
Conversation
On Windows, docker inspect .Config.Env rarely contains the container's PATH (servercore/nanoserver and most images don't declare it), so ParsePathFromConfigEnv returns empty. The later docker exec -e PATH= override then replaces the container PATH with only the prepended dirs -- System32 and PowerShell vanish and the next step's shell can't launch (hcs::CreateProcess 0x2, exit 126/127). PATH segments were also joined with a POSIX ':' separator. Read the container's real PATH at startup when .Config.Env has none, and join with Path.PathSeparator. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Owner
Author
|
Superseded — the real issue and PR are now open upstream:
Closing this review draft. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The fix (what this branch changes)
Two files, ~9 lines (see the Files changed tab).
ContainerOperationProvider.cs— on Windows, whendocker inspect .Config.Envyields no PATH (servercore/nanoserver/most Windows images), read the container's real PATH viadocker exec <id> cmd /c echo %PATH%.StepHost.cs— join the prepended dirs and the base PATH withPath.PathSeparatorinstead of a hard-coded POSIX:.Why this, not just a case-insensitive PATH key
The downstream workaround notes a case-sensitive
"PATH"lookup, but I confirmed empirically that the relevant Windows images (servercore:ltsc2025,nanoserver, thedotnetimages, and the real builder image) declare noPath/PATHin.Config.Envat all — the real PATH only exists at runtime. A case-insensitive read wouldn't help; the base must be read live. This patch is a superset of the case fix and also covers the "image omits PATH" case.Verification
dotnet buildclean;DockerUtilL0+StepHostL0+ContainerOperationProviderL0pass (61 tests).-e PATH="<prepend only>"->hcs::CreateProcess 0x2, exit 127; fixed-e PATH="<prepend>;<livePATH>"-> shell launches, prepend first, System32 present, exit 0.actions/runner, and the fix keepsDockerUtil.cs/DockerUtilL0.csuntouched for clean rebases.📋 Proposed UPSTREAM ISSUE (to open in sirredbeard/runner)
Title: Windows
container:job — container PATH dropped after a step writes$GITHUB_PATH(shell fails to launch, exit 126/127)Summary
In a Windows job-level
container:job, as soon as any step writes to$GITHUB_PATH(directly, or via asetup-*action), every subsequent in-container step fails to launch its shell:and the step exits 126/127.
Root cause
When a step appends to
$GITHUB_PATH,ContainerStepHost.ExecuteAsyncre-runs the in-container command with an explicit PATH override:ContainerRuntimePathis captured once at container start inContainerOperationProviderfromdocker inspect --format "{{range .Config.Env}}{{println .}}{{end}}" <id>, parsed byDockerUtil.ParsePathFromConfigEnv.Two problems surface on Windows:
.Config.Envhas no PATH. Typical Windows images (mcr.microsoft.com/windows/servercore,nanoserver, even thedotnetimages) do not declarePath/PATHin their image config. A Windows container's real PATH (System32, PowerShell, …) is provided by the OS at runtime and is not visible viadocker inspect .Config.Env. SoParsePathFromConfigEnvreturns empty andContainerRuntimePathis empty.:, which is wrong on Windows (separator is;, and drive letters contain:).With an empty base, the override collapses to
-e PATH="<prepended-dirs>"— the container's System32/PowerShell are gone, so the next step's shell can't be found.Reproduction
docker inspect <id> --format "{{range .Config.Env}}{{println .}}{{end}}"shows no PATH, whiledocker exec <id> cmd /c echo %PATH%shows the real one. Replaying the exact command line the runner produces against a real Windows container:Minimal workflow that triggers it:
Suggested fix
ContainerOperationProvider, when.Config.Envyields no PATH on Windows, read the container's real PATH (docker exec <id> cmd /c echo %PATH%).ContainerStepHost.ExecuteAsync, join withPath.PathSeparatorinstead of:.Small patch (2 files, ~9 lines); PR to follow.
📋 Proposed UPSTREAM PR description (to open in sirredbeard/runner)
Title: Fix Windows container PATH being dropped after a
$GITHUB_PATHwriteProblem
On a Windows
container:job, after any step writes$GITHUB_PATH, every later in-container step fails to launch its shell:When a step appends to
$GITHUB_PATH,ContainerStepHost.ExecuteAsyncre-execs with an explicit overridedocker exec -e PATH="<prepend>:<ContainerRuntimePath>".ContainerRuntimePathis read once at container start fromdocker inspect .Config.Env(DockerUtil.ParsePathFromConfigEnv). On Windows that base is empty: typical Windows images (servercore, nanoserver, thedotnetimages) don't declarePathin.Config.Env— a Windows container's real PATH only exists at runtime. The override therefore drops System32/PowerShell, and the segments were joined with a POSIX:.Fix
ContainerOperationProvider: when.Config.Envhas no PATH on Windows, read the container's real PATH viadocker exec <id> cmd /c echo %PATH%.ContainerStepHost.ExecuteAsync: join withPath.PathSeparatorinstead of:.Testing
dotnet buildclean; existingDockerUtilL0,StepHostL0,ContainerOperationProviderL0tests pass (61).-e PATH="<prepend only>") fails withhcs::CreateProcess 0x2/ exit 127; with the container's live PATH appended and;separator the shell launches, the prepended dir stays first, and System32 is present (exit 0).Linux is unaffected:
Path.PathSeparatoris:there, and the live-PATH read is Windows-only and only triggers when.Config.Envhas no PATH.