From 225e8b045cd7c8ec95c6dad12228015c35e76733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=BE=B7=E6=A3=AE?= Date: Wed, 21 Oct 2026 00:23:47 +0800 Subject: [PATCH 1/4] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20Windows=20?= =?UTF-8?q?=E5=AE=89=E8=A3=85=E5=8C=85=E5=9B=BE=E6=A0=87=E5=B0=BA=E5=AF=B8?= =?UTF-8?q?=E8=B6=85=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/desktop/README.md | 2 +- apps/desktop/build/icon-win.png | Bin 0 -> 71307 bytes apps/desktop/electrobun.config.ts | 2 +- apps/desktop/scripts/desktop.ts | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 apps/desktop/build/icon-win.png diff --git a/apps/desktop/README.md b/apps/desktop/README.md index 6b0f34c..b34618e 100644 --- a/apps/desktop/README.md +++ b/apps/desktop/README.md @@ -60,7 +60,7 @@ Git 钩子由 monorepo 根目录的 [simple-git-hooks](https://github.com/toplen GitHub Actions 的版本 tag、跨平台构建、签名配置和 Release 草稿验收见[发布流程](../../docs/发布流程.md)。 -应用图标的 1024 × 1024 完整画布主图保存在 `build/tarp-icon-source.png`,不含圆角裁切;`build/icon.png` 供 Windows、Linux 窗口与打包使用。macOS 使用已定稿的 `build/icon-mac.png`:1024 × 1024 透明画布,832 × 832 底板,四边各留白 96 像素。素材已包含圆角与透明留白,直接使用,不再缩放或补边。`build.mac.icons` 指向生成的 `out/icon.iconset`,配置与转换逻辑分别位于 `electrobun.config.ts` 和 `scripts/desktop.ts`。 +应用图标的 1024 × 1024 完整画布主图保存在 `build/tarp-icon-source.png`,不含圆角裁切;`build/icon.png` 供 Linux 窗口与打包使用。Windows 使用由它缩小得到的 `build/icon-win.png`(256 × 256);Hutch 的 Windows 打包器只接受边长不超过 256 像素的正方形 PNG。更新 `build/icon.png` 时同步生成 Windows 图标。macOS 使用已定稿的 `build/icon-mac.png`:1024 × 1024 透明画布,832 × 832 底板,四边各留白 96 像素。素材已包含圆角与透明留白,直接使用,不再缩放或补边。`build.mac.icons` 指向生成的 `out/icon.iconset`,配置与转换逻辑分别位于 `electrobun.config.ts` 和 `scripts/desktop.ts`。 更新 macOS 图标时直接替换 `build/icon-mac.png`,保留定稿文件自身的圆角和透明留白。开发环境重启应用后生效,发布包需要重新打包。界面中的横版 TARP 字标继续使用原 SVG。 diff --git a/apps/desktop/build/icon-win.png b/apps/desktop/build/icon-win.png new file mode 100644 index 0000000000000000000000000000000000000000..02f399899fa5788082b79b55def853b36c960778 GIT binary patch literal 71307 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 pN8yj@3eRo*SM Date: Wed, 21 Oct 2026 00:27:47 +0800 Subject: [PATCH 2/4] =?UTF-8?q?ci:=20=E5=9C=A8=20PR=20=E9=AA=8C=E6=94=B6?= =?UTF-8?q?=E8=B7=A8=E5=B9=B3=E5=8F=B0=E5=AE=89=E8=A3=85=E5=8C=85=E5=B9=B6?= =?UTF-8?q?=E5=8F=96=E6=B6=88=E5=88=86=E6=94=AF=20push=20=E6=A3=80?= =?UTF-8?q?=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build-desktop.yml | 108 ++++++++++++++++++ .github/workflows/ci.yml | 8 +- .github/workflows/release-desktop.yml | 83 +------------- ...21\345\270\203\346\265\201\347\250\213.md" | 14 +-- 4 files changed, 125 insertions(+), 88 deletions(-) create mode 100644 .github/workflows/build-desktop.yml diff --git a/.github/workflows/build-desktop.yml b/.github/workflows/build-desktop.yml new file mode 100644 index 0000000..8742d10 --- /dev/null +++ b/.github/workflows/build-desktop.yml @@ -0,0 +1,108 @@ +name: 桌面安装包构建与验收 + +on: + workflow_call: + inputs: + sign: + description: 使用传入的签名凭据,仅发布流程开启 + type: boolean + default: false + secrets: + MAC_CSC_LINK: + required: false + MAC_CSC_KEY_PASSWORD: + required: false + MAC_DEVELOPER_ID: + required: false + APPLE_ID: + required: false + APPLE_APP_SPECIFIC_PASSWORD: + required: false + APPLE_TEAM_ID: + required: false + +permissions: + contents: read + +jobs: + build: + name: 构建 ${{ matrix.platform }} ${{ matrix.arch }} + runs-on: ${{ matrix.os }} + timeout-minutes: 40 + strategy: + fail-fast: false + matrix: + include: + - os: windows-2022 + platform: win + arch: x64 + - os: ubuntu-24.04 + platform: linux + arch: x64 + - os: macos-15 + platform: mac + arch: arm64 + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: ./.github/actions/setup + - name: 校验 tag 与桌面版本 + if: github.ref_type == 'tag' + run: | + bun run - <<'JS' + const { version } = require('./apps/desktop/package.json'); + if (process.env.GITHUB_REF_NAME !== `desktop-v${version}`) { + throw new Error(`tag 必须为 desktop-v${version}`); + } + JS + - name: 导入 macOS 签名证书 + if: inputs.sign && runner.os == 'macOS' + env: + MAC_CSC_LINK: ${{ secrets.MAC_CSC_LINK }} + MAC_CSC_KEY_PASSWORD: ${{ secrets.MAC_CSC_KEY_PASSWORD }} + run: | + if [[ -z "$MAC_CSC_LINK" ]]; then exit 0; fi + python3 - <<'PYTHON' + import base64, os, pathlib, urllib.request + value = os.environ['MAC_CSC_LINK'] + data = urllib.request.urlopen(value).read() if value.startswith('https://') else base64.b64decode(value) + pathlib.Path(os.environ['RUNNER_TEMP'], 'tarp-signing.p12').write_bytes(data) + PYTHON + TARP_KEYCHAIN_PASSWORD=$(openssl rand -hex 24) + TARP_KEYCHAIN="$RUNNER_TEMP/tarp-signing.keychain-db" + security create-keychain -p "$TARP_KEYCHAIN_PASSWORD" "$TARP_KEYCHAIN" + security set-keychain-settings -lut 21600 "$TARP_KEYCHAIN" + security unlock-keychain -p "$TARP_KEYCHAIN_PASSWORD" "$TARP_KEYCHAIN" + security import "$RUNNER_TEMP/tarp-signing.p12" -k "$TARP_KEYCHAIN" -P "$MAC_CSC_KEY_PASSWORD" -T /usr/bin/codesign + security list-keychains -d user -s "$TARP_KEYCHAIN" login.keychain-db + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$TARP_KEYCHAIN_PASSWORD" "$TARP_KEYCHAIN" + - name: 构建安装包 + working-directory: apps/desktop + env: + TARP_CODESIGN: ${{ inputs.sign && secrets.MAC_DEVELOPER_ID != '' && matrix.platform == 'mac' && '1' || '0' }} + TARP_NOTARIZE: ${{ inputs.sign && secrets.MAC_DEVELOPER_ID != '' && secrets.APPLE_ID != '' && matrix.platform == 'mac' && '1' || '0' }} + ELECTROBUN_DEVELOPER_ID: ${{ matrix.platform == 'mac' && secrets.MAC_DEVELOPER_ID || '' }} + ELECTROBUN_APPLEID: ${{ matrix.platform == 'mac' && secrets.APPLE_ID || '' }} + ELECTROBUN_APPLEIDPASS: ${{ matrix.platform == 'mac' && secrets.APPLE_APP_SPECIFIC_PASSWORD || '' }} + ELECTROBUN_TEAMID: ${{ matrix.platform == 'mac' && secrets.APPLE_TEAM_ID || '' }} + run: bun run dist + - name: 验证打包后的 Bun、CLI、模组、Wasm 和 SQLite + run: bun scripts/release/smoke.ts desktop + - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: desktop-${{ matrix.platform }}-${{ matrix.arch }} + path: | + apps/desktop/release/*.exe + apps/desktop/release/*.tar.zst + apps/desktop/release/*.tar.gz + apps/desktop/release/*.json + apps/desktop/release/*.patch + apps/desktop/release/*.dmg + apps/desktop/release/*.zip + if-no-files-found: error + compression-level: 0 + retention-days: 14 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6fcf297..110e1af 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,8 +2,6 @@ name: 仓库检查 on: pull_request: - push: - branches: ["**"] workflow_dispatch: workflow_call: @@ -33,3 +31,9 @@ jobs: - run: bun run typecheck - run: bun run test - run: bun run build + + desktop: + name: 桌面分发验收 + if: github.event_name == 'pull_request' + needs: check + uses: ./.github/workflows/build-desktop.yml diff --git a/.github/workflows/release-desktop.yml b/.github/workflows/release-desktop.yml index f0f8287..133c968 100644 --- a/.github/workflows/release-desktop.yml +++ b/.github/workflows/release-desktop.yml @@ -16,86 +16,11 @@ jobs: uses: ./.github/workflows/ci.yml build: - name: 构建 ${{ matrix.platform }} ${{ matrix.arch }} needs: check - runs-on: ${{ matrix.os }} - timeout-minutes: 40 - strategy: - fail-fast: false - matrix: - include: - - os: windows-2022 - platform: win - arch: x64 - - os: ubuntu-24.04 - platform: linux - arch: x64 - - os: macos-15 - platform: mac - arch: arm64 - defaults: - run: - shell: bash - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - uses: ./.github/actions/setup - - name: 校验 tag 与桌面版本 - run: | - bun run - <<'JS' - const { version } = require('./apps/desktop/package.json'); - if (process.env.GITHUB_REF_NAME !== `desktop-v${version}`) { - throw new Error(`tag 必须为 desktop-v${version}`); - } - JS - - name: 导入 macOS 签名证书 - if: runner.os == 'macOS' - env: - MAC_CSC_LINK: ${{ secrets.MAC_CSC_LINK }} - MAC_CSC_KEY_PASSWORD: ${{ secrets.MAC_CSC_KEY_PASSWORD }} - run: | - if [[ -z "$MAC_CSC_LINK" ]]; then exit 0; fi - python3 - <<'PYTHON' - import base64, os, pathlib, urllib.request - value = os.environ['MAC_CSC_LINK'] - data = urllib.request.urlopen(value).read() if value.startswith('https://') else base64.b64decode(value) - pathlib.Path(os.environ['RUNNER_TEMP'], 'tarp-signing.p12').write_bytes(data) - PYTHON - TARP_KEYCHAIN_PASSWORD=$(openssl rand -hex 24) - TARP_KEYCHAIN="$RUNNER_TEMP/tarp-signing.keychain-db" - security create-keychain -p "$TARP_KEYCHAIN_PASSWORD" "$TARP_KEYCHAIN" - security set-keychain-settings -lut 21600 "$TARP_KEYCHAIN" - security unlock-keychain -p "$TARP_KEYCHAIN_PASSWORD" "$TARP_KEYCHAIN" - security import "$RUNNER_TEMP/tarp-signing.p12" -k "$TARP_KEYCHAIN" -P "$MAC_CSC_KEY_PASSWORD" -T /usr/bin/codesign - security list-keychains -d user -s "$TARP_KEYCHAIN" login.keychain-db - security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$TARP_KEYCHAIN_PASSWORD" "$TARP_KEYCHAIN" - - name: 构建安装包 - working-directory: apps/desktop - env: - TARP_CODESIGN: ${{ secrets.MAC_DEVELOPER_ID != '' && matrix.platform == 'mac' && '1' || '0' }} - TARP_NOTARIZE: ${{ secrets.MAC_DEVELOPER_ID != '' && secrets.APPLE_ID != '' && matrix.platform == 'mac' && '1' || '0' }} - ELECTROBUN_DEVELOPER_ID: ${{ matrix.platform == 'mac' && secrets.MAC_DEVELOPER_ID || '' }} - ELECTROBUN_APPLEID: ${{ matrix.platform == 'mac' && secrets.APPLE_ID || '' }} - ELECTROBUN_APPLEIDPASS: ${{ matrix.platform == 'mac' && secrets.APPLE_APP_SPECIFIC_PASSWORD || '' }} - ELECTROBUN_TEAMID: ${{ matrix.platform == 'mac' && secrets.APPLE_TEAM_ID || '' }} - run: bun run dist - - name: 验证打包后的 Bun、CLI、模组、Wasm 和 SQLite - run: bun scripts/release/smoke.ts desktop - - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 - with: - name: desktop-${{ matrix.platform }}-${{ matrix.arch }} - path: | - apps/desktop/release/*.exe - apps/desktop/release/*.tar.zst - apps/desktop/release/*.tar.gz - apps/desktop/release/*.json - apps/desktop/release/*.patch - apps/desktop/release/*.dmg - apps/desktop/release/*.zip - if-no-files-found: error - compression-level: 0 - retention-days: 14 + uses: ./.github/workflows/build-desktop.yml + with: + sign: true + secrets: inherit release: name: 汇总安装包并创建 Release 草稿 diff --git "a/docs/\345\217\221\345\270\203\346\265\201\347\250\213.md" "b/docs/\345\217\221\345\270\203\346\265\201\347\250\213.md" index 07ab310..1188607 100644 --- "a/docs/\345\217\221\345\270\203\346\265\201\347\250\213.md" +++ "b/docs/\345\217\221\345\270\203\346\265\201\347\250\213.md" @@ -2,20 +2,20 @@ ## 工作流 -| 入口 | 触发条件 | 行为 | -| --------------------------------------- | ---------------------- | -------------------------------------- | -| `.github/workflows/ci.yml` | PR、分支提交、手动运行 | 格式、类型、完整测试与构建 | -| `.github/workflows/release-desktop.yml` | `desktop-v*` tag | 检查 → 各平台打包与验收 → Release 草稿 | -| `.github/workflows/release-cli.yml` | `cli-v*` tag | 检查 → CLI 打包与验收 → Release 草稿 | +| 入口 | 触发条件 | 行为 | +| --------------------------------------- | -------------------------- | ----------------------------------------------- | +| `.github/workflows/ci.yml` | PR、手动运行、发布流程调用 | 格式、类型、完整测试与构建;PR 另验收桌面安装包 | +| `.github/workflows/release-desktop.yml` | `desktop-v*` tag | 检查 → 各平台打包与验收 → Release 草稿 | +| `.github/workflows/release-cli.yml` | `cli-v*` tag | 检查 → CLI 打包与验收 → Release 草稿 | 发布工作流复用 CI,共用 `.github/actions/setup/action.yml` 安装根级 `packageManager` 指定的 Bun。依赖统一从根目录按 `bun.lock` 安装;共享包随产品构建,官网和剧情模组不参与构建。CLI 兼容性检查与 CLI 发布流程另外安装 Node.js 22.12.0,验证支持的最低版本。第三方 Actions 固定到提交 SHA,升级时同步核对版本。 -日常 CI 只执行仓库检查;分发包验收放在对应发布流程。`scripts/release/smoke.ts` 使用独立临时模组与配置,验证分发产物的版本、帮助、模组加载、原生公式计算和退出码。CLI 从 tgz 独立安装后分别使用 Node.js 和 Bun 运行,使用符合类型目录结构的测试资料覆盖 JSON、TOML 与 Markdown 解析,并检查已安装运行依赖的许可文件;桌面则运行各平台打包后的应用,并验证包内 SQLite 驱动与 Kysely 的加载、写入、事务回滚和重开恢复。 +普通分支 push 不触发检查;创建或更新 PR 时执行仓库检查,通过后调用 `.github/workflows/build-desktop.yml`,构建并验收 Windows x64、Linux x64 和 macOS ARM64 安装包。PR 不传入签名凭据、不创建 Release;安装包作为 Actions 产物保留 14 天。桌面发布复用同一构建与验收流程,并按配置签名、公证;手动运行仓库检查只执行格式、类型、测试与构建。CLI 分发包验收仍在 CLI 发布流程执行。`scripts/release/smoke.ts` 使用独立临时模组与配置,验证分发产物的版本、帮助、模组加载、原生公式计算和退出码。CLI 从 tgz 独立安装后分别使用 Node.js 和 Bun 运行,使用符合类型目录结构的测试资料覆盖 JSON、TOML 与 Markdown 解析,并检查已安装运行依赖的许可文件;桌面则运行各平台打包后的应用,并验证包内 SQLite 驱动与 Kysely 的加载、写入、事务回滚和重开恢复。 ## 发布版本 1. 修改目标产品的 `package.json` 版本:桌面为 `apps/desktop/`,CLI 为 `packages/module-cli/`。 -2. 从根目录运行 `bun install` 更新根级锁文件,提交并合入默认分支,确认 CI 通过。影响公开行为或模组格式时同步修改官网正文。 +2. 从根目录运行 `bun install` 更新根级锁文件,提交 PR,确认检查和桌面分发验收通过后合入默认分支。影响公开行为或模组格式时同步修改官网正文。 3. 从该提交创建并推送对应 tag,版本必须与目标包完全一致: ```sh From 70c6e0a9c819768716b303fe3e24f86cdfa3fc25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=BE=B7=E6=A3=AE?= Date: Wed, 21 Oct 2026 00:35:06 +0800 Subject: [PATCH 3/4] =?UTF-8?q?ci:=20=E7=BC=93=E5=AD=98=20Bun=20=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E4=B8=8E=E6=A1=8C=E9=9D=A2=E6=9E=84=E5=BB=BA=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E9=93=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/actions/setup/action.yml | 27 +++++++++++++++++++ ...21\345\270\203\346\265\201\347\250\213.md" | 4 +++ 2 files changed, 31 insertions(+) diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index ba2e03d..5020380 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -6,6 +6,33 @@ runs: - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: bun-version-file: package.json + - name: 定位下载缓存目录 + id: cache-paths + shell: bash + run: | + bun run - <<'JS' >> "$GITHUB_OUTPUT" + const { homedir } = require('node:os'); + const { join } = require('node:path'); + console.log(`bun=${process.env.BUN_INSTALL_CACHE_DIR || join(homedir(), '.bun', 'install', 'cache')}`); + console.log(`hutch=${process.env.HUTCH_HOME || process.env.DASH_HOME || join(homedir(), '.hutch')}`); + JS + - name: 缓存 Bun 依赖下载 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ${{ steps.cache-paths.outputs.bun }} + key: bun-download-v1-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package.json', 'bun.lock') }} + restore-keys: | + bun-download-v1-${{ runner.os }}-${{ runner.arch }}- + - name: 缓存 Hutch 与 Electrobun 工具链 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: | + ${{ steps.cache-paths.outputs.hutch }}/npm + ${{ steps.cache-paths.outputs.hutch }}/releases + ${{ steps.cache-paths.outputs.hutch }}/toolchains + key: desktop-tools-v1-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package.json', 'bun.lock', 'apps/desktop/package.json', 'apps/desktop/hutch.config.ts') }} + restore-keys: | + desktop-tools-v1-${{ runner.os }}-${{ runner.arch }}- - name: 从根目录安装依赖 shell: bash env: diff --git "a/docs/\345\217\221\345\270\203\346\265\201\347\250\213.md" "b/docs/\345\217\221\345\270\203\346\265\201\347\250\213.md" index 1188607..25c1a53 100644 --- "a/docs/\345\217\221\345\270\203\346\265\201\347\250\213.md" +++ "b/docs/\345\217\221\345\270\203\346\265\201\347\250\213.md" @@ -10,6 +10,10 @@ 发布工作流复用 CI,共用 `.github/actions/setup/action.yml` 安装根级 `packageManager` 指定的 Bun。依赖统一从根目录按 `bun.lock` 安装;共享包随产品构建,官网和剧情模组不参与构建。CLI 兼容性检查与 CLI 发布流程另外安装 Node.js 22.12.0,验证支持的最低版本。第三方 Actions 固定到提交 SHA,升级时同步核对版本。 +开发环境安装步骤缓存 Bun 的依赖下载目录,以及 Hutch 下的 `npm/`、`releases/`、`toolchains/`;按操作系统、架构、锁文件与工具链配置区分缓存。命中后仍执行 `bun install --frozen-lockfile`、构建和验收,不缓存 `node_modules`、项目构建目录、安装包或签名凭据。缓存不可用时按正常流程重新下载。 + +GitHub 缓存有分支和 tag 作用域限制,PR 保存的缓存不能由合并后的发布 tag 直接读取;首次发布或新的 tag 可能需要重新下载,同一 tag 重跑可复用已有缓存。默认分支已有的兼容缓存也可供其他分支及发布流程读取。 + 普通分支 push 不触发检查;创建或更新 PR 时执行仓库检查,通过后调用 `.github/workflows/build-desktop.yml`,构建并验收 Windows x64、Linux x64 和 macOS ARM64 安装包。PR 不传入签名凭据、不创建 Release;安装包作为 Actions 产物保留 14 天。桌面发布复用同一构建与验收流程,并按配置签名、公证;手动运行仓库检查只执行格式、类型、测试与构建。CLI 分发包验收仍在 CLI 发布流程执行。`scripts/release/smoke.ts` 使用独立临时模组与配置,验证分发产物的版本、帮助、模组加载、原生公式计算和退出码。CLI 从 tgz 独立安装后分别使用 Node.js 和 Bun 运行,使用符合类型目录结构的测试资料覆盖 JSON、TOML 与 Markdown 解析,并检查已安装运行依赖的许可文件;桌面则运行各平台打包后的应用,并验证包内 SQLite 驱动与 Kysely 的加载、写入、事务回滚和重开恢复。 ## 发布版本 From 871b5f2e115e6841389eb5c5bcfaadb6e7cdbd03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=94=A1=E5=BE=B7=E6=A3=AE?= Date: Wed, 21 Oct 2026 00:42:18 +0800 Subject: [PATCH 4/4] =?UTF-8?q?fix:=20=E9=81=BF=E5=85=8D=E5=8E=9F=E5=AD=90?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E6=97=B6=E6=96=87=E4=BB=B6=E9=98=9F=E5=88=97?= =?UTF-8?q?=E8=BA=AB=E4=BB=BD=E6=BC=82=E7=A7=BB=E5=AF=BC=E8=87=B4=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E4=B8=A2=E5=A4=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/src/node/storage/file-queue.ts | 20 +++++++++++--- .../src/node/storage/structured-file.test.ts | 27 ++++++++++++++++++- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/packages/core/src/node/storage/file-queue.ts b/packages/core/src/node/storage/file-queue.ts index 2d7310a..8e082cb 100644 --- a/packages/core/src/node/storage/file-queue.ts +++ b/packages/core/src/node/storage/file-queue.ts @@ -1,4 +1,4 @@ -import { realpath } from "node:fs/promises"; +import { readlink, realpath } from "node:fs/promises"; import { basename, dirname, join, resolve } from "node:path"; const queues = new Map>(); @@ -9,17 +9,31 @@ export function isMissingFile(error: unknown): boolean { } /** 尚未创建的文件也按真实父目录归一化,避免目录链接绕过同文件队列。 */ -async function queueKey(path: string): Promise { +async function directoryKey(path: string): Promise { try { return await realpath(path); } catch (error) { if (!isMissingFile(error)) throw error; const parent = dirname(path); if (parent === path) throw error; - return join(await queueKey(parent), basename(path)); + return join(await directoryKey(parent), basename(path)); } } +async function queueKey(path: string, links = 0): Promise { + // Bun 在 Linux 上通过文件描述符解析 realpath;原子替换期间旧 inode + // 可能返回带「 (deleted)」的路径,不能用会被替换的文件本身作为队列身份。 + let target: string; + try { + target = await readlink(path); + } catch (error) { + if (!isMissingFile(error) && (error as NodeJS.ErrnoException).code !== "EINVAL") throw error; + return join(await directoryKey(dirname(path)), basename(path)); + } + if (links >= 40) throw Object.assign(new Error("文件链接层级过多"), { code: "ELOOP" }); + return queueKey(resolve(dirname(path), target), links + 1); +} + /** 保护当前进程内的一次完整文件操作;不同文件并行,失败不阻塞后续操作。 */ export async function withFileMutation(path: string, operation: () => Promise): Promise { // 注册顺序固定,避免异步 realpath 完成顺序改变调用顺序。 diff --git a/packages/core/src/node/storage/structured-file.test.ts b/packages/core/src/node/storage/structured-file.test.ts index 0484831..c03eb75 100644 --- a/packages/core/src/node/storage/structured-file.test.ts +++ b/packages/core/src/node/storage/structured-file.test.ts @@ -1,5 +1,6 @@ -import { it, onTestFinished } from "bun:test"; +import { it, onTestFinished, spyOn } from "bun:test"; import { strict as assert } from "node:assert"; +import * as fs from "node:fs/promises"; import { mkdir, mkdtemp, readFile, readdir, rm, symlink, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; @@ -46,6 +47,30 @@ it("多个存储实例对同文件完整读改写,保留全部增量和未知 assert.deepEqual(await store(path).read(), { count: 12, extra: "保留" }); }); +it("原子替换期间旧文件的 realpath 结果变化不会拆散同文件更新队列", async () => { + const path = join(await directory(), "config.json"); + await store(path).write({ count: 0, extra: "保留" }); + const realpath = fs.realpath; + let resolutions = 0; + const resolving = spyOn(fs, "realpath").mockImplementation((async ( + target: Parameters[0], + ) => { + const actual = await realpath(target); + // 模拟 Linux 在旧文件已被 rename 替换后返回的描述符路径。 + return target === path && ++resolutions % 2 === 0 ? `${actual} (deleted)` : actual; + }) as typeof realpath); + onTestFinished(() => resolving.mockRestore()); + await Promise.all( + Array.from({ length: 12 }, () => + store(path).update(async (value) => { + await Promise.resolve(); + return { ...value, count: value.count + 1 }; + }), + ), + ); + assert.deepEqual(await store(path).read(), { count: 12, extra: "保留" }); +}); + it("读取等待先前写入,写入使用调用时的快照", async () => { const path = join(await directory(), "config.json"); const value = { count: 1, nested: { label: "原值" } };