- 前端
- 桌面应用
- 图像处理
【免费下载链接】jspaint
🎨 Classic MS Paint, REVIVED + ✨Extras
导读
本文以 release-process.md 为核心,完整讲解 JS Paint 项目的版本发布流程:从维护 CHANGELOG.md 的 Unreleased 章节开始,通过npm run release一条命令完成代码检查、版本号 bump、文档与清单更新、Git 提交打标签并推送 tag,再由 GitHub Actions 自动构建全平台安装包并生成发布草稿(release draft),最后经人工测试后正式发布。读完本文,你将掌握 JS Paint 发布全链路中每一步的用途、底层脚本实现与必须注意的"不可回头"节点,可直接照搬该流程进行下一次版本发布。
一、发布前准备:维护 Unreleased 章节
发布的第一步不是执行命令,而是整理变更记录。JS Paint 采用 Keep a Changelog 规范 + Semantic Versioning 版本策略,CHANGELOG.md 顶部始终保留一个## [Unreleased]章节:
## [Unreleased] No changes here yet.在正式发布前,维护者需要翻阅该版本的提交历史(commit history),确保所有重要变更都已记录在 Unreleased 章节中。CHANGELOG 采用## [版本号] - 日期的分节格式,并在每个版本下按Added / Changed / Fixed等类型组织条目,正文底部还维护着用于版本间 diff 的对比链接(格式为https://github.com/1j01/jspaint/compare/v旧版本...v新版本)。
发布脚本对 Unreleased 章节有硬性校验:若该章节内容缺失或少于 10 个字符,脚本会直接报错退出(见 bump-changelog.js)。也就是说,空 changelog 是不允许被发布的,这正是"先记录、后发布"流程在代码层面的强制保障。
二、核心命令:npm run release -- $VERSION
一切准备就绪后,只需一条命令即可触发整个发布流水线:
npm run release -- $VERSION其中$VERSION为目标版本号。该命令在 package.json 中定义为node scripts/release/release.js,即实际执行 scripts/release/release.js。
根据官方文档与脚本逻辑,这一条命令依次完成了:lint 代码检查、package.json 与 changelog 中的版本号 bump、创建新版本的 git commit 与 tag,以及推送 tag 到 GitHub。推送 tag 会触发 GitHub Actions 工作流,为所有平台构建安装包并生成一个发布草稿(release draft),草稿的 release notes 会从 changelog 自动提取。
[!WARNING] 该命令中的版本号参数将被直接写入 git tag 与各类清单,格式错误会中断发布,务必传入合法的语义化版本号(详见下一节)。
三、发布脚本的源码级拆解
scripts/release/release.js 是发布流程的指挥中枢,其执行顺序可以划分为"前置校验 → 质量检查 → 版本更新 → Git 操作"四个阶段,下面逐阶段展开。
3.1 前置校验:版本、工作区与分支
脚本进入正式流程前会做四道严格检查:
- 版本号非空:
npm run release后未携带$VERSION会报错并提示用法Usage: npm run release -- <version>(L36-L40); - 版本号格式合法:必须匹配正则
/^\d+\.\d+\.\d+(-[\w.-]+)?$/,即主.次.修订三段式,可选带预发布后缀(如1.2.0-beta.1)(L41-L44); - 版本号必须递增:若与 package.json 中当前版本(仓库现状为
1.1.0)相同,会提示"请重置到干净状态以应对可能被中断的发布,并确保递增版本号"(L46-L50); - 工作区干净:
git status -u --porcelain有任何输出都会中断,防止未提交的改动混入发布提交(L53-L56)。
此外,脚本还会检查当前分支必须是master(L59-L62),确保发布只发生在主分支上。
3.2 质量检查与 CLI 文档同步
校验通过后首先执行npm run lint,这是仓库定义的一整套串行质量门禁(package.json 中为npm-run-all --continue-on-error --serial lint-*),依次包含:
lint-cspell:基于 cspell 的拼写检查;lint-tsc:通过tsc --noEmit --project jsconfig.json做 TypeScript 类型检查(JS Paint 以 JSDoc 类型标注方式使用 TS 能力);lint-eslint:ESLint 代码规范检查。
随后脚本加载 scripts/update-cli-docs.js,它通过执行npx jspaint --help获取最新命令行帮助输出,并回写到 CLI.md 的HELP_OUTPUT代码块中,保证 CLI 文档与当前版本命令输出保持同步。
3.3 版本号 bump 与四处清单更新
接下来是本次发布的核心改动集合,脚本按固定顺序执行五个子步骤,全部通过process.env.VERSION向子脚本传递目标版本号:
①npm version ${version} --no-git-tag-version
不带--git-tag-version,即只更新 package.json 的version字段、不自动打 git tag(tag 由主脚本统一控制)。这是后续所有子脚本的前置条件——它们都会校验process.env.VERSION与 package.json 中的版本一致,不一致即报错退出(例如 update-dl-links.js)。
② 更新 CHANGELOG(bump-changelog.js)
该脚本将## [Unreleased]替换为新的## [版本号] - 日期(日期取自DATE环境变量,缺省为当天),并插入一段空的## [Unreleased]供下一轮迭代使用;同时更新文件底部的版本对比链接,例如把[Unreleased]: .../compare/v1.0.0...HEAD改写为指向新版本的对比链接。脚本还会拦截"该版本已在 changelog 中发布过"的重复发布场景。
③ 更新下载链接(update-dl-links.js)
遍历 README.md、index.html、about.html 三个文件,把其中形如https://github.com/1j01/jspaint/releases/download/...的下载 URL 里的版本号统一替换为新版本,同时更新清单文件中的softwareVersion字段。脚本末尾还会用 fast-glob 扫描全仓库,对列表之外仍残留旧下载链接的文件给出警告,防止漏改。
④ 更新 MSIX 清单(update-msix-package-version.js)
Windows 应用商店使用的 Package.appxmanifest 要求四段式版本号,且最后一段保留给商店使用、必须为0,因此脚本写入msixVersion = version + ".0",并替换<Identity ... Version="...">属性。
⑤ 更新 About Paint 对话框版本号(update-about-paint-version.js)
替换 index.html 中<div id="jspaint-version">元素内的文本为Version ${version},使网页版与 Electron 桌面版的应用内"关于"窗口都显示最新版本号。
3.4 Git 提交、打标签与推送
所有文件改动落盘后,脚本依次执行(L96-L103):
git add . git commit -m "Release ${version}" git tag v${version} git push origin tag v${version}代码注释解释了这一设计意图:在进入耗时的构建过程之前先把改动全部提交,避免构建期间有人忍不住继续编辑文件。注意这里只推送了 tag,没有推送分支提交——git push被刻意延后(源码中有// run("git push"); // deferred so the release can be tested first),原因后文说明。
推送 tag 将触发 GitHub Actions 工作流:为所有平台构建桌面应用并创建发布草稿。草稿的 release notes 来自 changelog,配合脚本 extract-changelog.js 以 GitHub Actions 多行输出格式(changelog<<EndOfStringDelimiter)提取首个版本章节正文,并校验 changelog 版本与 package.json 版本一致,确保 notes 与本次发布严格对应。
四、安装实测与"不可回头"警告
脚本完成 push tag 后会在终端输出指引:从 GitHub 的 release draft 下载并安装各平台安装包,测试已安装的桌面应用。JS Paint 桌面端基于 Electron Forge 构建(forge.config.js),产物覆盖 Windows(Squirrel/MSIX)、Linux(deb/rpm/AppImage)与 macOS 等格式。
这一步对应 release-process.md 中醒目的警告块:
[!WARNING] "Point of no return"(不可回头点)
含义是:tag 一旦推送到远程,该版本号就已公开并不可撤销。即便后续发现安装包有问题,也无法"收回"这个 tag,只能通过发布新版本修正。因此推送 tag 之前的工作区检查、lint 与 changelog 校验,本质上都是在为这个不可逆动作兜底。
五、最终发布:两条收尾命令
桌面应用实测通过后,按文档完成最后两步(release-process.md):
git push:把Release ${version}提交推送到远程分支——这一步被脚本刻意延后,正是为了留出"先测试、再公开提交"的时间窗口;- 在 GitHub 上点击 Publish,将 release draft 转为正式发布。
至此,一次完整的 JS Paint 版本发布闭环完成:维护 Unreleased → npm run release -- $VERSION → 下载实测 → git push + 发布 release。
六、发布清单速查
| 阶段 | 动作 | 依据文件 |
|---|---|---|
| 准备 | 提交历史与 Unreleased 章节核对 | CHANGELOG.md |
| 触发 | npm run release -- $VERSION | scripts/release/release.js |
| 门禁 | lint(cspell/tsc/eslint)+ CLI 文档同步 | package.json、scripts/update-cli-docs.js |
| 版本更新 | package.json、CHANGELOG、下载链接、MSIX 清单、About 版本号 | scripts/release 下各子脚本 |
| Git | commitRelease ${version}、tagv${version}、仅推送 tag | scripts/release/release.js |
| 自动构建 | GitHub Actions 触发,生成 release draft 与 notes | scripts/release/extract-changelog.js |
| 测试 | 从 release draft 安装并实测桌面应用 | forge.config.js |
| 收尾 | git push并发布 GitHub release | release-process.md |
结语
JS Paint 的发布流程设计得相当"自动化但可中断":npm run release把校验、版本同步、提交与 tag 推送压缩成一条命令,却通过"仅推送 tag、延后 push 分支"和 release draft 机制为人工测试保留了充分的安全阀。理解 scripts/release/release.js 及其子脚本的执行顺序,你不仅能顺利完成版本发布,还能在需要定制(如支持预发布版本、接入更多安装包格式)时快速定位改动点。
- 前端
- 桌面应用
- 图像处理
【免费下载链接】jspaint
🎨 Classic MS Paint, REVIVED + ✨Extras
相关推荐
Nhost CLI npm 发布全流程指南:从 GitHub Release 到 npm 可信发布(OIDC)的工程化实践
Nhost CLI npm 发布全流程指南:从 GitHub Release 到 npm 可信发布(OIDC)的工程化实践 本篇指南面向 Nhost CLI 的
后端认证鉴权数据库无服务开发工具云原生KPConv部署实战:将训练好的点云模型集成到实际应用中
KPConv部署实战:将训练好的点云模型集成到实际应用中 你是否已经成功训练了KPConv点云深度学习模型,却不知道如何将其部署到实际应用中?本文将为你提供完整
人工智能深度学习计算机视觉jsPDF 版本发布全流程指南:从 GitHub Release 到 npm 自动发布的标准化操作手册
jsPDF 版本发布全流程指南:从 GitHub Release 到 npm 自动发布的标准化操作手册 本文以 jsPDF 官方仓库的 RELEASE.md h
后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考