☰
JS Paint 发布流程全解析:从 `npm run release` 到 GitHub Release 的一站式发布指南
2026/9/27 7:53:47 网站建设 项目流程
  • 前端
  • 桌面应用
  • 图像处理

【免费下载链接】jspaint

🎨 Classic MS Paint, REVIVED + ✨Extras

项目地址:https://gitcode.com/gh_mirrors/js/jspaint
点击查看免费下载

导读

本文以 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 前置校验:版本、工作区与分支

脚本进入正式流程前会做四道严格检查:

  1. 版本号非空:npm run release后未携带$VERSION会报错并提示用法Usage: npm run release -- <version>(L36-L40);
  2. 版本号格式合法:必须匹配正则/^\d+\.\d+\.\d+(-[\w.-]+)?$/,即主.次.修订三段式,可选带预发布后缀(如1.2.0-beta.1)(L41-L44);
  3. 版本号必须递增:若与 package.json 中当前版本(仓库现状为1.1.0)相同,会提示"请重置到干净状态以应对可能被中断的发布,并确保递增版本号"(L46-L50);
  4. 工作区干净: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):

  1. git push:把Release ${version}提交推送到远程分支——这一步被脚本刻意延后,正是为了留出"先测试、再公开提交"的时间窗口;
  2. 在 GitHub 上点击 Publish,将 release draft 转为正式发布。

至此,一次完整的 JS Paint 版本发布闭环完成:维护 Unreleased → npm run release -- $VERSION → 下载实测 → git push + 发布 release。

六、发布清单速查

阶段动作依据文件
准备提交历史与 Unreleased 章节核对CHANGELOG.md
触发npm run release -- $VERSIONscripts/release/release.js
门禁lint(cspell/tsc/eslint)+ CLI 文档同步package.json、scripts/update-cli-docs.js
版本更新package.json、CHANGELOG、下载链接、MSIX 清单、About 版本号scripts/release 下各子脚本
GitcommitRelease ${version}、tagv${version}、仅推送 tagscripts/release/release.js
自动构建GitHub Actions 触发,生成 release draft 与 notesscripts/release/extract-changelog.js
测试从 release draft 安装并实测桌面应用forge.config.js
收尾git push并发布 GitHub releaserelease-process.md

结语

JS Paint 的发布流程设计得相当"自动化但可中断":npm run release把校验、版本同步、提交与 tag 推送压缩成一条命令,却通过"仅推送 tag、延后 push 分支"和 release draft 机制为人工测试保留了充分的安全阀。理解 scripts/release/release.js 及其子脚本的执行顺序,你不仅能顺利完成版本发布,还能在需要定制(如支持预发布版本、接入更多安装包格式)时快速定位改动点。

  • 前端
  • 桌面应用
  • 图像处理

【免费下载链接】jspaint

🎨 Classic MS Paint, REVIVED + ✨Extras

项目地址:https://gitcode.com/gh_mirrors/js/jspaint
点击查看免费下载

相关推荐

上一篇:从卡顿到丝滑:Umi.js 4页面重渲染问题深度优化指南
下一篇:终极指南:7款高性能DotNet HTTP客户端库全解析

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询