133 lines
5.7 KiB
YAML
133 lines
5.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"
|
|
|
|
- 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 }}
|
|
run: gh release upload "$TAG" "SoulStream-Setup-$VERSION.exe" --repo "$TARGET" --clobber
|