Relayer logoRelayer

Publishing releases

Publish from the API, from CI, or automatically from GitHub releases.

Via the CLI

The fastest path from CI:

npx relayerctl releases create --app YOUR_APP_REF --channel stable \
  --version 1.4.2 --notes-file CHANGELOG.md \
  --artifact platform=windows,arch=x86_64,url=https://your-storage/setup.exe

See the CLI guide for auth, artifacts and push-mode commands.

Promote a GitHub release

With GitHub connected (see the Changelog guide for setup), the Releases tab has Promote from GitHub: pick one tagged release, choose the channel and starting rollout percentage, and its assets become artifacts automatically (URLs point at the GitHub assets - decisions, not bytes). Releases are never created from GitHub automatically; promoting is always a deliberate act.

Hosted changelog page

Every app gets a shareable public changelog at https://www.relayercli.com/changelog/your-app (pick the slug in app settings; the immutable ref works there too): your published changelog entries on a timeline with per-entry detail pages. See the Changelog guide for generating entries from GitHub activity. The machine-readable release feeds (RSS and JSON, per channel) stay under /feed/... and track published releases: rollbacks disappear from them automatically.

Via the API

curl -X POST https://www.relayercli.com/api/v1/releases \
  -H "Authorization: Bearer rl_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "app": "YOUR_APP_REF",
    "channel": "stable",
    "version": "1.4.2",
    "notes": "markdown release notes",
    "artifacts": [{
      "platform": "windows",
      "arch": "x86_64",
      "url": "https://your-storage/…/setup.exe",
      "sha512": "optional integrity hash",
      "size": 48234496,
      "signature": "optional (e.g. Tauri minisign)"
    }]
  }'

Works from any CI. Versions are unique per app+channel (409 on duplicates, so retried CI jobs are safe). See the API reference for all endpoints.

Manage serving via the API

Everything the Releases tab does to a shipped release works over PATCH /api/v1/releases too - ramp, pause, resume, roll back, target:

# ramp the rollout to 50%
curl -X PATCH https://www.relayercli.com/api/v1/releases \
  -H "Authorization: Bearer rl_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "app": "YOUR_APP_REF", "channel": "stable", "version": "1.4.2", "rollout": 50 }'

# target the canary ring, then later roll back
curl -X PATCH ... -d '{ "app": "...", "channel": "stable", "version": "1.5.0",
  "targets": { "matchLabels": { "tier": ["canary"] } } }'
curl -X PATCH ... -d '{ "app": "...", "channel": "stable", "version": "1.5.0",
  "status": "rolled_back" }'

The API enforces the exact same invariants as the dashboard, because they share the same code: once a release has been offered, the rollout percentage only increases and targeting only broadens (both answer 422 otherwise - pause to stop, roll back to pull), and a rolled-back release can never be re-served (409). Every change lands in the audit log with the API key as the actor.

Via GitHub releases

Keep your existing flow - gh release create v2.1.0 ./dist/* - and let the webhook do the rest.

Setup: on your app's Settings tab, click Connect under GitHub releases, then in your repo: Settings → Webhooks → Add webhook → paste the payload URL and secret → content type application/json → select only the Releases event.

Behavior:

  • Pre-releases land on beta, normal releases on stable.
  • The tag (minus a leading v) becomes the version; the release body becomes the notes.
  • Assets are classified by filename into platform/arch (works with electron-builder, Tauri, GoReleaser and common naming schemes); checksum and metadata files (.sig, .yml, SHA256SUMS, …) are excluded.
  • Drafts are ignored; GitHub's retry deliveries are answered as duplicates, never double-ingested.
  • Every delivery is HMAC-verified (SHA-256, timing-safe).

Test without a repo

Any correctly-signed POST is a valid delivery - sign one yourself with your webhook secret and openssl:

SECRET="<webhookSecret>"   # app Settings → GitHub releases
BODY='{"action":"published","repository":{"full_name":"you/app"},"release":{"id":1,"tag_name":"v1.2.0","name":"v1.2.0","body":"## Notes","draft":false,"prerelease":false,"html_url":"https://github.com/you/app/releases/tag/v1.2.0","assets":[{"name":"myapp-1.2.0-darwin-aarch64.dmg","browser_download_url":"https://example.com/myapp-1.2.0.dmg","size":52428800,"content_type":"application/octet-stream"}]}}'
SIG="sha256=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | sed 's/^.* //')"

curl -X POST <payload-url> \
  -H "Content-Type: application/json" \
  -H "X-GitHub-Event: release" \
  -H "X-Hub-Signature-256: $SIG" \
  -d "$BODY"

On this page