Use cached image from the release branch for backport PRs

This commit is contained in:
Mikhail f. Shiryaev 2022-07-01 16:45:00 +02:00
parent 6a67be3195
commit 27bd355525
No known key found for this signature in database
GPG Key ID: 4B02ED204C7D93F4
3 changed files with 63 additions and 14 deletions

View File

@ -210,6 +210,7 @@ def build_and_push_dummy_image(
def build_and_push_one_image(
image: DockerImage,
version_string: str,
additional_cache: str,
push: bool,
child: bool,
) -> Tuple[bool, str]:
@ -232,6 +233,16 @@ def build_and_push_one_image(
if child:
from_tag_arg = f"--build-arg FROM_TAG={version_string} "
cache_from = (
f"--cache-from type=registry,ref={image.repo}:{version_string} "
f"--cache-from type=registry,ref={image.repo}:latest"
)
if additional_cache:
cache_from = (
f"{cache_from} "
f"--cache-from type=registry,ref={image.repo}:{additional_cache}"
)
with open(build_log, "wb") as bl:
cmd = (
"docker buildx build --builder default "
@ -240,8 +251,7 @@ def build_and_push_one_image(
# A hack to invalidate cache, grep for it in docker/ dir
f"--build-arg CACHE_INVALIDATOR={GITHUB_RUN_URL} "
f"--tag {image.repo}:{version_string} "
f"--cache-from type=registry,ref={image.repo}:{version_string} "
f"--cache-from type=registry,ref={image.repo}:latest "
f"{cache_from} "
f"--cache-to type=inline,mode=max "
f"{push_arg}"
f"--progress plain {image.full_path}"
@ -260,6 +270,7 @@ def build_and_push_one_image(
def process_single_image(
image: DockerImage,
versions: List[str],
additional_cache,
push: bool,
child: bool,
) -> List[Tuple[str, str, str]]:
@ -267,7 +278,9 @@ def process_single_image(
result = []
for ver in versions:
for i in range(5):
success, build_log = build_and_push_one_image(image, ver, push, child)
success, build_log = build_and_push_one_image(
image, ver, additional_cache, push, child
)
if success:
result.append((image.repo + ":" + ver, build_log, "OK"))
break
@ -284,17 +297,23 @@ def process_single_image(
def process_image_with_parents(
image: DockerImage, versions: List[str], push: bool, child: bool = False
image: DockerImage,
versions: List[str],
additional_cache: str,
push: bool,
child: bool = False,
) -> List[Tuple[str, str, str]]:
result = [] # type: List[Tuple[str,str,str]]
if image.built:
return result
if image.parent is not None:
result += process_image_with_parents(image.parent, versions, push, False)
result += process_image_with_parents(
image.parent, versions, additional_cache, push, False
)
child = True
result += process_single_image(image, versions, push, child)
result += process_single_image(image, versions, additional_cache, push, child)
return result
@ -423,8 +442,10 @@ def main():
result_images = {}
images_processing_result = []
for image in changed_images:
# If we are in backport PR, then pr_info.release_pr is defined
# We use it as tag to reduce rebuilding time
images_processing_result += process_image_with_parents(
image, image_versions, args.push
image, image_versions, pr_info.release_pr, args.push
)
result_images[image.repo] = result_version

View File

@ -117,7 +117,7 @@ class TestDockerImageCheck(unittest.TestCase):
mock_popen.return_value.__enter__.return_value.wait.return_value = 0
image = di.DockerImage("path", "name", False, gh_repo_path="")
result, _ = di.build_and_push_one_image(image, "version", True, True)
result, _ = di.build_and_push_one_image(image, "version", "", True, True)
mock_open.assert_called_once()
mock_popen.assert_called_once()
mock_machine.assert_not_called()
@ -136,7 +136,7 @@ class TestDockerImageCheck(unittest.TestCase):
mock_machine.reset_mock()
mock_popen.return_value.__enter__.return_value.wait.return_value = 0
result, _ = di.build_and_push_one_image(image, "version2", False, True)
result, _ = di.build_and_push_one_image(image, "version2", "", False, True)
mock_open.assert_called_once()
mock_popen.assert_called_once()
mock_machine.assert_not_called()
@ -155,7 +155,7 @@ class TestDockerImageCheck(unittest.TestCase):
mock_popen.reset_mock()
mock_machine.reset_mock()
mock_popen.return_value.__enter__.return_value.wait.return_value = 1
result, _ = di.build_and_push_one_image(image, "version2", False, False)
result, _ = di.build_and_push_one_image(image, "version2", "", False, False)
mock_open.assert_called_once()
mock_popen.assert_called_once()
mock_machine.assert_not_called()
@ -169,13 +169,36 @@ class TestDockerImageCheck(unittest.TestCase):
)
self.assertFalse(result)
mock_open.reset_mock()
mock_popen.reset_mock()
mock_machine.reset_mock()
mock_popen.return_value.__enter__.return_value.wait.return_value = 1
result, _ = di.build_and_push_one_image(
image, "version2", "cached-version", False, False
)
mock_open.assert_called_once()
mock_popen.assert_called_once()
mock_machine.assert_not_called()
self.assertIn(
f"docker buildx build --builder default --label build-url={GITHUB_RUN_URL} "
f"--build-arg CACHE_INVALIDATOR={GITHUB_RUN_URL} "
"--tag name:version2 --cache-from type=registry,ref=name:version2 "
"--cache-from type=registry,ref=name:latest "
"--cache-from type=registry,ref=name:cached-version "
"--cache-to type=inline,mode=max --progress plain path",
mock_popen.call_args.args,
)
self.assertFalse(result)
mock_open.reset_mock()
mock_popen.reset_mock()
mock_machine.reset_mock()
only_amd64_image = di.DockerImage("path", "name", True)
mock_popen.return_value.__enter__.return_value.wait.return_value = 0
result, _ = di.build_and_push_one_image(only_amd64_image, "version", True, True)
result, _ = di.build_and_push_one_image(
only_amd64_image, "version", "", True, True
)
mock_open.assert_called_once()
mock_popen.assert_called_once()
mock_machine.assert_called_once()
@ -186,7 +209,7 @@ class TestDockerImageCheck(unittest.TestCase):
)
self.assertTrue(result)
result, _ = di.build_and_push_one_image(
only_amd64_image, "version", False, True
only_amd64_image, "version", "", False, True
)
self.assertIn(
"docker pull ubuntu:20.04; docker tag ubuntu:20.04 name:version; ",
@ -195,7 +218,7 @@ class TestDockerImageCheck(unittest.TestCase):
@patch("docker_images_check.build_and_push_one_image")
def test_process_image_with_parents(self, mock_build):
mock_build.side_effect = lambda w, x, y, z: (True, f"{w.repo}_{x}.log")
mock_build.side_effect = lambda v, w, x, y, z: (True, f"{v.repo}_{w}.log")
im1 = di.DockerImage("path1", "repo1", False)
im2 = di.DockerImage("path2", "repo2", False, im1)
im3 = di.DockerImage("path3", "repo3", False, im2)
@ -203,7 +226,7 @@ class TestDockerImageCheck(unittest.TestCase):
# We use list to have determined order of image builgings
images = [im4, im1, im3, im2, im1]
results = [
di.process_image_with_parents(im, ["v1", "v2", "latest"], True)
di.process_image_with_parents(im, ["v1", "v2", "latest"], "", True)
for im in images
]

View File

@ -85,6 +85,7 @@ class PRInfo:
self.changed_files = set() # type: Set[str]
self.body = ""
self.diff_urls = []
self.release_pr = ""
ref = github_event.get("ref", "refs/head/master")
if ref and ref.startswith("refs/heads/"):
ref = ref[11:]
@ -193,6 +194,10 @@ class PRInfo:
f"https://github.com/{GITHUB_REPOSITORY}/"
f"compare/{self.head_ref}...master.diff"
)
# Get release PR number.
self.release_pr = get_pr_for_commit(self.base_ref, self.base_ref)[
"number"
]
else:
self.diff_urls.append(pull_request["diff_url"])
else: