diff --git a/.gitea/workflows/project-ci.yml b/.gitea/workflows/project-ci.yml index 1602c9325..d796f3d91 100644 --- a/.gitea/workflows/project-ci.yml +++ b/.gitea/workflows/project-ci.yml @@ -232,6 +232,37 @@ jobs: done 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 覆盖不到它们; + # 而 check:native-shells 会经 agent-runtime-*:check 用 `cargo test --manifest-path` + # 单独跑这两个 crate。不在这里预热的话,这两条测试会在测试阶段自己 + # `Updating crates.io index`,crates.io 一抖动整条 native shell 作业就红 + # (见 #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 native shell gates run: npm run check:native-shells diff --git a/scripts/project-ci-workflow.test.ts b/scripts/project-ci-workflow.test.ts index 0e1fd681b..03eee48c6 100644 --- a/scripts/project-ci-workflow.test.ts +++ b/scripts/project-ci-workflow.test.ts @@ -321,4 +321,26 @@ describe('project CI workflow', () => { expect(nativeJob).toContain('server-rs/Cargo.toml'); expect(nativeJob).toContain('cargo fetch --locked'); }); + + it('prefetches the excluded standalone Rust crates before the native shell gates', () => { + const standaloneStep = stepSection( + 'native-shell-tests', + 'Prepare standalone Rust crate dependencies', + ); + for (const manifest of [ + 'server-rs/crates/agent-runtime-core/Cargo.toml', + 'server-rs/crates/agent-runtime-orchestration/Cargo.toml', + ]) { + expect(standaloneStep).toContain(manifest); + } + // 这两个 crate 没有提交 Cargo.lock,只能用不带 --locked 的 fetch: + // 带 --locked 会因为缺少锁文件直接失败。 + expect(standaloneStep).toContain('cargo fetch \\'); + expect(standaloneStep).not.toContain('cargo fetch --locked'); + + const nativeJob = jobSection('native-shell-tests'); + expect( + nativeJob.indexOf('Prepare standalone Rust crate dependencies'), + ).toBeLessThan(nativeJob.indexOf('run: npm run check:native-shells')); + }); });