Skip to content

Upgrading and versions

Replacing the binary, the protocol version window, the upgrade and unsupported marks in the agent list, and the 426 response.

An agent is upgraded by replacing a file and restarting. The identity, the key and agent.env all stay; nothing is enrolled again.

Replacing the binary

curl -fsSLO https://github.com/mr-jablon/runjet-agent/releases/latest/download/runjet-agent-linux-amd64
curl -fsSLO https://github.com/mr-jablon/runjet-agent/releases/latest/download/SHA256SUMS
sha256sum --check --ignore-missing SHA256SUMS
install -m 0755 runjet-agent-linux-amd64 /usr/local/bin/runjet-agent
systemctl restart runjet-agent

A restart mid-run kills the job's process, and the agent reports the run as failed anyway, with the sentence killed by agent shutdown; at the next tick the job runs again. Schedule the restart for a moment when nothing long is running on the host — the run history and the Running now band on the dashboard both say what is running.

The agent sends its version with every request, so it appears in the agent list straight after the restart, with no re-enrolment. The Version column shows it as it is and compares it with nothing: the agent is released on its own numbering, so an agent on v1.0.0 beside a Runjet on v0.1.2 — the foot of every screen names Runjet's — is how it is meant to be. What says an agent needs upgrading is the thing beside it: the protocol.

The version window

The agent and Runjet speak a protocol with a version number. Runjet serves not one number but a window — from the oldest version it still accepts to the one it speaks itself. Exact equality would be right for a single installation whose operator upgrades both halves together; here Runjet is deployed for everybody at once and agents live on machines Runjet cannot reach. Raising the number would stop every job at every customer until each of them acted, and the symptom would be "nothing happened".

The price of the window is a rule for every change to the protocol: it must be additive, or the response must be built for the version that asked. Accepting an old agent's request and then sending it a new shape would be the same outage with extra steps.

Both edges of the window are published by GET /api/version, and each agent's version is refreshed with every request it makes, so the agent list can warn before anything stops. A version leaves the window only in a release whose notes say so.

The marks in the agent list

Beside an agent's version, one of two marks may appear on the Agents screen. When there is none, the agent speaks the current version, or it has not reported in yet.

MarkWhat it meansWhat to do
upgradeThe agent speaks an older version that is still in the window. It is being served and everything runs.Replace the binary before that version leaves the window.
unsupportedThe agent speaks a version below the window's lower edge. Runjet refuses it and its jobs have stopped.Replace the binary now.

What the agent gets: 426

An agent outside the window gets a 426 Upgrade Required response to every request, with a body naming the window:

{"error":"unsupported protocol version","expected":2,"min":1,"max":2}

In the agent's log this looks like poll failed with that sentence and five seconds to the next attempt — and so on, round and round, until it is given a new binary. Nothing is deleted and nothing needs enrolling again. Runjet's other error responses are in the reference.

At enrolment the version is negotiated before the token is burnt: an agent Runjet would not serve is refused at the door with the same 426, and the token stays valid for a binary that gets through.