# 发布流程 本仓库的持续构建与发布由两个自包含的 workflow 承担,不依赖任何第三方 action。 | 文件 | 职责 | |---|---| | `.github/workflows/ci.yml` | 每次 push / PR:契约检查 + 构建一次发布包并留 artifact | | `.github/workflows/release.yml` | 打 tag 或被手动触发时:构建并上传 Release 资产 | 两者都先跑 `scripts/verify-bundle.mjs`。它检查的是「装得上但什么都不加载」这类缺陷:`dsh.bundle.patch` 指向不存在的文件、`exports` 目标被改名、`files` 里的条目不存在、入口文件语法错误。这些缺陷在安装那一刻之前都是隐形的,所以门禁放在构建之前。 ## 正式发布 **面板上按一次「一键发布」就是这三步**(发布同台,见 README):它提交并推送代码、在版本已被别的提交占用时自己升一个补丁号、触发 `release.yml` 取草稿、等这次运行成功、推 npm、公开 Release、再补 B 站播报。下面是同一件事的手工路径——没有面板、或故意要自己掌控每一步时用它。 ```bash # 1. 改 package.json 的 version —— release 会拿 tag 与它核对 # 2. 提交并推送 git commit -am "chore: release v1.2.3" git push origin main # 3. 打 tag 并推送,这一步才触发发布 git tag v1.2.3 git push origin v1.2.3 ``` tag 与 `package.json` 的 version 不一致时 workflow **直接失败**,不会发出版本漂移的包;tag 打错提交也一样会失败,而不是发一个内容不对的 Release。 > **同一个版本号不要重发**:`release.yml` 的第一步会核对 `v` 是否已经属于**另一个提交**,是则直接失败并要求升版本(理由:覆盖属于别的提交的 Release 会让 tag 与资产从此不一致,而且全程静默)。一键发布把这一步提前到了按下按钮之前(`releasePreflight`),所以它会在需要时自己升版本,而不是让你跑一次注定失败的工作流。 ## 手动触发 `Actions → Release → Run workflow`,默认勾选 draft。 - 它用 `package.json` 的 version 推出 tag `v`,你不需要先在本地打 tag。 - **默认发成草稿**:草稿对外不可见,确认无误后在 Release 页面点 `Publish release`。 - 同一个 tag 再跑一次会**替换资产**(`--clobber`),不会产生第二个 Release。 ## 资产内容 | 资产 | 用途 | |---|---| | `-.tgz` | **可安装的那份**:`dsh plugin add file:`,不用解压、不需要本地检出 | | `-.zip` | 整棵仓库树,给人看 / 审 / 做 diff | | `SHA256SUMS.txt` | 上面两个的校验和;用途是「确认你下载的没坏」,不是防篡改 | `.tgz` 由 `npm pack` 生成,**只带 `package.json` 的 `files` 白名单**;CI 与发布流程都会解包它并跑一次契约检查,所以"白名单漏了一个被 import 的文件"会在推送时就失败,而不是等到别人装上才发现。 - 用 `git archive` 打包**该提交的完整仓库树**,所以 `node_modules/`、`.git/`、编辑器与运行期本机状态天然不在里面——不需要手写排除规则,也不可能混入本机专有文件。 - 解压后是 `-/` 目录,内容就是一个标准 DSH bundle 包(`package.json` + `cordis.patch.yml` + 入口文件)。本机 profile 用 `link:` 指向本地检出目录安装,解压出来的目录同理。 - `SHA256SUMS.txt` 的用途是校验**下载到的那一份没坏**。 ### 关于「可复现」 内容是确定的:同一个 tag 永远打出同一棵树。但 **zip 字节不保证跨机一致**——容器里会写入打包工具的 deflate 实现信息,实测本机预演与 CI 产物的 zip 同尺寸、sha256 不同。所以不要把两台机器构建出的 sha256 拿来互相比对,也不要用它做「构建是否被篡改」的判据。 ## 本地预演 CI 上跑的就是这几条命令,本地可以原样复现: ```bash node scripts/verify-bundle.mjs # 全套离线检查(含 发布同台 的流水线:顺序、拒绝、Host 重启后续跑) node tests/host-checks.mjs && node tests/pipeline-check.mjs && node tests/mount-check.mjs \ && node tests/bump-e2e.mjs && node tests/client-render.mjs && node tests/bilibili-check.mjs mkdir -p dist NAME=$(node -p 'require("./package.json").name'); VERSION=$(node -p 'require("./package.json").version') git archive --format=zip --prefix="$NAME-$VERSION/" -o "dist/$NAME-$VERSION.zip" HEAD # 解压后再验一次:证明的是「发布出去的那份资产」完整,而不是检出目录完整 ```