mcpField
M
metabase-data-app-migrate

metabase-data-app-migrate

github.com/metabase开发49.9k158 次安装今天更新
代码仓库

关于 metabase-data-app-migrate

用于将 Metabase 数据应用迁移到新契约版本的操作技能。它引导开发者逐版执行并验证升级,同时约束版本变更与提交流程。

主要功能

  1. 01逐版本顺序升级
  2. 02按升级指南逐步验证
  3. 03约束版本号和提交变更
  4. 04最终类型、资源与构建检查
  5. 05恢复中断的迁移

适用场景

  1. 01契约变更后更新数据应用
  2. 02继续中断的数据应用迁移

安装

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

$npx skills add https://github.com/metabase/metabase --skill metabase-data-app-migrate

安装后在 Claude Code 中输入/metabase-data-app-migrate确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
maintainer-checklist.md
upgrade-guide-template.md
references/upgrades/
README.md

详细介绍

将数据应用迁移到当前契约版本

数据应用会在 data_app.yaml 中声明其代码所针对的契约版本 (version: N;没有该字段的清单即版本 1)。Metabase 仅在该契约发生 破坏性变更时才会提升其所提供的版本:即 @metabase/embedding-sdk-react/data-app API、bundle 工厂、清单、 queries/ 与 actions/ 约定,或应用可声明的内容。处于旧版本的应用会在 管理列表中标记为 已过时,对其他所有用户隐藏,并在迁移完成前拒绝打开。

迁移是一次对升级的遍历:N -> N+1 -> ... -> M,一次一个升级, 每个升级都由 references/upgrades/ 中的一份指南描述。不会跳过任何内容, 会话之间也不会记住任何内容:应用自身的文件和 git 历史承载着全部 状态。

四条不变量

以下每一步都源自这些不变量。切勿违反它们。

  1. version 最后写入。 某个升级的 version: N+1 只会在该升级的 所有检查都通过后,才写入 data_app.yaml。
  2. 每个升级在本地一次提交。 只有在目标版本的最终门禁通过后才 推送。版本行每次提交的变动绝不超过一个版本。
  3. 编译器与构建门禁仅在目标版本运行。 已安装的 SDK 就是目标版本, 因此一个尚处在多个升级中途的应用无法进行类型检查 或构建。不要提前运行它们,也不要提前“修复”它们的失败。
  4. 任何生成的内容都不得手动编辑。 dist/ 由 npm run build 写入,src/metabase.data.ts 由类型化 schema 导出写入, 绝不由你写入。应用集合在 collections/data_apps/ 下的文件 及其定义所命名的实体 ID(savedQuestionEntityId、 copiedActionEntityId)只在升级指南指明之处更改, 遵循关于编写应用集合文件的数据应用指引(使用技能发现)。

第 0 步 - 定位应用并读取其状态

在应用目录 <repo>/data_apps/<slug>/ 下操作。用 ROOT="$(git rev-parse --show-toplevel)" 解析仓库根目录。实例检查需要仓库根目录下的 .env.local 凭据(DATA_APP_MB_URL、DATA_APP_MB_API_KEY)。在子 shell 中 source 该文件来检查它们,只打印这两个变量是否都已设置;绝不要打印该文件或其变量。该 key 必须属于管理员:API 只向管理员返回 version 和 outdated,并拒绝向其他任何人返回已过时应用的元数据,因此非管理员 key 在这里无法证明任何事情。

下文的 npm 指应用自己的包管理器,即已提交锁文件(package-lock.json、yarn.lock、pnpm-lock.yaml、bun.lock)的那一个。绝不要引入第二个锁文件。

读取三个数字:

# version committed at HEAD (absent line means 1)
git show HEAD:data_apps/<slug>/data_app.yaml | grep -E '^version:' || echo "version: 1"
# version in the working tree
grep -E '^version:' data_app.yaml || echo "version: 1"
# target: the highest upgrade guide shipped with this skill (no guides means 1)
ls <skill-dir>/references/upgrades/ | sed -nE 's/^v[0-9]+-to-v([0-9]+)\.md$/\1/p' | sort -n | tail -1 | grep . || echo 1

<skill-dir> 是加载此 SKILL.md 的目录。当存在随此技能一同安装的 data-app 脚手架模板(<skills-dir>/*/template/data_app.yaml)时,目标必须等于其中的 version:;如果两者不同,说明这些技能来自不同的 Metabase 版本。停止,并告诉用户使用 Admin > Data apps 下显示的命令重新安装所有 data-app 技能。等待回答。

然后判断:

HEAD 版本工作区执行
等于目标干净无需迁移。说明这一点;仅当用户要求验证时才运行最终门禁。
高于目标任意停止。 没有降级。要么 Metabase、SDK 和技能都比应用旧,要么是针对错误实例提交了一次版本提升(git log -- data_apps/<slug>/data_app.yaml 会显示)。等待回答。
低于目标干净从 第 1 步 开始。
任意data_apps/<slug> 下有改动上一次会话被中断。先去 恢复。

第 1 步 - 预检,仅一次

  1. 用应用的包管理器安装与目标 Metabase 版本匹配的 SDK(npm install @metabase/embedding-sdk-react@<tag> 或等效命令);每份升级指南都会列出它所针对的 dist-tag。锁文件的变更随最终升级一起提交。
  2. 确认应用在其当前版本下仍符合模板形态:vite.config.ts 是单行 export default dataAppConfig(),且 src/index.tsx 默认导出 DataAppFactory。如果不是,停止:这不是版本迁移,而是结构性偏离。可提议在同一 slug 下搭建一个全新应用(单独任务:使用技能发现来创建 data app),并把 src/、queries/ 和 actions/ 迁移过去,或者按用户自担风险继续。等待回答。
  3. 在编辑任何内容之前,阅读从当前版本到目标的每一份升级指南,这样后续的升级就不会在较早升级进行到一半时给你带来意外。

第 2 步 - 升级循环

对于从 HEAD 版本到 target - 1 的每个 N:

  1. 打开 references/upgrades/v<N>-to-v<N+1>.md 并运行其中的 Preconditions。
  2. 按顺序应用该指南的 Steps。每一步都是机械性的,并以一条 Done when 命令结束。先运行该命令:如果它已经通过,就跳过这一步; 如果没有通过,就应用修改并再次运行它。一步的命令是它被执行过的唯一 证明;绝不要通过阅读就把某一步标记为完成。
  3. 应用 Instance steps(如果有)。它们的 Done when 是来自已连接的 Metabase 的 API 响应,使用 .env.local 中的凭据获取:
    ( source "$ROOT/.env.local"; curl -s -H "x-api-key: $DATA_APP_MB_API_KEY" "$DATA_APP_MB_URL/api/apps/<slug>" )
    
  4. 运行该指南的 Done-check summary。每一行都必须打印 ok。
  5. 只有到这时,才在 data_app.yaml 中设置 version: N+1。这是对该行的唯一 一次修改。
  6. 如果 N+1 < target:从仓库根目录执行 git add data_apps/<slug> collections/data_apps && git commit -m "Migrate <slug> data app to data-app version N+1" -- data_apps/<slug> collections/data_apps。 该路径规范会把应用之外任何已暂存的内容排除在提交之外。 不推送,不做类型检查,不构建。如果用户问为什么,就说应用在最后一次升级 完成前无法编译。
  7. 如果 N+1 == target:在提交前运行 Step 3。

不要跨升级批次处理步骤。在第 5 项之前不要改动 version。

第 3 步 - 仅在目标版本进行的最终关卡

  1. npm run typecheck。在应用自身的源代码中修复失败。如果失败信息提到的 某个 SDK 符号没有任何升级指南提及,那是指南的缺口,而不是用户的问题: 展示确切的错误,说明本应由哪份指南覆盖它,然后停止。否则,最多进行三轮 修复,然后停止并询问。
  2. npm run check-resources,然后 npm run build,当应用的集合文件无法支撑 这些定义时,构建会拒绝打包。遵循它们的提示信息;两者都不会调用 Metabase。
  3. npm run dev,然后从 Vite 打印的 Local: 行中获取预览 URL。 模板要求使用端口 5174,但当该端口被占用时 Vite 会迁移到下一个空闲端口, 所以绝不要假定它就是该端口。打开该 URL,然后从同一来源读取一次诊断 feed:
    curl -s "<preview-url>/__data-app/diagnostics?startEventId=0"
    
    预期为 clients: 1,且没有任何条目的 "alert": true。clients: 0 表示 没有打开预览标签页,因此空的 feed 什么也证明不了。
  4. 从仓库根目录执行 git status 必须只显示:升级修改、 data_app.yaml、构建出的 bundle、应用集合文件(如果有升级改动了它们), 以及 package lockfile(如果 SDK 被重新锁定)。应用目录内的任何其他内容 都是用户修改;在提交前要说明这一点。
  5. 从仓库根目录执行 git add data_apps/<slug> collections/data_apps && git commit -m "Migrate <slug> data app to data-app version M" -- data_apps/<slug> collections/data_apps, 推送,并告诉用户在 Admin > Data apps 下点击 Pull changes。
  6. 证明它。拉取之后:
    ( source "$ROOT/.env.local"; curl -s -H "x-api-key: $DATA_APP_MB_API_KEY" "$DATA_APP_MB_URL/api/apps/<slug>" )
    
    必须显示 "version": M 和 "outdated": false。 仅包含 name 和 display_name 的响应意味着该 key 不属于管理员:请索取 一个管理员 key,或让用户读取管理员列表,并说明证明仍然待定。报告该命令 和结果。没有它就不要声称迁移已完成。

恢复被中断的迁移

新会话对上一次会话没有任何记忆,也不需要。从 Step 0 读取三个数字,以及 git status --porcelain -- data_apps/<slug>,然后:

treeworking-tree version含义操作
clean等于 HEAD每个已完成的升级都是一次提交;没有做到一半的事从 HEAD 版本继续循环
dirty等于 HEADHEAD -> HEAD+1 升级正在进行中,其检查尚未全部通过重新运行该升级的每个 Done when;只应用命令失败的步骤;从循环第 4 项继续
dirty等于 HEAD + 1所有检查都已通过,版本号也已写入,但缺少提交(或版本号写入后的最终门禁失败)重新运行该升级的 Done-check summary(全部 ok,或有人在版本号写入后编辑过:停止并显示 git diff);如果它就是目标,运行最终门禁;提交
any大于 HEAD + 1,或低于 HEAD不变量被破坏停止。 显示 git diff -- data_apps/<slug>/data_app.yaml 并询问是把这一个文件恢复到 HEAD 并重新推导,还是暂存这棵工作树。等待回答。

在 data_apps/<slug> 之外变脏的文件不属于你:绝不要对它们执行 git add。

汇报

每次升级一行,按顺序:v1 -> v2: done (commit abc1234) 或 v2 -> v3: blocked - <失败的确切 Done-when 命令及其输出>。 绝不要弱化失败的检查。将 tsc 输出按根本原因分组,保留少量有代表性的诊断信息,而不是整段粘贴。

绝不要做

  • 在升级的检查通过之前设置或编辑 version,或一次改动超过一个版本。
  • 跳过某个升级,或同时应用两个升级的步骤。
  • 在最后一次升级之前运行 npm run typecheck 或 npm run build,或在最终门禁通过之前推送。
  • 手工编辑 dist/ 或 src/metabase.data.ts,或更改应用的集合文件,或超出升级指南所述范围更改定义的实体 ID。
  • 从上一会话的聊天中复制某一步的结果,而不是重新运行其 Done when。
  • 在已有升级指南的情况下按自己的清单进行迁移;当你需要的升级没有指南时,停下来并说明这一点。

升级指南

指南位于 references/upgrades/,每个升级一份,命名为 v<N>-to-v<N+1>.md。它们由 Metabase 在契约版本被提升时根据 references/upgrade-guide-template.md 中的模板编写;references/maintainer-checklist.md 描述了该流程。你需要的升级缺少指南,说明技能安装有问题,而不是要靠临场发挥来绕过。

评论

支持 Markdown