Files
computer-playbook/tests/unit/python/cli/contributing/mirror/test_sync.py
T
kevinveenbirkenbachandClaude Opus 5.5 87bc1be60f perf(ci): throttle only Docker Hub copies in the daily mirror and raise the limit
The daily mirror waited about 70 s before each of its 195 copies (50 images
per hour), roughly 3.8 h of pauses, and logged no single rate-limit error.
37 of the copies come from ghcr.io, registry.gitlab.com, quay.io,
registry.opencode.de and mcr.microsoft.com, which the Docker Hub pull limit
does not cover, and --only-missing also waited before images it then skipped.
The throttle now waits only before an actual copy from docker.io, and the
schedule allows 150 Docker Hub copies per hour (24 s apart).

Part of #1324

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 17:48:09 +01:00

148 lines
4.6 KiB
Python

from __future__ import annotations
import unittest
from unittest.mock import patch
import cli.contributing.mirror.sync.__main__ as sync_main
from cli.contributing.mirror.model import ImageRef
class TestThrottle(unittest.TestCase):
def test_only_docker_hub_copies_wait_for_the_throttle(self) -> None:
def image(name: str, registry: str) -> ImageRef:
return ImageRef(
role="r",
service=name,
name=name,
version="1",
source=f"{registry}/{name}:1",
registry=registry,
)
images = [
image("a", "docker.io"),
image("b", "ghcr.io"),
image("c", "quay.io"),
image("d", "docker.io"),
]
with (
patch(
"cli.contributing.mirror.sync.__main__.iter_role_images",
return_value=images,
),
patch(
"cli.contributing.mirror.sync.__main__.iter_runner_images",
return_value=[],
),
patch.object(sync_main.GHCRProvider, "image_base", return_value="g/x"),
patch.object(sync_main.GHCRProvider, "mirror") as mock_mirror,
patch.object(sync_main.time, "monotonic", return_value=0.0),
patch.object(sync_main.time, "sleep") as mock_sleep,
patch(
"sys.argv",
[
"mirror-sync",
"--ghcr-namespace",
"acme",
"--ghcr-repository",
"myrepo",
"--images-per-hour",
"150",
],
),
):
result = sync_main.main()
self.assertEqual(result, 0)
self.assertEqual(mock_mirror.call_count, 4)
self.assertEqual([call.args for call in mock_sleep.call_args_list], [(24.0,)])
class TestMirrorSync(unittest.TestCase):
def test_only_missing_skips_existing_destination(self) -> None:
image = ImageRef(
role="web-app-nextcloud",
service="app",
name="nextcloud",
version="31.0.0",
source="docker.io/library/nextcloud:31.0.0",
registry="docker.io",
)
with (
patch(
"cli.contributing.mirror.sync.__main__.iter_role_images",
return_value=[image],
),
patch(
"cli.contributing.mirror.sync.__main__.iter_runner_images",
return_value=[],
),
patch.object(
sync_main.GHCRProvider,
"image_base",
return_value="ghcr.io/acme/myrepo/mirror/docker.io/nextcloud",
),
patch.object(
sync_main.GHCRProvider, "tag_exists", return_value=True
) as mock_tag_exists,
patch.object(sync_main.GHCRProvider, "mirror") as mock_mirror,
patch(
"sys.argv",
[
"mirror-sync",
"--ghcr-namespace",
"acme",
"--ghcr-repository",
"myrepo",
"--only-missing",
],
),
):
result = sync_main.main()
self.assertEqual(result, 0)
mock_tag_exists.assert_called_once_with(image)
mock_mirror.assert_not_called()
def test_runner_images_are_mirrored_with_the_role_images(self) -> None:
image = ImageRef(
role="runner",
service="coredns",
name="coredns/coredns",
version="1.14.4",
source="docker.io/coredns/coredns:1.14.4",
registry="docker.io",
source_file="compose.yml",
)
with (
patch(
"cli.contributing.mirror.sync.__main__.iter_role_images",
return_value=[],
),
patch(
"cli.contributing.mirror.sync.__main__.iter_runner_images",
return_value=[image],
),
patch.object(sync_main.GHCRProvider, "mirror") as mock_mirror,
patch(
"sys.argv",
[
"mirror-sync",
"--ghcr-namespace",
"acme",
"--ghcr-repository",
"myrepo",
],
),
):
result = sync_main.main()
self.assertEqual(result, 0)
mock_mirror.assert_called_once_with(image)
if __name__ == "__main__": # pragma: no cover
unittest.main()