Skip to main content
A host is a machine you control that builds your factory’s items. The runner, outerlayer runner, is the process on that host. It takes items from two queues:
  • implement builds an item from its issue.
  • amend answers the review threads on an item’s open pull request.
For each item, the runner sets up a place to work, runs your agent, and cleans up. You decide two things on the host: how each build is isolated (the hooks) and which command starts your agent for each queue. A host that uses the built-in hooks writes no script at all.

What happens to one build

  1. Claim. The runner claims an item someone asked a host to build, with outerlayer work build or Build on the Work page. An item added with outerlayer work build --local or Build locally is never queued for a host. If a report hook is set, it runs now with OUTERLAYER_PHASE=start.
  2. Provision. The provision hook makes the working directory, such as a clone inside a container of its own.
  3. Command. Your command starts the agent in that directory. The runner renews its claim while the build runs. A claim it stops renewing expires after fifteen minutes.
  4. Host checks. When the command exits 0, the runner runs the repository’s host checks and records their results.
  5. Sync. The runner runs outerlayer sync, so the build’s sessions upload.
  6. Cleanup. The cleanup hook runs, however the command ended.
  7. Verdict. When the command exited 0, the runner reads the item’s checks to decide between ok and incomplete. See When the command exits 0.
  8. Report. If a report hook is set, it runs again with OUTERLAYER_PHASE=end and the outcome the release carries.
  9. Release. The runner releases the claim with the outcome.
An item another claim holds, such as a person’s own session, is refused. Linked sessions and pull requests never stop a build by themselves.

When the command exits 0

An exit of 0 says only that the agent’s session ended normally. So after the checks, the sync and the cleanup, the runner reads the item’s evidence verdict, the evaluation that GET /v1/work-items/{workItemId} returns. It reads it before the report hook, so that hook sees the outcome the release carries.
  • The item has a pull request and passes, or waits only on a person’s review: the release is ok.
  • The item has no pull request: a build that opens no pull request is released incomplete, saying so, whatever the checks say. A runner build opens its pull request with outerlayer work open-pr.
  • A check failed or has no result: the release is incomplete. Its reason names each such check and marks the ones with no result, for example checks not passing: Migration must run: Migrations ran against a local database (no result). While the build held the claim, a required check with nothing recorded was only waiting. The build has ended, so the runner counts it as missing.
  • The item has no verdict yet, or still waits on session links to be confirmed: the release is incomplete, and its reason says so.
  • The read fails: the release is incomplete, and its reason says the item’s status could not be read.
The verdict is computed again after the build’s sessions and checks arrive, so it can lag them. A verdict that is not passing is read again every 30 seconds, for up to 5 minutes. The runner decides on the last read. A passing verdict is believed at once. incomplete uses up the build request, as ok does. No host takes the item again until a person asks for another build. To ask, run outerlayer work build --item <n>, or select Build again on a host in the item page’s Last build block. The control appears only when the build ended with no open pull request, and only for a member who can run outerlayer work build. A gateway too old to return a verdict is read as passing. A gateway that refuses incomplete is sent the release again as ok, with the same reason. A runner older than runner protocol 12 releases such a build ok.

Choose how a build is isolated

The hooks you name decide what a build can reach on the host. outerlayer runner init picks the strongest isolation the machine supports: builtin:vm on x86_64 Linux whose account can open /dev/kvm, else builtin:container. The full rule is in outerlayer runner init.

Where to go next