| OLD | NEW |
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import logging | 5 import logging |
| 6 | 6 |
| 7 from google.appengine.ext import ndb | 7 from google.appengine.ext import ndb |
| 8 | 8 |
| 9 from common import appengine_util | 9 from common import appengine_util |
| 10 from common import constants | 10 from common import constants |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 analysis = WfAnalysis.Create(master_name, builder_name, build_number) | 35 analysis = WfAnalysis.Create(master_name, builder_name, build_number) |
| 36 analysis.status = analysis_status.PENDING | 36 analysis.status = analysis_status.PENDING |
| 37 analysis.request_time = time_util.GetUTCNow() | 37 analysis.request_time = time_util.GetUTCNow() |
| 38 analysis.put() | 38 analysis.put() |
| 39 return True | 39 return True |
| 40 elif force: | 40 elif force: |
| 41 # A new analysis could be forced if last analysis was completed. | 41 # A new analysis could be forced if last analysis was completed. |
| 42 if not analysis.completed: | 42 if not analysis.completed: |
| 43 # TODO: start a new analysis if the last one has started running but it | 43 # TODO: start a new analysis if the last one has started running but it |
| 44 # has no update for a considerable amount of time, eg. 10 minutes. | 44 # has no update for a considerable amount of time, eg. 10 minutes. |
| 45 logging.info('Existing analysis is not completed yet. No new analysis.') |
| 45 return False | 46 return False |
| 46 | 47 |
| 47 analysis.Reset() | 48 analysis.Reset() |
| 48 analysis.request_time = time_util.GetUTCNow() | 49 analysis.request_time = time_util.GetUTCNow() |
| 49 analysis.put() | 50 analysis.put() |
| 50 return True | 51 return True |
| 51 elif failed_steps and analysis.completed: | 52 elif failed_steps and analysis.completed: |
| 52 # If there is any new failed step, a new analysis is needed. | 53 # If there is any new failed step, a new analysis is needed. |
| 53 for step in failed_steps: | 54 for step in failed_steps: |
| 54 analyzed = any(step == s for s in analysis.not_passed_steps) | 55 analyzed = any(step == s for s in analysis.not_passed_steps) |
| 55 if analyzed: | 56 if analyzed: |
| 56 continue | 57 continue |
| 57 | 58 |
| 58 logging.info('At least one new failed step is detected: %s', step) | 59 logging.info('At least one new failed step is detected: %s', step) |
| 59 analysis.Reset() | 60 analysis.Reset() |
| 60 analysis.request_time = time_util.GetUTCNow() | 61 analysis.request_time = time_util.GetUTCNow() |
| 61 analysis.put() | 62 analysis.put() |
| 62 return True | 63 return True |
| 63 | 64 |
| 64 # Start a new analysis if the build cycle wasn't completed in last analysis, | 65 # Start a new analysis if the build cycle wasn't completed in last analysis, |
| 65 # but now it is completed. This will potentially trigger a try-job run. | 66 # but now it is completed. This will potentially trigger a try-job run. |
| 66 if analysis.completed and not analysis.build_completed and build_completed: | 67 if analysis.completed and not analysis.build_completed and build_completed: |
| 67 return True | 68 return True |
| 68 | 69 |
| 69 # TODO: support following cases | 70 # TODO: support following cases |
| 70 # * Automatically retry if last analysis failed with errors. | 71 # * Automatically retry if last analysis failed with errors. |
| 71 # * Analysis is not complete and no update in the last 5 minutes. | 72 # * Analysis is not complete and no update in the last 5 minutes. |
| 73 logging.info('Not match any cases. No new analysis.') |
| 72 return False | 74 return False |
| 73 | 75 |
| 74 | 76 |
| 75 def ScheduleAnalysisIfNeeded(master_name, builder_name, build_number, | 77 def ScheduleAnalysisIfNeeded(master_name, builder_name, build_number, |
| 76 failed_steps=None, | 78 failed_steps=None, |
| 77 build_completed=False, | 79 build_completed=False, |
| 78 force=False, | 80 force=False, |
| 79 force_try_job=False, | 81 force_try_job=False, |
| 80 queue_name=constants.DEFAULT_QUEUE): | 82 queue_name=constants.DEFAULT_QUEUE): |
| 81 """Schedules an analysis if needed and returns the build analysis. | 83 """Schedules an analysis if needed and returns the build analysis. |
| (...skipping 29 matching lines...) Expand all Loading... |
| 111 # specified explicitly, and the default target is used rather than the one | 113 # specified explicitly, and the default target is used rather than the one |
| 112 # in the queue.yaml file, but this contradicts the documentation in | 114 # in the queue.yaml file, but this contradicts the documentation in |
| 113 # https://cloud.google.com/appengine/docs/python/taskqueue/tasks#Task. | 115 # https://cloud.google.com/appengine/docs/python/taskqueue/tasks#Task. |
| 114 pipeline_job.target = appengine_util.GetTargetNameForModule( | 116 pipeline_job.target = appengine_util.GetTargetNameForModule( |
| 115 constants.WATERFALL_BACKEND) | 117 constants.WATERFALL_BACKEND) |
| 116 pipeline_job.start(queue_name=queue_name) | 118 pipeline_job.start(queue_name=queue_name) |
| 117 | 119 |
| 118 logging.info('An analysis was scheduled for build %s, %s, %s: %s', | 120 logging.info('An analysis was scheduled for build %s, %s, %s: %s', |
| 119 master_name, builder_name, build_number, | 121 master_name, builder_name, build_number, |
| 120 pipeline_job.pipeline_status_path()) | 122 pipeline_job.pipeline_status_path()) |
| 123 else: |
| 124 logging.info('An analysis is not needed for build %s, %s, %s', |
| 125 master_name, builder_name, build_number) |
| 121 | 126 |
| 122 return WfAnalysis.Get(master_name, builder_name, build_number) | 127 return WfAnalysis.Get(master_name, builder_name, build_number) |
| OLD | NEW |