work-order-monitor/scripts/publish.mjs

121 lines
4.0 KiB
JavaScript
Raw Normal View History

2026-03-25 10:06:25 +08:00
#!/usr/bin/env node
/**
* @file /scripts/publish.mjs
* @description 构建后生成 update.json 并上传到远程服务器
* @usage node scripts/publish.mjs [--notes "更新说明"]
*
* 前置条件
* 1. 已运行 `pnpm run tauri-build` 生成构建产物
* 2. 远程服务器 SSH 可达192.168.2.127:22
*/
import { readFileSync, writeFileSync, readdirSync, existsSync } from "node:fs";
import { resolve, dirname, basename } from "node:path";
import { fileURLToPath } from "node:url";
import { execSync } from "node:child_process";
const __dirname = dirname(fileURLToPath(import.meta.url));
const root = resolve(__dirname, "..");
// ===== 配置 =====
const REMOTE_USER = "root_test";
const REMOTE_HOST = "192.168.2.127";
const REMOTE_PORT = 22;
const REMOTE_DIR = "/var/www/html/work-order-monitor";
const BASE_URL = "http://web.nps.yunvip123.cn/work-order-monitor";
// ===== 解析参数 =====
const args = process.argv.slice(2);
let notes = "";
const notesIdx = args.indexOf("--notes");
if (notesIdx !== -1 && args[notesIdx + 1]) {
notes = args[notesIdx + 1];
}
// ===== 读取版本号 =====
const pkg = JSON.parse(readFileSync(resolve(root, "package.json"), "utf-8"));
const version = pkg.version;
// ===== 查找构建产物 =====
const bundleDir = resolve(root, "src-tauri/target/release/bundle/nsis");
if (!existsSync(bundleDir)) {
console.error(`错误: 未找到构建目录 ${bundleDir}`);
console.error("请先运行: pnpm run tauri-build");
process.exit(1);
}
const files = readdirSync(bundleDir);
const setupFile = files.find((f) => f.includes(version) && f.endsWith("-setup.exe"));
const sigFile = files.find((f) => f.includes(version) && f.endsWith("-setup.exe.sig"));
if (!setupFile || !sigFile) {
console.error(`错误: 未找到版本 ${version} 的 -setup.exe 或 -setup.exe.sig 文件`);
console.error(`目录内容: ${files.join(", ")}`);
process.exit(1);
}
const setupPath = resolve(bundleDir, setupFile);
const sigPath = resolve(bundleDir, sigFile);
const signature = readFileSync(sigPath, "utf-8").trim();
console.log(`\n版本: ${version}`);
console.log(`安装包: ${setupFile}`);
console.log(`签名文件: ${sigFile}`);
console.log(`签名: ${signature.substring(0, 40)}...`);
// ===== 生成 update.json =====
const encodedFileName = encodeURIComponent(setupFile);
const updateJson = {
version,
notes: notes || `v${version} 更新`,
pub_date: new Date().toISOString(),
platforms: {
"windows-x86_64": {
url: `${BASE_URL}/${encodedFileName}`,
signature,
},
},
};
const updateJsonPath = resolve(bundleDir, "update.json");
writeFileSync(updateJsonPath, JSON.stringify(updateJson, null, 2), "utf-8");
console.log(`\nupdate.json 已生成`);
console.log(JSON.stringify(updateJson, null, 2));
// ===== 上传到远程服务器 =====
console.log(`\n正在上传到 ${REMOTE_HOST}:${REMOTE_DIR} ...`);
try {
// 确保远程目录存在
execSync(
`ssh -p ${REMOTE_PORT} ${REMOTE_USER}@${REMOTE_HOST} "mkdir -p ${REMOTE_DIR}"`,
{ stdio: "inherit" }
);
// 上传安装包
console.log(` 上传 ${setupFile} ...`);
execSync(
`scp -P ${REMOTE_PORT} "${setupPath}" ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/`,
{ stdio: "inherit" }
);
// 上传 update.json
console.log(` 上传 update.json ...`);
execSync(
`scp -P ${REMOTE_PORT} "${updateJsonPath}" ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/`,
{ stdio: "inherit" }
);
console.log("\n全部上传完成!");
console.log(`更新地址: ${BASE_URL}/update.json`);
console.log(`下载地址: ${BASE_URL}/${encodedFileName}\n`);
} catch (e) {
console.error("\n上传失败:", e.message);
console.error("请检查 SSH 连接是否正常,或手动上传以下文件:");
console.error(` 1. ${setupPath}`);
console.error(` 2. ${updateJsonPath}`);
console.error(` → 目标: ${REMOTE_HOST}:${REMOTE_DIR}/`);
process.exit(1);
}