# Releases and updates (/docs/releases)



Stable GitHub Releases are the production deployment interface. Publishing a
non-draft, non-prerelease tag named `vX.Y.Z` runs the unified release workflow
against that exact commit. One release deploys the API, portal, browser app,
and this documentation site; starts both EAS store submissions; and attaches
the OBS plugin packages to the same GitHub Release.

## Before tagging [#before-tagging]

Set the same `X.Y.Z` (no leading `v`) in:

* `apps/native/app.json`
* `apps/native/package.json`
* every `MARKETING_VERSION` entry in the committed iOS project
* `apps/obs-plugin/buildspec.json`

Tag a commit on `main` and publish the release. Draft and prerelease
publications are ignored, and concurrent releases are serialized.

## What the workflow does [#what-the-workflow-does]

1. Runs the repository tests, type checks, and every production build first —
   a red check stops the release before anything deploys.
2. Connects to the app host over an ephemeral Tailscale identity and runs the
   root-owned `visp-release` bootstrap with the tag and its 40-character
   commit SHA.
3. Starts EAS builds that submit Android to Play internal testing and iOS to
   the `VISP Internal` TestFlight group.
4. Builds, signs, and notarizes the OBS packages and attaches them with
   `SHA256SUMS.txt` — uploads use overwrite semantics, so rerunning a failed
   job is safe.

## How the server update stays safe [#how-the-server-update-stays-safe]

The bootstrap verifies the tag and SHA, takes a host lock, refuses to run over
tracked local changes, checks out the exact release, and then executes that
release's own helper from `/usr/local/libexec` — so helper fixes take effect in
the same release that ships them.

The helper installs frozen dependencies, migrates the database, and builds all
four app-host artifacts **before** restarting anything. It validates the Caddy
configuration before installing it, restarts `visp-server` and `visp-web`,
reloads Caddy, and runs local smoke checks. An install, migration, or build
failure therefore leaves the currently running services untouched.

Two rules follow from this design:

* Migrations must stay backward-compatible; database rollback is manual.
* A MediaMTX (relay) restart is never part of a release. Schedule relay
  upgrades in a maintenance window because they end active streams. API and
  portal restarts do not.

## After the release [#after-the-release]

* Portal and API healthy; a deep browser-app route and OAuth return work at
  `stream.visp-stream.com`; WebRTC publishes through the relay.
* Docs respond at `docs.visp-stream.com`: `/docs`, `/api/search`, `/llms.txt`,
  `/llms-full.txt`.
* Expo shows Android in Play internal testing and iOS in TestFlight.
* The GitHub Release carries all three OBS packages, the macOS package is
  notarized, and every file matches `SHA256SUMS.txt`.

Store promotion to public production, OBS plugin installation on broadcaster
machines, OTA updates, automatic database rollback, and relay restarts are
intentionally outside the workflow. Operator-side prerequisites (environment
files, GitHub environment variables and secrets, DNS) are documented in the
repository's `deploy/UPDATE.md`.
