Index: appengine/findit/waterfall/build_failure_analysis_pipelines.py |
diff --git a/appengine/findit/waterfall/build_failure_analysis_pipelines.py b/appengine/findit/waterfall/build_failure_analysis_pipelines.py |
index 91af3608be8b35d6959fd22afd1d4e436faa60f2..972288159f2d67bcc577fd56baa5be633dae34d7 100644 |
--- a/appengine/findit/waterfall/build_failure_analysis_pipelines.py |
+++ b/appengine/findit/waterfall/build_failure_analysis_pipelines.py |
@@ -1,81 +1,84 @@ |
-# Copyright (c) 2014 The Chromium Authors. All rights reserved. |
+# Copyright 2014 The Chromium Authors. All rights reserved. |
# Use of this source code is governed by a BSD-style license that can be |
# found in the LICENSE file. |
+from datetime import datetime |
import logging |
from google.appengine.ext import ndb |
-from pipeline_utils import pipelines |
- |
-from model.build import Build |
+from model.build_analysis import BuildAnalysis |
from model.build_analysis_status import BuildAnalysisStatus |
- |
- |
-# TODO(stgao): remove BasePipeline after http://crrev.com/810193002 is landed. |
-class BasePipeline(pipelines.AppenginePipeline): # pragma: no cover |
- def run_test(self, *args, **kwargs): |
- pass |
- |
- def finalized_test(self, *args, **kwargs): |
- pass |
- |
- def callback(self, **kwargs): |
- pass |
- |
- def run(self, *args, **kwargs): |
- raise NotImplementedError() |
+from waterfall.base_pipeline import BasePipeline |
+from waterfall.detect_first_failure_pipeline import DetectFirstFailurePipeline |
class BuildFailurePipeline(BasePipeline): |
+ def __init__(self, master_name, builder_name, build_number): |
+ super(BuildFailurePipeline, self).__init__( |
+ master_name, builder_name, build_number) |
+ self.master_name = master_name |
+ self.builder_name = builder_name |
+ self.build_number = build_number |
+ |
+ def finalized(self): |
+ analysis = BuildAnalysis.GetBuildAnalysis( |
+ self.master_name, self.builder_name, self.build_number) |
+ if self.was_aborted: # pragma: no cover |
+ analysis.status = BuildAnalysisStatus.ERROR |
+ else: |
+ analysis.status = BuildAnalysisStatus.ANALYZED |
+ analysis.put() |
+ |
# Arguments number differs from overridden method - pylint: disable=W0221 |
def run(self, master_name, builder_name, build_number): |
- build = Build.GetBuild(master_name, builder_name, build_number) |
+ analysis = BuildAnalysis.GetBuildAnalysis( |
+ master_name, builder_name, build_number) |
+ analysis.pipeline_url = self.pipeline_status_url() |
+ analysis.status = BuildAnalysisStatus.ANALYZING |
+ analysis.start_time = datetime.utcnow() |
+ analysis.put() |
- # TODO: implement the logic. |
- build.analysis_status = BuildAnalysisStatus.ANALYZED |
- build.put() |
+ yield DetectFirstFailurePipeline(master_name, builder_name, build_number) |
@ndb.transactional |
def NeedANewAnalysis(master_name, builder_name, build_number, force): |
- """Check analysis status of a build and decide if a new analysis is needed. |
+ """Checks status of analysis for the build and decides if a new one is needed. |
+ |
+ A BuildAnalysis entity for the given build will be created if none exists. |
Returns: |
- (build, need_analysis) |
- build (Build): the build as specified by the input. |
- need_analysis (bool): True if an analysis is needed, otherwise False. |
+ True if an analysis is needed, otherwise False. |
""" |
- build_key = Build.CreateKey(master_name, builder_name, build_number) |
- build = build_key.get() |
- |
- if not build: |
- build = Build.CreateBuild(master_name, builder_name, build_number) |
- build.analysis_status = BuildAnalysisStatus.PENDING |
- build.put() |
- return build, True |
+ analysis = BuildAnalysis.GetBuildAnalysis( |
+ master_name, builder_name, build_number) |
+ |
+ if not analysis: |
+ analysis = BuildAnalysis.CreateBuildAnalysis( |
+ master_name, builder_name, build_number) |
+ analysis.status = BuildAnalysisStatus.PENDING |
+ analysis.put() |
+ return True |
elif force: |
# TODO: avoid concurrent analysis. |
- build.Reset() |
- build.put() |
- return build, True |
+ analysis.Reset() |
+ analysis.put() |
+ return True |
else: |
# TODO: support following cases |
# 1. Automatically retry if last analysis failed with errors. |
# 2. Start another analysis if the build cycle wasn't completed in last |
# analysis request. |
# 3. Analysis is not complete and no update in the last 5 minutes. |
- return build, False |
+ return False |
def ScheduleAnalysisIfNeeded(master_name, builder_name, build_number, force, |
queue_name): |
- """Schedule an analysis if needed and return the build.""" |
- build, need_new_analysis = NeedANewAnalysis( |
- master_name, builder_name, build_number, force) |
- |
- if need_new_analysis: |
+ """Schedules an analysis if needed and returns the build analysis.""" |
+ if NeedANewAnalysis(master_name, builder_name, build_number, force): |
pipeline_job = BuildFailurePipeline(master_name, builder_name, build_number) |
pipeline_job.start(queue_name=queue_name) |
@@ -85,4 +88,4 @@ def ScheduleAnalysisIfNeeded(master_name, builder_name, build_number, force, |
else: # pragma: no cover |
logging.info('Analysis was already triggered or the result is recent.') |
- return build |
+ return BuildAnalysis.GetBuildAnalysis(master_name, builder_name, build_number) |