
Strapi v4 到 v5 的自动化迁移集成测试tests/migration 测试体系全解【免费下载链接】strapi Strapi is the leading open-source headless CMS. It’s 100% JavaScript/TypeScript, fully customizable, and developer-first.项目地址: https://gitcode.com/GitHub_Trending/st/strapiStrapi 从 v4 升级到 v5 是一次涉及数据库 schema、迁移脚本与内部数据模型的深层变更官方为此构建了一套端到端的迁移集成测试体系以 npm 上发布的 v4 版本为基线播种真实数据再让当前 monorepoworkspace版本在同一个数据库上执行自动迁移并逐项校验迁移结果。本文以 tests/migration/README.md 为核心结合 场景运行器、校验框架 与 测试夹具 examples/complex 的源码完整讲解这套测试如何运行、如何配置、如何接入 CI以及如何做本地调试。读完本文你可以在本地跑通 v4→v5 迁移验证、读懂场景scenarioJSON 的编写规则并理解 CI 中migration_v5job 的触发条件与排障要点。整体架构fixture 与 runner 分离这套迁移测试采用「数据夹具」与「测试编排」双目录结构职责划分非常清晰examples/complex/workspace 名complex承载 Strapi 应用本体、内容类型 schema、种子脚本seeds、迁移校验脚本与数据库工具。从源码结构看它是完整的测试夹具应用而非普通示例项目——其 README 明确声明该目录是 test infrastructure, not a casual demo like getstarted。tests/migration/只拥有运行器与 CI 接线。该目录下的 README 原文说明fixture 路径是历史遗留未来可能整体迁移到tests/migration/之下在那之前CI 会同时监听两棵目录树见.github/filters.yaml。tests/migration/的内部结构可通过 目录 确认路径职责scripts/run-migration-scenario.ts入口 runner解析 CLI 参数与场景文件驱动全流程framework/基线构建v4/v5、版本解析、Docker 数据库管理、校验器调度等框架代码fixture/校验实现checks/、期望值推导derive-expectations、注册表及对应单元测试scenarios/v4-to-head.jsonCI 使用的规范场景canonical scenarioscenario-schema.json场景 JSON 的松散文档非运行时校验器CHECKPOINTS.md本地数据库快照调试指南快速上手四条核心命令README 给出的快速参考命令在根 package.json 中均有对应脚本test:migrations、test:migrations:plan、test:migrations:smoke、test:migrations:unit见 package.json#L102-L105实际均以node --import tsx tests/migration/scripts/run-migration-scenario.ts为底层入口# 本地快速冒烟dist 已构建时约 1–2 分钟 yarn test:migrations:smoke # 仅打印迁移计划秒级、不装依赖legacy 解析需要 npm yarn test:migrations:plan --initial legacy # 完整本地运行默认 sqlite已构建过就加 --skip-build yarn test:migrations --initial legacy --database sqlite --skip-build # 与 CI 相同的路径使用命名场景文件 yarn test:migrations --scenario tests/migration/scenarios/v4-to-head.json另有一条独立的单元测试命令用于校验 fixture 规范、校验器与 v4 脚手架模板的快速守卫也包含在 CI 的migration_v5中但不属于 nx 的test:unityarn test:migrations:unit关键参数--initial 与 --scenarioREADME 明确了两条核心约束--initial version起始 Strapi npm 版本必填除非传了--scenario。传legacy表示使用最新版 v4strapi/strapilegacy也可以传明确 semver如4.26.2。终点永远是 workspace即当前 monorepo不存在最终 Strapi 版本参数。--scenario可选加载 scenarios/v4-to-head.json 替代 CLI 旗标。从 runner 源码run-migration-scenario.ts#L260-L274可以确认当未传--scenario且--initial为空时进程会打印错误并退出提示必须传起始版本或使用场景文件错误信息中也再次强调了 The last step is alwaysworkspace。版本别名legacy以及源码中的latest-v4的解析逻辑在 framework/resolve-strapi-version.ts 中它执行npm view strapi/strapilegacy version将别名物化为具体 semver并把原始请求记入requestedInitialVersion字段以便日志追溯。场景文件baseline stages 的 JSON 模型规范场景 scenarios/v4-to-head.json 全文如下非常简洁{ $schema: ../scenario-schema.json, id: v4-to-head, description: Strapi v4 scaffold seed, then workspace Strapi (current monorepo) with full migration validators. This is the canonical path exercised in CI., dataOrigin: v4, baseline: { type: v4-scaffold, initialVersion: legacy }, stages: [ { id: workspace, type: workspace, validate: [full] } ] }结合 scenario-schema.json其$comment声明这是Loose documentation… not a runtime schema validator与 runner 中的assertScenarioShaperun-migration-scenario.ts#L203-L248场景的运行时硬约束为baseline.type只能是v4-scaffold或v5-pinned且必须有initialVersionstages必须非空数组其中workspace阶段恰好一个且必须是最后一个迁移永远终结于 workspace终结的workspace阶段必须带非空validate数组strapi-pinned类型阶段必须提供version。validate数组里可用的校验器名在 framework/validators.ts#L80-L130 的REGISTRY中定义fullv4 起源的完整校验等价full-v4-origin、full-v5-origin、full-ladder与 full 相同但跳过 DP join-table 源校验用于阶梯式/双次丢弃草稿场景。当通过 CLI 旗标构造场景且传了--via时runner 默认将校验器切换为full-ladder见--validators旗标描述run-migration-scenario.ts#L95-L99。CLI 旗标模式下还支持--via version可重复例如--via 5.30.0表示先播种、再逐个启动钉住版本的 Strapi、最后到 workspace的阶梯路径--multiplier N控制种子/校验数据量解析优先级为 CLI 环境变量MIGRATION_MULTIPLIER/SEED_MULTIPLIER 1run-migration-scenario.ts#L146-L156。Runner 的执行流程yarn test:migrations的完整流程对应 run-migration-scenario.ts 的run()函数可归纳为加载环境读取 tests/migration/v5/.env.example 对应的tests/migration/v5/.envDOTENV_PATH见 framework/context.ts#L16-L28参数与 Node 校验--initial/--scenario二选一断言--initial-node与--workspace-node别名是同一主机 Node major 守卫——因为 runner 是单一 Node 进程两者设置不同会直接退出run-migration-scenario.ts#L162-L183workspace 构建默认构建strapi/core与strapi/database两个 workspace测试加载的是packages/core/core/dist与packages/core/database/dist编译产物--build触发根目录全量yarn build--skip-build跳过并在日志中提示若结果疑似过期请重新构建这两个 workspaceframework/shared.ts#L261-L297版本物化与断言materializeScenarioVersions把legacy解析为具体版本assertScenarioShape校验场景结构v4 基线还会执行 Node ≤ 20 的引擎提示assertNodeForV4容器端口解析与状态清理postgres/mysql/mariadb 会通过get-port自动探测空闲宿主端口Postgres 5432、MySQL 3306、MariaDB 3307 为默认锚点然后执行docker compose down -v并rimraf掉examples/complex/.migration-v5/目录——每次运行都会删除迁移状态这正是 CHECKPOINTS.md 中在下次运行前拷贝数据库文件建议的原因构建基线v4-scaffold走runV4Baseline脚手架一个一次性 v4 应用并播种v5-pinned走runV5PinnedBaseline逐阶段推进strapi-pinned阶段启动钉住版本终结workspace阶段调用runValidators校验runValidators通过node --import tsx在examples/complex目录下执行 scripts/validate-migration.ts并把MIGRATION_MULTIPLIER、SEED_MULTIPLIER、MIGRATION_VALIDATOR_PROFILE、MIGRATION_DATA_ORIGIN注入环境framework/validators.ts#L31-L78。其中数据库环境变量由buildDatabaseEnvForClient统一生成framework/shared.ts#L104-L144mariadb 会被映射为DATABASE_CLIENTmysql因为 Strapi 只暴露 postgres | mysql | sqlite 三种 clientKnex 用 mysql2 驱动连 MariaDB默认账号/库名为strapisqlite 则使用固定文件examples/complex/.migration-v5/migration.sqlite。--print-plan模式只做解析输出包含baseline、pinned、stages、destination: workspace与将使用的 database/multiplier 的 JSON 计划后直接退出不触发任何构建、Docker 或嵌套安装——这是排查配置问题的首选手段。测试夹具 examples/complex 提供的能力README 反复指向examples/complex它不只是被校验的一方还提供了迁移测试的完整数据面8 个内容类型覆盖 v4→v5 迁移触及的全部特性面basic、basic-dp草稿/发布、basic-dp-i18n、relation关系 morphs 组件 动态区、relation-dp、relation-dp-i18n以及一对反模式压力 schemahc-m2m-source/hc-m2m-target——后者在--multiplier 100下产生约 2K×2K×10 fanout 2 万 join 行用于跨越copyRelationTableRows中 1000 行分页边界支持的数据库PostgreSQL 16${POSTGRES_PORT:-5432}、MySQL 8${MYSQL_PORT:-3306}、MariaDB 11宿主默认3307→ 容器3306、SQLite本地文件。容器运行时按podman compose→podman-compose→docker compose→docker-compose顺序自动探测可用STRAPI_BENCH_RUNTIMEpodman|docker覆盖数据库快照工具yarn db:snapshot:db name/db:restore:db/db:wipe:db/db:check:db快照落在 gitignored 的snapshots/目录Postgres 为.sqlSQLite 为原始文件拷贝校验器实现tests/migration/fixture/checks/ 下的 check 覆盖行数对账row-counts、join 表对账join-table-parity、关系 API 对账relation-api-parity、媒体对账media-parity、嵌套组件对账、草稿/发布配对、实体图谱与 DB morph 检查、document id 回填等由 checks/index.ts 汇总。CI 接入migration_v5 job 的触发与执行README 的 CI 章节给出了.github/workflows/tests.yml中migration_v5job 的精确行为可以归纳为三点执行命令在sqlite、postgres、mysql、mariadb矩阵上Node20yarn test:migrations --initial legacy --initial-node 20 --database matrix --skip-build其中legacy在 CI 上解析为 npm 的最新 Strapi v4strapi/strapilegacy该步骤使用timeout 25m作为安全上限runner 源码头注释同样注明 CI usestimeout 25mas a safety cap。触发条件job 在migrations路径过滤器匹配 PR/push diff 时运行具体的 glob 仅定义在.github/filters.yaml该文件中其他分组如global:相互独立。本地与 CI 的对等性CI parity——这是排障时最关键的细节README 逐条列出一次性应用.migration-v5/内的嵌套yarn install使用空yarn.lock独立项目标记并配合YARN_ENABLE_IMMUTABLE_INSTALLSfalse避免 PR 强化模式下 lockfile 被填充时报YN0028CI 还在 job 级设置YARN_ENABLE_IMMUTABLE_INSTALLS: false并传--initial-node 20对齐 runnerPostgres / MySQL / MariaDB 矩阵腿通过 examples/complex/docker-compose.dev.yml 启动 DB 容器CI 设置STRAPI_BENCH_RUNTIMEdocker且compose.ts在GITHUB_ACTIONStrue时优先 Docker因为 runner 上常安装了 Podman 但未运行若 CI 在嵌套安装阶段失败而本地通过先对比 Node major 版本再以--initial-node 20重跑。本地调试数据库检查点CHECKPOINTS由于 runner 每次运行都会删除examples/complex/.migration-v5/下的共享数据库状态sqlite 下即migration.sqliteCHECKPOINTS.md 给出了官方的检查点做法运行迁移测试后在下一次运行之前或在中断后另开终端拷贝数据库文件cp examples/complex/.migration-v5/migration.sqlite /tmp/after-baseline.sqlite用拷贝做查询或指向sqlite3工具。若要从检查点恢复而不重跑整个 harness可以手动把DATABASE_FILENAME或tests/migration/v5/.env中的等价变量指向该文件并手动启动 Strapi——文档明确这不是一等公民特性by design为避免快照泛滥该流程仅限本地调试CI 完全不基于存储的快照。总结tests/migration/是 Strapi v4→v5 数据迁移正确性的守门员它把从 npm 取 v4 基线 → 脚手架 播种 → workspace 自动迁移 → 逐项校验固化为可脚本化的场景baseline stages 模型用 examples/complex 夹具覆盖关系、i18n、草稿/发布、动态区乃至高基数 M2M 压力路径并通过migration_v5job 在四种数据库 × Node 20 的 CI 矩阵上持续回归。对开发者而言日常开发建议的入口是yarn test:migrations:plan确认计划、yarn test:migrations:smoke快速冒烟、yarn test:migrations --initial legacy --database sqlite --skip-build完整验证遇到嵌套安装类失败时优先对照上文 CI parity 清单核对 Node major 与 yarn 不可变安装设置。【免费下载链接】strapi Strapi is the leading open-source headless CMS. It’s 100% JavaScript/TypeScript, fully customizable, and developer-first.项目地址: https://gitcode.com/GitHub_Trending/st/strapi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考