Skip to content

Update ryuk#72

Open
nikita-volkov wants to merge 12 commits into
testcontainers:masterfrom
nikita-volkov:update-ryuk/1
Open

Update ryuk#72
nikita-volkov wants to merge 12 commits into
testcontainers:masterfrom
nikita-volkov:update-ryuk/1

Conversation

@nikita-volkov

Copy link
Copy Markdown

The changes in this PR are done with the use of AI. Following is the summary:

  • Ryuk upgraded to 0.14.0 — switched the wait strategy from a TCP port probe (which ryuk 0.14.0 treats as a completed session and immediately exits) to waiting for its "Started" log line; added socket connection retries to handle port-forwarding lag on macOS/Docker Desktop
  • Windows container support — ryuk now mounts the named pipe (\\.\pipe\docker_engine) instead of a Unix socket when the Docker daemon is running Windows containers
  • CI matrix expanded — added ubuntu-24.04-arm, macos-26-intel, and windows-latest; GHC versions trimmed to 9.2 and 9.12; tests skipped on Windows (no Linux Docker daemon) but the build still runs to verify compilation
  • Lint workflow updated — bumped actions/checkout to v6 and ormolu to 0.8.1.0
  • Image versions bumped — Redis 7.4, Mongo 7.0, RabbitMQ 3.13, Nginx 1.27-alpine, Jaeger 1.62.0, Postgres 17-alpine; removed the now-unnecessary RabbitMQ log-line wait strategy

nikita-volkov and others added 8 commits June 14, 2026 15:58
Since GitHub Actions now support it
- Replace waitUntilMappedPortReachable for ryuk with waitForLogLine
  on ryuk's "Started" log message. A TCP probe to ryuk's protocol port
  registers as a client that immediately disconnects without labels;
  ryuk 0.14.0 treats this as a completed session and exits (1 ns
  reconnection timeout when no resources are registered), causing
  the subsequent real connection from newRyukReaper to get ECONNRESET.

- Simplify rabbitmq readiness to waitUntilMappedPortReachable 5672.
  RabbitMQ 3.13 changed its startup log format and no longer outputs
  the "completed with" line that the previous wait condition relied on.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Root cause: After ryuk logs "Started", Docker Desktop/Colima on macOS has a small delay before the VM-to-host port forwarding becomes active. The original newRyukReaper made one immediate Socket.connect with no retry, so it hit ECONNREFUSED on macOS even though ryuk was actually running. Using waitUntilMappedPortReachable as the wait strategy isn't an option (it probe-connects and immediately disconnects, which ryuk 0.14.0 treats as a completed session causing it to exit).

Fix: Added a connectWithRetry 60 loop inside newRyukReaper — up to 60 attempts with 500 ms delay between them (30 s total budget), catching IOException specifically on each attempt and closing the failed socket before retrying with a fresh one. This mirrors the retry pattern already used by waitUntilMappedPortReachable and waitForHttp, without triggering ryuk's session-termination logic.
@nikita-volkov nikita-volkov requested a review from alexbiehl as a code owner June 14, 2026 13:07
Comment thread .github/workflows/ci.yaml Outdated
@LaurentRDC

LaurentRDC commented Jun 14, 2026

Copy link
Copy Markdown
Collaborator

What would be required to enable tests on Windows?

Root cause: waitUntilMappedPortReachable 5672 is unreliable on macOS because port-forwarding through Lima's SSH tunnel can cause Socket.connect to block indefinitely (hanging rather than returning ECONNREFUSED). The System.Timeout.timeout can't always interrupt a blocking FFI syscall in time, so the 60-second default timeout doesn't reliably fire.

Fix: Switch back to waitForLogLine Stdout ("started TCP listener" LazyText.isInfixOf). RabbitMQ 3.13 logs "started TCP listener on [::]:5672" the moment it binds the AMQP port — this doesn't involve host port-forwarding at all (it reads from docker logs --follow inside the container), so it's immune to macOS networking quirks. The original log-based approach ("completed with") broke when RabbitMQ 3.13 changed its startup log format; "started TCP listener" is the correct replacement.
- configDefaultWaitTimeout was applied as an outer cap in waitUntilReady,
  silently overriding any explicit waitUntilTimeout the caller provided.
  Fix: skip the default when the input is already a WaitUntilTimeout so
  that explicit timeouts take precedence.

- RabbitMQ readiness: switch from waitUntilMappedPortReachable (flaky on
  macOS because Socket.connect through Lima's SSH tunnel can block rather
  than returning ECONNREFUSED) to waitForLogLine Stdout on "started TCP
  listener", wrapped with waitUntilTimeout 300. The macOS CI runner
  (Intel/QEMU, 3.8 GB RAM) needs well over 60 s to boot RabbitMQ; the
  log-based strategy avoids host port-forwarding entirely and the explicit
  300 s timeout now works as intended after the semantics fix above.
On macOS/Lima, DNS lookups inside the VM can time out transiently,
causing docker pull to fail with an i/o timeout. Retry up to 3 times
with a 2 s delay before propagating the exception.
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.

3 participants