Skip to content

1.15.0 — 2026-10-19

Choose a tag to compare

@github-actions github-actions released this 19 Oct 07:54

Release Notes

A Tower that is asked to stop now lets what it is running finish, and Layover can update itself: it
hears of a new release, gets it ready, verified and checked against the factory, and — asked —
installs it between runs and restarts on it, rolling back one that cannot prove itself.

Compatibility. Additive for layover.toml and the HTTP API: every factory that loaded under
1.14 loads unchanged, and the one new table, [update], is optional. What an existing factory will
notice:

  • The first Ctrl+C on layover serve drains instead of exiting at once: nothing new starts, what
    is running finishes, and then it exits. A second Ctrl+C cuts what is running off and exits.
  • The Tower makes one request a day to github.com, for the newest release's manifest, and says
    when a newer release exists. It downloads and changes nothing. [update] mode = "off" stops it
    for a factory and LAYOVER_UPDATE=off for a machine.
  • layover doctor begins with a line saying which Layover runs and what this machine last
    learned about releases.
  • One Tower serves a factory. A second serve on a factory another is serving refuses to start,
    where it used to race the first for its queue.
  • The service files layover autostart writes for systemd and launchd set
    LAYOVER_SUPERVISOR
    , so a Tower installing a release exits 75 for the service to restart it.
    Regenerate an older one; a systemd service is recognised without it.
  • validate warns when [update] max_drain is shorter than a run's timeout, which the
    defaults never are.
  • The HTTP API: GET /health gains stopping, and /update is new, with apply, skip and
    rollback beneath it.

Added

  • layover stop asks the Tower serving a factory to stop, from another terminal or a script: it
    drains and exits, and --now cuts what is running off. It writes .layover/stop-request.json,
    which the Tower honours and removes, and which a Tower starting later ignores.
  • Cutting off kills the runs. A Tower cut off — a second Ctrl+C, or layover stop --now — kills
    each live run's process tree and leaves it for the next Tower to record as interrupted, rather
    than leaving it running with nobody listening. Every way of stopping exits 0, so a systemd or
    launchd service that restarts on failure leaves a stopped Tower stopped.
  • Draining. While a Tower stops, nothing new starts — queued work stays queued for the next
    start, and schedule ticks are held — except work that completes a rendezvous already holding an
    arrival, which would otherwise be lost. The Tower exits once nothing is alive and nothing is
    parked, so stopping it no longer interrupts runs or loses arrivals.
  • The dashboard says when a Tower is stopping: the version pill reads · stopping, also from a
    --watch-only dashboard in another process.
  • Hearing about a newer Layover. [update] — mode (notify by default, or off), channel
    (stable, or prerelease for release candidates) and check_every ("24h"). The Tower looks on
    that schedule; the version pill reads v1.14.0 → 1.15.0 and opens the release's Compatibility
    note and notes; doctor says so. What was found is kept per machine, so factories sharing a
    binary ask once between them.
  • layover update check looks now and prints what a newer release changes; layover update skip <version> stops offering one on this machine, and --clear undoes it.
  • layover about says what a binary is — version, platform, state layout, HTTP API and the
    oldest release it can be updated from — and --json says it to a program.
  • Staging a release, with [update] mode = "stage" or layover update stage: the newest
    release is downloaded (capped at 64 MB), its SHA-256 matched to the manifest and its .sha256
    file, its GitHub attestation verified with gh attestation verify pinned to this repository's
    release workflow and tag, its binary unpacked with nothing allowed outside the staging folder and
    asked what it is with layover about --json, and the factory validated by it. Nothing downloaded
    runs before it is verified; without gh, --trust-checksum-only runs it on a person's say-so.
    Nothing is installed.
  • Installing a release: layover update apply, or Update now in the dashboard. The
    Tower drains — up to [update] max_drain ("4h"), then cuts off what is still running for
    recovery to restart on the new version, unless an agent with recovery = "manual" is running,
    which postpones it — swaps its binary, keeping the old one for [update] keep_previous ("7d"),
    and hands over: on Windows it starts the new version at its own address and waits for it to
    answer, putting its own binary back if it does not; under systemd or launchd it exits 75. The new
    Tower keeps the dashboard's token, proves itself healthy, and writes to .layover/serve.log.
    With no Tower serving, the binary is replaced at once. A Homebrew or npm install is left to its
    package manager, with the command to run. Exit codes say how it went.
  • Installing unattended, with [update] mode = "auto": a patch or minor release (allow), a
    day or two after it was published (min_age = { patch = "24h", minor = "48h" }), staged,
    verified (require_provenance) and validating the factory with no new warning, is installed in
    the window ("Sat 02:00-06:00", local time) or once the factory has been idle for idle_for
    ("10m"). A major release and one that changes the state layout always wait for a person. An
    install whose window closes before runs finish is postponed to the next. The dashboard's bell
    rings for a new release, an update and a rollback.
  • layover update rollback goes back to the version the last update replaced; status
    says where things stand; log prints .layover/updates.jsonl.
  • GET /update: what this machine last learned about releases, for this factory, and — once a
    release is staged — how far staging got (staged), what it made of this factory (gate), the
    install under way (request), the last update (last_update) and the version kept to go back
    to (previous). POST /update/apply, DELETE /update/apply, POST /update/skip
    and POST /update/rollback do from the dashboard what the commands do.
  • LAYOVER_UPDATE, LAYOVER_UPDATE_SOURCE (a mirror laid out as GitHub's releases) and
    LAYOVER_GITHUB_TOKEN (for the API, on the prerelease channel).
  • cargo xtask verify refuses a CHANGELOG release section without a **Compatibility.**
    paragraph, which the updater shows before an install, and a dist upgrade until the pinned
    release manifest the updater is tested against is refreshed.

Tried

Released first as two candidates, 1.15.0-rc.1 and rc.2, on GitHub only. A throwaway 1.14.0 install
found rc.1, verified it with gh, waited for a live run, installed it in place and rolled it back.
A factory on rc.1 in mode = "auto" then found rc.2, staged and verified it, waited out its day,
and installed it by itself once idle, keeping its dashboard's token. What the candidates turned
up — an install marked done before the new Tower had answered, and layover update check not
mentioning apply — is fixed here.

Install layover-cli 1.15.0

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/KotkaZ/layover-project/releases/download/v1.15.0/layover-cli-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/KotkaZ/layover-project/releases/download/v1.15.0/layover-cli-installer.ps1 | iex"

Install prebuilt binaries via Homebrew

brew install KotkaZ/tap/layover

Install prebuilt binaries into your npm project

npm install @layover/layover-cli@1.15.0

Download layover-cli 1.15.0

File Platform Checksum
layover-cli-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
layover-cli-x86_64-apple-darwin.tar.xz Intel macOS checksum
layover-cli-x86_64-pc-windows-msvc.zip x64 Windows checksum
layover-cli-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
layover-cli-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum

Verifying GitHub Artifact Attestations

The artifacts in this release have attestations generated with GitHub Artifact Attestations. These can be verified by using the GitHub CLI:

gh attestation verify <file-path of downloaded artifact> --repo KotkaZ/layover-project

You can also download the attestation from GitHub and verify against that directly:

gh attestation verify <file-path of downloaded artifact> --bundle <file-path of downloaded attestation>