dsh-plugin-cicd
把 DSH 插件仓库的持续构建与发布搬进应用:侧边栏面板逐仓库显示最近一次工作流运行、已发布与草稿 Release,以及本地检出相对上次发布的领先与未提交情况,并提供触发构建、发布、公开草稿、重跑、取消、查失败日志等按钮。通过本机已登录的 gh CLI 驱动工作流,插件自身不保存任何凭据,被监视的仓库列表放在配置文件里、不打进包。
安装
dsh plugin --profile web add dsh-plugin-cicd
沙箱测试结果
| 阶段 | 结果 |
|---|---|
| 1 安装 | ✓ |
| 2 列装 | ✓ |
| 3 挂载 | ✓ |
| 4 启动 | — |
四阶段在隔离沙箱里跑:安装(有网)→ 列装 → 挂载 → 启动(后三步断网)。
README
dsh-plugin-cicd(DSH 插件发布台)
把 DSH 插件的持续构建与发布(CI/CD)搬进 DeepSeek Harness:侧边栏一个图标,点开是一个占满主区域的独立面板。
名字:界面显示名为「DSH 插件发布台」(副标题「持续构建与发布(CI/CD)」;英文界面为DSH Plugin CI/CD)。包名与仓库 id 保持dsh-plugin-cicd—— 它们只是技术标识,改名会破坏已有安装(profile 的link:路径、bundles 条目、patch 里的 row id、配置文件路径)。
它回答四个 GitHub 页面各自只说了一部分的问题:
- 构建过了吗 —— 每个仓库最近一次运行的状态、耗时、触发事件。
- 发布了吗 —— 已发布的 Release、还在草稿箱里的 Release、资产清单。
- 本地领先于发布吗 —— 本地
package.json版本、领先/落后提交数、未提交文件数。 - 装的是发布出去的那份吗 —— 本机 profile 里这份是
link:的本地检出、还是 Release 上的 tgz;差几号版本。 - npm 上是哪一版 —— 这个版本在不在公开源上;不在的话,一次点击就能推上去。
也就是说:一个包,两条分发渠道。GitHub Release 给人下载与审阅,npm 让 dsh plugin add <名字> 一条命令装完。
面板上能直接做的动作,行上的顺序就是工作的顺序:提交(git add -A + commit + push)、构建(触发 ci.yml)、发布(触发 release.yml,默认产出草稿)、升版本并发布、公开发布草稿、推送到 npm vX(+ 在面板里写 npm token)、装 Release vX / 更新到 vX、重跑、取消、看失败日志,以及更新之后的 立即重启 DSH。
提交 为什么排在最前面:构建 和 发布 都作用于 GitHub 上的那个提交——workflow 跑的是推送上去的 commit。所以只存在于工作区、或只存在于本机的改动,它们都看不见。面板一直在警告这件事(脏工作区那行、↑N 那个 chip),在这之前唯一的出路是开终端。它永远不是主按钮:它是步骤,不是目的。
提交 一个按钮两种含义,因为两者是同一个陷阱的两半:有改动 → 提交并推送;工作区干净但领先上游 → 只推送(按钮此时显示推送);两者皆无 → 按钮禁用并写明原因。git add -A 是刻意的(发布也需要新增文件),所以确认框会把待提交的文件名列出来——"7 个改动"可能是你要的 3 个加上你没见过的 4 个。提交信息为空时确认按钮保持禁用。
安装
本机 profile 用 link: 指向检出目录,和其它插件一致:
dsh plugin --profile desktop add "link:F:\CodeProj\dsh-plugin-cicd"
装完需要重启 DSH 才会被组合进运行时(宿主半边与浏览器半边都要)。
零代码操作(给不写程序的人)
面板的目标是只用鼠标就能完成日常使用。凡是下表打了勾的,都不需要打开终端:
要做的事 · 怎么做 · 需要命令行吗
登录 GitHub · 面板顶部的「用浏览器登录 GitHub」→ 打开授权页 → 输入面板显示的一次性代码 · 不需要(Host 替你跑 gh auth login --web,把码显示出来)
补齐权限 · 同一处的「补齐权限」,走同样的浏览器流程 · 不需要
添加仓库 · 「管理仓库」→ 从你的仓库列表勾选(本地检出自动匹配) · 不需要
移除仓库 · 取消勾选 · 不需要
触发构建 · 仓库那一行的「构建」 · 不需要
发布(一键:代码推送 + Release + npm) · 仓库那一行的「一键发布」→ 确认框(脏工作区就填提交信息,2FA 就填一次性密码)→「确认发布」 · 不需要(Host 起一条流水线,跟着 CI 走完:升版本、推 npm、公开 Release、B 站播报都由它自己接着做)
只出草稿(不要一键) · 配置里关掉 oneClickRelease,「发布」回到只触发构建 · 不需要
公开草稿(手动路径) · 展开行 →「公开草稿」→「确认公开?」(两次点击) · 不需要
给 npm 一个 token · 面板顶部(未登录时才出现)粘贴 Access Token →「写入并验证」 · 不需要(Host 写进 npm 自己读的 ~/.npmrc,插件不保存 token)
单独推送到 npm(手动路径) · 展开行 →「推送到 npm vX」→「确认推送」(两次点击;开了 2FA 就在同一行填一次性密码) · 不需要(Host 用 DSH 自带的 pnpm 发布,复用同一个包管理器)
更新已装的那份 · 行上的「更新到 vX」(只有 profile 装的是更旧的发布包时才有;link: 检出与"装它会降级"两种情况的按钮在展开处)→ 展开处「确认更新」 · 不需要(Host 把 tgz 交给 DSH 自己的插件管理器安装)
让新版生效 · 更新后面板直接问「现在重启?」→「立即重启 DSH」 · 不需要(转发给 dsh-plugin-restart;没装它会明确说)
看失败日志 / 重跑 / 取消 · 展开行里的对应按钮 · 不需要
账号、权限、仓库清单 · 设置 → 插件 → DSH 插件发布台 → GitHub · 不需要
仍然需要命令行的两件事,如实列出,不假装不需要:
1. 安装这个插件本身(一次性)——见下一节。
2. 打 tag(只有想走 tag 触发那条路时)——版本号由【一键发布】自己升(版本已被别的提交占用时),但 git tag vX && git push origin vX 仍是发布之外的动作,面板不做。
「更新」装完要重启才生效,这一步面板会主动问(见下文《更新已安装的插件》);重启由 dsh-plugin-restart 执行,发布台自己不碰进程。
「更新」装完要重启才生效,这一步面板会主动问(见下文《更新已安装的插件》);重启由 dsh-plugin-restart 执行,发布台自己不碰进程。
连 gh 都没装时,面板给下载页链接;而安装 gh 这一步在 Windows 上目前仍需一次终端(或用安装包)。
别人怎么装(下载即用)
Release 里有两个资产,回答两个不同的问题:
资产 · 用途
dsh-plugin-cicd-<version>.tgz · 可安装的那份:一条命令装,不用解压、不需要本地检出
dsh-plugin-cicd-<version>.zip · 整棵仓库树,给人看/审/做 diff
SHA256SUMS.txt · 上面两个的校验和(用途是"确认你下载的没坏",不是防篡改——见 [RELEASING.md](RELEASING.md))
# 1. 下载 tgz(或从 Release 页面直接下) gh release download v0.1.0 -R SOH4C4759/dsh-plugin-cicd -p '*.tgz' # 2. 装进你的 profile(把 desktop 换成你自己的) dsh plugin --profile desktop add "file:$PWD\dsh-plugin-cicd-0.1.0.tgz" # 3. 重启 DSH,侧边栏出现「发布台」图标
file: 指向本地的 tgz,pnpm 会解包进 profile 的 node_modules。这条路径已经在发布资产上实测过:解包后 scripts/verify-bundle.mjs 与 tests/host-checks.mjs 都能跑通,cordis.patch.yml 与 scripts/configure.mjs 都在包里(npm pack 只带 files 白名单,CI 每次都验这两点)。
更新已安装的插件(把上一条从终端搬进面板)
上面那三行命令,现在就是面板上一个按钮:「装 Release vX」/「更新到 vX」。它做的正是那三行的前两步,第三步(重启)由面板接着问。
每一行都会先回答"这个 profile 里现在装的是什么",因为版本号相等不代表同一份代码:
profile 里的依赖 · 面板的判断 · 行上有没有按钮
link:F:\...(本地检出) · 本地检出 —— 跑的不是发布出去的那份,即使版本号与 Release 完全相同 · 没有。展开处有次要按钮【装 Release vX】(+ 说明会替换掉什么),因为这台机器是开发这份插件的地方,行上的按钮只会把正在改的代码换成 tgz
file:...\x-1.2.0.tgz,装的是 1.2.0,Release 是 1.3.0 · 可更新 —— 行上出现「可更新 v1.3.0」标记 · 有,【更新到 v1.3.0】——这是行上唯一会被摆出来的安装动作
装的是 2.0.0,Release 是 1.3.0 · 面板明说装它会往回退,不假装是"更新" · 没有(等于把降级当日常维护)。展开处仍可点,但只是次要按钮
为什么把行让出来:面板的行是"你现在要做的事"。对插件作者自己来说,link: 是常态,装 Release 不是要做的事,而是取消掉让开发能进行的那套设置;而 ahead(profile 里更新)那种情况,行上摆按钮等于把降级摆在最显眼的位置。这个能力保留在展开处——"发布出去的那份到底装不装得起来"仍然要能在这里回答——只是不再叫卖。
装的是 1.2.0-rc.1 · 两边无法比较,如实说不能比较,而不是猜一个先后
版本相同、且就是 Release 的 tgz · 已是最新,没有按钮
不在这个 profile 的依赖里 · 未安装 —— 没有"已装的那份"可以更新,并写出找的是哪个 profile
还没有已发布的 Release(草稿不算) · 没有可装的
装的时候:
1. gh release download <tag> -p <tgz> 把资产下到插件自己的目录 <DSH_HOME>\dsh-plugin-cicd\downloads\(不是临时目录——profile 的依赖会指向这个路径,下完就删会让清单再也装不上)。
2. 交给 DSH 自己的插件管理器(ctx.get('pluginManager').installBundle),也就是 dsh plugin add 走的同一条 pnpm 路径:它持有 profile 锁,失败时把 package.json / pnpm-lock.yaml 还原。发布台不自己起一个 dsh plugin 子进程——那会是对同一个 profile 的第二个写入者。
3. 面板接着问要不要重启(不假设答案)。重启转发给 dsh-plugin-restart;没装这个插件时回一句明确的「没挂载」,而不是一个看不出所以然的失败。
一次只跑一个更新(再来一个回 409 busy),因为插件管理器本来就会排队,而两个转圈比一个明确的拒绝更难懂。
没有装它就没有这部份:update 路由需要 Host 提供 pluginManager 服务,没有就回 501 plugin-manager-missing,而不是假装装过。
发布同台:一次点击 = 代码推送 + Release + npm
按下「发布」就是三件事一起做完,因为分开做留下了三种"看起来成功"的半成品:没人公开的草稿、npm 上有版本而 GitHub 上没有 Release、Release 构建的是一个 GitHub 根本没收到过的提交(工作区里的改动、或只提交在本机的改动,两个 workflow 都看不见)。
顺序不是实现细节,是这个功能的全部:
代码推送 → 版本号 → 触发构建 → 等待构建 → npm 推送 → 公开 Release → B 站播报
- 代码推送最前,因为
ci.yml与release.yml跑的都是推上去的那个提交。有改动就git add -A+ commit + push(需要一条提交信息,确认框里填;确认框把改动文件名列出来,因为这是面板上唯一能扫进你没打算发布的东西的动作)。工作区干净但有本地提交就只 push,两者都没有就跳过这一格。 - 版本号第二,因为它要写一个提交,而升版本拒绝脏工作区——顺序反过来没有意义。这一格做的是「为什么点发布曾经必然失败」那件事:
release.yml拒绝复用属于另一个提交的版本,所以流水线先问(releasePreflight),真被占用就自己升一个补丁号、提交、推送。 - 触发构建明确要草稿(
-f draft=true)。草稿只有作者看得见,这正是后面两格能成立的原因。 - **
…(truncated)
以上内容来自 npm 上的 README,我们只做格式化,不改内容。
版本
npm 上共发布:5,最后更新 2026-10-18