mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-21 14:05:41 +00:00
31d6e5bd77
- tauri-plugin-updater wired into lib.rs with pubkey + GitHub Releases endpoint in tauri.conf.json; updater:default capability granted - AppUpdater.tsx: on macOS, the download button now invokes the updater plugin (check + downloadAndInstall) which downloads the signed .app.tar.gz, verifies the minisign signature against the bundled pubkey, replaces /Applications/Psysonic.app, and relaunches. Windows and Linux keep the existing "download DMG/EXE/AppImage via reqwest then point to the folder" flow - CI: pass TAURI_SIGNING_PRIVATE_KEY + _PASSWORD to tauri-action so the .sig files are produced alongside the update bundles - New generate-manifest job (after build-macos-windows) runs scripts/generate-update-manifest.js which downloads the .sig files from the release, assembles latest.json for darwin-aarch64 and darwin-x86_64, and uploads it back as a release asset Windows will be added to latest.json once the Certum cert is active. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
90 lines
2.8 KiB
JavaScript
90 lines
2.8 KiB
JavaScript
#!/usr/bin/env node
|
|
// Generates latest.json for the Tauri updater from a GitHub release.
|
|
// Reads .sig files uploaded by tauri-action, assembles the manifest, writes latest.json.
|
|
//
|
|
// macOS-only for now — Windows + Linux are added once their signing pipelines
|
|
// (Certum cert for Windows, native package managers for Linux) are wired up.
|
|
//
|
|
// Required env vars: VERSION, GITHUB_TOKEN
|
|
// Usage: node scripts/generate-update-manifest.js
|
|
|
|
const { execSync } = require('child_process');
|
|
const fs = require('fs');
|
|
|
|
const VERSION = process.env.VERSION;
|
|
const REPO = 'Psychotoxical/psysonic';
|
|
const TAG = `app-v${VERSION}`;
|
|
|
|
if (!VERSION) {
|
|
console.error('VERSION env var required');
|
|
process.exit(1);
|
|
}
|
|
|
|
// Platform → update bundle filename (produced by tauri-action with updater plugin)
|
|
const PLATFORM_FILES = {
|
|
'darwin-aarch64': 'Psysonic_aarch64.app.tar.gz',
|
|
'darwin-x86_64': 'Psysonic_x64.app.tar.gz',
|
|
};
|
|
|
|
const platforms = {};
|
|
|
|
// A real minisign .sig file is multi-line and ~200+ chars.
|
|
// A public key (RWTxxx... single line, ~56 chars) must never appear here.
|
|
function validateSignature(sig, platform, sigFile) {
|
|
if (/^RWT[A-Za-z0-9+/]{10,}={0,2}$/.test(sig)) {
|
|
throw new Error(
|
|
`${platform}: .sig file "${sigFile}" contains a PUBLIC KEY instead of a signature.\n` +
|
|
` Got: ${sig}\n` +
|
|
` TAURI_SIGNING_PRIVATE_KEY must be the private key, not the public one.`
|
|
);
|
|
}
|
|
if (sig.length < 80) {
|
|
throw new Error(
|
|
`${platform}: .sig file "${sigFile}" looks too short (${sig.length} chars) to be a valid signature.`
|
|
);
|
|
}
|
|
}
|
|
|
|
for (const [platform, filename] of Object.entries(PLATFORM_FILES)) {
|
|
const sigFile = `${filename}.sig`;
|
|
try {
|
|
execSync(
|
|
`gh release download "${TAG}" --repo "${REPO}" -p "${sigFile}" --clobber`,
|
|
{ stdio: 'pipe' }
|
|
);
|
|
const signature = fs.readFileSync(sigFile, 'utf8').trim();
|
|
validateSignature(signature, platform, sigFile);
|
|
const url = `https://github.com/${REPO}/releases/download/${TAG}/${filename}`;
|
|
platforms[platform] = { signature, url };
|
|
console.log(`✓ ${platform}`);
|
|
} catch (e) {
|
|
console.warn(`⚠ Skipping ${platform}: ${e.message}`);
|
|
}
|
|
}
|
|
|
|
if (Object.keys(platforms).length === 0) {
|
|
console.error('No platforms found — aborting manifest generation');
|
|
process.exit(1);
|
|
}
|
|
|
|
let notes = '';
|
|
try {
|
|
const raw = execSync(
|
|
`gh release view "${TAG}" --repo "${REPO}" --json body`,
|
|
{ stdio: 'pipe' }
|
|
).toString();
|
|
notes = JSON.parse(raw).body ?? '';
|
|
} catch {
|
|
console.warn('Could not fetch release notes');
|
|
}
|
|
|
|
const manifest = {
|
|
version: VERSION,
|
|
notes,
|
|
pub_date: new Date().toISOString(),
|
|
platforms,
|
|
};
|
|
|
|
fs.writeFileSync('latest.json', JSON.stringify(manifest, null, 2));
|
|
console.log(`\nWrote latest.json for v${VERSION} with platforms: ${Object.keys(platforms).join(', ')}`);
|