Wardrobe/scripts/ota-genkey.mjs
jif2.zhang 38b5e3190a init: Wardrobe 衣物管理系统 - 项目首页、OTA 升级、Android CI/CD
- 响应式项目首页 (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/构建阻塞问题
2026-09-11 15:46:42 +08:00

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')
}
}