From 5b964788fb0949b43abe8197a4600a8c592cf4c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bobby=E2=84=A2?= Date: Sat, 31 Oct 2026 15:14:35 +0100 Subject: [PATCH] docs: add platform matrix, surface Go 1.22 requirement earlier Based on feedback from bravo-ledger via the Reponite review campaign. The process subcommand's Linux/macOS scope was only mentioned mid-page; - New Platform support table after Install makes it findable before someone picks the wrong command. Go 1.22 minimum now appears near source install too, not just at the bottom of the Install section. --- README.md | 77 ++++++++++++++++++++++++++----------------------------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 9763f2b..7282d61 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,8 @@ # waitfor -> _Block until a condition is true, or tell you exactly why it wasn't._ +Block until a condition is true, or find out exactly why it wasn't. -`waitfor` polls a condition on a configurable interval until it becomes true -or a timeout expires. The killer feature isn't the polling — it's the -**failure output**. Every other tool says `timed out`. `waitfor` tells you -_why_. +`waitfor` polls a condition on a configurable interval until it becomes true or a timeout expires. The killer feature isn't the polling. It's the failure output. Every other tool says `timed out`. `waitfor` tells you why. ``` $ waitfor port 5432 --timeout 5s @@ -23,14 +20,15 @@ $ waitfor port 5432 --timeout 5s ### From source +Requires Go 1.22 or newer. + ```bash go install github.com/0xProgress/waitfor@latest ``` ### Prebuilt binaries -Download the latest release from the [Releases page](https://github.com/0xProgress/waitfor/releases). -Checksums and cross-platform archives are published for every tag. +Download the latest release from the [Releases page](https://github.com/0xProgress/waitfor/releases). Checksums and cross-platform archives are published for every tag. ### Build locally @@ -45,6 +43,21 @@ Requires Go 1.22 or newer. --- +## Platform support + +Tested on Linux and macOS. Windows is untested. Most subcommands will likely work, but `process` won't (it uses `/proc` on Linux and `ps` on macOS). PRs welcome. + +| Subcommand | Linux | macOS | +| ---------- | ----- | ----- | +| `port` | ✅ | ✅ | +| `http` | ✅ | ✅ | +| `file` | ✅ | ✅ | +| `process` | ✅ | ✅ | +| `command` | ✅ | ✅ | +| `all` | ✅ | ✅ | + +--- + ## Quickstart ```bash @@ -73,8 +86,7 @@ waitfor all port 5432 port 6379 http localhost:8080/health ### `waitfor port ` -Waits for a TCP port on localhost to accept connections. Tries IPv4 -(`127.0.0.1`) first, then IPv6 (`[::1]`). +Waits for a TCP port on localhost to accept connections. Tries IPv4 (`127.0.0.1`) first, then IPv6 (`[::1]`). | Failure state | Meaning | | -------------------- | ------------------------------------------ | @@ -98,8 +110,7 @@ Waits for an HTTP endpoint to return the expected status (default: any 2xx). | `--insecure` | `false` | Skip TLS verification | | `--header "K: V"` | — | Add a request header (repeatable) | -URLs without a scheme are auto-prepended with `http://` and a warning is -printed. On non-2xx responses, the last body is captured and shown. +URLs without a scheme are auto-prepended with `http://` and a warning is printed. On non-2xx responses, the last body is captured and shown. ```bash waitfor http localhost:8080/health @@ -127,8 +138,7 @@ Waits for a file or directory to exist. | `--min-size ` | `0` | File must be at least N bytes | | `--nonempty` | `false` | Shorthand for `--min-size 1` | -Distinguishes `not found`, `empty`, `size N < M`, `permission denied`, and -`parent directory missing`. +Distinguishes `not found`, `empty`, `size N < M`, `permission denied`, and `parent directory missing`. ```bash waitfor file ./tmp/ready @@ -138,16 +148,14 @@ waitfor file ./tmp/ready --nonempty ### `waitfor process ` -Waits for a process matching a name to be running (substring match by default). +Waits for a process matching a name to be running (substring match by default). Linux and macOS only (see [Platform support](#platform-support)). | Flag | Default | Description | | ------------------- | ------- | --------------------------------------- | | `--exact` | `false` | Exact name match instead of substring | | `--user ` | — | Only match processes owned by this user | -Runs on Linux (`/proc`) and macOS (`ps`). On other platforms, returns an -error immediately. Numeric PIDs are rejected with a hint to use -`waitfor command 'kill -0 '`. +Numeric PIDs are rejected with a hint to use `waitfor command 'kill -0 '`. ```bash waitfor process postgres @@ -155,9 +163,7 @@ waitfor process postgres --exact waitfor process postgres --user deploy ``` -**Limitation:** Linux `comm` is capped at 15 characters by the kernel. Names -longer than 15 chars won't match on Linux. This is a kernel constraint, not -a `waitfor` bug. +**Heads up:** Linux `comm` is capped at 15 characters by the kernel. Names longer than 15 chars won't match on Linux. That's a kernel constraint, not a bug. ### `waitfor command ""` @@ -167,9 +173,7 @@ Waits for a shell command to exit with the expected code. | ----------------- | ------- | ------------------ | | `--exit-code ` | `0` | Expected exit code | -The command is passed to `sh -c` unmodified, so pipes, redirection, and -command substitution all work. It runs as the current user; `waitfor` never -elevates. +The command is passed to `sh -c` unmodified, so pipes, redirection, and command substitution all work. Runs as the current user. `waitfor` never elevates. ```bash waitfor command "docker inspect mycontainer | jq -e '.State.Running'" @@ -188,12 +192,9 @@ $ waitfor command 'docker inspect mycontainer | jq ".State.Running"' --timeout 3 ### `waitfor all [condition...]` -Waits for multiple conditions simultaneously. All must pass. Runs each -condition in its own goroutine. +Waits for multiple conditions simultaneously. All must pass. Each condition runs in its own goroutine. -Global flags may appear **anywhere** in the argument list. Sub-condition -flags (like `--status` or `--exit-code`) apply only to the condition they -follow. +Global flags may appear anywhere in the argument list. Sub-condition flags like `--status` or `--exit-code` apply only to the condition they follow. ```bash waitfor all port 5432 port 6379 @@ -233,7 +234,7 @@ $ waitfor all port 5432 port 6379 http localhost:8080/health | Code | Meaning | | ---- | ---------------------------------------------------------------- | | `0` | Condition met | -| `1` | Timeout — condition never met | +| `1` | Timeout: condition never met | | `2` | Bad arguments / invalid input | | `3` | Permission error _(reserved; no condition currently emits this)_ | @@ -255,15 +256,13 @@ Every subcommand supports `--json`: } ``` -Optional fields (`detail_label`, `detail_value`) are omitted when empty. For -`all`, a `children` array carries one entry per sub-condition. +`detail_label` and `detail_value` are omitted when empty. For `all`, a `children` array carries one entry per sub-condition. --- ## Use in CI/CD -See **[docs/ci-cd.md](docs/ci-cd.md)** for copy-paste recipes covering GitHub -Actions, GitLab CI, Docker Compose, and Kubernetes. The short version: +See [docs/ci-cd.md](docs/ci-cd.md) for copy-paste recipes covering GitHub Actions, GitLab CI, Docker Compose, and Kubernetes. The short version: ```yaml # GitHub Actions @@ -274,20 +273,18 @@ Actions, GitLab CI, Docker Compose, and Kubernetes. The short version: Why `waitfor` beats `sleep 10` in CI: - **Fast on success.** Returns the instant the condition is met, not after a fixed delay. -- **Diagnostic on failure.** The timeout output tells you _which_ thing failed and _why_, so you don't have to re-run with more logging. +- **Diagnostic on failure.** The timeout output tells you which thing failed and why, so you don't have to re-run with more logging. - **Deterministic in flaky environments.** Configurable timeout and interval let you tune per-job. --- ## Edge cases -`waitfor` handles these per spec: - -- `--timeout 0s` performs a single check and reports `Condition not met (single check, no timeout set)`. +- `--timeout 0s` does a single check and reports `Condition not met (single check, no timeout set)`. - `--interval` shorter than 100ms is clamped to 100ms. -- `--interval` longer than `--timeout` warns and performs a single check. -- `--timeout` or `--interval` < 0 is rejected with exit 2. -- URLs without a scheme are auto-prepended with `http://` and a warning is printed _before_ polling begins. +- `--interval` longer than `--timeout` warns and does a single check. +- Negative `--timeout` or `--interval` is rejected with exit 2. +- URLs without a scheme get `http://` prepended with a warning printed before polling starts. - SIGINT/SIGTERM cancel polling cleanly and exit 1 with the last observed state. - `waitfor all` with zero conditions is an error, not a silent success.