58 lines
1.7 KiB
JavaScript
58 lines
1.7 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Sign release APK files with minisign (same key as desktop updater).
|
|
* Expects TAURI_SIGNING_PRIVATE_KEY (+ optional password) in env.
|
|
*
|
|
* Usage: node scripts/sign-android-apks.mjs <apk> [<apk> ...]
|
|
*/
|
|
import { existsSync, readFileSync } from 'node:fs';
|
|
import { spawnSync } from 'node:child_process';
|
|
import process from 'node:process';
|
|
|
|
function requireSigningKey() {
|
|
if (!process.env.TAURI_SIGNING_PRIVATE_KEY) {
|
|
throw new Error('TAURI_SIGNING_PRIVATE_KEY is required to sign Android APKs');
|
|
}
|
|
}
|
|
|
|
function signApk(apkPath) {
|
|
if (!existsSync(apkPath)) {
|
|
throw new Error(`APK not found: ${apkPath}`);
|
|
}
|
|
const sigPath = `${apkPath}.sig`;
|
|
if (existsSync(sigPath)) {
|
|
console.log(`Already signed: ${sigPath}`);
|
|
return sigPath;
|
|
}
|
|
|
|
// Prefer `tauri signer sign` (bundled minisign wrapper used by desktop release).
|
|
const tauriBin = process.platform === 'win32' ? 'npx.cmd' : 'npx';
|
|
const result = spawnSync(tauriBin, ['tauri', 'signer', 'sign', apkPath], {
|
|
stdio: 'inherit',
|
|
env: process.env,
|
|
shell: process.platform === 'win32',
|
|
});
|
|
if (result.status !== 0) {
|
|
throw new Error(`tauri signer sign failed for ${apkPath} (exit ${result.status ?? 'unknown'})`);
|
|
}
|
|
if (!existsSync(sigPath)) {
|
|
throw new Error(`Signature file missing after sign: ${sigPath}`);
|
|
}
|
|
console.log(`Signed ${apkPath} -> ${sigPath}`);
|
|
return sigPath;
|
|
}
|
|
|
|
function main() {
|
|
requireSigningKey();
|
|
const apks = process.argv.slice(2);
|
|
if (apks.length === 0) {
|
|
console.error('Usage: node scripts/sign-android-apks.mjs <apk> [<apk> ...]');
|
|
process.exit(1);
|
|
}
|
|
for (const apk of apks) {
|
|
signApk(apk);
|
|
}
|
|
}
|
|
|
|
main();
|