- 响应式项目首页 (Landing, 含 R2 APK 下载) + 路由 /home 调整 - OTA 升级: tauri-plugin-hotswap (lib.rs/main.rs 拆分, 客户端热替换) - OTA 服务端 (check/bundle/manifest-web) + build-ota/genkey/upload 脚本 - 密钥/凭据统一存配置中心 (signing + ota + cloudflare 分组) - Android CI (android-* 分支) + OTA CI (手动触发), 产物上传 R2 - 修复 tsc/构建阻塞问题
68 lines
2.8 KiB
JavaScript
68 lines
2.8 KiB
JavaScript
#!/usr/bin/env node
|
|
// 生成 minisign 密钥对 (ota-package/hotswap.{key,pub})
|
|
// 首次跑一遍: node scripts/ota-genkey.mjs
|
|
// - hotswap.key: 私钥, 不要提交, 部署时由 CI 注入 (环境变量 / secret)
|
|
// - hotswap.pub: 公钥, 写到 src-tauri/tauri.conf.json 的 plugins.hotswap.pubkey
|
|
//
|
|
// 依赖: minisign (https://jedisct1.github.io/minisign/)
|
|
// - Windows: scoop install minisign 或 choco install minisign (或下载官方 win64 二进制)
|
|
// - macOS: brew install minisign
|
|
// - Linux: apt install minisign
|
|
import fs from 'node:fs'
|
|
import path from 'node:path'
|
|
import { spawnSync } from 'node:child_process'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
const __filename = fileURLToPath(import.meta.url)
|
|
const __dirname = path.dirname(__filename)
|
|
const ROOT = path.resolve(__dirname, '..')
|
|
const OUT_DIR = path.join(ROOT, 'ota-package')
|
|
fs.mkdirSync(OUT_DIR, { recursive: true })
|
|
|
|
const KEY = path.join(OUT_DIR, 'hotswap.key')
|
|
const PUB = path.join(OUT_DIR, 'hotswap.pub')
|
|
|
|
if (fs.existsSync(KEY) || fs.existsSync(PUB)) {
|
|
console.error('[ota-genkey] 已存在密钥, 如需重新生成请先删除 ota-package/hotswap.{key,pub}')
|
|
console.error(' 注意: 重新生成密钥会导致旧 bundle 无法被客户端验证, 慎用!')
|
|
process.exit(1)
|
|
}
|
|
|
|
// 检查 minisign 是否存在
|
|
const which = spawnSync('minisign', ['-v'], { stdio: 'pipe' })
|
|
if (which.status !== 0 && which.error) {
|
|
console.error('[ota-genkey] 未找到 minisign 命令, 请先安装:')
|
|
console.error(' Windows: scoop install minisign')
|
|
console.error(' macOS: brew install minisign')
|
|
console.error(' Linux: apt install minisign')
|
|
process.exit(1)
|
|
}
|
|
|
|
// -G: 生成 -W: 无密码 -p: 公钥输出 -s: 私钥输出
|
|
const r = spawnSync('minisign', ['-G', '-W', '-p', PUB, '-s', KEY], { stdio: 'inherit' })
|
|
if (r.status !== 0) {
|
|
console.error('[ota-genkey] minisign 生成失败')
|
|
process.exit(1)
|
|
}
|
|
|
|
console.log('\n=== 密钥生成完成 ===')
|
|
console.log('私钥: ' + KEY + ' (不要提交到 git!)')
|
|
console.log('公钥: ' + PUB)
|
|
|
|
const pubText = fs.readFileSync(PUB, 'utf8')
|
|
const lines = pubText.split(/\r?\n/)
|
|
const pubB64 = lines.find((l) => l.startsWith('RWR') || l.startsWith('RWT') || l.startsWith('RWQ'))
|
|
console.log('\n请把下面这一行 pubkey 写到 src-tauri/tauri.conf.json -> plugins.hotswap.pubkey:')
|
|
console.log(' ' + (pubB64 || '').trim())
|
|
|
|
// 自动写 .gitignore 提醒
|
|
const gitignore = path.join(ROOT, '.gitignore')
|
|
if (fs.existsSync(gitignore)) {
|
|
let txt = fs.readFileSync(gitignore, 'utf8')
|
|
if (!txt.includes('ota-package/hotswap.key')) {
|
|
if (!txt.endsWith('\n')) txt += '\n'
|
|
txt += '\n# OTA 升级私钥, 不要提交\nota-package/hotswap.key\n'
|
|
fs.writeFileSync(gitignore, txt)
|
|
console.log('\n[ota-genkey] 已把 ota-package/hotswap.key 加入 .gitignore')
|
|
}
|
|
} |