deploydoubles
v0.1.0
Published
Verify that a deploy actually works: reads the app's deploy report, runs outside checks, returns one exit code.
Maintainers
Readme
deploydoubles
Verify that a deploy actually works. The verifier reads the app's deploy report, runs the outside checks and returns one exit code.
npx deploydoubles verify https://your-deploy.example --commit <deployed sha> --jsonRequires Node 24 or newer. No runtime dependencies.
verify
deploydoubles verify <url> --commit <sha> [--run-id <id>] [--token <t>] [--during-deploy] [--timeout <s>] [--json]| Option | Meaning |
|---|---|
| --commit <sha> | The commit you deployed. Required. Abbreviations of 7+ characters are accepted. |
| --run-id <id> | The DEPLOY_RUN_ID you set for this deploy. Sent as the Deploy-Run-Id header and checked only when given. |
| --token <t> | DEPLOY_REPORT_TOKEN, sent as Authorization: Bearer, to read the full report. Only over https://, or http:// to a loopback address; anything else is a usage error. |
| --during-deploy | Start before the deploy: sends a request every 250 ms until the new commit serves, then counts requests, failed requests and the longest gap. Any failed request fails the run; if the old release never answered, no switch was measured and the result is pending (exit 2). |
| --timeout <s> | Seconds to wait for the report to settle. Default 300. |
| --json | Print one JSON object and nothing else. |
It polls the report until it is settled and the expected commit is serving, honouring retry_after. For https:// URLs on a non-loopback host it also checks TLS and the HTTP→HTTPS redirect.
A settled report counts only when its newest checked_at is at or after the moment the verifier first saw the expected commit (on the server's clock, from its Date header). After a rollback, or a redeploy of a commit that ran before, the app's stored results can describe the earlier deploy until its scheduler runs again; the verifier keeps polling until they don't.
The report's own verdict is never overruled: a top-level status: fail, an HTTP status other than 200 for pass/warn (or 503 for fail), or a report that disagrees with its checks never exits 0.
Redirects are followed only within the origin you gave, so the token and run ID are never sent anywhere else. Everything printed is the verifier's own text: hints come from its fixed table by code, check names outside the specification are replaced, and control characters are stripped.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Every check passed on the deployed commit |
| 1 | A check failed |
| 2 | Still pending, or no result produced since the release was first seen, when the timeout passed |
| 3 | Unreachable, wrong release, or run ID mismatch |
| 64 | Usage error (bad arguments); nothing was verified |
JSON output
{
"ok": false,
"exit_code": 1,
"url": "https://your-deploy.example",
"commit": "3f2c1a9…",
"served_commit": "3f2c1a9…",
"checks": [
{ "name": "reachability", "status": "pass" },
{ "name": "release", "status": "pass" },
{ "name": "queue", "status": "fail", "hint": "A probe job has waited more than two minutes without being processed. Start a queue worker for this release." }
]
}downtime (requests, failed, longest_gap_ms, old_release_seen) is added with --during-deploy. Besides the inside checks, checks holds the outside checks reachability, tls, https_redirect, release, run_id (with --run-id), report (the report is consistent and fresh) and downtime. The token and run ID never appear in the output.
list
deploydoubles list [--needs <a,b>] [--catalog <path or url>] [--json]Picks a double from the catalog (catalog.json in the monorepo, generated from every double's double.json). --needs keeps only the doubles that have all of the given names, used verbatim from the manifests: services (postgres, mysql, redis), service kinds (database, cache, queue), processes (worker, scheduler), the runtime (php, node) or the framework (laravel, symfony, next). An unknown name matches nothing.
npx deploydoubles list --needs postgres,worker --json
# {"doubles":[{"id":"symfony-postgres-worker", ..., "repository":"https://github.com/deploydoubles/symfony-postgres-worker","broken":false}]}The catalog is read from https://raw.githubusercontent.com/deploydoubles/doubles/main/catalog.json unless --catalog names a file or URL. A double whose own nightly conformance run fails carries "broken": true. Exit 0 with a list (possibly empty); exit 3 when the catalog cannot be read.
The catalog is remote input, read like a report. Only https:// is fetched (http:// only on a loopback address); redirects are followed within the same origin only; the body is read up to 1 MB. An entry is dropped unless its repository is exactly https://github.com/deploydoubles/<id>; a service, process, runtime or framework name that does not match the manifest schema's name pattern is dropped; and control, bidirectional and zero-width characters are stripped from the description, in human and --json output alike.
Licence
MIT. Developed in the deploydoubles/doubles monorepo.
