SIGN IN SIGN UP

ci: create the buildx builder before the e2e builds race for it (#2782)

## Description

`Install Kagent` in the e2e job fails intermittently in the merge queue
with a buildx builder race. It has taken out at least #2778 (twice) and
#2766.

`Install Kagent` builds five images four at a time:

```
printf '%s\n' controller golang-adk claude-harness codex-harness byo-a2a \
  | xargs -P4 -n1 bash -c '... make build-${image}'
```

Every `build-*` target depends on `buildx-create`, and that target is a
check-then-create:

```make
docker buildx inspect $(BUILDX_BUILDER_NAME) 2>&1 > /dev/null || \
docker buildx create --name $(BUILDX_BUILDER_NAME) ... --use ... || true
docker buildx use $(BUILDX_BUILDER_NAME) || true
```

Four of those starting at the same instant on a runner with no builder
yet all fail the check, all run `create`, and one wins. The log reads
exactly in that order:

```
ERROR: no builder "kagent-builder-v0.23.0" found                                    ×3
ERROR: existing instance for "kagent-builder-v0.23.0" but no append mode            ×2
error: dial unix /run/buildkit/buildkitd.sock: connect: no such file or directory   ×2
ERROR: listing workers for Build: failed to list workers … reading server preface: EOF
make: *** [Makefile:301: build-golang-adk] Error 1
```

`|| true` swallows the create failures, so the losers carry on and build
against a builder whose buildkit is not serving.

## The change

**`ci.yaml` runs `make buildx-create` once before the fan-out**, so
there is no concurrent create left to lose. This is what
`.github/actions/upgrade-test-setup` already does for the same builder
name, via `docker/setup-buildx-action` — the e2e job is the one place
that doesn't.

**`buildx-create` ends with `inspect --bootstrap`.** `create` returns
before its container is serving, which is the `buildkitd.sock` error
above. Bootstrapping also makes the target safe to run concurrently in
general: a loser of the create race waits for the winner's builder
instead of building against a half-made one.

11 added lines, nothing removed.

## Testing

- `ci.yaml` parses.
- Four concurrent `make buildx-create` from a clean slate: all exit `0`,
and the builder is left `Status: running`. On `main` the same thing
leaves it `Status: inactive`.

**The CI failure is not reproduced locally**, and I'd rather say so than
imply otherwise: it needs four real image builds starting against a
builder mid-creation, and a single probe build succeeds either way
because buildx boots the builder lazily for it. The evidence that this
is the cause is the log above plus the builder being left unbootstrapped
by the race.

Worth noting the create-race *messages* still appear even with this,
since the guarded check-then-create is unchanged — they are harmless
once the builder is bootstrapped, but if you'd prefer them gone I can
make `buildx-create` create-then-fall-back rather than
check-then-create.

---
*🤖 written by Claude*

Signed-off-by: Nicholas Bucher <behappy54321@gmail.com>
N
Nicholas Bucher committed
87bca81584a8806ce21572ef3fc920b45ef3535c
Parent: d393f17
Committed by GitHub <noreply@github.com> on 9/9/2026, 8:58:58 PM