Merge branch 'master' into editor-agent-more-tools
This commit is contained in:
@@ -4,6 +4,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- codex/ai-game-creator-app
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -97,9 +98,6 @@ jobs:
|
||||
- name: Run repository lint gates
|
||||
run: npm run lint
|
||||
|
||||
- name: Run frontend and script tests
|
||||
run: npm run test
|
||||
|
||||
- name: Build web applications
|
||||
run: npm run build
|
||||
|
||||
@@ -115,8 +113,28 @@ jobs:
|
||||
git cat-file -e "${base_ref}^{commit}"
|
||||
git diff --check "${base_ref}"...HEAD
|
||||
|
||||
backend-checks:
|
||||
name: Backend checks
|
||||
frontend-tests:
|
||||
name: Frontend tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Node.js 22
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
||||
with:
|
||||
node-version: '22'
|
||||
|
||||
- name: Install npm dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run frontend and script tests
|
||||
run: npm run test
|
||||
|
||||
backend-tests:
|
||||
name: Backend tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout full history
|
||||
@@ -144,6 +162,7 @@ jobs:
|
||||
clang \
|
||||
cmake \
|
||||
curl \
|
||||
ffmpeg \
|
||||
libclang-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libssl-dev \
|
||||
@@ -202,14 +221,17 @@ jobs:
|
||||
- name: Check server-rs boundaries
|
||||
run: npm run check:server-rs-ddd
|
||||
|
||||
- name: Run server-rs workspace tests
|
||||
run: cargo test --locked --workspace --no-fail-fast --manifest-path server-rs/Cargo.toml
|
||||
|
||||
- name: Check api-server targets
|
||||
run: cargo check --locked -p api-server --all-targets --manifest-path server-rs/Cargo.toml
|
||||
|
||||
- name: Check SpacetimeDB module
|
||||
run: cargo check --locked -p spacetime-module --manifest-path server-rs/Cargo.toml
|
||||
|
||||
native-shell-checks:
|
||||
name: Native shell checks
|
||||
native-shell-tests:
|
||||
name: Native shell tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout full history
|
||||
|
||||
@@ -264,12 +264,12 @@ npm run check:server-rs-ddd
|
||||
|
||||
## Gitea CI 与 PR 检查
|
||||
|
||||
- 仓库 CI 入口是 `.gitea/workflows/project-ci.yml`,向 `master` 推送和所有 PR 创建、更新时必须运行,也允许手工触发。
|
||||
- CI 固定拆分为 `Repository checks`、`Backend checks`、`Native shell checks` 三个 required job;对应 PR context 完整名称是 `Project CI / Repository checks (pull_request)`、`Project CI / Backend checks (pull_request)`、`Project CI / Native shell checks (pull_request)`,首次运行后仍须从 Gitea 最近一周 context 表复核。前两项覆盖仓库/Web 与后端边界/编译,原生壳验收单独运行以便定位重型构建失败。
|
||||
- 三个 job 共同覆盖 `npm run check`,并追加 `npm run check:server-rs-ddd`、`cargo check -p api-server --all-targets --manifest-path server-rs/Cargo.toml` 和 `cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml`。
|
||||
- 仓库 CI 入口是 `.gitea/workflows/project-ci.yml`,向 `master`、`codex/ai-game-creator-app` 推送和所有 PR 创建、更新时必须运行,也允许手工触发。
|
||||
- CI 固定拆分为 `Repository checks`、`Frontend tests`、`Backend tests`、`Native shell tests` 四个 required job;对应 PR context 完整名称是 `Project CI / Repository checks (pull_request)`、`Project CI / Frontend tests (pull_request)`、`Project CI / Backend tests (pull_request)`、`Project CI / Native shell tests (pull_request)`,首次运行后仍须从 Gitea 最近一周 context 表复核。测试使用独立 job,不能只藏在综合检查 step 中;原生壳验收单独运行以便定位重型构建失败。
|
||||
- 四个 job 共同覆盖 `npm run check`,并追加 `npm run check:server-rs-ddd`、`cargo test --locked --workspace --no-fail-fast --manifest-path server-rs/Cargo.toml`、`cargo check -p api-server --all-targets --manifest-path server-rs/Cargo.toml` 和 `cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml`。后端 runner 安装 `ffmpeg`,避免视频抽帧测试因工具缺失提前返回。`codex/ai-game-creator-app` 分支的原生壳入口还必须覆盖 `npm run ai-game-creator-shell:check` 和 release build smoke。
|
||||
- checkout 必须使用完整历史。PR 将 base SHA 写入 `SPACETIME_SCHEMA_BASE_REF`,直接推送 `master` 使用 before SHA;事件基线不可解析时直接失败。Gitea 检查的是 PR head 而非预合并 commit,workflow 必须拒绝不包含最新 base commit 的过期 PR,分支保护同时保持“PR 过期禁止合并”。
|
||||
- 普通 PR job 不读取业务 secret,不运行真实 API/SpacetimeDB/OSS/支付/生成/live smoke,也不执行会修改外部状态的维护、迁移、发布或备份命令。
|
||||
- Gitea 至少升级到 `1.26.4` 后才能注册执行 PR job 的 runner;`ubuntu-latest` 标签只映射到固定 digest 的 Ubuntu 24.04 级 Docker/临时隔离镜像,不使用浮动镜像 tag,不映射 host,不向 job 暴露 Docker socket、业务 secret 或不必要内网。runner 能访问 Gitea、GitHub Actions 与 `actions/node-versions`、nodejs.org、npm、Rust 分发和 crates.io;workflow 的官方 action 固定完整 commit,若内网禁用 GitHub,先在当前 Gitea 镜像对应 commit 并改用绝对 URL。受控镜像优先预装 rustup。Gitea 1.26 的任务超时由 runner 全局配置控制;首次运行成功后,`master` 分支保护必须要求上述三个 job 全部成功。
|
||||
- Gitea 至少升级到 `1.26.4` 后才能注册执行 PR job 的 runner;`ubuntu-latest` 标签只映射到固定 digest 的 Ubuntu 24.04 级 Docker/临时隔离镜像,不使用浮动镜像 tag,不映射 host,不向 job 暴露 Docker socket、业务 secret 或不必要内网。runner 能访问 Gitea、GitHub Actions 与 `actions/node-versions`、nodejs.org、npm、Rust 分发和 crates.io;workflow 的官方 action 固定完整 commit,若内网禁用 GitHub,先在当前 Gitea 镜像对应 commit 并改用绝对 URL。受控镜像优先预装 rustup。Gitea 1.26 的任务超时由 runner 全局配置控制;首次运行成功后,`master` 分支保护必须要求上述四个 job 全部成功。
|
||||
|
||||
## 后端相关默认验证
|
||||
|
||||
|
||||
@@ -200,19 +200,20 @@ npm run check
|
||||
|
||||
### Gitea Actions PR 门禁
|
||||
|
||||
仓库级 Gitea Actions 工作流固定为 `.gitea/workflows/project-ci.yml`,在向 `master` 推送、创建或更新 PR,以及手工触发时运行。工作流拆成三个必须通过的 job:
|
||||
仓库级 Gitea Actions 工作流固定为 `.gitea/workflows/project-ci.yml`,在向 `master` 或 `codex/ai-game-creator-app` 推送、创建或更新 PR,以及手工触发时运行。工作流拆成四个必须通过的 job:
|
||||
|
||||
- `Repository checks`:执行 `npm run lint`、完整 Vitest、主站与后台生产构建、内容数据检查和提交差异空白检查。
|
||||
- `Backend checks`:执行 `npm run check:server-rs-ddd`、`api-server --all-targets` 编译和 `spacetime-module` 编译。
|
||||
- `Native shell checks`:独立执行 `npm run check:native-shells`,覆盖微信壳、Expo 和 Tauri 的完整验收,并确认 Tauri `Cargo.lock` 没有被构建过程改写,避免把重型原生壳或依赖锁漂移隐藏在基础检查末尾。
|
||||
- `Repository checks`:执行 `npm run lint`、主站与后台生产构建、内容数据检查和提交差异空白检查。
|
||||
- `Frontend tests`:独立执行根 `npm run test`,让 Vitest 文件数和测试数在 Gitea job 列表中明确可见。
|
||||
- `Backend tests`:执行 `npm run check:server-rs-ddd`、`cargo test --locked --workspace --no-fail-fast`、`api-server --all-targets` 编译和 `spacetime-module` 编译;runner 安装 `ffmpeg`,避免视频抽帧测试因工具缺失提前返回。依赖真实服务或密钥的测试必须显式 `ignored`,不能让普通 PR job访问现场环境。
|
||||
- `Native shell tests`:独立执行 `npm run check:native-shells`,覆盖微信壳、Expo 和 Tauri 的完整验收,并确认 Tauri `Cargo.lock` 没有被构建过程改写,避免把重型原生壳或依赖锁漂移隐藏在基础检查末尾。`codex/ai-game-creator-app` 分支的同名脚本还会执行 `npm run ai-game-creator-shell:check` 和 AI 游戏创作壳 release build smoke。
|
||||
|
||||
三个 job 合起来覆盖根 `npm run check`,并补齐根检查没有包含的 server-rs DDD 与现役后端编译门禁。普通 PR CI 不注入业务密钥,不启动真实 API、SpacetimeDB、OSS、支付、图片生成或生产 live smoke;需要现场环境、可变外部状态、Docker 编排或发布凭据的 `check:*` 继续按对应专题和 Jenkins 发布流程执行,不能遍历所有同名前缀脚本冒充 PR 门禁。
|
||||
四个 job 合起来覆盖根 `npm run check`,并补齐根检查没有包含的 server-rs DDD、正式 workspace Rust 测试与现役后端编译门禁。普通 PR CI 不注入业务密钥,不启动真实 API、SpacetimeDB、OSS、支付、图片生成或生产 live smoke;需要现场环境、可变外部状态、Docker 编排或发布凭据的 `check:*` 继续按对应专题和 Jenkins 发布流程执行,不能遍历所有同名前缀脚本冒充 PR 门禁。
|
||||
|
||||
PR checkout 必须保留完整 Git 历史,并把 PR base SHA 传给 `SPACETIME_SCHEMA_BASE_REF`。`check:spacetime-schema` 依赖该基线识别已有表字段删除、改名、重排和改类型;事件给出的基线缺失或本地不可解析时必须直接失败,不能退化为空差异检查。Gitea 的 PR checkout 是 PR head,不是与目标分支的预合并 commit,因此 workflow 还会验证 PR head 包含事件中的最新 base commit;分支保护必须继续开启“PR 过期禁止合并”,过期分支先更新再重跑。向 `master` 直接推送时使用 push before SHA,手工触发时回退到 `origin/master`。
|
||||
|
||||
启用或注册执行 PR job 的 runner 前,Gitea 服务端必须至少升级到 `1.26.4`;不得在 `1.26.2` 上执行不受信任 PR 代码。runner 必须提供 `ubuntu-latest` 标签,并将其映射到经验证且固定 digest 的 Ubuntu 24.04 级 Docker/临时隔离镜像;禁止使用浮动镜像 tag,禁止将该标签映射到 host 执行器,禁止向 job 暴露 Docker socket、业务环境变量、业务密钥或不必要的内网。workflow 会安装 Node 22、仓库 `rust-toolchain.toml` 固定的 Rust 1.96.0,以及 clang/lld 和 Tauri Linux 依赖;受控 runner 镜像应预装 rustup,fallback 下载只用于首次引导。runner 仍需能访问 Gitea、GitHub Actions 与 `actions/node-versions`、nodejs.org、npm registry、Rust 分发和 crates.io。workflow 中的 `actions/checkout` / `actions/setup-node` 固定到完整 commit;内网 runner 不允许访问 GitHub 时,先把对应 commit 镜像到当前 Gitea 并把 workflow 改为绝对 action URL。首版不使用 Actions cache,避免未配置 runner cache 网络时把缓存恢复错误变成 PR 失败。Gitea 1.26 不执行 workflow 的 `timeout-minutes`,任务最长运行时间在 runner 全局配置收口,不能只在 YAML 写一个不会生效的超时值。
|
||||
|
||||
workflow 首次成功运行后,在 Gitea `master` 分支保护中把 `Project CI / Repository checks (pull_request)`、`Project CI / Backend checks (pull_request)`、`Project CI / Native shell checks (pull_request)` 三个完整 context 都设为合并必需检查,并从最近一周已上报 context 表复核名称后再保存。不能只填裸 job 名,否则无法匹配 Gitea 实际上报的 `<workflow> / <job> (<event>)`。只提交 workflow 文件不会自动创建 runner,也不会自动修改分支保护;如果 Actions 长时间停留在等待状态,先到仓库或组织的 Actions runner 页面确认存在在线、带 `ubuntu-latest` 标签的 runner。
|
||||
workflow 首次成功运行后,在 Gitea `master` 分支保护中把 `Project CI / Repository checks (pull_request)`、`Project CI / Frontend tests (pull_request)`、`Project CI / Backend tests (pull_request)`、`Project CI / Native shell tests (pull_request)` 四个完整 context 都设为合并必需检查,并从最近一周已上报 context 表复核名称后再保存。不能只填裸 job 名,否则无法匹配 Gitea 实际上报的 `<workflow> / <job> (<event>)`。只提交 workflow 文件不会自动创建 runner,也不会自动修改分支保护;如果 Actions 长时间停留在等待状态,先到仓库或组织的 Actions runner 页面确认存在在线、带 `ubuntu-latest` 标签的 runner。
|
||||
|
||||
视觉小说负向扫描与验收门禁:
|
||||
|
||||
|
||||
@@ -1702,8 +1702,8 @@ mod tests {
|
||||
serde_json::from_str(&editor_generation_result_payload_json(&job, &response))
|
||||
.expect("worker 结果应是合法 JSON");
|
||||
|
||||
assert_eq!(payload["sourceModule"], json!("puzzle"));
|
||||
assert_eq!(payload["sourceEntityId"], json!("session-1:puzzle-level-1"));
|
||||
assert_eq!(payload["sourceModule"], json!("editor"));
|
||||
assert_eq!(payload["sourceEntityId"], json!("project-1"));
|
||||
assert_eq!(
|
||||
payload["warning"],
|
||||
json!({
|
||||
|
||||
@@ -2682,7 +2682,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn profile_play_stats_requires_authentication() {
|
||||
async fn retired_profile_play_stats_route_is_not_mounted() {
|
||||
let app = build_router(AppState::new(AppConfig::default()).expect("state should build"));
|
||||
|
||||
let response = app
|
||||
@@ -2696,7 +2696,7 @@ mod tests {
|
||||
.await
|
||||
.expect("request should succeed");
|
||||
|
||||
assert_eq!(response.status(), StatusCode::UNAUTHORIZED);
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -198,7 +198,7 @@ fn generated_asset_sheet_muted_green_alpha_requires_explicit_option() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generated_asset_sheet_magenta_key_preserves_green_white_and_disconnected_key_subject() {
|
||||
fn generated_asset_sheet_magenta_key_preserves_subject_and_removes_internal_hole() {
|
||||
let mut sheet = RgbaImage::from_pixel(28, 28, Rgba([255, 0, 255, 255]));
|
||||
for y in 6..22 {
|
||||
for x in 6..14 {
|
||||
@@ -227,8 +227,8 @@ fn generated_asset_sheet_magenta_key_preserves_green_white_and_disconnected_key_
|
||||
assert_eq!(cleaned.get_pixel(18, 8).0[3], 255);
|
||||
assert_eq!(
|
||||
cleaned.get_pixel(13, 13).0[3],
|
||||
255,
|
||||
"非边缘连通的 key 色像素不应被当成背景清掉"
|
||||
0,
|
||||
"达到阈值的主体内部 key 色镂空区域应被清理"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ export default defineConfig({
|
||||
'src/services/activeAppTitle.test.ts',
|
||||
'src/services/authService.test.ts',
|
||||
'src/services/apiClient.test.ts',
|
||||
'src/services/clipboard.test.ts',
|
||||
'src/services/host-bridge/**/*.test.ts',
|
||||
'src/services/image-editor/**/*.test.ts',
|
||||
'src/services/external-generation/**/*.test.ts',
|
||||
@@ -43,6 +44,7 @@ export default defineConfig({
|
||||
'src/components/platform-entry/PlatformProfileWalletLedgerModal.test.tsx',
|
||||
'src/components/platform-entry/platformProfile*.test.ts',
|
||||
'src/components/platform-entry/usePlatformProfileCenterController.test.tsx',
|
||||
'src/hooks/useHostNavigationCanGoBack.test.tsx',
|
||||
'apps/admin-web/src/**/*.test.ts',
|
||||
'apps/admin-web/src/**/*.test.tsx',
|
||||
'miniprogram/**/*.test.js',
|
||||
|
||||
Reference in New Issue
Block a user