Docs

Releases & app updates

A hosted build produces artifacts. A release is what ships them. Promote a succeeded build onto a release channel and every target in that build goes where that target ships:

  • macos-arm64:direct and android-arm64:direct โ†’ your update feed, so installed apps update themselves;
  • android-arm64:play โ†’ Google Play, on the track that channel is set to;
  • ios-arm64:testflight / :app_store โ†’ App Store Connect (the upload already happened on the runner; promoting records it as released).

Promotion happens in the web dashboard. There is no CLI promote command today.

every publish is the DIY path, not this one. That command signs and uploads a locally built release to your own bucket from your machine. See DIY app updates. If you promote hosted builds you never run it: the Platform signs and uploads for you. Both paths write the same feed format, so an app can move between them without its installed copies noticing.

1. Connect a bucket

Self-distributed targets, meaning macOS and Android outside Play, publish into an S3-compatible bucket you own: AWS S3, Cloudflare R2, DigitalOcean Spaces, MinIO, or anything else that speaks the S3 API.

Add one under Settings โ†’ Buckets: its endpoint, bucket name, access keys, and the public base URL your app will fetch from. The keys are encrypted at rest and used only by the Platform's own publish jobs. Unlike signing credentials, they never reach a build runner. Verify the connection from that page before your first release.

You bring the bucket, so the artifacts and the bill stay in your account.

Android direct releases work without a bucket too. With no bucket connected the Platform hosts the .apk itself and serves it from the app's public download page. That path has no update feed: connect a bucket and republish to get one.

2. Point your app at the feed

Open your app in the dashboard and, under Update feed, choose the bucket and an optional key prefix. The page then generates the exact block to paste into everywhere.yml:

config/everywhere.yml yaml
updates:
  url: https://updates.example.com/notes
  channel: stable
  public_key: "RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3"
  # auto: check       # off | check (notify) | download | install (silent)
  # interval: 21600   # seconds between background checks

The public key's private half never leaves the Platform, and shipped apps refuse any update not signed with it. All of this is baked into the build, so set it before the release you want people to update from, then build again.

3. Promote a build

Open a succeeded build, scroll to Promote to a release, pick a channel, add release notes if you want them, and press Promote. The page names exactly where that build's targets are about to go before you press it.

Publishing then runs per target, and the release rolls up to published once they have all landed. Release notes travel with it: plain text for the shell's native update dialog, HTML for in-app changelogs, and the release notes on a Google Play track.

A build that spans several bundle ids, such as a desktop id plus a distinct Android or iOS one, belongs to more than one app. Promoting from one app's channel ships only that app's targets; the siblings promote from their own pages.

Release channels

A channel is what your shipped apps poll. Stable exists from the start, and you can add Beta, Nightly, and so on up to your plan's limit.

  • The channel's key is the path segment in the feed URL. Renaming the channel is free; changing the key strands apps already polling the old one.
  • Exactly one release per channel is published at a time. Promoting a newer one supersedes the previous.
  • Each channel also carries a Google Play track: internal, alpha, beta, or production. That is the track its play targets are released to. Pick it on the channel row before promoting.

To roll back, open an older release and republish it. The feed is rewritten from artifacts still in Platform storage, and the newer releases are marked rolled back.

Android downloads

Android direct releases also get a public install page at /d/<org>/<app>/<channel>, showing the version, size, SHA-256, a Download APK button, a QR code to open it on a phone, and instructions for Android's "install unknown apps" prompt. It is a link you can hand a tester or print, and it is served whether the bytes live in your bucket or in Platform storage. See Android on the Platform.

iOS and Play releases

Store targets do not use the update feed at all, because a store owns distribution. Promoting them is how the Platform records and completes that hand-off:

  • TestFlight and the App Store. The macOS runner uploaded the .ipa to App Store Connect during the build, since only a Mac with Xcode can do that. Promoting checks that the upload really happened and marks the release published. It does not move the build along in App Store Connect. Handing it to external testers, and submitting an app_store build for review, stay manual steps there.
  • Google Play. The Platform uploads the .aab to Play itself, over the Play Developer API, and points the channel's track at the new version code. Your service-account key never leaves the server.
Rails ยท Hanami ยท Sinatra โ€” built with Ruby