mcpField
M
motoko-mops-package-maintenance

motoko-mops-package-maintenance

github.com/research-ag开发048 次安装9 周前更新
代码仓库

关于 motoko-mops-package-maintenance

面向维护 MOPS 已发布 Motoko 包的 AI Agent 的分步指南,涵盖依赖升级、验证、文档、CI 和版本发布准备,并明确规定工具链与包文件的处理方式。

主要功能

  1. 01MOPS 依赖升级流程
  2. 02包测试与基准检查
  3. 03嵌套清单和示例维护
  4. 04文档与仓库规范检查
  5. 05发布分支与变更日志准备

适用场景

  1. 01定期更新包依赖
  2. 02发布前验证 Motoko 包
  3. 03整理供使用者采用的嵌套示例

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/research-ag/motoko-skills --skill motoko-mops-package-maintenance

安装后在 Claude Code 中输入/motoko-mops-package-maintenance确认已加载。

详细介绍

Mops 包维护

这是什么

一份分步操作指南,帮助 AI Agent 全面维护发布在 MOPS 上的 Motoko 包:升级依赖、验证包、完善文档、格式化代码、确保 CI 正常运行,并准备好带版本号的发布分支——一次自动完成所有操作。

适用场景

  • 定期执行依赖升级维护。
  • 发布新版本前。
  • 用户要求“更新依赖”“维护此包”或“准备发布”时。

关键约定(全程适用)

以下步骤会引用这些规则。请先通读一遍。

  • pocket-ic 是唯一的基准测试运行时——像 moc 一样固定版本。 mops CLI v3.0.0 已完全移除对 dfx-replica 的支持(mops test/mops bench 中的 --replica 标志也已移除)。如果包包含基准测试、副本测试,或使用 --check-deploy,则必须固定 [toolchain] pocket-ic,否则 mops bench 会直接失败。与 files 字段不同,此项不会自动处理:如果缺少,请使用 mops toolchain use pocket-ic <version> 添加(mops 自身的错误信息会给出具体版本,例如 15.0.0),处理方式与主动管理 [toolchain] moc 相同。
  • 基准测试应测量经过优化的 Wasm——配置 [optimize] 并固定 wasm-opt 版本。 只有当 mops.toml 中存在 [optimize] 段时,mops bench(以及 mops build)才会运行 Binaryen 的 wasm-opt——即使该段为空,也会启用优化,默认值为 level = "O3" / keep-names = true。如果没有该段,则完全不会运行优化,基准测试数据反映的是编译器原始输出,而不是实际部署到生产容器中的内容。与 pocket-ic 一样,[optimize] 要求显式固定 [toolchain] wasm-opt 版本,否则构建会在编译前失败。如果包包含基准测试但缺少 [optimize],维护期间应同时添加两项(见步骤 5),不要等用户发现后再处理。
  • **mops.toml 中不应自动处理的字段:**绝不自动编辑 [package] files,也不自动向 [toolchain] 添加条目。应改为报告并发出警告。例外:[toolchain] pocket-ic 和 [optimize] / [toolchain] wasm-opt——见上面两条;基准测试需要时应添加,处理方式与 moc 相同。
  • CHANGELOG 只列出用户可见的版本变更:[dependencies] 和 [requirements]。绝不列出 [toolchain] 或 [dev-dependencies]。
  • **文档门槛:**如果 MOPS 显示 Documentation = 100%(步骤 1),则完全跳过步骤 7 和 8。否则应以达到 100% 为目标——至少为每个缺少 /// 文档字符串的公共声明补上文档。
  • **CI 中不要运行 moc --check。**这是 Agent 在维护期间本地运行的检查;不同的 CI 编译器版本可能会导致用户遇到虚假的失败。
  • mops add 会重写 mops.toml,并可能静默地将 [requirements] moc 重置为 "1.0.0"。每次运行 mops add 后都要检查差异,并恢复预期值。

前置条件

  • mops CLI(npm i -g ic-mops)
  • moc(Motoko 编译器;通过 mops.toml 中的 [toolchain] moc 固定版本,并使用 mops toolchain bin moc 下载——自 mops CLI v3.0.0 起,不再提供由 dfx 捆绑的备用版本,必须固定版本)
  • pocket-ic(基准测试运行时;如果包包含基准测试,则通过 [toolchain] pocket-ic 固定版本——见“关键约定”)
  • wasm-opt(Binaryen;仅在 mops.toml 中设置 [optimize] 时运行,且只有此时才需要固定 [toolchain] wasm-opt 版本——见“关键约定”)
  • dfx(DFINITY SDK;可选——仅构建容器或示例时需要,运行 mops bench 不需要)
  • node >= 22 / npm。使用 node --version 验证。
  • git
  • prettier 和 prettier-plugin-motoko——运行 prettier 前请先在本地安装;仅运行 npx -y 不会在干净的检出目录中自动解析该插件。

工作流

按顺序完成每个步骤。如果某一步失败,请先修复,再继续。

步骤 0 — 创建维护分支
git checkout -b chore/dependency-bump-$(date +%Y-%m-%d)

现在也快照未跟踪文件列表,以便在步骤 11 中区分临时文件和你自己新增的文件:

git status --short > /tmp/baseline.txt
步骤 1 — 在 MOPS 上验证包的质量
  1. 打开 mops.toml。如果没有 [package] 部分(只有 [canister],或两者都没有),则该包尚未发布 — 跳到步骤 2。
  2. 访问 https://mops.one/<package-name> 并查看 Package Quality 部分(Documentation、License、Repository、Tests、Benchmarks)。
    • mops.one 是单页应用(SPA)— curl/WebFetch 只能看到空壳。如果无法渲染页面,请在本地检查相关信号:运行 mo-doc 并搜索 (no description);验证 mops.toml 中的 [package] license 和 [package] repository;确认 mops test 和 mops bench 均成功。对于无法通过程序验证的内容,请向用户确认。
  3. 对于任何不为 "yes" / "100%" 的指标:
    • Documentation < 100%:在步骤 7–8 中运行 motoko-doc-strings 技能。如果已经达到 100%,则跳过步骤 7–8。
    • 缺少 License/Repository:在 mops.toml 的 [package] 中设置它们。
    • Tests/Benchmarks:在步骤 4–5 中处理;确保步骤 9c 中配置了 CI。
  4. 对于无法自动修复的问题,向用户发出警告。
步骤 2 — 查找过时的依赖项
mops outdated
# Fallback: mops search <package-name>

记录需要升级的包。

moc 策略:将 [toolchain] moc 升级到最新版本;将 [requirements] moc 设为仍能正常工作的绝对最低版本(在步骤 3 中通过迭代确定)— 不要盲目地让它与工具链或依赖项声明的版本一致。

步骤 3 — 升级 mops.toml 中的依赖项

更新 [dependencies] 和 [dev-dependencies] 中所有过时条目的版本。

确定 [requirements] moc:

  1. 初始版本 — 常规 [dependencies] 所需的最高 moc 版本,不包括 core:
    1. 列出根目录 mops.toml 中的 [dependencies](跳过 core)。
    2. 对每个依赖项,读取 .mops/<name>@<version>/mops.toml 并提取 [requirements] moc(如果不存在则跳过)。
    3. 取最高版本。如果低于当前 [requirements] moc,则保留当前值。
  2. 检查 core — 运行 mops install 后,读取 .mops/core@<version>/mops.toml 中的 [requirements] moc。
  3. 迭代验证(仅当 core 的要求高于初始版本时): 你必须按顺序测试每个中间 moc 版本,不得跳过(例如,从 1.0.0 升到 1.4.0 时,测试 1.1.0、1.2.0、1.3.0……)。 对每个候选版本 X:
    1. 设置 [toolchain] moc = "X"。
    2. 运行 mops test(如果存在测试)。
    3. 运行 mops bench(如果存在基准测试)。
    4. 构建示例(仅限 Motoko canister — 忽略资源/Rust):
      EXAMPLES_DIR=""
      if [ -d "examples" ]; then EXAMPLES_DIR="examples"
      elif [ -d "example" ]; then EXAMPLES_DIR="example"; fi
      if [ -n "$EXAMPLES_DIR" ]; then
        cd "$EXAMPLES_DIR"
        mops install
        if [ -f "icp.yaml" ] && command -v icp >/dev/null; then icp build --all
        elif [ -f "dfx.json" ]; then dfx build; fi
        cd ..
      fi
      
    5. 如果全部通过,则设置 [requirements] moc = "X" 并停止。
  4. **失败:**如果连 core 要求的版本都无法通过测试,则将 [requirements] moc 恢复为初始值,并警告用户。
  5. **最终同步:**将 [toolchain] moc 恢复为最新版本。

然后安装:

mops install

确认 mops install 成功且没有解析错误,并且 mops.lock 已更新。切勿手动编辑锁定文件。

步骤 3a — 同步嵌套的 mops.toml 文件

查找所有嵌套的清单文件(例如示例、子 canister 等):

find . -name mops.toml -not -path "./node_modules/*" -not -path "./.mops/*"

对于每个嵌套的 mops.toml:

  • 第三方 [dependencies] 版本通常应与根目录保持一致 (示例可以添加额外依赖,但共有依赖应保持一致)。
  • [toolchain] 中的 moc 必须与根目录一致,并且存在于 CI setup-mops 操作使用的 fork 中。
  • 正在维护的包必须通过相对本地路径,使用其真实包名引用自身 (例如 self-package-name = "../"),并添加注释,注明最新发布版本, 方便使用者手动替换。
  • 替换示例 .mo 文件中的相对源代码导入: import "../../src/Main" → import "mo:self-package-name/Main"。 这样可以让示例直接复制粘贴使用。

examples/mops.toml 示例:

[dependencies]
core = "2.5.0"
self-package-name = "../"
# Replace with:
# self-package-name = "0.0.3"

[toolchain]
moc = "1.6.0"
步骤 3b — 检查仓库卫生文件
  • .gitignore — 如果不存在则创建;确保其中包含:
    .mops/
    .icp/
    mops.lock        # for libraries only — mops install reminds you
    node_modules/
    package.json
    package-lock.json
    .dfx/
    build/
    skills-lock.json
    .agents
    
    个人文件和编辑器文件(.idea、.vscode、.claude、.junie、 .copilot、.tmp、*.swp、.DS_Store)应放在开发者的全局忽略文件中, 而不是这里。
  • package-lock.json — 如果不存在,不要添加。
  • package.json — 如果存在,确保其 license 与 mops.toml 一致。如果不存在,不要添加(也不要提交 npm 可能创建的文件)。
  • mops.toml [package] files — 不要修改(参见关键约定)。 将其内容告知用户,并在发现问题时发出提醒(例如,存在 examples/, 但未将其列入其中)。mops publish 仅支持 .mo、.did、 .md、.toml 文件 — 如果出现其他扩展名,请发出提醒。
步骤 3c — 修复编译器警告

运行 fix-compiler-warnings 技能。仅处理编译器实际发出的警告或错误 — 不要凭空提出“改进”。

仅捕获 Motoko canister 的警告(忽略 asset/Rust):

# DFX projects:
dfx build --check 2>&1 | tee /tmp/dfx_build_output.txt

# MOPS packages:
find src -type f -name "*.mo" -print0 | xargs -0 -n1 $(mops toolchain bin moc) --check $(mops sources) 2>&1 | tee /tmp/moc_check_output.txt

# ICP-CLI projects:
icp build 2>&1 | tee /tmp/icp_build_output.txt

每次修复一种警告,重新运行检查;如适用,运行 mops test / mops bench 以发现回归问题。

步骤 4 — 运行测试
mops test

如果测试失败,请确认是否因升级后的依赖更改了 API;如有必要,调整源代码并重新运行。对于非简单的更改 (重命名、签名变更),请在 CHANGELOG 中记录。

第 5 步 — 运行基准测试

如果软件包包含基准测试(bench/ 目录中有 *.bench.mo 文件),在运行 mops bench 之前,确保基准测试工具链已完整配置。mops CLI v3.0.0 要求显式固定以下两项,否则 mops bench 会直接失败(参见 Key Conventions):

  1. [toolchain] pocket-ic — 如果缺少,请添加:
    mops toolchain use pocket-ic <version>   # mops's own error names one, e.g. 15.0.0
    
  2. [optimize] + [toolchain] wasm-opt — 如果 mops.toml 中缺少 [optimize],请立即添加,不要只标记出来。空配置段即可(默认值为 level = "O3"、keep-names = true):
    [optimize]
    
    [toolchain]
    wasm-opt = "<version>"
    
    按与 pocket-ic 相同的方式固定版本:
    mops toolchain use wasm-opt <version>   # or: mops toolchain info wasm-opt
    
    如果没有 [optimize],mops bench 会静默地测量未经优化的 Wasm — 这并非 CHANGELOG 中的基准测试数据应体现的情况。如果将 [optimize] 添加到此前没有该配置的软件包中,请在 CHANGELOG(第 6 步)中说明:由此导致的基准测试数据变化属于测量方法的变更,而非代码回归或改进。

然后运行:

mops install   # picks up any new [toolchain] pins
mops bench

针对编译/运行失败,采用第 4 步的方式进行修复。

环境问题与代码问题。 如果 mops bench 在 Deploying canisters... 行之后报错 — 通常包括:

  • TrustError: Certificate verification error: "Invalid signature"
  • UND_ERR_SOCKET / fetch failed
  • Could not find the PocketIC binary

— 基准测试已成功编译;这是 pocket-ic/mops Agent 兼容性问题,并非本次升级所致。请依次处理:终止过期的 pocket-ic 进程;确认 [toolchain] pocket-ic 已固定并重新获取二进制文件(mops toolchain bin pocket-ic);如果版本看起来已过期或缺失,则使用 mops toolchain use pocket-ic <version> 固定到较新版本(参见 Key Conventions — 截至 mops CLI v3.0.0,没有可退回使用的 dfx-replica);最后才考虑从 CI 中移除 bench 作业,并告知用户。不要为此耽误发布。

重大回归:在 CHANGELOG 中记录,但除非用户提出要求,否则不要阻止发布。

第 6 步 — 更新 CHANGELOG

打开或创建 CHANGELOG.md,并在顶部为即将发布的版本添加一个小节(版本号将在第 10 步最终确定)。

仅包含 [dependencies] 和 [requirements](参见 Key Conventions):

  • 升级的依赖项 — 列出每个已升级的 [dependencies] 条目,旧版本 → 新版本。
  • 破坏性/重要变更 — 源代码调整。
  • 错误修复 — 本次过程中发现并修复的所有问题。

如果不存在 CHANGELOG,请创建一个:

# Changelog

## Unreleased

### Changed

- Updated `core` from `2.0.0` to `2.5.0`.
- Bumped `bench` from `1.0.0` to `2.0.1`.
- Updated `[requirements] moc` from `1.2.0` to `1.3.0` (only if changed).

### Fixed

- Adapted `<function>` to new `<dep>` API (renamed `old` → `new`).

最新版本放在最上方。如果已有 CHANGELOG,请遵循其现有风格。

第 7 步 — 审查并改进文档字符串

如果 MOPS Documentation = 100%,则跳过(参见 Key Conventions)。否则,以达到 100% 为目标。

扫描 src/ 下的每个 .mo 文件,检查公开声明(type、func、actor、actor class、let、module)。对每项声明:

  1. 确保其正上方有 /// 文档字符串。
  2. 从初次使用者的角度检查:用途是否清晰?是否说明了参数类型/单位/约束?是否说明了陷阱/错误行为?非简单函数是否提供了示例?
  3. 根据需要进行改进或补充。

如果已安装 motoko-doc-strings skill,请遵循其检查清单。

第 8 步 — 审查 README 和其他 Markdown 文档

如果 MOPS Documentation = 100%,则跳过。

对于 README.md 和其他所有 .md 文件:

  1. 检查事实是否准确(版本、API 名称、示例)。
  2. 修正过时的信息,提升清晰度、语法和完整性。
  3. 为升级后的依赖项新增的 API 添加相应章节。
  4. 确保 README.md 记录了格式化命令,例如 npx -y prettier --plugin prettier-plugin-motoko --write '**/*.{mo,json,md}' (如果缺少 "Development" 或 "Formatting" 章节,请添加)。
第 9 步 — 格式化
9a — Prettier 配置

如果缺少 .prettierrc,或者文件存在但内容过于简单(例如只有 tabWidth),请写入:

{
  "plugins": ["prettier-plugin-motoko"],
  "bracketSpacing": true,
  "printWidth": 80,
  "semi": true,
  "tabWidth": 2,
  "trailingComma": "es5",
  "useTabs": false
}
9b — 格式化代码

prettier 的 --plugin 标志不会自动解析包。请先在本地安装插件(在干净的检出目录中直接运行 npx -y prettier --plugin prettier-plugin-motoko ... 会因 Cannot find package 'prettier-plugin-motoko' 而失败):

npm install --no-save prettier prettier-plugin-motoko
npx prettier --plugin prettier-plugin-motoko --write '**/*.{mo,json,md}'
9c — 验证或添加 CI 工作流

如果已安装 motoko-github-ci-workflow 技能,请遵循其说明,而非本节内容。

否则,创建或更新 .github/workflows/ci.yml,加入测试和格式检查。如果包包含基准测试,则必须固定 [toolchain] pocket-ic(遵循关键约定),并在 CI 中于运行 mops bench 前通过 mops toolchain bin pocket-ic 安装;截至 mops CLI v3.0.0,PocketIC 是唯一的基准测试运行时。mops bench 会启动并停止自己的 PocketIC 实例——切勿添加手动的 dfx start --background 步骤;如果发现此步骤,请将其删除。如果 mops.toml 中有 [optimize] 部分(遵循关键约定,该部分应该存在;如果缺少,则在步骤 5 中添加),还要在 CI 中于运行 mops bench 前通过 mops toolchain bin wasm-opt 安装 wasm-opt。

name: CI

on:
  push:
    branches: [main, master]
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review]

jobs:
  test:
    name: Tests and Benchmarks
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: latest
      - uses: caffeinelabs/setup-mops@v1
      - run: mops install
      - run: mops test   # Omit if no tests
      # Benchmarks: pocket-ic is the only bench runtime (mops CLI
      # v3.0.0 removed dfx-replica support). Requires [toolchain]
      # pocket-ic to be pinned in mops.toml. Omit both steps if there
      # are no benchmarks.
      - name: Make sure pocket-ic is installed
        run: mops toolchain bin pocket-ic
      # Only if mops.toml has an [optimize] section (see Key
      # Conventions / Step 5) — otherwise omit this step too.
      - name: Make sure wasm-opt is installed
        run: mops toolchain bin wasm-opt
      - run: mops bench

  fmt:
    name: Formatting Check
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: latest
      - name: Prettier Check
        run: |
          npm install prettier prettier-plugin-motoko --no-save
          npx -y prettier --plugin prettier-plugin-motoko --check '**/*.{mo,json,md}'

遵循关键约定,不要在 CI 中添加 moc --check 步骤。

步骤 10 — 更新版本号
  1. 在根目录的 mops.toml 中递增版本号。默认递增修订号(1.2.3 → 1.2.4)。如果满足以下任一条件,则递增次版本号(并将修订号重置为 0):

    • [requirements] moc 已提高(使用者需要更新的编译器);
    • [dependencies] 中的某个包升了主版本号,且此包会重新导出该包的类型或函数;
    • 使用者可能依赖的源代码签名或运行时语义发生了变化。

    对于 0.x.y,将规则右移一段。

    [package]
    name = "my-package"
    version = "1.2.4"   # was 1.2.3
    
  2. 将 CHANGELOG 中的 Unreleased 标题更新为新版本号: ## 1.2.4。

  3. 将每个嵌套 mops.toml 中的自依赖注释(来自步骤 3a)更新为新版本号:

    self-package-name = "../"
    # Replace with:
    # self-package-name = "1.2.4"
    
步骤 11 — 提交并推送

先检查未跟踪文件。 将 git status --short 的结果与 /tmp/baseline.txt(步骤 0)进行比较。早于本次工作的文件(*.debug.bench.mo、roxy.txt、临时实验文件)都属于临时文件——保持未暂存、将其加入 .gitignore,或删除。不允许不加检查地运行 git add -A。如有疑问,请询问用户。

暂存更改。如果开始时不存在 package.json / package-lock.json,但 npm install 创建了这些文件,不要提交它们。

git add -u
git add .gitignore CHANGELOG.md .prettierrc .github/workflows/*.yml 2>/dev/null || true
git status
git commit -m "chore: bump dependencies and prepare v<NEW_VERSION>"

告知用户:

Branch: chore/dependency-bump-YYYY-MM-DD
Ready for review. Run `git push -u origin HEAD` to push.

常见陷阱

  1. 依赖项主版本号升级。 如果某个 MOPS 依赖项跨主版本升级(1.x → 2.x),请阅读其 CHANGELOG——API 很可能已更改。将非简单迁移告知用户。
  2. 穷尽搜索 [requirements] moc。 测试每个中间版本(步骤 3);绝不能跳过。优先选择通过所有检查的最低版本,即使低于 core 声明的版本,以最大限度提高使用者兼容性。
  3. 锁文件漂移。 编辑 mops.toml 后始终运行 mops install。绝不要手动编辑 mops.lock。
  4. CHANGELOG 排序。 最新内容放在顶部。
  5. 未设置 [optimize] 就进行基准测试。 如果包有基准测试却没有 [optimize] 部分,mops bench 会静默地测量未经优化的 Wasm(参见关键约定 / 步骤 5)。不要因为 mops bench 不加该部分“也能运行”就跳过添加——能运行和结果有代表性是两回事。

验证是否正常运行

mops install
mops test
mops bench

所有检查都必须成功,且不得出现错误。

评论

支持 Markdown