0388fa0912
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
为Project CI增加同分支并发取消,避免旧运行覆盖新结果 将Vitest默认线程数固定为1,降低异步UI测试竞态
526 lines
21 KiB
YAML
526 lines
21 KiB
YAML
name: Project CI
|
||
|
||
on:
|
||
push:
|
||
branches:
|
||
- master
|
||
pull_request:
|
||
workflow_dispatch:
|
||
|
||
concurrency:
|
||
group: project-ci-${{ github.event.pull_request.number || github.ref }}
|
||
cancel-in-progress: true
|
||
|
||
permissions:
|
||
contents: read
|
||
|
||
env:
|
||
CI: 'true'
|
||
CARGO_INCREMENTAL: '0'
|
||
CARGO_HTTP_MULTIPLEXING: 'false'
|
||
CARGO_NET_RETRY: '10'
|
||
CARGO_TERM_COLOR: always
|
||
NPM_CONFIG_AUDIT: 'false'
|
||
NPM_CONFIG_FETCH_RETRIES: '10'
|
||
NPM_CONFIG_FETCH_RETRY_FACTOR: '2'
|
||
NPM_CONFIG_FETCH_RETRY_MAXTIMEOUT: '60000'
|
||
NPM_CONFIG_FETCH_RETRY_MINTIMEOUT: '2000'
|
||
NPM_CONFIG_FUND: 'false'
|
||
NPM_CONFIG_PREFER_OFFLINE: 'true'
|
||
RUSTUP_AUTO_INSTALL: '0'
|
||
RUSTC_WRAPPER: ''
|
||
CARGO_BUILD_RUSTC_WRAPPER: ''
|
||
|
||
# job 声明顺序就是 runner 领取顺序,因此把最长尾的客户端 Rust 门禁排在前面,
|
||
# 让它在最少的等待下占用并发槽位;其余 job 按时长递减排列。
|
||
#
|
||
# 客户端(微信壳 / Expo 移动壳 / Tauri 桌面壳 / AI 游戏创作壳)门禁原先全部串在
|
||
# `Native shell tests` 一个 job 里,实测 18 分 37 秒。现在按门禁组拆成一个分组一个 job:
|
||
# `Native shell tests`(契约 + H5 / 微信 / 移动 / 桌面壳门禁 + 发布构建 smoke)、
|
||
# `AI game creator shell web tests`(typecheck + 壳内测试)、`AI game creator shell
|
||
# Rust shard 1/4` 到 `4/4`(AGC 壳 bin 单测按名单分 4 片)、`AI game creator shell
|
||
# Rust smoke`(agent-run smoke)与 `AI game creator shell Rust crates`(AGC 壳依赖的
|
||
# 共享 / 平台 crate 测试)。各自的命令与拆分前逐一对应,本地
|
||
# `npm run check:native-shells` 仍是同一条串行序列。
|
||
#
|
||
# AGC 壳的 bin 单测(2466 条)按名单分 4 片、一片一个 job:片内保持 `--test-threads=1`
|
||
# (当年线程并行会互相干扰的是进程内后台锁与异步终态),片与片之间靠 job 级并发摊开。
|
||
# 不要改回「一个 job 里多进程并行这几片」:同一容器内它们会争抢共享 HOME、target 与固定
|
||
# 临时路径,实测比整套串行还慢。每个分片 job 都会自校验「片并集等于全集且互斥」。
|
||
jobs:
|
||
# AGC 壳自身的 Rust bin 单测分片,4 片各自独立 job 并发执行、片内仍保持
|
||
# `--test-threads=1`。这里不装 npm 依赖:壳 Rust 门禁只用 cargo 与 node 内建模块,
|
||
# 也只需要 AGC 壳自己那份锁定依赖。
|
||
ai-game-creator-shell-rust-shard-1:
|
||
name: AI game creator shell Rust shard 1/4
|
||
runs-on: genarrative-ci
|
||
steps:
|
||
- name: Checkout full history from Gitea
|
||
env:
|
||
GENARRATIVE_GITEA_FETCH_DEPTH: '0'
|
||
GENARRATIVE_GITEA_TOKEN: ${{ github.token }}
|
||
run: genarrative-gitea-checkout
|
||
|
||
- name: Validate preinstalled CI job image and sandbox
|
||
run: GENARRATIVE_GITEA_CI_CHECK_RUNTIME=1 bash scripts/check-gitea-ci-job-image.sh
|
||
|
||
- name: Prepare AI game creator shell Rust dependencies
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
# AGC 壳有独立 Cargo.lock,其 path 依赖已含 platform-llm、platform-agent、
|
||
# agent-runtime-core 与 shared-contracts,因此只锁这一份 manifest 就能覆盖壳测试
|
||
# 与 smoke 的全部第三方依赖;server-rs 那次预热归 crate 级 job,不在这里重复。
|
||
for attempt in $(seq 1 5); do
|
||
if cargo fetch --locked \
|
||
--target x86_64-unknown-linux-gnu \
|
||
--manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml; then
|
||
break
|
||
fi
|
||
if [[ "${attempt}" -eq 5 ]]; then
|
||
echo 'AI game creator shell Cargo dependency fetch failed after 5 attempts.' >&2
|
||
exit 1
|
||
fi
|
||
sleep $((attempt * 2))
|
||
done
|
||
|
||
- name: Run AI game creator shell Rust shard 1/4
|
||
run: npm run check:native-shells:agc-rust-shard-1
|
||
|
||
ai-game-creator-shell-rust-shard-2:
|
||
name: AI game creator shell Rust shard 2/4
|
||
runs-on: genarrative-ci
|
||
steps:
|
||
- name: Checkout full history from Gitea
|
||
env:
|
||
GENARRATIVE_GITEA_FETCH_DEPTH: '0'
|
||
GENARRATIVE_GITEA_TOKEN: ${{ github.token }}
|
||
run: genarrative-gitea-checkout
|
||
|
||
- name: Validate preinstalled CI job image and sandbox
|
||
run: GENARRATIVE_GITEA_CI_CHECK_RUNTIME=1 bash scripts/check-gitea-ci-job-image.sh
|
||
|
||
- name: Prepare AI game creator shell Rust dependencies
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
for attempt in $(seq 1 5); do
|
||
if cargo fetch --locked \
|
||
--target x86_64-unknown-linux-gnu \
|
||
--manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml; then
|
||
break
|
||
fi
|
||
if [[ "${attempt}" -eq 5 ]]; then
|
||
echo 'AI game creator shell Cargo dependency fetch failed after 5 attempts.' >&2
|
||
exit 1
|
||
fi
|
||
sleep $((attempt * 2))
|
||
done
|
||
|
||
- name: Run AI game creator shell Rust shard 2/4
|
||
run: npm run check:native-shells:agc-rust-shard-2
|
||
|
||
ai-game-creator-shell-rust-shard-3:
|
||
name: AI game creator shell Rust shard 3/4
|
||
runs-on: genarrative-ci
|
||
steps:
|
||
- name: Checkout full history from Gitea
|
||
env:
|
||
GENARRATIVE_GITEA_FETCH_DEPTH: '0'
|
||
GENARRATIVE_GITEA_TOKEN: ${{ github.token }}
|
||
run: genarrative-gitea-checkout
|
||
|
||
- name: Validate preinstalled CI job image and sandbox
|
||
run: GENARRATIVE_GITEA_CI_CHECK_RUNTIME=1 bash scripts/check-gitea-ci-job-image.sh
|
||
|
||
- name: Prepare AI game creator shell Rust dependencies
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
for attempt in $(seq 1 5); do
|
||
if cargo fetch --locked \
|
||
--target x86_64-unknown-linux-gnu \
|
||
--manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml; then
|
||
break
|
||
fi
|
||
if [[ "${attempt}" -eq 5 ]]; then
|
||
echo 'AI game creator shell Cargo dependency fetch failed after 5 attempts.' >&2
|
||
exit 1
|
||
fi
|
||
sleep $((attempt * 2))
|
||
done
|
||
|
||
- name: Run AI game creator shell Rust shard 3/4
|
||
run: npm run check:native-shells:agc-rust-shard-3
|
||
|
||
ai-game-creator-shell-rust-shard-4:
|
||
name: AI game creator shell Rust shard 4/4
|
||
runs-on: genarrative-ci
|
||
steps:
|
||
- name: Checkout full history from Gitea
|
||
env:
|
||
GENARRATIVE_GITEA_FETCH_DEPTH: '0'
|
||
GENARRATIVE_GITEA_TOKEN: ${{ github.token }}
|
||
run: genarrative-gitea-checkout
|
||
|
||
- name: Validate preinstalled CI job image and sandbox
|
||
run: GENARRATIVE_GITEA_CI_CHECK_RUNTIME=1 bash scripts/check-gitea-ci-job-image.sh
|
||
|
||
- name: Prepare AI game creator shell Rust dependencies
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
for attempt in $(seq 1 5); do
|
||
if cargo fetch --locked \
|
||
--target x86_64-unknown-linux-gnu \
|
||
--manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml; then
|
||
break
|
||
fi
|
||
if [[ "${attempt}" -eq 5 ]]; then
|
||
echo 'AI game creator shell Cargo dependency fetch failed after 5 attempts.' >&2
|
||
exit 1
|
||
fi
|
||
sleep $((attempt * 2))
|
||
done
|
||
|
||
- name: Run AI game creator shell Rust shard 4/4
|
||
run: npm run check:native-shells:agc-rust-shard-4
|
||
|
||
# agent-run smoke 会 spawn `cargo run`(走壳自己的 manifest),同样不装 npm 依赖,
|
||
# 单独一个 job,免得把已经压到 4 分钟级的片 job 拖长。
|
||
ai-game-creator-shell-rust-smoke:
|
||
name: AI game creator shell Rust smoke
|
||
runs-on: genarrative-ci
|
||
steps:
|
||
- name: Checkout full history from Gitea
|
||
env:
|
||
GENARRATIVE_GITEA_FETCH_DEPTH: '0'
|
||
GENARRATIVE_GITEA_TOKEN: ${{ github.token }}
|
||
run: genarrative-gitea-checkout
|
||
|
||
- name: Validate preinstalled CI job image and sandbox
|
||
run: GENARRATIVE_GITEA_CI_CHECK_RUNTIME=1 bash scripts/check-gitea-ci-job-image.sh
|
||
|
||
- name: Prepare AI game creator shell Rust dependencies
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
for attempt in $(seq 1 5); do
|
||
if cargo fetch --locked \
|
||
--target x86_64-unknown-linux-gnu \
|
||
--manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml; then
|
||
break
|
||
fi
|
||
if [[ "${attempt}" -eq 5 ]]; then
|
||
echo 'AI game creator shell Cargo dependency fetch failed after 5 attempts.' >&2
|
||
exit 1
|
||
fi
|
||
sleep $((attempt * 2))
|
||
done
|
||
|
||
- name: Run AI game creator shell agent-run smoke
|
||
run: npm run check:native-shells:agc-rust-smoke
|
||
|
||
# AGC 壳依赖的共享 / 平台 crate 测试用的是 server-rs workspace 与两个无锁独立 crate
|
||
# 的 manifest,属另一套依赖图,因此单独一个 job 预热、单独跑。
|
||
ai-game-creator-shell-rust-crates:
|
||
name: AI game creator shell Rust crates
|
||
runs-on: genarrative-ci
|
||
steps:
|
||
- name: Checkout full history from Gitea
|
||
env:
|
||
GENARRATIVE_GITEA_FETCH_DEPTH: '0'
|
||
GENARRATIVE_GITEA_TOKEN: ${{ github.token }}
|
||
run: genarrative-gitea-checkout
|
||
|
||
- name: Validate preinstalled CI job image and sandbox
|
||
run: GENARRATIVE_GITEA_CI_CHECK_RUNTIME=1 bash scripts/check-gitea-ci-job-image.sh
|
||
|
||
- name: Prepare server-rs Rust dependencies
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
for attempt in $(seq 1 5); do
|
||
if cargo fetch --locked \
|
||
--target x86_64-unknown-linux-gnu \
|
||
--manifest-path server-rs/Cargo.toml; then
|
||
break
|
||
fi
|
||
if [[ "${attempt}" -eq 5 ]]; then
|
||
echo 'server-rs Cargo dependency fetch failed after 5 attempts.' >&2
|
||
exit 1
|
||
fi
|
||
sleep $((attempt * 2))
|
||
done
|
||
|
||
- name: Prepare standalone Rust crate dependencies
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
# agent-runtime-core / agent-runtime-orchestration 被 server-rs/Cargo.toml 的
|
||
# exclude 排除,不参与上面的 workspace 锁文件,因此上面那次锁定 fetch 覆盖不到它们;
|
||
# 而 `npm run ai-game-creator-shell:check:rust:crates` 会用
|
||
# `cargo test --manifest-path` 单独跑这两个 crate。不在这里预热的话,这两条测试
|
||
# 会在测试阶段自己 `Updating crates.io index`,crates.io 一抖动整条 job 就红
|
||
# (见 #327 / PR #316 run 1950)。
|
||
# 两个 crate 都没有提交 Cargo.lock,所以这里只能做不带锁标志的 fetch:
|
||
# 加锁标志会因为缺少锁文件直接失败。生成的 Cargo.lock 落在两个 crate 目录内,
|
||
# 已被各自的 .gitignore 忽略,只留在容器里;随后的测试阶段因此能用锁定版本
|
||
# 解析,不再触碰 registry index。
|
||
for manifest_path in \
|
||
server-rs/crates/agent-runtime-core/Cargo.toml \
|
||
server-rs/crates/agent-runtime-orchestration/Cargo.toml; do
|
||
for attempt in $(seq 1 5); do
|
||
if cargo fetch \
|
||
--target x86_64-unknown-linux-gnu \
|
||
--manifest-path "${manifest_path}"; then
|
||
break
|
||
fi
|
||
if [[ "${attempt}" -eq 5 ]]; then
|
||
echo "standalone crate dependency fetch failed after 5 attempts: ${manifest_path}" >&2
|
||
exit 1
|
||
fi
|
||
sleep $((attempt * 2))
|
||
done
|
||
done
|
||
|
||
- name: Run AI game creator shell shared crate gates
|
||
run: npm run check:native-shells:agc-rust-crates
|
||
|
||
backend-tests:
|
||
name: Backend tests
|
||
runs-on: genarrative-ci
|
||
steps:
|
||
- name: Checkout full history from Gitea
|
||
env:
|
||
GENARRATIVE_GITEA_FETCH_DEPTH: '0'
|
||
GENARRATIVE_GITEA_TOKEN: ${{ github.token }}
|
||
run: genarrative-gitea-checkout
|
||
|
||
- name: Validate preinstalled CI job image and sandbox
|
||
run: GENARRATIVE_GITEA_CI_CHECK_RUNTIME=1 bash scripts/check-gitea-ci-job-image.sh
|
||
|
||
- name: Resolve comparison base
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
base_ref="$(node -e '
|
||
const fs = require("node:fs");
|
||
const event = JSON.parse(fs.readFileSync(process.env.GITHUB_EVENT_PATH, "utf8"));
|
||
process.stdout.write(event.pull_request?.base?.sha ?? event.before ?? "");
|
||
')"
|
||
if [[ -n "${base_ref}" && ! "${base_ref}" =~ ^0+$ ]]; then
|
||
git cat-file -e "${base_ref}^{commit}" 2>/dev/null || {
|
||
echo "comparison base commit is unavailable: ${base_ref}" >&2
|
||
exit 1
|
||
}
|
||
else
|
||
base_ref="$(git merge-base HEAD origin/master 2>/dev/null || git rev-parse HEAD)"
|
||
fi
|
||
resolved_base_ref="$(git rev-parse --verify "${base_ref}^{commit}" 2>/dev/null || true)"
|
||
head_ref="$(git rev-parse HEAD)"
|
||
if [[ "${resolved_base_ref}" == "${head_ref}" ]]; then
|
||
resolved_base_ref="$(git rev-parse --verify HEAD^ 2>/dev/null || true)"
|
||
fi
|
||
if [[ -z "${resolved_base_ref}" ]]; then
|
||
echo 'comparison base must resolve to a commit distinct from HEAD.' >&2
|
||
exit 1
|
||
fi
|
||
base_ref="${resolved_base_ref}"
|
||
if [[ "${GITHUB_EVENT_NAME:-}" == 'pull_request' ]] \
|
||
&& ! git merge-base --is-ancestor "${base_ref}" HEAD; then
|
||
echo 'pull request head does not contain the latest base commit; update the branch and rerun CI.' >&2
|
||
exit 1
|
||
fi
|
||
echo "SPACETIME_SCHEMA_BASE_REF=${base_ref}" >> "${GITHUB_ENV}"
|
||
|
||
- name: Install npm dependencies
|
||
run: bash scripts/ci-npm-ci-with-retry.sh
|
||
|
||
- name: Prepare server-rs Rust dependencies
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
for attempt in $(seq 1 5); do
|
||
if cargo fetch --locked \
|
||
--target x86_64-unknown-linux-gnu \
|
||
--manifest-path server-rs/Cargo.toml; then
|
||
break
|
||
fi
|
||
if [[ "${attempt}" -eq 5 ]]; then
|
||
echo 'server-rs Cargo dependency fetch failed after 5 attempts.' >&2
|
||
exit 1
|
||
fi
|
||
sleep $((attempt * 2))
|
||
done
|
||
|
||
- name: Check server-rs boundaries
|
||
run: npm run check:server-rs-ddd
|
||
|
||
- name: Run server-rs workspace tests
|
||
run: cargo test --locked --workspace --exclude spacetime-module --no-fail-fast --manifest-path server-rs/Cargo.toml
|
||
|
||
- name: Run SpacetimeDB module unit tests
|
||
run: cargo test --locked -p spacetime-module --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
|
||
|
||
# 客户端的壳级与契约门禁:静态契约断言、H5 / 微信 / 移动 / 桌面壳运行时门禁,
|
||
# 以及依赖发布产物的构建 smoke。
|
||
native-shell-tests:
|
||
name: Native shell tests
|
||
runs-on: genarrative-ci
|
||
steps:
|
||
- name: Checkout full history from Gitea
|
||
env:
|
||
GENARRATIVE_GITEA_FETCH_DEPTH: '0'
|
||
GENARRATIVE_GITEA_TOKEN: ${{ github.token }}
|
||
run: genarrative-gitea-checkout
|
||
|
||
- name: Validate preinstalled CI job image and sandbox
|
||
run: GENARRATIVE_GITEA_CI_CHECK_RUNTIME=1 bash scripts/check-gitea-ci-job-image.sh
|
||
|
||
- name: Install npm dependencies
|
||
run: bash scripts/ci-npm-ci-with-retry.sh
|
||
|
||
- name: Prepare native Rust dependencies
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
for manifest_path in \
|
||
apps/desktop-shell/src-tauri/Cargo.toml \
|
||
apps/ai-game-creator-shell/src-tauri/Cargo.toml; do
|
||
for attempt in $(seq 1 5); do
|
||
if cargo fetch --locked \
|
||
--target x86_64-unknown-linux-gnu \
|
||
--manifest-path "${manifest_path}"; then
|
||
break
|
||
fi
|
||
if [[ "${attempt}" -eq 5 ]]; then
|
||
echo "Cargo dependency fetch failed after 5 attempts: ${manifest_path}" >&2
|
||
exit 1
|
||
fi
|
||
sleep $((attempt * 2))
|
||
done
|
||
done
|
||
|
||
- name: Run native shell contract gates
|
||
run: npm run check:native-shells:contract
|
||
|
||
- name: Run native shell gates
|
||
run: npm run check:native-shells:shells
|
||
|
||
- name: Run native shell release build smoke
|
||
run: npm run check:native-shells:release
|
||
|
||
- name: Ensure native lockfiles are unchanged
|
||
run: git diff --exit-code -- apps/desktop-shell/src-tauri/Cargo.lock apps/ai-game-creator-shell/src-tauri/Cargo.lock
|
||
|
||
frontend-tests:
|
||
name: Frontend tests
|
||
runs-on: genarrative-ci
|
||
steps:
|
||
- name: Checkout source from Gitea
|
||
env:
|
||
GENARRATIVE_GITEA_FETCH_DEPTH: '1'
|
||
GENARRATIVE_GITEA_TOKEN: ${{ github.token }}
|
||
run: genarrative-gitea-checkout
|
||
|
||
- name: Validate preinstalled CI job image and sandbox
|
||
run: GENARRATIVE_GITEA_CI_CHECK_RUNTIME=1 bash scripts/check-gitea-ci-job-image.sh
|
||
|
||
- name: Install npm dependencies
|
||
run: bash scripts/ci-npm-ci-with-retry.sh
|
||
|
||
- name: Run frontend and script tests
|
||
run: npm run test
|
||
|
||
- name: Run BgFilter worker smoke harness tests
|
||
run: npm run bgfilter-worker:smoke-test
|
||
|
||
- name: Validate production health patrol behavior
|
||
run: npm run check:production-health-patrol
|
||
|
||
- name: Validate production API release behavior
|
||
run: npm run check:production-api-release
|
||
|
||
- name: Validate production API deploy behavior
|
||
run: npm run check:production-api-deploy
|
||
|
||
repository-checks:
|
||
name: Repository checks
|
||
runs-on: genarrative-ci
|
||
steps:
|
||
- name: Checkout full history from Gitea
|
||
env:
|
||
GENARRATIVE_GITEA_FETCH_DEPTH: '0'
|
||
GENARRATIVE_GITEA_TOKEN: ${{ github.token }}
|
||
run: genarrative-gitea-checkout
|
||
|
||
- name: Validate preinstalled CI job image and sandbox
|
||
run: GENARRATIVE_GITEA_CI_CHECK_RUNTIME=1 bash scripts/check-gitea-ci-job-image.sh
|
||
|
||
- name: Resolve comparison base
|
||
shell: bash
|
||
run: |
|
||
set -euo pipefail
|
||
base_ref="$(node -e '
|
||
const fs = require("node:fs");
|
||
const event = JSON.parse(fs.readFileSync(process.env.GITHUB_EVENT_PATH, "utf8"));
|
||
process.stdout.write(event.pull_request?.base?.sha ?? event.before ?? "");
|
||
')"
|
||
if [[ -n "${base_ref}" && ! "${base_ref}" =~ ^0+$ ]]; then
|
||
git cat-file -e "${base_ref}^{commit}" 2>/dev/null || {
|
||
echo "comparison base commit is unavailable: ${base_ref}" >&2
|
||
exit 1
|
||
}
|
||
else
|
||
base_ref="$(git merge-base HEAD origin/master 2>/dev/null || git rev-parse HEAD)"
|
||
fi
|
||
resolved_base_ref="$(git rev-parse --verify "${base_ref}^{commit}" 2>/dev/null || true)"
|
||
head_ref="$(git rev-parse HEAD)"
|
||
if [[ "${resolved_base_ref}" == "${head_ref}" ]]; then
|
||
resolved_base_ref="$(git rev-parse --verify HEAD^ 2>/dev/null || true)"
|
||
fi
|
||
if [[ -z "${resolved_base_ref}" ]]; then
|
||
echo 'comparison base must resolve to a commit distinct from HEAD.' >&2
|
||
exit 1
|
||
fi
|
||
base_ref="${resolved_base_ref}"
|
||
if [[ "${GITHUB_EVENT_NAME:-}" == 'pull_request' ]] \
|
||
&& ! git merge-base --is-ancestor "${base_ref}" HEAD; then
|
||
echo 'pull request head does not contain the latest base commit; update the branch and rerun CI.' >&2
|
||
exit 1
|
||
fi
|
||
echo "SPACETIME_SCHEMA_BASE_REF=${base_ref}" >> "${GITHUB_ENV}"
|
||
|
||
- name: Install npm dependencies
|
||
run: bash scripts/ci-npm-ci-with-retry.sh
|
||
|
||
- name: Run repository checks
|
||
run: npm run check:repository-ci
|
||
|
||
# 客户端的 AI 游戏创作壳前端门禁:typecheck 与壳内测试,不触碰 Cargo。
|
||
ai-game-creator-shell-web-tests:
|
||
name: AI game creator shell web tests
|
||
runs-on: genarrative-ci
|
||
steps:
|
||
- name: Checkout full history from Gitea
|
||
env:
|
||
GENARRATIVE_GITEA_FETCH_DEPTH: '0'
|
||
GENARRATIVE_GITEA_TOKEN: ${{ github.token }}
|
||
run: genarrative-gitea-checkout
|
||
|
||
- name: Validate preinstalled CI job image and sandbox
|
||
run: GENARRATIVE_GITEA_CI_CHECK_RUNTIME=1 bash scripts/check-gitea-ci-job-image.sh
|
||
|
||
- name: Install npm dependencies
|
||
run: bash scripts/ci-npm-ci-with-retry.sh
|
||
|
||
- name: Run AI game creator shell web gates
|
||
run: npm run check:native-shells:agc-web
|