Files
KeelrLeek 12fff9f6ad setup, updater: the installer window was a dev build with nothing inside it, and latest never matched a prerelease
Tauri decides dev-vs-production from the `custom-protocol` feature, not from
--release, and both workflows build the setup exe with a plain `cargo build`.
So cfg(dev) stayed on, the frontend was never embedded, and the window a
tester opened loaded devUrl: "localhost refused to connect" on a blank
800x580. The feature is a default of the crate now, with a build.rs guard
that fails a release build without it, and build.rs tracks setup/dist so a
changed window cannot be left out of the binary it is supposed to be in.

Behind that, the next wall: /releases/latest answers only with full
releases, and every release here is an alpha, so it 404s. The setup app read
that as a refused key and the app's Stable channel read it as a token that
cannot see the repository — both have been broken since the first alpha.
Each now lists /releases and takes the newest that is neither a draft nor
the rolling nightly, which the list really does put first.

And check_saved_key threw the saved key away on any failure at all, a
dropped connection included. The entry it deletes is the app's own updater
token, so only a refusal clears it now.

The release notes name the file to hand a tester: six assets on the page and
nothing saying which, while the bare NSIS installer is the biggest of them
and installs with no key gate and no signature check.
2026-09-10 07:19:15 -05:00

152 lines
6.7 KiB
YAML

# 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
# The file testers run: our own setup window (setup/). It carries no
# installer — it downloads the latest release with the tester's key and
# verifies the signature — so it is built the same for every release.
- name: Build SoulStream Setup
shell: bash
env:
VERSION: ${{ steps.stamp.outputs.version }}
run: |
npx vite build --config vite.setup.config.js
cargo build --release -p soulstream-setup
cp target/release/SoulStream-Setup.exe "SoulStream-Setup-$VERSION.exe"
ls -la "SoulStream-Setup-$VERSION.exe"
# Which of the files on the page a tester runs, said on the page: the
# bare NSIS installer reads like the download and installs with no key
# gate and no signature check.
- name: Publish SoulStream Setup
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
VERSION: ${{ steps.stamp.outputs.version }}
SHA: ${{ github.sha }}
run: |
gh release upload "$TAG" "SoulStream-Setup-$VERSION.exe" --repo "$TARGET" --clobber
{
echo "### Download \`SoulStream-Setup-$VERSION.exe\`"
echo
echo "It asks for your alpha key, fetches this build with it, checks the signature and installs — no admin prompt."
echo
echo "The other files are the ones Setup uses:"
echo
echo "- \`SoulStream_${VERSION}_x64-setup.exe\` — the bare installer Setup downloads. Running it yourself skips the key and the signature check."
echo "- \`SoulStream_${VERSION}_x64-setup.exe.sig\` — its signature."
echo "- \`latest.json\` — the manifest the app's Nightly channel reads."
echo
echo "Built from main at $SHA. Nightlies can break."
} > notes.md
gh release edit "$TAG" --repo "$TARGET" --notes-file notes.md