aboutsummaryrefslogtreecommitdiffhomepage
path: root/infra/cifuzz/continuous_integration.py
diff options
context:
space:
mode:
authorGravatar jonathanmetzman <31354670+jonathanmetzman@users.noreply.github.com>2021-10-31 22:59:44 -0400
committerGravatar GitHub <noreply@github.com>2021-11-01 02:59:44 +0000
commit1ece14aeb26967eb7d7cefb55e6ca4ad10dc6d33 (patch)
tree86d1462445f7a934e93dad68cb4117038ab04c58 /infra/cifuzz/continuous_integration.py
parent4ce563f882b41c658621a9a57737aeb8ff849510 (diff)
Abstract away duplicate code in prepare_for_fuzzer_build (#6706)
Share more code between the 4 implementations of `prepare_for_fuzzer_build`. This simplifies the code of these implementations, reduces repetition and makes them easier to understand. Create helper functions/methods for: 1. Creating a failed `BuildPreparationResult`: `get_build_preparation_failure` 2. Building an external project docker image: `_build_external_project_docker_image` 3. Cloning a repo and checking out the specified commit/pr: `_clone_repo_and_checkout` 4. Detecting the main repo `_detect_main_repo` 5. Creating a repo manager from an existing checkout: `_create_repo_manager_for_project_src_path` Change `ExternalGeneric` implementation of `prepare_for_fuzzer_build` to: 1. Call `_create_repo_manager_for_project_src_path` 2. Call `_build_external_project_docker_image` Change `InternalGeneric` implementation of `prepare_for_fuzzer_build` to: 1. Call `_detect_main_repo` 2. Call `_create_repo_manager_for_project_src_path` Change `ExternalGithub` implementation of `prepare_for_fuzzer_build` to: 1. Call `_clone_repo_and_checkout` 2. Call `_build_external_project_docker_image` Change `InternalGithub` implementation of `prepare_for_fuzzer_build` to: 1. Call `_detect_main_repo` 2. Call `_clone_repo_and_checkout`
Diffstat (limited to 'infra/cifuzz/continuous_integration.py')
-rw-r--r--infra/cifuzz/continuous_integration.py136
1 files changed, 66 insertions, 70 deletions
diff --git a/infra/cifuzz/continuous_integration.py b/infra/cifuzz/continuous_integration.py
index 230d2c96..4d739f7d 100644
--- a/infra/cifuzz/continuous_integration.py
+++ b/infra/cifuzz/continuous_integration.py
@@ -96,6 +96,49 @@ class BaseCi:
project builder container."""
raise NotImplementedError('Child class must implement method.')
+ def _build_external_project_docker_image(self, manager):
+ """Helper for child classes that builds an external project's docker image.
+ Returns a BuildPreparationResult indicating failure or success."""
+ build_integration_abs_path = os.path.join(
+ manager.repo_dir, self.config.build_integration_path)
+ if not build_external_project_docker_image(manager.repo_dir,
+ build_integration_abs_path):
+ logging.error('Failed to build external project.')
+ return get_build_preparation_failure()
+ image_repo_path = os.path.join('/src', self.config.project_repo_name)
+ return BuildPreparationResult(success=True,
+ image_repo_path=image_repo_path,
+ repo_manager=manager)
+
+ 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)
+ # Checkout project's repo in the shared volume.
+ manager = repo_manager.clone_repo_and_get_manager(
+ repo_url,
+ self.workspace.repo_storage,
+ repo_name=repo_name,
+ username=self.config.actor,
+ password=self.config.token)
+ checkout_specified_commit(manager, self.config.pr_ref, self.config.git_sha)
+ return manager
+
+ 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."""
+ inferred_url, image_repo_path = build_specified_commit.detect_main_repo(
+ self.config.oss_fuzz_project_name,
+ repo_name=self.config.project_repo_name)
+ if not inferred_url or not image_repo_path:
+ logging.error('Could not detect repo.')
+ return inferred_url, image_repo_path
+
+ def _create_repo_manager_for_project_src_path(self):
+ """Returns a repo manager for |project_src_path|."""
+ return repo_manager.RepoManager(self.config.project_src_path)
+
def get_build_command():
"""Returns the command to build the project inside the project builder
@@ -187,33 +230,16 @@ class InternalGithub(GithubCiMixin, BaseCi):
def prepare_for_fuzzer_build(self):
"""Builds the fuzzer builder image, checks out the pull request/commit and
returns the BuildPreparationResult."""
- logging.info('Building OSS-Fuzz project on Github Actions.')
+ 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 = (build_specified_commit.detect_main_repo(
- self.config.oss_fuzz_project_name,
- repo_name=self.config.project_repo_name))
-
+ # _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:
- logging.error('Could not detect repo.')
- return BuildPreparationResult(success=False,
- image_repo_path=None,
- repo_manager=None)
-
- os.makedirs(self.workspace.repo_storage, exist_ok=True)
+ 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)
-
- # Checkout project's repo in the shared volume.
- manager = repo_manager.clone_repo_and_get_manager(
- inferred_url,
- self.workspace.repo_storage,
- repo_name=image_repo_name,
- username=self.config.actor,
- password=self.config.token)
- checkout_specified_commit(manager, self.config.pr_ref, self.config.git_sha)
-
+ manager = self._clone_repo_and_checkout(inferred_url, image_repo_name)
return BuildPreparationResult(success=True,
image_repo_path=image_repo_path,
repo_manager=manager)
@@ -225,6 +251,13 @@ class InternalGithub(GithubCiMixin, BaseCi):
return get_replace_repo_and_build_command(host_repo_path, image_repo_path)
+def get_build_preparation_failure():
+ """Returns a BuildPreparationResult indicating failure."""
+ return BuildPreparationResult(success=False,
+ image_repo_path=None,
+ repo_manager=None)
+
+
class InternalGeneric(BaseCi):
"""Class representing CI for an OSS-Fuzz project on a CI other than Github
actions."""
@@ -244,19 +277,14 @@ class InternalGeneric(BaseCi):
GitHub actions. Returns the repo_manager. Does not checkout source code
since external projects are expected to bring their own source code to
CIFuzz."""
- logging.info('Building OSS-Fuzz project.')
+ logging.info('InternalGeneric: preparing for fuzzer build.')
# detect_main_repo builds the image as a side effect.
- _, image_repo_path = (build_specified_commit.detect_main_repo(
- self.config.oss_fuzz_project_name,
- repo_name=self.config.project_repo_name))
+ _, image_repo_path = self._detect_main_repo()
if not image_repo_path:
- logging.error('Could not detect repo.')
- return BuildPreparationResult(success=False,
- image_repo_path=None,
- repo_manager=None)
+ return get_build_preparation_failure()
- manager = repo_manager.RepoManager(self.config.project_src_path)
+ manager = self._create_repo_manager_for_project_src_path()
return BuildPreparationResult(success=True,
image_repo_path=image_repo_path,
repo_manager=manager)
@@ -294,21 +322,8 @@ class ExternalGeneric(BaseCi):
def prepare_for_fuzzer_build(self):
logging.info('ExternalGeneric: preparing for fuzzer build.')
- manager = repo_manager.RepoManager(self.config.project_src_path)
- build_integration_abs_path = os.path.join(
- manager.repo_dir, self.config.build_integration_path)
- if not build_external_project_docker_image(manager.repo_dir,
- build_integration_abs_path):
- logging.error('Failed to build external project: %s.',
- self.config.project_repo_name)
- return BuildPreparationResult(success=False,
- image_repo_path=None,
- repo_manager=None)
-
- image_repo_path = os.path.join('/src', self.config.project_repo_name)
- return BuildPreparationResult(success=True,
- image_repo_path=image_repo_path,
- repo_manager=manager)
+ manager = self._create_repo_manager_for_project_src_path()
+ return self._build_external_project_docker_image(manager)
def get_build_command(self, host_repo_path, image_repo_path): # pylint: disable=no-self-use
"""Returns the command for building the project that is run inside the
@@ -324,32 +339,13 @@ class ExternalGithub(GithubCiMixin, BaseCi):
actions. Sets the repo manager. Does not checkout source code since external
projects are expected to bring their own source code to CIFuzz. Returns True
on success."""
- logging.info('Building external project.')
- os.makedirs(self.workspace.repo_storage, exist_ok=True)
+ logging.info('ExternalGithub: preparing for fuzzer build.')
# Checkout before building, so we don't need to rely on copying the source
- # into the image.
+ # from the image.
# TODO(metzman): Figure out if we want second copy at all.
- manager = repo_manager.clone_repo_and_get_manager(
- self.config.git_url,
- self.workspace.repo_storage,
- repo_name=self.config.project_repo_name,
- username=self.config.actor,
- password=self.config.token)
- checkout_specified_commit(manager, self.config.pr_ref, self.config.git_sha)
-
- build_integration_abs_path = os.path.join(
- manager.repo_dir, self.config.build_integration_path)
- if not build_external_project_docker_image(manager.repo_dir,
- build_integration_abs_path):
- logging.error('Failed to build external project.')
- return BuildPreparationResult(success=False,
- image_repo_path=None,
- repo_manager=None)
-
- image_repo_path = os.path.join('/src', self.config.project_repo_name)
- return BuildPreparationResult(success=True,
- image_repo_path=image_repo_path,
- repo_manager=manager)
+ manager = self._clone_repo_and_checkout(self.config.git_url,
+ self.config.project_repo_name)
+ return self._build_external_project_docker_image(manager)
def get_build_command(self, host_repo_path, image_repo_path): # pylint: disable=no-self-use
"""Returns the command for building the project that is run inside the