Skip to content

fix(keploy-ci): start-docker asks each daemon with curl; one Go patch (1.27.2) in every image - #36

Merged
slayerjain merged 2 commits into
mainfrom
fix/start-docker-nits
Oct 19, 2026
Merged

slayerjain merged 2 commits into
mainfrom
fix/start-docker-nits

Conversation

@slayerjain

@slayerjain slayerjain commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

Two changes for the next keploy-ci release (v1.2.46), one commit each.

1. start-docker asks each daemon with curl, its bound from the dial (#33's review NITs)

  • Why: the one bounded look at a socket no pidfile names used timeout 10 docker info. docker info runs its CLI plugins before it dials, so on a starved host a dead socket could pass for a mute one and fail the start.

  • What curl asks:

    • dockerd: its /_ping.
    • containerd: its Version, sent as an empty gRPC message over HTTP/2.
  • How it runs: with -q (no ~/.curlrc), and with --max-time counted from the dial.

  • What its exit decides:

    curl exit Meaning start-docker
    7 the socket refuses takes it over
    28 mute fails, and says so
    0 the daemon answered reuses it
    anything else something answers as no such daemon does fails, and says so

    Before, a failed probe took the socket over.

  • dockerd's waits ask /_ping too.

  • -s is now among the short flags that take a value.

  • Tests:

    • dead, mute and foreign sockets, for both daemons;
    • a reused dockerd that no pidfile names, run with a .curlrc present;
    • a slow probe whose delay sits inside curl's own transfer;
    • a deterministic wedged dockerd;
    • the shim gated on a file, not a sleep;
    • -spool.

2. One Go patch, 1.27.2, in every CI image that ships Go (D8)

  • Why: a shared Go build cache is keyed by toolchain, and the images were on three Go patches: keploy-ci 1.27.0, go-build and golint on whatever golang:1.27-bookworm was at build time, ebpf-objects 1.27.1.
  • What is pinned now:
    • keploy-ci: GO_VERSION=1.27.2, its tarball checked against go.dev's SHA-256 for each arch;
    • go-build and golint: FROM golang:1.27.2-bookworm@sha256:5cf287a7…;
    • ebpf-objects: the 1.27.2 tarball via ADD --checksum.
  • What holds it: docker-build.yml gets a static go-patch job and a runtime go env GOVERSION check on each Go image's build.

Testing (on .142, keploy-ci:1.2.45)

  • start-docker-test.sh: 26/26 cases pass.
  • start-docker mutants (.sdmut): all 43 killed. 41 ran against the tests before the .curlrc case was added, and the 3 added after it (/_pingX and the two -q drops) ran against the final tests.
  • D8 images: all four build and report go1.27.2.
  • keploy/ebpf's objects-reproducible lane, run in the new ebpf-objects image, rebuilds every committed object byte-identical, as it does on 1.2.43.
  • actionlint and shellcheck v0.11.0 are clean.
  • Independent review: CLEAN for both changes.

After the release: pin bumps to 1.2.46 by digest, including go-build, golint, and ebpf-objects in keploy/ebpf.

…om the dial

The one bounded look start-docker takes at a socket no pidfile names ran
`timeout 10 docker info` (`ctr version` for containerd's) and read a 124
as "listens and does not answer". docker info runs its CLI plugins
(buildx, compose) before it dials. That took 0.04 s at one CPU and 2.3 s
at 0.03, against 0.01-0.4 s for curl. On a starved enough host, a socket
nothing listens on, which start-docker takes over, could be called mute
and fail the start.

curl asks now:
- dockerd's /_ping;
- containerd's Version, an empty gRPC message over HTTP/2, its
  grpc-status read from the trailers.
It runs with -q, so no ~/.curlrc changes the request, and with --max-time
bounding the transfer from the dial. Its exit says what it found:
- 7 refuses: taken over;
- 28 mute: fails, said;
- 0 answered: reused.
Anything else fails the start, said, rather than being started over: an
HTTP server on dockerd's socket (named with its HTTP status), or a
containerd without its Version service. Before, a `ctr version` that
failed took such a socket over, and dockerd and containerd unlink and
rebind a live listener's path. dockerd's waits ask /_ping too: it
answers only once dockerd serves its API, after its init, as docker info
did, and a look no longer runs two CLI plugins on a starved host.

-s (--storage-driver) takes a value, so the run-together short-flag scan
stops at it, as at -l, -G, -b and -e.

Tests:
- dead-socket: both daemons' sockets are dead, and curl, docker and ctr
  each take 3 s to start against a bound of 2; both sockets are taken
  over.
- mute-socket and foreign-socket now cover containerd's socket as well
  as dockerd's. foreign-socket adds an HTTP 404 server on each, and a
  containerd without its Version service.
- The test listener binds beside the socket and renames onto it once it
  listens, so the socket is never there unlistened.
- unnamed-dockerd: an answering dockerd that no pidfile names is reused
  after one look, with a ~/.curlrc in place that would make curl speak
  HTTP/2.
- slow-probe holds each connection 8 s in a relay, inside curl's own
  transfer, so a bound on the waits' probe (timeout or --max-time) fails
  it.
- dockerd-wedged's dockerd is a stand-in that listens and never answers.
  A real dockerd, stopped once its socket is there, could finish its
  init first on a starved host. Its containerd runs before the start, so
  the 4 looks of silence are dockerd's alone.
- killed-before-dockerd-pidfile holds its stand-in dockerd on a file the
  case creates once the next start has looked, not on a 5 s sleep.
- settings: -spool is a fine flag (-s's value is not read as -p).

On .142, on keploy-ci:1.2.45, all 26 cases pass and all 43 mutants of
start-docker are killed.

Signed-off-by: slayerjain <shubhamkjain@outlook.com>
A Go build cache is keyed by the toolchain that wrote it. keploy-ci (and
every image FROM it) shipped go1.27.0, go-build and golint whatever
golang:1.27-bookworm was when they were built (1.27.1 at v1.2.40, 1.27.2
at v1.2.45), and ebpf-objects 1.27.1: lanes on two patches that share a
cache split it, each rebuilding what the other cached.

All four are on 1.27.2 now, the current patch:
- keploy-ci: GO_VERSION=1.27.2, its tarball checked against go.dev's
  SHA-256 for each architecture (GO_SHA256_AMD64 / _ARM64) before it is
  unpacked;
- go-build and golint: FROM golang:1.27.2-bookworm by its index digest,
  so a rebuild cannot float to the next patch;
- ebpf-objects: the 1.27.2 tarball, ADDed with its --checksum, and its
  build's `go version` check.

docker-build.yml holds them to one:
- a job reads keploy-ci's GO_VERSION (one X.Y.Z, with both checksums) and
  fails when go-build or golint is not FROM that patch's golang image by
  digest, when ebpf-objects does not fetch and check that patch's
  tarball, or when an instruction names another Go: another golang image
  (by tag, digest or variable), another version's tarball (binary or
  source) written out, from any host, Debian's golang packages, or a
  GOTOOLCHAIN naming a toolchain, quoted or not;
- each of the four images, once built, must report that patch from its
  own go (go env GOVERSION).

On .142: all four build (amd64) and report go1.27.2; the arm64 tarball's
SHA-256 matches go.dev's; and keploy/ebpf's objects-reproducible lane,
run in the new ebpf-objects image on its main (770c564), rebuilds every
committed object byte-identical, as in ebpf-objects-1.2.43.

Signed-off-by: slayerjain <shubhamkjain@outlook.com>
@slayerjain
slayerjain marked this pull request as ready for review October 19, 2026 18:58
@slayerjain
slayerjain merged commit f91a66e into main Oct 19, 2026
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant