Skip to content

[CI] Escape $BUILDKITE_PARALLEL_JOB in flakiness parallel-fanout dispatch - #150223

Merged
jozala merged 1 commit into
elastic:mainfrom
jozala:flakiness-escape-parallel-job
May 29, 2026
Merged

jozala merged 1 commit into
elastic:mainfrom
jozala:flakiness-escape-parallel-job

Conversation

@jozala

@jozala jozala commented May 29, 2026 •

Copy link
Copy Markdown
Contributor

What & why

step.command in toBuildkitePipeline (the parallel-fanout dispatcher) was emitting:

VARNAME="BATCH_COMMAND_${BUILDKITE_PARALLEL_JOB}"; eval "${!VARNAME}"

${BUILDKITE_PARALLEL_JOB} (single $) is a per-job runtime variable, but Buildkite's pipeline-upload interpolation pass runs before the agent injects per-job env. BK can't resolve it at upload time, so it substitutes empty. The runtime command becomes:

VARNAME="BATCH_COMMAND_"; eval "${!VARNAME}"

Bash indirect lookup ${!VARNAME} of the unset $BATCH_COMMAND_ expands to empty, eval "" is a no-op, the job exits 0 in ~2s with zero JUnit XML, and BK reports it green.

Bug has been present since the flakiness-detection modularization commit 9003f9233a6c. It was masked because the analyzer treats "no artifacts" the same as "no flakiness found" — silent no-op all the way through. It surfaced today only after #150209 (the wrapper-hang fix) let parallel jobs finish quickly enough to inspect the log end-to-end.

Example before the fix: build 150689 job 019e73e0-1758

$ VARNAME="BATCH_COMMAND_"; eval "${!VARNAME}"
~~~ Uploading artifacts
INFO  No files matched paths: **/build/test-results/**/TEST-*.xml

Change

-step.command = 'VARNAME="BATCH_COMMAND_${BUILDKITE_PARALLEL_JOB}"; eval "$${!VARNAME}"';
+step.command = 'VARNAME="BATCH_COMMAND_$${BUILDKITE_PARALLEL_JOB}"; eval "$${!VARNAME}"';

$$BUILDKITE_PARALLEL_JOB defers interpolation past BK's upload pass; the agent then resolves it correctly to 0, 1, … per parallel job.

Test plan

  • bun test scripts/flakiness-detection — 109 pass / 208 expect()
  • New regression assertion: step.command must contain $${BUILDKITE_PARALLEL_JOB} and must not contain the unescaped form
  • Once merged, observe next flakiness-detection parallel-fanout step on a real PR: the job log should show VARNAME="BATCH_COMMAND_0" (or 1, 2, …) and produce real JUnit XML.

The parallel-fanout step used `${BUILDKITE_PARALLEL_JOB}` (single `$`)
in step.command. Buildkite's pipeline-upload interpolation pass treats
that as an upload-time variable and substitutes empty (the value is
only injected by the agent at job-run time). The runtime command
becomes:

    VARNAME="BATCH_COMMAND_"; eval "${!VARNAME}"

Indirect lookup of an unset `$BATCH_COMMAND_` expands to empty, eval
runs nothing, the job exits 0 in ~2 seconds with no JUnit XML, and BK
reports it green. See e.g. build 150689 job 019e73e0-1758.

Escape as `$$BUILDKITE_PARALLEL_JOB` to defer interpolation past the
upload pass; the agent then resolves it correctly to 0, 1, … per job.

Bug has existed since the modularization commit (9003f92) but was
masked: missing test results look identical to "no flakiness found".
Found while verifying the `--foreground` wrapper fix on PR 150209.
@jozala
jozala requested a review from a team as a code owner May 29, 2026 13:48
@elasticsearchmachine elasticsearchmachine added needs:triage Requires assignment of a team area label v9.5.0 labels May 29, 2026
@jozala jozala added >non-issue :Delivery/Build Build or test infrastructure labels May 29, 2026
@elasticsearchmachine elasticsearchmachine added Team:Delivery (obsolete) Meta label for the former Delivery team. Obsolete. Please use Team:Core/Infra instead. and removed needs:triage Requires assignment of a team area label labels May 29, 2026
@elasticsearchmachine

Copy link
Copy Markdown
Collaborator

Pinging @elastic/es-delivery (Team:Delivery)

@jozala
jozala marked this pull request as draft May 29, 2026 13:53
@jozala

jozala commented May 29, 2026

Copy link
Copy Markdown
Contributor Author

Verified by #150225: parallel-fanout dispatch fix works in CI — 3 parallel unit-test batches ran real Gradle, uploaded JUnit XML, and analyze reported 13300 iterations.

@jozala
jozala marked this pull request as ready for review May 29, 2026 14:30
@jozala jozala added the auto-merge-without-approval Automatically merge pull request when CI checks pass (NB doesn't wait for reviews!) label May 29, 2026
@jozala
jozala merged commit 0eee2f2 into elastic:main May 29, 2026
37 of 38 checks passed
@jozala
jozala deleted the flakiness-escape-parallel-job branch May 29, 2026 14:34
szybia added a commit to szybia/elasticsearch that referenced this pull request May 29, 2026
* upstream/main:
  In file watching tests, add 2s to guarantee a timestamp change (elastic#149937)
  Add query filter to more query types (elastic#150127)
  [DOCS] Fix setting error and edit reindex-indices.md (elastic#150139)
  Rename ResumeBulkByScrollRequest to ResumeBulkByPaginatedSearchRequest (elastic#150210)
  Fail search shards in resharding disruption tests (elastic#150124)
  Tests: Fix ShardSearchPhaseAPMMetricsTests (elastic#150200)
  ES|QL PromQL: implicit type coercion for counter/gauge (elastic#149985)
  Fix OTelMetricsBufferingIT: explicitly produce multiple delta batches (elastic#150136)
  [Test] Fix testActionStats off-by-one on powers of two (elastic#150218)
  Escape BUILDKITE_PARALLEL_JOB in batch dispatch (elastic#150223)
  Handle patterns that require resource on every project (elastic#149980)
  Mute org.elasticsearch.xpack.inference.external.http.sender.RequestExecutorServiceTests testChangingCapacity_DoesNotRejectsOverflowTasks_BecauseOfQueueFull elastic#150226
  Add timestamp accumulator for cache quota tracking (elastic#149890)
@jozala

jozala commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

Post-merge verification: confirmed working on a real PR build

Following up on the open test-plan item ("observe next flakiness-detection parallel-fanout step on a real PR"). The earlier check was on the synthetic verification PR #150225; this confirms the fix on a genuine post-merge PR build running main with the fix merged.

Build: elasticsearch-pull-request #153989 (unrelated contributor PR, 2026-06-16)

The flakiness-detection:unit step fanned out to 3 parallel jobs (parallel_group_total=3), all passed, each resolving a distinct BATCH_COMMAND_N and uploading distinct JUnit XML:

Parallel index Job Distinct test classes uploaded
0 019ed02b-7fe8-436d LlamaServiceTests, CohereEmbeddingsServiceSettingsTests
1 019ed02b-7fe8-46ec LlamaChatCompletionServiceSettingsTests, LlamaActionCreatorTests, LlamaChatCompletionModelTests
2 019ed02b-7fe9-4048 LlamaEmbeddingsServiceSettingsTests

No overlap across jobs → each parallel job ran its own batch, which is only possible if $$BUILDKITE_PARALLEL_JOB resolves per-job at runtime. Pre-fix, all three would have run the empty BATCH_COMMAND_ no-op and uploaded zero XML.

Analyze step: 019ed02b-7fe9-4531 — downloaded all 6 distinct XMLs and reported real data: Iterations attempted: 12600, Successful cases: 12600, Real failures: 0.

This is not a one-off: scanning the last ~20 passed post-merge builds, 7 had a genuine parallel flakiness fan-out (153989, 153974, 153951, 154017, 154014, 154004, 153978), all passed with exit=0.

(Note: the echoed $ prompt line still shows the literal ${BUILDKITE_PARALLEL_JOB} because Buildkite de-escapes $$→$ when displaying the command; runtime resolution is proven by the distinct batches above.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auto-merge-without-approval Automatically merge pull request when CI checks pass (NB doesn't wait for reviews!) :Delivery/Build Build or test infrastructure >non-issue Team:Delivery (obsolete) Meta label for the former Delivery team. Obsolete. Please use Team:Core/Infra instead. v9.5.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants