16 KiB
YCode 更新发布说明
2026-10-20 23:53(Asia/Shanghai)追加发布:线上 latest 已更新为 0.0.7。包含技能/MCP 输入引用、Archify 内置推荐与官方 GitHub API 固定包安装、仓库 owner 本地头像、统一详情与全局遮罩、原位安装及新任务“去使用”、斜杠原子消费和焦点恢复修正。以下旧版本条目保留为历史,不代表当前 latest。
安装包:
release/publish/0.0.7/YCode-0.0.7-Setup-x64.exe,237351255 字节,SHA-256 506768934c92979ba38c4ab922b58d2de98b590a125fd1a5dacd8dadd2ddaff3。公开地址:http://192.168.10.6/ycode/releases/versions/0.0.7/YCode-0.0.7-Setup-x64.exe。完成升级回归、发布流程17项自测、类型检查与完整构建。使用官方 checksums.json 校验过的 Electron 37.10.3 缓存 ZIP,通过命令行 electronDist 打包,未更改全局下载配置;包内版本、固定 GitHub 来源与 commit、新详情/遮罩/安装状态/Slate 删除接口、离线头像哈希和公钥一致性检查通过。先生成 Ed25519 签名清单,再以
npm run release -- --version 0.0.7 --resume执行部署预检、SSH 发布与 HTTP 清单复核,历史目录不覆盖,暂存目录已清理。正式
0.0.7生产 EXE 使用隔离数据启动,真实 IPC 检查服务器返回 up-to-date;模拟旧版本通过正式更新后端实际完整下载,大小/SHA-256 一致、状态 ready,安装器适配器调用为0,真实安装文件/注册表状态未变化。报告:.tmp/updates-live/2026-10-20T15-53-57-094Z/report.json。已检查生产包启动截图。此验证没有执行 NSIS 安装/覆盖升级。安装包 Authenticode 状态为 NotSigned,不能将 Ed25519 清单签名表述为 Windows 代码签名。日志:
.tmp/release-0.0.7-updates.log、.tmp/release-0.0.7-build.log、.tmp/release-0.0.7-package.log、.tmp/release-0.0.7-package-verification.json、.tmp/release-0.0.7-prepare.log、.tmp/release-0.0.7-publish.log、.tmp/release-0.0.7-live-verification.log。本地版本与 lock 更新为0.0.7,未 Git 提交或打 tag,未安装或重启用户安装版。
2026-10-20 追加发布:线上 latest 已更新为
0.0.6,移除升级前的原生二次确认窗。 安装包为release/publish/0.0.6/YCode-0.0.6-Setup-x64.exe,大小237189173字节, SHA-2567e672b4a76349fb799e6c509c2901a199e5e6bb4266dc4e78d6bffe978c33c5c。 更新测试、完整构建、打包内版本/公钥/旧弹窗移除/ASAR修复检查、SSH 发布、HTTP 签名清单和完整安装包哈希复核通过。 首次一键执行在打包时访问 GitHub 超时;使用本机已有 Electron 37.10.3 缓存 ZIP(按 electron 包自带 checksums.json 验证 SHA-256)完成打包, 生成签名清单后通过npm run release -- --version 0.0.6 --resume完成发布。未修改发布脚本或全局下载配置。 日志:.tmp/release-0.0.6.log、.tmp/release-0.0.6-package-retry.log、.tmp/release-0.0.6-resume.log。 未执行安装器、覆盖升级或重启用户应用;下方0.0.5状态保留为历史记录。
日期:2026-10-20
状态:发布工具、服务端与推荐版本 0.0.5 已发布;隔离启动和真实签名下载已验收,
尚未执行真实覆盖升级验收
1. 当前结果
- 更新服务器:
local001,HTTP 基址http://192.168.10.6/ycode/releases/。 - 发布根目录:
/srv/ycode;不可变版本目录:/srv/ycode/releases/versions/。 - SSH 暂存目录:
/srv/ycode-staging,不对外提供 HTTP 访问。 - nginx 独立片段:
/etc/nginx/snippets/ycode-releases.conf。 - nginx 首次变更前备份:
/var/backups/nginx/ycode-before-20261020T091317Z-default。 - 下载页路由变更前备份:
/var/backups/nginx/ycode-before-20261020T092709Z-default。 /srv/baocode和原有/baocode/location 未改动。/ycode/releases/latest.json当前返回 200、Cache-Control: no-store,版本为0.0.5。/ycode/releases/当前返回 200,显示从签名清单生成的0.0.5下载页;页面无脚本。- 线上
latest.json于2026-10-20T10:27:49.041Z发布,SHA-256 为d985b7b94ed9e4661eec03489e801ba41aff295b4d9ea6be8a6930edf8247245;下载页 SHA-256 为42fb30160c2250ff04f23b3505a6fb0bb97aa3a1a91cb91ef4dd0cf0c314f285。 - 推荐线上安装包实测
237106337字节,SHA-256 为a3b8ece96077af81f9c8c676cb7d0d71f16a5d73332bc48b865c5cba7e92fd0d。 0.0.2、0.0.3、0.0.4安装包作为不可变历史版本保留,均已被0.0.5取代。- 发布完成后
/srv/ycode-staging为空;所有访问和文件校验均已完成。 - 公钥:
resources/updates/public-key.pem;ElectronextraResources会把它打包为resources/updates/public-key.pem。 - 公钥 SPKI SHA-256 指纹:
320a1f9016e9fbb7097074a68e1d3d15633fe05da5cb418f448372d37a8c3ea5。 - 私钥:
%USERPROFILE%\.ycode-release\update-signing.key,仅当前 Windows 账户可访问,不在仓库内。
当前 package.json 为内部版本 0.0.5,安装包名为
YCode-${version}-Setup-${arch}.${ext}。0.0.5 已构建、签名清单验证并发布到
local001。本轮未执行安装包 Authenticode 复验,不能把该发布包声明为已做代码签名。
2. 清单契约
完整契约见 resources/updates/manifest-contract.md。
{
"payload": {
"schemaVersion": 1,
"version": "0.0.5",
"publishedAt": "2026-10-20T10:00:00.000Z",
"notes": { "zh": "更新说明", "en": "Release notes" },
"platforms": {
"windows-x64": {
"url": "http://192.168.10.6/ycode/releases/versions/0.0.5/YCode-0.0.5-Setup-x64.exe",
"size": 123456789,
"sha256": "64-lowercase-hex"
}
}
},
"signature": "base64-ed25519-signature"
}
- Ed25519 签名覆盖且仅覆盖
Buffer.from(JSON.stringify(payload), "utf8")。 - payload 字段插入顺序属于签名契约,发布脚本固定为
schemaVersion, version, publishedAt, notes, platforms。 - SHA-256 为小写十六进制;大小是实际安装包字节数。
- 安装包 URL 必须是绝对 HTTP(S)、无查询、无片段、无凭据,并精确位于
<base>/versions/<version>/下。 - 客户端只接受与清单同源的安装包 URL 和同源重定向。
latest.json禁止缓存;版本目录和安装包内容不可覆盖。
3. 发布命令
一键打包发布(推荐)
在 Windows x64 发布机的项目目录运行:
npm run release
按提示输入新的正式版本号,例如 0.0.6,随后自动执行预检、更新本地版本、升级回归测试、
完整构建、NSIS 打包、签名清单生成、部署预检、SSH 发布与 HTTP 清单复核。默认发布到
local001,继续使用现有用户目录中的私钥和仓库公钥,不需要手动复制安装包或清单。
只输入版本号时会使用通用更新说明,也可以直接传参:
npm run release -- --version 0.0.6 --notes-zh '移除升级前的二次确认窗。' --notes-en 'Remove the upgrade confirmation dialog.'
npm run release -- --help
- 仅接受
x.y.z正式版本;新发布版本必须高于服务器 latest,且不得低于仓库版本。 - 安装包、签名清单保存在
release/publish/<版本>/;不会覆盖历史安装包,也不会自动安装或重启应用。 - 同步更新
package.json、package-lock.json的项目版本,不执行 Git 提交或打 tag。 - 任一步失败即停止。本地目标版本和已有产物保留,不自动回滚服务器。
- 已完成安装包和签名清单、但发布中断时,可复用原始产物重试;不会重新打包或重新签名:
npm run release -- --version 0.0.6 --resume
复用模式仍校验版本、签名、大小、哈希和安装包身份;服务器同版本必须与本地清单完全一致,
更高版本或同版本不同内容都会被拒绝。若失败时尚未生成完整签名清单,不能使用复用模式。
若已留下不完整的版本输出目录,普通模式不会覆盖它;可使用更高版本重新发布,或确认该版本
未发布后手动移走不完整产物,再重新运行同版本发布。
脚本使用本地独占锁避免重复运行;异常终止留下锁时,应先确认没有发布进程运行,再处理报错指出的锁文件。
npm run test:release 使用隔离的假执行器验证流程,不连接升级服务器、不实际打包或发布。
以下为手动分步命令,便于排障;通常无需执行。
先完成协调方构建,确认安装包已经包含 updater 并完成基础启动验收。不要发布当前
release/YCode-v0.01-Setup-x64.exe:它的 ProductVersion 是 0.0.1,且没有更新能力。
3.1 准备签名清单
Set-Location 'C:\Users\Administrator\code\YCode'
node scripts/updates/prepare-release.mjs `
--installer 'release\YCode-0.0.5-Setup-x64.exe' `
--version '0.0.5' `
--notes-zh '修复 Electron ASAR 安装标记误判,恢复重启升级。' `
--notes-en 'Fix Electron ASAR installation-marker misclassification and restore restart-based upgrades.' `
--output '.tmp\updates\0.0.5\latest.json'
该命令在生成清单前强制检查:
- 文件名安全且为
.exe。 - 实际 EXE ProductVersion 等于
--version。 package.json的版本等于--version。- 版本高于无 updater 的
0.0.1基线。 - 安装包大小为 20 MiB 到 4 GiB,SHA-256 从实际文件计算。
- 签名能被仓库公钥验证。
3.2 只读预检
node scripts/updates/deploy.mjs `
--manifest '.tmp\updates\0.0.5\latest.json' `
--installer 'release\YCode-0.0.5-Setup-x64.exe' `
--transport ssh `
--ssh-host local001 `
--dry-run
预检会重新计算安装包哈希、验证清单签名、读取并验证服务器现有
latest.json,然后检查版本单调性;不会修改服务器。
3.3 正式发布
node scripts/updates/deploy.mjs `
--manifest '.tmp\updates\0.0.5\latest.json' `
--installer 'release\YCode-0.0.5-Setup-x64.exe' `
--transport ssh `
--ssh-host local001
发布顺序:
- 安装包和清单先上传到
/srv/ycode-staging/<随机 ID>/。 - 服务端重新校验大小和 SHA-256。
- 新版本先以目录重命名方式进入不可变
versions/<version>/。 - 从已验签 payload 生成转义后的静态
index.html,包含版本、安装包链接、SHA-256 和中英文说明。 - 在文件锁下再次确认现有
latest.json未在发布期间变化。 - 先原子替换
index.html,再原子替换latest.json;最后一步失败时回滚旧页面。
任何一步失败,旧 latest.json 保持不变。已落盘但未成为 latest 的版本目录可以作为
同版本重试的幂等产物;若同版本目录中的包哈希不同,发布会被拒绝。
3.4 发布后复核
node scripts/updates/deploy.mjs `
--manifest '.tmp\updates\0.0.5\latest.json' `
--installer 'release\YCode-0.0.5-Setup-x64.exe' `
--transport ssh `
--ssh-host local001 `
--dry-run
Invoke-WebRequest 'http://192.168.10.6/ycode/releases/latest.json' -UseBasicParsing |
Select-Object StatusCode,Headers,Content
4. 验证命令
4.1 发布工具自测
node scripts/updates/selftest.mjs
node scripts/updates/contract-selftest.mjs
selftest.mjs 使用临时目录、临时密钥和本地 HTTP 服务,不上传 SSH,也不会写正式站点。
当前覆盖:
- 密钥生成、公钥格式和 Windows ACL。
- SemVer 优先级和 build metadata 规则。
- 签名精确载荷、说明/哈希/签名篡改拒绝。
- URL 查询、片段、凭据、跨版本路径、时间格式和小写哈希策略。
- 本地假传输发布、HTTP 拉取、大小与 SHA-256 复核。
- 幂等重发、同版本冲突、降级拒绝、失败前旧 latest 保持。
- 下载页文本转义、无脚本、latest/页面同步切换和失败时页面回滚。
contract-selftest.mjs 用 esbuild 加载 src/main/updates/manifest.ts,验证发布端清单能被
后端实际解析、验签和路径策略接受。
4.2 服务端验证
ssh local001 "nginx -t"
Invoke-WebRequest 'http://192.168.10.6/ycode/releases/latest.json' -Method Head -UseBasicParsing
Invoke-WebRequest 'http://192.168.10.6/ycode/releases/' -UseBasicParsing
Invoke-WebRequest 'http://192.168.10.6/baocode/' -Method Head -UseBasicParsing
当前预期状态:YCode latest 为 200 且版本为 0.0.5,下载页为 200 并包含线上版本、链接和哈希,
/baocode/ 为 403;YCode 不能开启目录浏览。
0.0.5 的隔离启动和真实 LAN 清单/安装包下载验证已通过:
- 脚本:
node scripts/verify-updates-live.cjs --expected-version 0.0.5 - 结果:PASS;实际启动、签名清单校验、完整下载、大小和 SHA-256 均通过。
- 报告:
.tmp/updates-live/2026-10-20T10-28-49-489Z/report.json。 - 产物验证:
app.asar内版本为0.0.5,更新实现包含修复后的 ASAR 安装标记判定,打包公钥与仓库一致。 - 边界:本轮没有启动 NSIS 安装器,没有重启或修改当前用户安装,因此这不等于真实覆盖升级验收。
5. 首次更新基线
现有 0.0.1 客户端没有 updater,不能通过更新服务器升级到 0.0.5。
正在运行的 0.0.3、0.0.4 客户端受旧版检查器的 ASAR 安装标记误判影响,应手工安装
0.0.5 引导包,不能把“发现更新”视为该路径已经可用。0.0.1 同样需要手工安装
0.0.5。其他旧版客户端的真实覆盖路径仍以隔离环境复测为准。引导到 0.0.5 后:
0.0.1(无 updater,手动安装 0.0.5)
0.0.3 / 0.0.4(检查器存在已知问题,手动安装 0.0.5)
→ 启动 0.0.5 并确认实际版本
→ 后续版本由 0.0.5 检查、下载、签名校验
→ 用户在应用中确认重启
→ NSIS 覆盖安装
→ 新版本启动后核对实际版本
不能把“上传成功”“清单可下载”或“客户端显示发现更新”当作端到端升级验收。至少还需要一次
隔离安装目录的真实 0.0.4 → 0.0.5 覆盖安装测试。
6. 密钥管理
- 私钥只允许存在于发布机用户目录或离线加密备份,不进入仓库、服务器、构建产物、聊天记录和日志。
- 公钥随客户端分发并作为固定信任锚。
- 当前私钥 ACL 仅授予
WIN-JA8HHLU9216\Administrator。 - 发布前可运行
init-key.mjs的默认路径检查;路径已存在时脚本会拒绝覆盖。 - 私钥丢失或泄露时,不能用旧客户端认可的常规更新完成轮换。需要构建一个包含新公钥的 临时安装包,手工分发并安装,同时提升版本;之后再由新密钥继续发布。
- 不要为了“省事”在服务器上保留私钥,也不要将私钥复制到
/srv/ycode。
7. 已知限制
- 当前为 LAN HTTP,仅适用于能访问
192.168.10.6的设备。没有 TLS、登录鉴权、限流和外部 CDN。 - 签名可防止安装包和清单被替换,但不能防止同网段攻击者阻断下载或造成拒绝服务。
- 尚未接入 HTTPS 域名、证书、灰度发布、多渠道、增量更新或正式 Authenticode 签名。
- 服务端没有回滚命令;发布后需要回退时必须发布一个更高版本,不能覆盖已发布版本目录。
resources/updates/public-key.pem已进入 ElectronextraResources;正式包仍需做一次资源存在性验收。- 推荐
0.0.5安装包的 Authenticode 状态本轮未复验;真实性目前以 Ed25519 签名清单、 文件大小和 SHA-256 为已验证边界。 - 本轮没有执行真实
0.0.4 → 0.0.5覆盖升级,也没有在独立用户目录完成完整安装/卸载验收。 - 专用 NSIS 运行时探针没有执行;安装器写入、覆盖、重启和卸载行为仍是测试缺口。