case studies

Clean Machine Case Study: Ready in 49.6 Seconds, and a Missing Redis Caught at the Ready Step

A setup file that looks right proves nothing. The only proof is a machine that starts empty, runs the setup, and then passes the project’s own tests. That is what an agent’s cloud machine does every time a session starts, and when the setup is wrong, the agent finds out in the middle of its task, if at all. GitHub’s documentation says that when a setup step fails, Copilot skips the remaining steps and begins working with the machine as it is.

preconfig verify runs that proof before any agent does. In the Alpha demo it ran the orders-api setup on a clean Ubuntu 24.04 container, and again with Redis left out of the spec. The first run was READY. The second set everything up without an error and then failed at the ready step, with the test runner’s own message.

Step 5 of the live demo: preconfig verify with Redis left out of the spec. The terminal shows the spec warning, each step with its time and the failed ready step; the panel shows a timeline with a bar per step, the last one red, and NOT READY, exit 1.

The second run as recorded: the setup works, the tests don’t, and verify says which step broke.

The Set-Up

Clean machine
The machine A fresh ubuntu:24.04 container on a Linux machine with two CPUs and Docker
The repository orders-api: orders in PostgreSQL, counts cached in Redis, four tests
Run 1 The full spec: Python 3.12, PostgreSQL 16, Redis 7
Run 2 The same spec with Redis left out, as someone might trim a spec they think has too much in it
The command preconfig verify --network host --ca-file proxy-ca.crt, because the test machine reaches the internet through a proxy that inspects TLS

What Happened

Run 1: the full spec. verify started the container, copied the repository in and ran the generated setup script, then the tests. Each step printed a marker, and verify timed each one:

verify    0.0s  start  orders-api: python 3.12, postgres 16, redis 7, on a clean ubuntu:24.04
verify   15.6s  ok     machine 1/5: system packages  (14.8 s)
verify   22.4s  ok     machine 2/5: python 3.12  (6.8 s)
verify   32.3s  ok     machine 3/5: postgres 16  (9.9 s)
verify   35.9s  ok     machine 4/5: redis 7  (3.6 s)
verify   36.0s  have   python 3.12.3, postgres 16.15, redis 7.0.15
verify   38.5s  ok     services 1/2: postgres 16  (2.6 s)
verify   38.6s  warn   PAYMENTS_API_KEY is not set
verify   45.5s  ok     project 2/2: .venv/bin/pip install -r requirements.txt  (4.0 s)
verify   46.0s  ok     ready 1/1: .venv/bin/pytest -q  (0.5 s)
verify   49.6s  READY  4 passed in 0.25s; 10 steps

The warning is the secret: the spec names PAYMENTS_API_KEY, the machine running verify didn’t have it, and the setup said so without stopping. The tests don’t need it.

Run 2: no Redis. preconfig warned before it started anything:

preconfig.yaml:16:14: warning S062: REDIS_URL points at Redis on this machine, but services doesn't list redis
    Add redis under services, or point REDIS_URL somewhere else.

A warning doesn’t stop verify, so it went on. Every setup step passed. Then the tests ran against a Redis that nothing had started:

verify   51.8s  FAIL   ready 1/1: .venv/bin/pytest -q  (exit code 1)
verify   55.1s  NOT READY  the setup worked, but the ready check failed (exit 1)
               the last lines it printed:
               | E           redis.exceptions.ConnectionError: Error 111 connecting to localhost:6379. Connection refused.
               | E               ConnectionRefusedError: [Errno 111] Connection refused
               | .venv/lib/python3.12/site-packages/redis/connection.py:1077: ConnectionError
               | =========================== short test summary info ============================
               | FAILED tests/test_orders.py::test_place_order_returns_an_id - redis.exception...
               | FAILED tests/test_orders.py::test_count_is_cached_in_redis - redis.exceptions...
               | FAILED tests/test_orders.py::test_new_order_clears_the_cached_count - redis.e...
               | 3 failed, 1 passed in 1.18s

The test that passed checks that a negative total is refused, which never reaches Redis. verify picked pytest’s own error lines out of the 472 lines the tests printed and exited with 1: the setup worked, the ready check didn’t. A failed install step would have exited with 2 and named that step instead.

Three Runs Each

Run Result Time Detail
Full spec, 1 READY 49.6 s Python 3.12.3, PostgreSQL 16.15, Redis 7.0.15; 4 tests passed
Full spec, 2 READY 68.7 s The same
Full spec, 3 READY 73.0 s The same
No Redis, 1 NOT READY, exit 1 55.1 s Failed at the ready step; 3 tests failed on a refused Redis connection, 1 passed
No Redis, 2 NOT READY, exit 1 64.4 s The same
No Redis, 3 NOT READY, exit 1 71.0 s The same

The Numbers

Run 1 Run 2
Steps 10 8
System packages 14.8 s 17.6 s
Runtimes and services installed 20.3 s 21.4 s
Services started 2.6 s 2.4 s
Project setup 6.9 s 6.9 s
Ready check 0.5 s, passed 1.5 s, failed
Total, container removal included 49.6 s 55.1 s
verify’s exit code 0 1

Most of the spread between runs is downloads: the system packages step alone took 14.8 to 24.0 seconds across the six runs.

What the Alpha Revealed: A Warning Is Easy to Miss

preconfig saw the missing Redis before anything ran: REDIS_URL points at localhost and no service listed provides it. But a warning scrolls past, and a spec with warnings still builds. The run that followed took 55 seconds to show what the warning meant. The Alpha keeps both, the cheap warning and the expensive proof, and the Beta looks at making the checks on a pull request stricter than the ones on a developer’s desk, so a warning like this one can stop a merge.

Next: The Same Proof on Every Pull Request

verify ran on one machine, and only the Python, PostgreSQL 16 and Redis 7 install paths could run on its network. In the Beta, verify runs every install path the spec offers, on an open network and behind a company proxy, and a GitHub Action runs it when a pull request changes the spec. The roadmap has the plan.

Try It Yourself

Open the live demo and press Play, or jump to step 4. Steps 4 and 5 are these two runs, replayed five times faster, with a bar for each step and the machine’s own output underneath. Then, in the first panel under the replay, pick orders-api and delete the redis line: the warning appears as you type.