Repository navigation
test(worker): isolate JobExtensionL0 from host job-hook env vars - #235
Closed
florentianayuwono wants to merge 2 commits into
Closed
florentianayuwono wants to merge 2 commits into
florentianayuwono wants to merge 2 commits into
Conversation
JobExtension.InitializeJob reads ACTIONS_RUNNER_HOOK_JOB_STARTED and ACTIONS_RUNNER_HOOK_JOB_COMPLETED directly from the process environment to decide whether to inject extra job-hook steps into the returned step list. JobExtensionL0's tests never clear or mock these variables, implicitly assuming they're always unset. That assumption doesn't hold on this fork's self-hosted CI runners, which configure a job-started hook for their own lifecycle management (confirmed in the raw CI logs: "A job started hook has been configured by the self-hosted runner administrator"). Since these are real, process-level environment variables, they're inherited by the child dotnet test process and silently add one extra step to preJobSteps, which is why JobExtensionBuildStepsList failed with "Expected 5, Actual 6" identically on both the linux-x64 and linux-arm64 legs of #233's CI run, while never reproducing in a clean local environment without the hook configured. Capture and clear both hook variables in the constructor (xUnit creates a new instance per test) and restore the original values in Dispose(), following the same env-var isolation pattern already used for the ARM32 kill-switch override tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The 'L0' step's condition compared matrix.runtime (always 'linux-*'-
prefixed, e.g. 'linux-x64', 'linux-arm64') against bare arch names
('arm64', 'amd64') that only ever appear in the separate matrix.runs_on
field. This mismatch meant the condition never evaluated true for any
matrix leg, so ./dev.sh test has silently never run as part of this
workflow, on any architecture, on PRs or pushes.
Compared against upstream actions/runner's build.yml to confirm intent:
upstream runs L0 on every runtime except the ones that can't execute
natively on its GitHub-hosted runners (linux-arm64, linux-arm, osx-arm64,
win-arm64, since those jobs run cross-compiled on amd64 hosts). This
fork instead builds each target on matching self-hosted native hardware
(runs-on: matrix.runs_on), so linux-arm64 can safely run its own tests
directly, unlike upstream.
Fix: compare against the correct matrix.runtime values and enable L0 for
linux-x64 and linux-arm64 (native, unpatched builds). linux-arm (32-bit
armv7l, cross-targeted), ppc64le, and s390x are intentionally left
disabled for now -- they require their respective patches applied first,
and their dotnet-test behavior under cross/32-bit targeting is not yet
validated. Enabling genuine L0 coverage for those is tracked as separate
follow-up work.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Author
florentianayuwono
deleted the
fix/job-extension-hook-env-isolation-isd-5856
branch
October 6, 2026 18:10
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.
Summary
JobExtensionL0.JobExtensionBuildStepsListfails on this fork's self-hosted CI runners withAssert.Equal(5, result.Count)→Actual: 6, identically on both thelinux-x64andlinux-arm64legs of #233's CI run. It is not architecture-specific, and does not reproduce in a clean local sandbox.Root cause
JobExtension.InitializeJobreads two environment variables directly from the real OS process environment (not mocked/injected):preJobStepsis merged directly into the step list returned byInitializeJob(steps.AddRange(preJobSteps); steps.AddRange(jobSteps);), so if this variable is set, the returned list silently grows by one.JobExtensionL0's tests never cleared or mocked this variable, implicitly assuming it's always unset. That assumption doesn't hold on this fork's self-hosted CI fleet, which configures a job-started hook for its own lifecycle management — confirmed directly in the raw CI logs:Because this is a real, process-level environment variable (not scoped to the outer GitHub Actions job wrapper), it's inherited by the child
dotnet testprocess, so the inner unit test picks it up too — explaining why the failure is identical across architectures (same hook infra on every self-hosted runner) yet absent in any clean/non-hooked environment.Fix
JobExtensionL0now implementsIDisposable:ACTIONS_RUNNER_HOOK_JOB_STARTEDandACTIONS_RUNNER_HOOK_JOB_COMPLETED, then force-clears both.Dispose()(runs after every test) restores the original values.This mirrors the env-var isolation pattern already used for the ARM32 kill-switch override tests (#232), properly isolating the test from ambient host/runner configuration instead of just assuming it away.
Testing
dotnet build Test/Test.csproj -c Debug— builds cleanly, 0 warnings/errors.dotnet test --filter "FullyQualifiedName~JobExtensionL0"— 34/34 passed.