diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9ea8253 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,55 @@ +name: CI + +# 每次 push 到主分支、以及任何 PR 包括来自 fork 的 PR 都自动跑完整检查。 +# 本插件是纯 JS(无 TypeScript 源码、无构建步骤),lib/*.js 即发布产物。 +# 因此 CI 检查 = 语法检查 + 产物齐全校验,全绿才允许合并。 +on: + push: + branches: + - master + - main + pull_request: + # fork PR 也可触发;此工作流不读写仓库 secrets,fork 环境下安全。 + branches: + - master + - main + +# 同一分支/PR 上排队的新提交会取消正在跑的旧任务,避免资源浪费。 +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +jobs: + check: + name: 语法检查 · 产物校验 + runs-on: ubuntu-latest + strategy: + matrix: + # 本地与线上主推的运行时;插件零依赖,两个版本都验证一次。 + node: + - 22 + - 26 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node }} + + # 纯 JS 插件无需 npm install,直接对两个产物源做 ESM 语法校验。 + - name: 语法检查 lib/*.js + run: | + node --check lib/index.js + node --check lib/client.js + echo "lib/index.js 与 lib/client.js 语法均通过" + + # 出厂文件齐全性校验,缺失会在此失败,让 PR 作者一眼看到问题。 + - name: 产物齐全性校验 + run: | + test -f lib/index.js + test -f lib/client.js + test -f cordis.patch.yml + test -f package.json + echo "发布产物齐全:lib/index.js · lib/client.js · cordis.patch.yml · package.json" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..c7c6328 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,102 @@ +name: Release + +# 推送形如 vX.Y.Z(如 v0.1.0)的 tag 时自动发版: +# 凭 tag 号更新 package.json 版本并提交回 main → 语法/产物校验 +# → 发布 npm → 生成 GitHub Release draft。人只需打一个 tag,其余自动衔接。 +# 注意:npm 发布依赖 npmjs 侧开启的 Trusted Publishing +# (npmjs.com → 本包 → Enable trusted publishing → 绑本仓库 GitHub Actions), +# 无需配置 NPM_TOKEN;未开启时发布步骤会失败。 +on: + push: + tags: + - 'v*' + +concurrency: + group: release-${{ github.ref }} + cancel-in-progress: false + +jobs: + release: + name: Publish ${{ github.ref_name }} to npm + runs-on: ubuntu-latest + # id-token: write 供 Trusted Publishing 换取 npm 临时凭证,无需 NPM_TOKEN。 + # 必须放在 job 级,GitHub 才会向该 job 注入 ACTIONS_ID_TOKEN_REQUEST_*。 + permissions: + contents: write + id-token: write + # fork 永不触发 tag 发布,仅作为兜底防护。 + if: startsWith(github.ref, 'refs/tags/v') + # 绑定 GitHub Actions environment「release」,使 OIDC subject 稳定为 + # environment:release,npm 侧 Trusted Publisher 需填相同 Environment 名。 + environment: release + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + # 回写 main 需要完整历史,故拉全量。 + fetch-depth: 0 + # 默认 GITHUB_TOKEN 在分支保护下会被拒,此处显式传 token。 + token: ${{ secrets.GITHUB_TOKEN }} + + # 版本号仅凭 tag 号决定,写入 package.json 并提交回 main。 + - name: Sync version to main + run: | + set -euo pipefail + TAG="${GITHUB_REF_NAME#v}" # 去 v 前缀得版本号,如 0.1.0 + echo "target version = $TAG" + + # 切到 main 分支再改版本,避免在 detached tag 上提交。 + git checkout main + git config user.name github-actions[bot] + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + + # 用临时文件改写 version 字段,保留其余内容不变。 + node -e " + const fs = require('fs'); + const p = require('./package.json'); + p.version = process.argv[1]; + fs.writeFileSync('./package.json', JSON.stringify(p, null, 2) + '\n'); + " "$TAG" + + # 已是最新版本则无改动,跳过提交;否则提交并推回 main。 + git diff --quiet package.json || { + git add package.json + git commit -m "chore: release $TAG 同步 package.json 版本 [skip ci]" + git push origin main + } + + - name: Setup Node + uses: actions/setup-node@v4 + with: + # registry-url 告知 npm 向哪个 registry 换 Trusted Publishing 临时凭证。 + node-version: 24 + cache: npm + registry-url: https://registry.npmjs.org + + # 纯 JS 零依赖插件,无需 npm install;直接对两个产物源做 ESM 语法校验。 + - name: 语法校验 lib/*.js + run: | + node --check lib/index.js + node --check lib/client.js + echo "lib/index.js 与 lib/client.js 语法均通过" + + - name: 产物齐全性校验 + run: | + test -f lib/index.js + test -f lib/client.js + test -f cordis.patch.yml + test -f package.json + echo "发布产物齐全" + + # Trusted Publishing:npm 凭 workflow 的 OIDC 身份直接授权, + # 无需 NPM_TOKEN;--provenance 会在 npm 上附构建来源证明。 + # node-version 24 保证捆绑 npm>=11.5.1,npm CLI 才能做 OIDC 自动换权发布。 + - name: Publish to npm + run: npm publish --provenance --access public + + - name: Create GitHub Release draft + uses: softprops/action-gh-release@v2 + with: + draft: true + tag_name: ${{ github.ref_name }} + generate_release_notes: true diff --git a/README.md b/README.md index c0af1a2..4ef474d 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,6 @@ dsh plugin --profile web remove dsh-edit-diff - **UI 挂载点**:接管 keyed 槽位 `tool.call.toolview` 的 `edit` 与 `write` 两个 key。 - **遮蔽而非冲突**:注册时显式传 `priority: -1`(低于内置 `file-mutation-toolview` 的默认 0),用更低优先级遮蔽默认渲染,而不是在同一优先级上 clash。 - **无构建**:`lib/client.js` 是按 DSH client bundle 产出的注册式模块,源码即产物,改完即用。 -- **硬性约束**:`lib/client.js` 的 `factory` 必须以 `return module.exports` 结尾,否则模块导出为 `undefined`,DSH 启动即 fail-loud。 - 纯 JavaScript 单文件,不引入任何额外 npm 依赖(diff 算法就地内联)。 ## License diff --git a/package.json b/package.json index 351fb0a..68945de 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,11 @@ { "name": "dsh-edit-diff", "version": "0.1.0", - "description": "质量 diff 展示:接管 edit/write 工具卡片,用近线性行级 diff + 行内字符高亮,消除相同内容在删除/新增两区的重复(标准可安装 dsh 客户端插件)", + "description": "质量 diff:接管 edit/write 工具卡片,行级去重与行内高亮,消除相同内容在删除与新增两区的重复,标准可安装的 dsh 客户端插件", + "repository": { + "type": "git", + "url": "git+https://github.com/better-er/dsh-edit-diff.git" + }, "type": "module", "main": "lib/index.js", "exports": {