first run, updates, installer: a setup tour stands in front of a fresh install, releases arrive through an in-app updater with stable and nightly channels behind a read-only token, and the branded installer builds again

This commit is contained in:
KeelrLeek committed 2026-09-09 16:16:19 -05:00
1 parent 07810f7543
commit cd2391198e
19 files changed
+2010 -15

No files matched your search

+92
View File
@@ -0,0 +1,92 @@
# A release: push a tag `v1.8.0` (the version in tauri.conf.json, package.json
# and Cargo.toml must already say 1.8.0) and this builds the Windows installer,
# signs its updater artifact with the project key, and publishes a GitHub
# release carrying the installer, its .sig and latest.json — the manifest the
# app's Stable channel reads (src-tauri/src/updater.rs).
#
# Secrets this needs on the repository:
# TAURI_SIGNING_PRIVATE_KEY the private key (content of soulstream.key)
# TAURI_SIGNING_PRIVATE_KEY_PASSWORD its password — empty (or unset) for a key without one
# Optional, to publish somewhere other than this repository (this one is
# private, and a private release cannot be read by the updater without a
# token — a separate PUBLIC releases repo is the usual answer):
# RELEASES_TOKEN a token with contents:write on that repository
# vars.RELEASES_OWNER / vars.RELEASES_REPO where to publish
name: release
on:
push:
tags: ["v*"]
workflow_dispatch:
permissions:
contents: write
jobs:
windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
workspaces: "./src-tauri -> ../target"
- run: npm ci
- name: Read the version
id: version
shell: bash
run: echo "version=$(node -p \"require('./src-tauri/tauri.conf.json').version\")" >> "$GITHUB_OUTPUT"
- name: Build, sign and publish
uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.RELEASES_TOKEN || secrets.GITHUB_TOKEN }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
with:
owner: ${{ vars.RELEASES_OWNER || github.repository_owner }}
repo: ${{ vars.RELEASES_REPO || github.event.repository.name }}
tagName: v__VERSION__
releaseName: "SoulStream __VERSION__"
releaseBody: "See the commits since the last release."
releaseDraft: false
prerelease: ${{ contains(github.ref_name, '-') }}
includeUpdaterJson: true
args: --bundles nsis
# A private repository's assets are reachable only through the API, so the
# manifest's download URLs become API asset URLs — the app sends its token
# and `Accept: application/octet-stream` for those (updater.rs). Public
# repositories serve the same URLs to anyone, so nothing is lost.
- name: Point the manifest at the API assets
shell: bash
env:
GH_TOKEN: ${{ secrets.RELEASES_TOKEN || secrets.GITHUB_TOKEN }}
TARGET: ${{ vars.RELEASES_OWNER || github.repository_owner }}/${{ vars.RELEASES_REPO || github.event.repository.name }}
TAG: v${{ steps.version.outputs.version }}
run: |
gh release download "$TAG" --repo "$TARGET" --pattern latest.json --output latest.json --clobber
gh api "repos/$TARGET/releases/tags/$TAG" > release.json
node -e '
const fs = require("fs");
const m = JSON.parse(fs.readFileSync("latest.json", "utf8"));
const rel = JSON.parse(fs.readFileSync("release.json", "utf8"));
for (const p of Object.values(m.platforms)) {
const name = decodeURIComponent(p.url.split("/").pop());
const a = rel.assets.find((x) => x.name === name);
if (!a) { console.error("no asset named", name); process.exit(1); }
p.url = a.url;
}
fs.writeFileSync("latest.json", JSON.stringify(m, null, 2) + "\n");
console.log(JSON.stringify(m, null, 2));
'
gh release upload "$TAG" latest.json --repo "$TARGET" --clobber