aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar jonathanmetzman <31354670+jonathanmetzman@users.noreply.github.com>2021-12-01 09:36:08 -0500
committerGravatar GitHub <noreply@github.com>2021-12-01 09:36:08 -0500
commita458e3c8edc4191488bca4563bc1bcf92043226b (patch)
tree894c544fe81b11784d8c58739df4f4ca555a50d5
parentfaaa6c13004c47c10c3162548861adce7d44eace (diff)
[cifuzz] Copy repo from image before checking out. (#6941)
* [cifuzz] Copy repo from image before checking out. Do this instead of cloning repo anew. Fixes: https://github.com/google/oss-fuzz/issues/6755 * fix tests * Add test code for cifuzz-example * fix
-rw-r--r--infra/cifuzz/build_fuzzers.py6
-rw-r--r--infra/cifuzz/build_fuzzers_test.py10
-rw-r--r--infra/cifuzz/continuous_integration.py36
3 files changed, 37 insertions, 15 deletions
diff --git a/infra/cifuzz/build_fuzzers.py b/infra/cifuzz/build_fuzzers.py
index c35115c4..19a22dc5 100644
--- a/infra/cifuzz/build_fuzzers.py
+++ b/infra/cifuzz/build_fuzzers.py
@@ -85,14 +85,14 @@ class Builder: # pylint: disable=too-many-instance-attributes
docker_args.extend(
_get_docker_build_fuzzers_args_not_container(self.host_repo_path))
+ build_command = self.ci_system.get_build_command(self.host_repo_path,
+ self.image_repo_path)
docker_args.extend([
docker.get_project_image_name(self.config.oss_fuzz_project_name),
'/bin/bash',
'-c',
+ build_command,
])
- build_command = self.ci_system.get_build_command(self.host_repo_path,
- self.image_repo_path)
- docker_args.append(build_command)
logging.info('Building with %s sanitizer.', self.config.sanitizer)
# TODO(metzman): Stop using helper.docker_run so we can get rid of
diff --git a/infra/cifuzz/build_fuzzers_test.py b/infra/cifuzz/build_fuzzers_test.py
index daaf84b4..e3f6e2a2 100644
--- a/infra/cifuzz/build_fuzzers_test.py
+++ b/infra/cifuzz/build_fuzzers_test.py
@@ -111,7 +111,7 @@ class InternalGithubBuildTest(unittest.TestCase):
builder.repo_manager = repo_manager.RepoManager('/fake')
return builder
- @mock.patch('repo_manager._clone', side_effect=None)
+ @mock.patch('helper.docker_run', return_value=True)
@mock.patch('continuous_integration.checkout_specified_commit',
side_effect=None)
def test_correct_host_repo_path(self, _, __):
@@ -159,8 +159,8 @@ class BuildFuzzersIntegrationTest(unittest.TestCase):
"""Integration tests for build_fuzzers."""
def setUp(self):
- self.temp_dir_obj = tempfile.TemporaryDirectory()
- self.workspace = self.temp_dir_obj.name
+ self.temp_dir_ctx_manager = test_helpers.docker_temp_dir()
+ self.workspace = self.temp_dir_ctx_manager.__enter__()
self.out_dir = os.path.join(self.workspace, 'build-out')
test_helpers.patch_environ(self)
@@ -168,7 +168,7 @@ class BuildFuzzersIntegrationTest(unittest.TestCase):
os.environ['PATH'] = os.environ['PATH'] + os.pathsep + base_runner_path
def tearDown(self):
- self.temp_dir_obj.cleanup()
+ self.temp_dir_ctx_manager.__exit__(None, None, None)
def test_external_github_project(self):
"""Tests building fuzzers from an external project on Github."""
@@ -195,7 +195,7 @@ class BuildFuzzersIntegrationTest(unittest.TestCase):
# github.com/jonathanmetzman/cifuzz-external-example.
manager = repo_manager.clone_repo_and_get_manager(
'https://github.com/jonathanmetzman/cifuzz-external-example',
- self.temp_dir_obj.name)
+ self.workspace)
project_src_path = manager.repo_dir
config = test_helpers.create_build_config(
project_repo_name=project_repo_name,
diff --git a/infra/cifuzz/continuous_integration.py b/infra/cifuzz/continuous_integration.py
index 4d739f7d..96a4d028 100644
--- a/infra/cifuzz/continuous_integration.py
+++ b/infra/cifuzz/continuous_integration.py
@@ -110,11 +110,14 @@ class BaseCi:
image_repo_path=image_repo_path,
repo_manager=manager)
+ def _make_repo_storage_dir(self):
+ os.makedirs(self.workspace.repo_storage, exist_ok=True)
+
def _clone_repo_and_checkout(self, repo_url, repo_name):
"""Helper for child classes that clones the git repo specified by |repo_url|
to |repo_name|, checks out the specified commit, and returns the
|manager|."""
- os.makedirs(self.workspace.repo_storage, exist_ok=True)
+ self._make_repo_storage_dir()
# Checkout project's repo in the shared volume.
manager = repo_manager.clone_repo_and_get_manager(
repo_url,
@@ -122,9 +125,12 @@ class BaseCi:
repo_name=repo_name,
username=self.config.actor,
password=self.config.token)
- checkout_specified_commit(manager, self.config.pr_ref, self.config.git_sha)
+ self._checkout_specified_commit(manager)
return manager
+ def _checkout_specified_commit(self, manager):
+ checkout_specified_commit(manager, self.config.pr_ref, self.config.git_sha)
+
def _detect_main_repo(self):
"""Helper for child classes that detects the main repo and returns a tuple
containing the inffered url and path to the repo in the image."""
@@ -192,7 +198,7 @@ def checkout_specified_commit(repo_manager_obj, pr_ref, git_sha):
except (RuntimeError, ValueError):
logging.error(
'Can not check out requested state %s. '
- 'Using current repo state', pr_ref or git_sha)
+ 'Using current repo state.', pr_ref or git_sha)
class GithubCiMixin:
@@ -227,19 +233,35 @@ class GithubCiMixin:
class InternalGithub(GithubCiMixin, BaseCi):
"""Class representing CI for an OSS-Fuzz project on Github Actions."""
+ def _copy_repo_from_image(self, image_repo_path):
+ self._make_repo_storage_dir()
+ repo_name = os.path.basename(image_repo_path)
+ host_repo_path = os.path.join(self._repo_dir, repo_name)
+ bash_command = f'cp -r {image_repo_path} {host_repo_path}'
+ docker_args, _ = docker.get_base_docker_run_args(
+ self.workspace, self.config.sanitizer, self.config.language,
+ self.config.docker_in_docker)
+ docker_args.extend([
+ docker.get_project_image_name(self.config.oss_fuzz_project_name),
+ '/bin/bash', '-c', bash_command
+ ])
+ if not helper.docker_run(docker_args):
+ raise RuntimeError('Failed to copy repo.')
+ return repo_manager.RepoManager(host_repo_path)
+
def prepare_for_fuzzer_build(self):
"""Builds the fuzzer builder image, checks out the pull request/commit and
returns the BuildPreparationResult."""
logging.info('InternalGithub: preparing for fuzzer build.')
assert self.config.pr_ref or self.config.git_sha
# _detect_main_repo builds the image as a side effect.
- inferred_url, image_repo_path = self._detect_main_repo()
- if not inferred_url or not image_repo_path:
+ _, image_repo_path = self._detect_main_repo()
+ if not image_repo_path:
return get_build_preparation_failure()
# Use the same name used in the docker image so we can overwrite it.
- image_repo_name = os.path.basename(image_repo_path)
- manager = self._clone_repo_and_checkout(inferred_url, image_repo_name)
+ manager = self._copy_repo_from_image(image_repo_path)
+ self._checkout_specified_commit(manager)
return BuildPreparationResult(success=True,
image_repo_path=image_repo_path,
repo_manager=manager)