a5fd25f10a
- 客户端接入 tauri-plugin-updater:原生侧注册插件,删除自研更新下载命令、下载进度事件与安装器启动逻辑 - 客户端更新服务与更新提示改走官方插件接口,删除自研清单解析、版本比较与下载实现 - 更新能力只授予客户端主窗口,移除只为自研清单放行的 OSS 白名单与 CSP 连接项 - 新增构建期更新检查开关:开发态默认关闭,agc 启动不请求更新清单、不显示更新入口 - 发布脚本按渠道生成官方更新插件清单与签名,universal macOS 产物同时挂两个平台键,缺签名失败关闭 - 发布脚本按渠道上传安装包、签名与渠道清单,并为 dev-win 生成旧协议 sha256 迁移清单 - 构建期按渠道注入更新端点配置,渠道与目标平台不匹配时发布失败关闭 - Jenkins 流水线新增渠道参数与签名凭据注入,归档补充签名与迁移清单 - 新增发布上传 dry-run 开关,只打印 ossutil 命令且不回显凭据 - 更新技术方案与开发运维文档,登记 macOS 渠道落地待办
93 lines
3.1 KiB
JavaScript
93 lines
3.1 KiB
JavaScript
import { spawnSync } from 'node:child_process';
|
|
import path from 'node:path';
|
|
|
|
import { formatOssutilCommand, readReleaseDryRun } from './release-oss.mjs';
|
|
|
|
const bucket = process.env.AGC_OSS_BUCKET?.trim() || 'agc-dev';
|
|
const endpoint =
|
|
process.env.AGC_OSS_ENDPOINT?.trim() || 'oss-rg-china-mainland.aliyuncs.com';
|
|
if (!/^[a-z0-9][a-z0-9.-]{1,62}$/u.test(bucket) || /[\r\n\0]/u.test(endpoint)) {
|
|
throw new Error('OSS bucket 或 endpoint 配置无效');
|
|
}
|
|
process.env.AGC_UPDATE_OSS_BASE_URL ||= `https://${bucket}.${endpoint}/agc`;
|
|
const dryRun = readReleaseDryRun();
|
|
|
|
const { generateUpdateManifest, prepareReleaseVersion, runTauriBuild } =
|
|
await import('./build-release.mjs');
|
|
|
|
function runOssutil(args) {
|
|
const binary = process.env.OSSUTIL_BIN?.trim() || 'ossutil';
|
|
const accessKeyId = process.env.AGC_OSS_ACCESS_KEY_ID?.trim();
|
|
const accessKeySecret = process.env.AGC_OSS_ACCESS_KEY_SECRET;
|
|
if (Boolean(accessKeyId) !== Boolean(accessKeySecret)) {
|
|
throw new Error('OSS AccessKey ID 和 Secret 必须同时提供');
|
|
}
|
|
if (dryRun) {
|
|
// 演练:只打印将要执行的上传,凭据以占位符呈现,不写入 OSS。
|
|
console.log(
|
|
`[dry-run] ${formatOssutilCommand({
|
|
binary,
|
|
args,
|
|
endpoint,
|
|
credentials: Boolean(accessKeyId),
|
|
})}`,
|
|
);
|
|
return;
|
|
}
|
|
const credentialArgs = accessKeyId
|
|
? ['--access-key-id', accessKeyId, '--access-key-secret', accessKeySecret]
|
|
: [];
|
|
const result = spawnSync(
|
|
binary,
|
|
[...args, '--endpoint', endpoint, ...credentialArgs],
|
|
{
|
|
stdio: 'inherit',
|
|
shell: false,
|
|
},
|
|
);
|
|
if (result.error) {
|
|
throw new Error(`无法执行 ${binary},请先安装并配置 ossutil`);
|
|
}
|
|
if (result.status !== 0) process.exit(result.status ?? 1);
|
|
}
|
|
|
|
await prepareReleaseVersion();
|
|
runTauriBuild([]);
|
|
const { artifact, channel, legacyManifestPath, manifest, manifestPath } =
|
|
generateUpdateManifest();
|
|
const artifactKey = `agc/${channel}/${manifest.version}/${path.basename(artifact)}`;
|
|
// Jenkins/ossutil 默认会在目标对象已存在时交互询问并按默认值跳过;
|
|
// 发布清单是固定的 latest 指针,必须显式覆盖,否则流水线会误报成功但远端仍保留旧版本。
|
|
runOssutil(['cp', '--force', artifact, `oss://${bucket}/${artifactKey}`]);
|
|
runOssutil([
|
|
'cp',
|
|
'--force',
|
|
`${artifact}.sig`,
|
|
`oss://${bucket}/${artifactKey}.sig`,
|
|
]);
|
|
runOssutil([
|
|
'cp',
|
|
'--force',
|
|
manifestPath,
|
|
`oss://${bucket}/agc/${channel}/latest.json`,
|
|
]);
|
|
console.log(`[ai-game-creator-shell] 已上传 oss://${bucket}/${artifactKey}`);
|
|
console.log(
|
|
`[ai-game-creator-shell] 已上传 oss://${bucket}/agc/${channel}/latest.json`,
|
|
);
|
|
if (legacyManifestPath) {
|
|
// 迁移桥:让仍走旧 sha256 清单的已发布客户端升级到新协议,一个版本周期后删除。
|
|
runOssutil([
|
|
'cp',
|
|
'--force',
|
|
legacyManifestPath,
|
|
`oss://${bucket}/agc/latest.json`,
|
|
]);
|
|
console.log(
|
|
`[ai-game-creator-shell] 已上传迁移指针 oss://${bucket}/agc/latest.json`,
|
|
);
|
|
}
|
|
if (dryRun) {
|
|
console.log('[ai-game-creator-shell] dry-run:未写入任何 OSS 对象');
|
|
}
|