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:
1 parent
07810f7543
commit
cd2391198e
19 files changed
+2010
-15
No files matched your search
@@ -0,0 +1,110 @@
|
||||
# The nightly: every day at 06:00 UTC (or by hand), build `main` as
|
||||
# `X.Y.Z-nightly.YYYYMMDD.<sha>` — X.Y.Z being the version the tree declares
|
||||
# with its prerelease part dropped — and publish it as the rolling `nightly`
|
||||
# prerelease, replacing yesterday's. The app's Nightly channel reads
|
||||
# `releases/download/nightly/latest.json`; a different build is always an
|
||||
# update there (updater.rs), so the number does not need to climb.
|
||||
#
|
||||
# Same secrets and optional publish target as release.yml.
|
||||
name: nightly
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 6 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
windows:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: main
|
||||
|
||||
- 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: Stamp the nightly version
|
||||
id: stamp
|
||||
shell: bash
|
||||
run: |
|
||||
base=$(node -p "require('./package.json').version.split('-')[0]")
|
||||
ver="$base-nightly.$(date -u +%Y%m%d).$(git rev-parse --short HEAD)"
|
||||
echo "version=$ver" >> "$GITHUB_OUTPUT"
|
||||
node -e '
|
||||
const fs = require("fs"); const v = process.argv[1];
|
||||
for (const f of ["package.json", "package-lock.json"]) {
|
||||
const j = JSON.parse(fs.readFileSync(f, "utf8"));
|
||||
j.version = v; if (j.packages && j.packages[""]) j.packages[""].version = v;
|
||||
fs.writeFileSync(f, JSON.stringify(j, null, 2) + "\n");
|
||||
}
|
||||
const c = JSON.parse(fs.readFileSync("src-tauri/tauri.conf.json", "utf8"));
|
||||
c.version = v; fs.writeFileSync("src-tauri/tauri.conf.json", JSON.stringify(c, null, 2) + "\n");
|
||||
' "$ver"
|
||||
sed -i "0,/^version = \"[^\"]*\"/s//version = \"$ver\"/" Cargo.toml
|
||||
echo "nightly $ver"
|
||||
|
||||
- name: Replace yesterday's nightly
|
||||
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 }}
|
||||
run: gh release delete nightly --repo "$TARGET" --cleanup-tag --yes || true
|
||||
|
||||
- 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: nightly
|
||||
releaseName: "Nightly ${{ steps.stamp.outputs.version }}"
|
||||
releaseBody: "Built from main at ${{ github.sha }}. Nightlies can break."
|
||||
releaseDraft: false
|
||||
prerelease: true
|
||||
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: nightly
|
||||
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
|
||||
@@ -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
|
||||
Reference in new issue
Block a user