修复 CI 缓存镜像组装的基础镜像引用
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 Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (push) Successful in 1m18s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m50s
Project CI / Backend tests (push) Successful in 3m40s
Project CI / Frontend tests (push) Successful in 2m0s
Project CI / AI game creator shell Rust lane 2/2 (push) Successful in 7m13s
Project CI / Native shell tests (push) Successful in 5m47s
Project CI / AI game creator shell Rust lane 1/2 (push) Successful in 8m34s
Project CI / AI game creator shell web tests (push) Successful in 1m32s
Project CI / Repository checks (push) Successful in 1m55s
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 Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (push) Successful in 1m18s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m50s
Project CI / Backend tests (push) Successful in 3m40s
Project CI / Frontend tests (push) Successful in 2m0s
Project CI / AI game creator shell Rust lane 2/2 (push) Successful in 7m13s
Project CI / Native shell tests (push) Successful in 5m47s
Project CI / AI game creator shell Rust lane 1/2 (push) Successful in 8m34s
Project CI / AI game creator shell web tests (push) Successful in 1m32s
Project CI / Repository checks (push) Successful in 1m55s
使用临时本地标签和宿主默认 builder 组装缓存镜像 组装成功或失败后清理临时标签,保持基础镜像清理归属 补充基础镜像复用、重建及失败清理测试 同步部署文档和项目共享记忆
This commit was merged in pull request #484.
This commit is contained in:
@@ -519,14 +519,22 @@ class Maintenance:
|
||||
shutil.copyfile(inherited / "sccache", snapshot / "sccache")
|
||||
(snapshot / "sccache").chmod(0o755)
|
||||
(snapshot / "base-image.txt").write_text(base + "\n")
|
||||
# BuildKit 的 FROM 不接受裸 Image ID;维护锁内使用一个临时本地别名。
|
||||
# 别名不登记为 owned base,避免把接管前的基础镜像纳入自动清理。
|
||||
assembly_base = "genarrative/gitea-project-ci:assembly-base"
|
||||
(work / "Dockerfile").write_text(
|
||||
f"FROM {base}\nCOPY snapshot/ /opt/genarrative-ci/rust-cache/\n"
|
||||
f"FROM {assembly_base}\nCOPY snapshot/ /opt/genarrative-ci/rust-cache/\n"
|
||||
f'LABEL world.genarrative.ci.rust-cache-source="{sha}"\n'
|
||||
f'LABEL world.genarrative.ci.rust-cache-base="{base}"\n')
|
||||
(work / ".dockerignore").write_text("**\n!Dockerfile\n!snapshot/\n!snapshot/**\n")
|
||||
with operation("assemble cache candidate image", build_log=build_log):
|
||||
with build_log.open("a") as out:
|
||||
self.docker("build", "--pull=false", "--tag", tag, str(work), output=out, timeout=1800)
|
||||
self.docker("image", "tag", base, assembly_base)
|
||||
try:
|
||||
with build_log.open("a") as out:
|
||||
self.docker("build", "--builder", "default", "--pull=false", "--tag", tag,
|
||||
str(work), output=out, timeout=1800)
|
||||
finally:
|
||||
self.docker("image", "rm", assembly_base)
|
||||
self.build_command(build_log, "gitea-ci-job-image.sh", "verify", tag, env=env,
|
||||
description="verify cache candidate image")
|
||||
image = self.image_info(tag)["Id"]
|
||||
|
||||
@@ -374,15 +374,27 @@ class GiteaCacheMaintenanceTest(unittest.TestCase):
|
||||
self.assertIsNone(self.select_source(instance))
|
||||
|
||||
def test_assembly_uses_ci_objects_and_trusted_binary_without_warming_compiler(self):
|
||||
self.assert_assembly()
|
||||
|
||||
def test_assembly_uses_rebuilt_local_base(self):
|
||||
self.assert_assembly(rebuild=True)
|
||||
|
||||
def test_failed_assembly_removes_temporary_base_alias(self):
|
||||
self.assert_assembly(build_fails=True)
|
||||
|
||||
def assert_assembly(self, *, rebuild=False, build_fails=False):
|
||||
instance, _, _, _ = self.source_fixture()
|
||||
source = self.select_source(instance)
|
||||
shell_calls, docker_calls = [], []
|
||||
base_tag = "genarrative/gitea-project-ci:base-auto-" + SHA
|
||||
assembly_base = "genarrative/gitea-project-ci:assembly-base"
|
||||
instance.build_command = lambda log, script, *args, **kw: shell_calls.append((script, args))
|
||||
def info(image, inner=False):
|
||||
return {"Id": IMAGE if image.startswith("genarrative/") else image, "Config": {"Labels": {
|
||||
image_id = BASE_IMAGE if image == base_tag else IMAGE if image.startswith("genarrative/") else image
|
||||
return {"Id": image_id, "Config": {"Labels": {
|
||||
"world.genarrative.ci.rust-cache-source": "b" * 40,
|
||||
"world.genarrative.ci.rust-cache-base": BASE_IMAGE,
|
||||
"com.genarrative.ci.definition-sha256": "definition",
|
||||
"com.genarrative.ci.definition-sha256": "old-definition" if rebuild else "definition",
|
||||
}}}
|
||||
instance.image_info = info
|
||||
def docker(*args, **kw):
|
||||
@@ -395,6 +407,16 @@ class GiteaCacheMaintenanceTest(unittest.TestCase):
|
||||
(root / "sccache").write_bytes(b"trusted binary")
|
||||
if args[-2:] == ("rustc", "-vV"):
|
||||
return "rustc test\n"
|
||||
if args[0] == "build":
|
||||
self.assertEqual(args[1:5], ("--builder", "default", "--pull=false", "--tag"))
|
||||
work = Path(args[-1])
|
||||
self.assertTrue((work / "Dockerfile").read_text().startswith(f"FROM {assembly_base}\n"))
|
||||
self.assertIn(f'world.genarrative.ci.rust-cache-base="{BASE_IMAGE}"',
|
||||
(work / "Dockerfile").read_text())
|
||||
self.assertEqual((work / "snapshot/base-image.txt").read_text(), BASE_IMAGE + "\n")
|
||||
self.assertEqual(docker_calls[-2], ("image", "tag", BASE_IMAGE, assembly_base))
|
||||
if build_fails:
|
||||
raise RuntimeError("assembly failed")
|
||||
return ""
|
||||
instance.docker = docker
|
||||
instance.api.download = lambda path, destination, expected_size: destination.write_bytes(b"download")
|
||||
@@ -407,10 +429,22 @@ class GiteaCacheMaintenanceTest(unittest.TestCase):
|
||||
"workspace": "/workspace/team/project", "base_image": BASE_IMAGE})()
|
||||
with patch.object(maintenance_module, "command", return_value="definition\n"), \
|
||||
patch.object(maintenance_module, "merge_snapshots", merge):
|
||||
instance.build(source)
|
||||
self.assertEqual(shell_calls, [("gitea-ci-job-image.sh", ("verify", "genarrative/gitea-project-ci:rust-cache-auto-" + SHA))])
|
||||
if build_fails:
|
||||
with self.assertRaisesRegex(RuntimeError, "assembly failed"):
|
||||
instance.build(source)
|
||||
else:
|
||||
instance.build(source)
|
||||
expected_calls = [("gitea-ci-job-image.sh", ("build",))] if rebuild else []
|
||||
if not build_fails:
|
||||
expected_calls.append(("gitea-ci-job-image.sh", ("verify", "genarrative/gitea-project-ci:rust-cache-auto-" + SHA)))
|
||||
self.assertEqual(shell_calls, expected_calls)
|
||||
self.assertIn(("create", OLD_IMAGE), docker_calls)
|
||||
self.assertIn(("rm", "--volumes", "temporary-copy-container"), docker_calls)
|
||||
self.assertEqual(docker_calls[-1], ("image", "rm", assembly_base))
|
||||
self.assertEqual(instance.state.get("bases", {}), {BASE_IMAGE: base_tag} if rebuild else {})
|
||||
if build_fails:
|
||||
self.assertIsNone(instance.state.get("candidate"))
|
||||
return
|
||||
self.assertEqual(instance.state["candidate"], IMAGE)
|
||||
self.assertEqual(instance.version(IMAGE)["run_id"], 44)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user