def Run(self):
        """Main runner for this builder class.  Runs build and prints summary.

    Returns:
      Whether the build succeeded.
    """
        self._InitializeTrybotPatchPool()

        if self._run.options.bootstrap:
            bootstrap_stage = self._GetBootstrapStage()
            if bootstrap_stage:
                # BootstrapStage blocks on re-execution of cbuildbot.
                bootstrap_stage.Run()
                return bootstrap_stage.returncode == 0

        print_report = True
        exception_thrown = False
        success = True
        sync_instance = None
        try:
            self.Initialize()
            sync_instance = self.GetSyncInstance()
            self._RunSyncStage(sync_instance)

            if self._run.ShouldPatchAfterSync():
                # Filter out patches to manifest, since PatchChangesStage can't handle
                # them.  Manifest patches are patched in the BootstrapStage.
                non_manifest_patches = self.patch_pool.FilterManifest(
                    negate=True)
                if non_manifest_patches:
                    self._RunStage(sync_stages.PatchChangesStage,
                                   non_manifest_patches)

            # Now that we have a fully synced & patched tree, we can let the builder
            # extract version information from the sources for this particular build.
            self.SetVersionInfo()
            if self._run.ShouldReexecAfterSync():
                print_report = False
                success = self._ReExecuteInBuildroot(sync_instance)
            else:
                self._RunStage(report_stages.BuildReexecutionFinishedStage)
                self._RunStage(report_stages.ConfigDumpStage)
                self.RunStages()

        except Exception as ex:
            if isinstance(ex, failures_lib.ExitEarlyException):
                # One stage finished and exited early, not a failure.
                raise

            exception_thrown = True
            build_identifier, _ = self._run.GetCIDBHandle()
            buildbucket_id = build_identifier.buildbucket_id
            if results_lib.Results.BuildSucceededSoFar(self.buildstore,
                                                       buildbucket_id):
                # If the build is marked as successful, but threw exceptions, that's a
                # problem. Print the traceback for debugging.
                if isinstance(ex, failures_lib.CompoundFailure):
                    print(str(ex))

                traceback.print_exc(file=sys.stdout)
                raise

            if not (print_report and isinstance(ex, failures_lib.StepFailure)):
                # If the failed build threw a non-StepFailure exception, we
                # should raise it.
                raise

        finally:
            if print_report:
                results_lib.WriteCheckpoint(self._run.options.buildroot)
                completion_instance = self.GetCompletionInstance()
                self._RunStage(report_stages.ReportStage, completion_instance)
                build_identifier, _ = self._run.GetCIDBHandle()
                buildbucket_id = build_identifier.buildbucket_id
                success = results_lib.Results.BuildSucceededSoFar(
                    self.buildstore, buildbucket_id)
                if exception_thrown and success:
                    success = False
                    logging.PrintBuildbotStepWarnings()
                    print("""\
Exception thrown, but all stages marked successful. This is an internal error,
because the stage that threw the exception should be marked as failing.""")

        return success
    def _ReExecuteInBuildroot(self, sync_instance):
        """Reexecutes self in buildroot and returns True if build succeeds.

    This allows the buildbot code to test itself when changes are patched for
    buildbot-related code.  This is a no-op if the buildroot == buildroot
    of the running chromite checkout.

    Args:
      sync_instance: Instance of the sync stage that was run to sync.

    Returns:
      True if the Build succeeded.
    """
        if not self._run.options.resume:
            results_lib.WriteCheckpoint(self._run.options.buildroot)

        args = sync_stages.BootstrapStage.FilterArgsForTargetCbuildbot(
            self._run.options.buildroot, constants.PATH_TO_CBUILDBOT,
            self._run.options)

        # Specify a buildroot explicitly (just in case, for local trybot).
        # Suppress any timeout options given from the commandline in the
        # invoked cbuildbot; our timeout will enforce it instead.
        args += [
            '--resume', '--timeout', '0', '--notee', '--nocgroups',
            '--buildroot',
            os.path.abspath(self._run.options.buildroot)
        ]

        # Set --version. Note that --version isn't legal without --buildbot.
        if (self._run.options.buildbot
                and hasattr(self._run.attrs, 'manifest_manager')):
            ver = self._run.attrs.manifest_manager.current_version
            args += ['--version', ver]

        pool = getattr(sync_instance, 'pool', None)
        if pool:
            filename = os.path.join(self._run.options.buildroot,
                                    'validation_pool.dump')
            pool.Save(filename)
            args += ['--validation_pool', filename]

        # Reset the cache dir so that the child will calculate it automatically.
        if not self._run.options.cache_dir_specified:
            commandline.BaseParser.ConfigureCacheDir(None)

        with tempfile.NamedTemporaryFile(prefix='metadata',
                                         mode='w') as metadata_file:
            metadata_file.write(self._run.attrs.metadata.GetJSON())
            metadata_file.flush()
            args += ['--metadata_dump', metadata_file.name]

            # Re-run the command in the buildroot.
            # Finally, be generous and give the invoked cbuildbot 30s to shutdown
            # when something occurs.  It should exit quicker, but the sigterm may
            # hit while the system is particularly busy.
            return_obj = cros_build_lib.run(args,
                                            cwd=self._run.options.buildroot,
                                            error_code_ok=True,
                                            kill_timeout=30)
            return return_obj.returncode == 0