同步 CI 镜像 tag 与文档口径,并补上工具链一致性护栏
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Failing after 17s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Failing after 11s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Failing after 14s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Failing after 12s
Project CI / AI game creator shell Rust smoke (pull_request) Failing after 11s
Project CI / AI game creator shell Rust crates (pull_request) Failing after 10s
Project CI / Backend tests (pull_request) Failing after 10s
Project CI / Native shell tests (pull_request) Failing after 10s
Project CI / Frontend tests (pull_request) Failing after 5s
Project CI / Repository checks (pull_request) Failing after 11s
Project CI / AI game creator shell web tests (pull_request) Failing after 11s

- 将 CI job 镜像默认 tag 从 genarrative/gitea-project-ci:20260807.1 升为 20260920.1
- 将 Dockerfile 两处 org.opencontainers.image.version 统一为 2026.09.20.1(原先一处 2026.07.23.1、一处 2026.08.07.1,后写的覆盖先写的)
- 同步 deploy/container/README.md 与开发运维文档中的镜像归档示例名
- 订正 pitfalls.md 中 CI 镜像的 Rust 版本,并记录 number_of_links 在 1.98.1 上实测仍未稳定
- 在 decision-log.md 追加本次 Rust 工具链升级到 1.98.1 的决策条目
- 在 scripts/project-ci-workflow.test.ts 新增一致性用例:镜像版本段、digest 与 tag 必须与 rust-toolchain.toml 及两份运维文档一致
This commit is contained in:
2026-09-20 17:06:49 +08:00
parent e1c8edd6bf
commit a35cdcc68c
7 changed files with 83 additions and 8 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
dockerfile_context_path="deploy/container/gitea-ci-job.Dockerfile"
image_tag="${GENARRATIVE_GITEA_CI_IMAGE_TAG:-genarrative/gitea-project-ci:20260807.1}"
image_tag="${GENARRATIVE_GITEA_CI_IMAGE_TAG:-genarrative/gitea-project-ci:20260920.1}"
runner_container="${GENARRATIVE_GITEA_RUNNER_CONTAINER:-gitea-runner}"
write_build_context_file_list() {
+65
View File
@@ -35,6 +35,21 @@ const apiServerDockerfile = readFileSync(
'utf8',
);
const deployContainerReadme = readFileSync(
resolve(process.cwd(), 'deploy/container/README.md'),
'utf8',
);
const operationsDoc = readFileSync(
resolve(
process.cwd(),
'docs/【开发运维】本地开发验证与生产运维-2026-05-15.md',
),
'utf8',
);
const rustToolchainToml = readFileSync(
resolve(process.cwd(), 'rust-toolchain.toml'),
'utf8',
);
const jobNames = [
'repository-checks',
'frontend-tests',
@@ -551,4 +566,54 @@ describe('project CI workflow', () => {
cratesJob.indexOf('run: npm run check:native-shells:agc-rust-crates'),
);
});
// 预构建镜像的 Rust 版本分散在四处:rust-toolchain.toml 的 channel、Dockerfile 的
// RUST_IMAGE digest、构建脚本的默认 tag,以及两份运维文档。漏改任何一处都会让 job
// 在 runtime 校验里失败(`RUSTUP_AUTO_INSTALL=0` 不允许现场补装),或者让文档指向
// 已经不存在的镜像,所以这里把它们钉成同一个事实。
it('keeps the prebuilt CI job image Rust version, digest and tag in sync with the ops docs', () => {
const channel = rustToolchainToml.match(/^channel = "([^"]+)"$/mu)?.[1];
expect(channel).toBeTruthy();
const channelValue = channel ?? '';
const rustImage = imageDockerfile.match(
/^ARG RUST_IMAGE=([^\s@]+)@(sha256:[a-f0-9]{64})$/mu,
);
expect(rustImage).not.toBeNull();
const rustImageRef = rustImage?.[1] ?? '';
const rustImageDigest = rustImage?.[2] ?? '';
const [major, minor] = channelValue.split('.');
expect(rustImageRef).toBe(`rust:${major}.${minor}-bookworm`);
// 同一 Dockerfile 里可能出现在多个 LABEL 块中(后写的覆盖前者),必须同值,
// 否则镜像真实版本会和脚本、文档的说法分叉。
const labelVersions = [
...imageDockerfile.matchAll(
/org\.opencontainers\.image\.version="([0-9]{4}\.[0-9]{2}\.[0-9]{2}\.[0-9]+)"/gu,
),
].map((match) => match[1] ?? '');
expect(labelVersions.length).toBeGreaterThan(0);
expect(new Set(labelVersions).size).toBe(1);
const stampMatch = (labelVersions.at(-1) ?? '').match(
/^(\d{4})\.(\d{2})\.(\d{2})\.(\d+)$/u,
);
expect(stampMatch).not.toBeNull();
const imageTagStamp = `${stampMatch?.[1] ?? ''}${stampMatch?.[2] ?? ''}${
stampMatch?.[3] ?? ''
}.${stampMatch?.[4] ?? ''}`;
expect(imageBuildScript).toContain(
`genarrative/gitea-project-ci:${imageTagStamp}`,
);
for (const doc of [deployContainerReadme, operationsDoc]) {
expect(doc).toContain(rustImageDigest);
expect(doc).toContain(`Rust \`${channelValue}\``);
expect(doc).toContain(imageTagStamp);
}
// runtime 校验按 rust-toolchain.toml 的 channel 逐字比对镜像内工具链名,
// 所以基础镜像 digest 里的 RUST_VERSION 必须与 channel 完全相同。
expect(imageCheckScript).toContain(
'rustup toolchain list | rg -q "^${expected_toolchain}(-[^ ]+)?( |$)"',
);
});
});