Appearance
ts release
Manage the Turbo Client, Turbo Update Service, and Turbo Server releases this server offers: what each channel serves, the release feed that publishes into channels, and the versions this server gets from Turbo. Reach for halt first when a version misbehaves: it stops offering the version at once and decides nothing for good.
Usage
text
ts release status
ts release list [<channel>]
ts release activate <channel> <version>
ts release promote <channel> <version> [--rollout=PERCENT]
ts release publish <channel> <version>
ts release halt <channel> <version>
ts release withdraw <channel> <version>
ts release hold <channel> [--reason=TEXT]
ts release resume <channel>
ts release subscribe <channel>... [--auto=CHANNEL]... [--upstream=URL]
ts release unsubscribe
ts release approve <channel> <version> [--rollout=PERCENT]
ts release upload <installer> --channel=CHANNEL [--arch=ARCH] [--app=APP] [--activate]Description
ts release works on the releases of this server's Update API, the same ones the Deployment Dashboard (/updates) shows. Run it on the server itself, as root or an administrator: the Update API is reachable only there. It mints its own token from the install, so it needs no ts login, and it refuses --server.
Channels, Versions, and States
A release is one build of an app on one channel for one architecture. The apps include the Turbo Client (turbo-client), the Turbo Update Service (turbo-update-service), and Turbo Server (turbo-server). Architectures are x64 and arm64; Turbo Server's are its platforms, win-x64 and linux-x64. A device follows one channel, and a device with no channel set follows stable.
You name a version in a channel as ts release list shows it, and each command acts on every architecture the version went to; only upload takes an architecture. A version in a channel is in one of these states:
| State | Meaning |
|---|---|
live | Offered to devices. |
halted | Still the channel's release, offered to nobody. |
past | Replaced, and a rollback can return to it. |
withdrawn, rolled back, stopped | Taken off, so the feed never deploys it again: withdrawn, replaced by an older version, or stopped when the catalog does not say which. activate takes it live again. |
The Release Feed
The release feed is the part of the Update API that publishes into channels on its own. It runs on a server set up with a feed.json, and every 15 minutes polls its source: Turbo's CI builds on a server that publishes them, or Turbo's signed release list on a server that gets releases from Turbo. status shows how each channel takes releases:
automatically— The feed publishes each new build into it, as intocanary.by promotion— It takes only a version promoted from a channel below it, asstabletakesbeta's.on request— It gets a release only when you ask for one.by approval from <channel>— It takes a version Turbo offers on that channel once it is approved.
publish, promote, and approve hand the feed a request and return. The feed runs one request per channel, and status shows it waiting, running, and how it ended; a channel with a different request waiting refuses another.
hold, resume, publish, promote, and approve need the feed. A server without one, where status says it has no feed.json, still takes uploads, and activate, halt, and withdraw work there. Those five commands take a channel name that several apps share as turbo-client's; name another app's channel as <app>/<channel>, as status prints it: turbo-update-service/beta.
Reading State
status says whether this server runs the release feed, when it last polled and when it polls next, and, on a server that gets releases from Turbo, which server that is and when its release list last verified. Each channel's row says how the feed publishes into it, whether it is held (by whom, since when, and why) or running, and what the last poll found. Under the table: what Turbo offers on each channel, a request waiting for the feed or running, how the last one ended, why a poll went wrong, and a release devices are failing to install. The APP column appears when the status covers more than one app.
list shows each version in each channel, newest first, one row per version with every architecture it went to; name a channel to see only it. STATE is one of the states above, and names the architectures that differ when they do (live on x64, halted on arm64). SINCE is when the version arrived in the channel, in this machine's time zone. list names no app, so every app's versions on a channel are listed together.
Taking a Version Live and Rolling Back
activate <channel> <version> makes the version live on every architecture of the channel at 100%, replacing whatever each offered; a halted version is resumed at the rollout it had. Going back to an older version rolls back from the newer one, which the feed then never promotes again. A build the channel does not carry yet, such as an upload, is deployed to it. Until the server has a public domain, devices cannot download the installers it hosts, so deploying one is refused. Architectures go live one at a time, and a refusal stops the rest and names those already live.
promote <channel> <version> asks the feed to take the version live on the channel with the build a channel it promotes from already holds, such as beta's; a version no such channel holds is published from its CI build instead. The feed turns the promotion down if the channel already has a newer version. Once the version is live, the feed deletes older releases on the channel, keeping the newest few. For a ramp or an install deadline, use the Promote dialog in the Deployment Dashboard. A channel that gets its releases by approval takes approve instead.
publish <channel> <version> asks the feed to publish that version of a CI build into the channel now, rather than at its next poll, with the checks a poll makes. A channel that gets releases only by promotion, such as stable, takes none.
Stopping a Bad Version
halt <channel> <version> halts the version on every architecture of the channel that serves it. Devices and servers are no longer offered it, so a server upgrade to it pauses, and a device that downloaded it installs nothing until it is resumed; devices that already installed it keep it. activate resumes it. halt refuses a version that is not live.
withdraw <channel> <version> takes the version off every architecture of the channel for good: the feed never deploys it there again, and an architecture it served serves nothing, since nothing older is restored. Devices that already installed it keep it. activate deploys it again, or an older version in its place.
Neither command puts the previous version back. To do that, activate the previous version, which rolls back from the bad one.
When too many devices fail to install a client version, the feed withdraws it on its own, and holds the channel, only on the canary of a server that publishes CI builds. On the other channels it leaves the version live and reports it under the status table.
Holding a Channel
hold <channel> stops the feed publishing into the channel, and turns down the requests already waiting for it, until resume. Devices keep the releases they have. --reason is shown with the hold. A request you make while the channel is held passes the hold and leaves it in place.
resume <channel> clears the hold, whoever set it. A channel the feed publishes automatically is polled at once and gets the newest build it does not have yet; a version you halted or withdrew stays so. stable, and any other channel the feed does not publish automatically, gets a release only when you ask for one.
On a server that runs the feed, halt, withdraw, activate, and upload --activate hold the channel too, so the feed cannot publish over your change, and say so: The feed is held on stable until you resume it. Only resume clears that hold; resuming the version with activate does not. A channel the feed publishes automatically starts held and gets nothing until you resume it.
Getting Releases from Turbo
subscribe <channel>... sets which of Turbo's channels this server gets releases on: stable, lts, beta, or canary, each into the channel here of the same name, or pilot=stable for a channel here of another name (lowercase letters, digits, dots, and dashes). The server reads Turbo's release list and checks its signature before it saves anything, and saves nothing when it cannot. --upstream names another server to get releases from; a saved subscription keeps its server until --upstream names another.
Each channel takes a version when you approve it, or, given to --auto, approves each newer version on its own. Without --auto, a channel already saved keeps its setting, and a new channel that takes canary approves on its own; with it, every other channel named waits for you. A channel that takes lts never approves on its own: each LTS line takes a version only when you approve it. Saving the subscription lifts the hold a channel starts with from each channel that approves on its own. Naming channels again replaces the ones saved: a channel you leave out keeps what its devices have now and gets nothing new.
status lists the versions Turbo offers on each channel. approve <channel> <version> asks the feed to download the version the server it gets releases from offers on the channel's own channel there (stable for pilot=stable), for every architecture, check each installer against what that server signed, and take it live on the channel. Devices download it from this server. The feed turns the approval down if the server no longer offers the version as it did, or the channel already has a newer one. For a ramp or an install deadline, use the Approve dialog in the Deployment Dashboard.
unsubscribe stops this server getting releases from Turbo. Every release it holds stays, and devices keep what it offers them now. Nothing new arrives until you upload a release or subscribe again.
Uploading a Build
upload <installer> --channel=<channel> uploads the installer as a new build for the channel, not live until --activate or activate takes it live there. The version comes from the file name, and so does the architecture: a name with -arm64 is arm64, -win-x64 or -linux-x64 is that Turbo Server platform, and any other is x64. A client or updater installer is an .msi; a Turbo Server one is an .msi or a .tar.gz, uploaded with --app turbo-server. Upload each architecture's installer of a version, then activate takes them live together.
A version that is not newer than the one the channel already holds for the architecture is refused before the upload starts. To publish an older build on purpose, add it in the Deployment Dashboard and enter its version there. When --activate is refused, the build stays uploaded and live nowhere.
A Turbo Server release reaches this deployment's servers through the channel chosen in the Administration site under System → Updates, which also sets when they install it.
Options
| Flag | Description | Default/Values | Notes |
|---|---|---|---|
--rollout | Percentage of devices offered the version once it is live. | 1 to 100; default 100 | promote and approve. 0 is refused: stopping a version is halt. Change it later with Edit Rollout in the Deployment Dashboard. |
--reason | Why, shown with the hold. | Text; default no reason given | hold only. |
--auto | A channel here that approves each newer version on its own. | A channel the command names | subscribe only. Give one --auto for each such channel; every other channel named then takes a version only when you approve it. Left out, each channel keeps its setting. Refused for a channel that takes lts. |
--upstream | The server to get releases from. | HTTPS URL; default the one already saved, else this server's setting, else https://app.turbo.net | subscribe only. |
--activate | Take the build live once it is uploaded. | upload only. | |
--app | App the installer is for. | Default turbo-client; turbo-server for a Turbo Server installer | upload only. |
--arch | Architecture of the installer. | x64, arm64, win-x64, linux-x64; default from the file name, else x64 | upload only. |
--channel | Channel to upload to, such as stable. | upload only, and required there. |
Examples
bash
# What does each channel offer, and what is the feed doing?
ts release list
ts release status
# Get stable and beta from Turbo; beta approves each newer version on its own
ts release subscribe stable beta --auto beta
# Approve a version Turbo offers on stable, for 10% of devices at first
ts release approve stable 26.10.14.3902 --rollout 10
ts release status
# Add a pilot channel that takes Turbo's stable, keeping the channels already saved
ts release subscribe stable beta pilot=stable
# Upload both architectures of a client build, then take them live together
ts release upload TurboClient-26.10.14.3902.msi --channel stable
ts release upload TurboClient-26.10.14.3902-arm64.msi --channel stable
ts release activate stable 26.10.14.3902
# Upload a Turbo Server build for Linux and take it live
ts release upload TurboServer-26.10.14.3902-linux-x64.tar.gz --channel stable --app turbo-server --activate
# A version misbehaves: stop offering it while you look
ts release halt stable 26.10.14.3902
# It is fine: offer it again, then let the feed publish into stable again
ts release activate stable 26.10.14.3902
ts release resume stable
# It is bad: roll back to the version before it
ts release activate stable 26.10.7.3880
ts release resume stable
# Or take it off with nothing in its place
ts release withdraw stable 26.10.14.3902
# Stop the feed publishing into canary without changing what devices get
ts release hold canary --reason "crashes on launch"
# On a server that publishes CI builds, promote a beta version to stable
ts release promote stable 26.10.14.3902 --rollout 25bash
# Naming channels replaces the saved ones: this drops beta, whose devices
# keep what they have and get nothing new
ts release subscribe stableOutput
ts release list on a server that gets stable and beta from Turbo. 26.10.9.1250 is the Turbo Update Service's version, listed with the client's:
text
CHANNEL VERSION STATE ARCHES SINCE
beta 26.10.14.3902 live x64, arm64 yesterday 16:40
beta 26.10.9.1250 live x64, arm64 2026-10-10 08:15
beta 26.10.7.3880 past x64, arm64 2026-10-08 10:05
stable 26.10.9.1250 live x64, arm64 2026-10-12 14:30
stable 26.10.8.3884 rolled back x64, arm64 2026-10-16 10:31
stable 26.10.7.3880 live x64, arm64 2026-10-15 11:30ts release status on the same server, trimmed to two of its apps:
text
Release feed is on. Last poll 10:16, next 10:31.
Gets releases from app.turbo.net; its release list verified 10:16.
APP CHANNEL PUBLISHES STATE LAST POLL
turbo-client beta by approval from beta held by Cli (alice@TS01), today 09:12 (under review) skipped, held
turbo-client stable by approval from stable running -
turbo-update-service beta by approval from beta running nothing new
turbo-update-service stable by approval from stable running -
turbo-client/beta: app.turbo.net offers 26.10.14.3902.
turbo-client/stable: app.turbo.net offers 26.10.14.3902.
turbo-client/stable: promotion request running since 10:20: 26.10.14.3902, rollout 10%, asked by Cli (alice@TS01).
turbo-update-service/beta: app.turbo.net offers 26.10.9.1250.
turbo-update-service/stable: app.turbo.net offers 26.10.9.1250.A hold ts set names the operating-system account and machine that ran it. A channel the feed publishes automatically and no one has resumed shows held by UpdateApi (starts held until an operator resumes it).
With --format=json, list gives each version's releases with their ID, architecture, state, rollout, and download URL, and status gives the feed's status as the Update API reports it.
Exit Codes
0 on success, including a publish, promote, or approve the feed has taken; status shows how it ends. -1 when the command or the server refuses: --server given, or no Turbo Server install on this machine; a version that is not one; a halt of a version that is not live, or a withdraw of one already taken off; a deploy devices could not download; a release changed while the command ran; a version the feed turns down; a request while the channel has a different one waiting; promote into a channel that gets releases by approval, or approve into one that does not; an --auto channel the command does not name, or one that takes lts; a release list that could not be read or did not verify; an installer that does not exist or whose file name carries no version; and an upload no newer than what the channel holds. -2 when an argument is missing, upload has no --channel, or --rollout is outside 1 to 100. -3 when the server's services on this machine cannot be reached. -4 when the Update API refuses ts's credential. -5 when ts cannot read the install's credential, because it is not running as root or an administrator, or the server refuses that credential. -6 when the channel holds no release of the version (for activate, when no build of it exists either), when the feed has no such channel or this server runs no feed, and for unsubscribe on a server that runs no feed.
Related Commands
- ts publisher — Lets a CI job publish releases of one app to its channels, without
upload. - ts server — The servers of this deployment, which update themselves from the Turbo Server channel chosen under System → Updates.
- ts status — The server's own health;
ts release statusasks the same of the release feed.
