diff options
author | 2021-12-01 09:36:08 -0500 | |
---|---|---|
committer | 2021-12-01 09:36:08 -0500 | |
commit | a458e3c8edc4191488bca4563bc1bcf92043226b (patch) | |
tree | 894c544fe81b11784d8c58739df4f4ca555a50d5 | |
parent | faaa6c13004c47c10c3162548861adce7d44eace (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.py | 6 | ||||
-rw-r--r-- | infra/cifuzz/build_fuzzers_test.py | 10 | ||||
-rw-r--r-- | infra/cifuzz/continuous_integration.py | 36 |
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) |