Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(746)

Side by Side Diff: commit-queue/verification/try_job_steps.py

Issue 135363007: Delete public commit queue to avoid confusion after move to internal repo (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # coding=utf8
2 # Copyright (c) 2013 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import model
7
8
9 # CQ uses this delay to decide if a triggered job hasn't show up from
10 # rietveld processing time or if it has gone missing
11 PROPOGATION_DELAY_S = 3 * 60 * 60
12
13
14 def need_to_trigger(builder_name, need_to_run, try_jobs):
15 """Returns which tests need to be triggered.
16
17 These are the tests that are not pending on any try job, either running or
18 in the pending list.
19 """
20 need_to_run = set(need_to_run)
21 for try_job in try_jobs:
22 if try_job.builder == builder_name:
23 need_to_run -= set(try_job.steps_passed)
24 if not try_job.completed:
25 if try_job.requested_steps == []:
26 # Special case jobs discovered by CQ that it did not send. Wait for
27 # these jobs to complete rather than trying to interpret the filter
28 assert try_job.started
29 need_to_run.clear()
30 else:
31 need_to_run -= (
32 set(try_job.requested_steps) - set(try_job.steps_failed))
33
34 return need_to_run
35
36
37 def waiting_for(builder_name, tests, try_jobs):
38 """Returns the tests that we are waiting for results on pending or running
39 builds.
40 """
41 tests = set(tests)
42 for try_job in try_jobs:
43 if try_job.builder == builder_name:
44 tests -= set(try_job.steps_passed)
45 return tests
46
47
48 class TryJobStepsBase(model.PersistentMixIn):
49 builder_name = unicode
50
51 # Name of the prerequisite builder.
52 prereq_builder = unicode
53 # List of prerequisite tests to look for.
54 prereq_tests = list
55
56 def __init__(self, **kwargs):
57 kwargs.setdefault('prereq_builder', u'')
58 kwargs.setdefault('prereq_tests', [])
59 required = set(self._persistent_members())
60 actual = set(kwargs)
61 assert required == actual, (required - actual, required, actual)
62 super(TryJobStepsBase, self).__init__(**kwargs)
63 # Then mark it read-only.
64 self._read_only = True
65
66 @model.immutable
67 def unmet_prereqs(self, try_jobs):
68 """
69 Determine if this TryJobSteps has unmet prerequisites.
70
71 Returns True iff prereq is unmet.
72 """
73 if not self.prereq_builder or not self.prereq_tests:
74 return None
75 unmet_steps = set(self.prereq_tests)
76 for try_job in try_jobs.itervalues():
77 if try_job.builder == self.prereq_builder:
78 unmet_steps -= set(try_job.steps_passed)
79 return bool(unmet_steps)
80
81 @model.immutable
82 def get_triggered_steps(self, _builder, _steps):
83 """Returns the steps on this builder that will get triggered by the given
84 builder and its steps, which is always None since this isn't a triggered
85 bot."""
86 return (self.builder_name, [])
87
88
89 class TryJobSteps(TryJobStepsBase):
90 steps = list
91
92 @model.immutable
93 def waiting_for(self, try_jobs):
94 """Returns the tests that we are waiting for results on pending or running
95 builds.
96 """
97 return (self.builder_name,
98 waiting_for(self.builder_name, self.steps, try_jobs.itervalues()))
99
100 @model.immutable
101 def need_to_trigger(self, try_jobs, _now):
102 """Returns which tests need to be triggered.
103
104 These are the tests that are not pending on any try job, either running or
105 in the pending list.
106 """
107 if self.unmet_prereqs(try_jobs):
108 return (self.builder_name, [])
109 return (self.builder_name,
110 need_to_trigger(self.builder_name, self.steps,
111 try_jobs.itervalues()))
112
113
114 class TryJobTriggeredSteps(TryJobStepsBase):
115 # The name of the bot that triggers this bot.
116 trigger_name = unicode
117 # Maps the triggered_bot_step -> trigger_bot_step required to trigger it.
118 steps = dict
119
120 @model.immutable
121 def _triggered_try_jobs(self, try_jobs):
122 """Return all the try jobs that were on this builder and had been trigger
123 by the trigger_name bot."""
124 triggered_try_jobs = []
125 for try_job in try_jobs.itervalues():
126 if (try_job.builder == self.builder_name and
127 try_job.parent_key and try_job.parent_key in try_jobs and
128 try_jobs[try_job.parent_key].builder == self.trigger_name):
129 triggered_try_jobs.append(try_job)
130
131 return triggered_try_jobs
132
133 @model.immutable
134 def waiting_for(self, try_jobs):
135 """Returns the tests that we are waiting for results on pending or running
136 builds.
137 """
138 return (self.builder_name,
139 waiting_for(self.builder_name, self.steps,
140 self._triggered_try_jobs(try_jobs)))
141
142 @model.immutable
143 def need_to_trigger(self, try_jobs, now):
144 """Returns which tests need to be triggered.
145
146 These are the tests that are not pending on any try job, either running or
147 in the pending list.
148 """
149 if self.unmet_prereqs(try_jobs):
150 return (self.builder_name, [])
151 need_to_run = set(self.steps)
152 steps_to_trigger = need_to_trigger(self.builder_name, need_to_run,
153 self._triggered_try_jobs(try_jobs))
154
155 # Convert the steps to trigger to their trigger options.
156 trigger_need_to_run = set(self.steps[step] for step in steps_to_trigger)
157
158 # See which triggered builds have already started, so we can then ignore
159 # their parents when seeing if more triggered build are on the way.
160 detected_triggered_keys = set(
161 job.parent_key for key, job in try_jobs.iteritems()
162 if job.builder == self.builder_name)
163
164 # Remove any trigger options that are waiting to run from the set to
165 # trigger.
166 for key, try_job in try_jobs.iteritems():
167 if try_job.builder == self.trigger_name:
168 if (try_job.completed and
169 not (now - try_job.init_time > PROPOGATION_DELAY_S) and
170 key not in detected_triggered_keys):
171 # If we get here a triggered build hasn't started yet, so wait for
172 # any steps that should run on the triggered build.
173 trigger_need_to_run -= (
174 set(step for step in self.steps.itervalues()
175 if step in try_job.requested_steps))
176 if not try_job.completed:
177 trigger_need_to_run -= (
178 set(try_job.requested_steps) - set(try_job.steps_failed))
179
180 return (self.trigger_name, trigger_need_to_run)
181
182 @model.immutable
183 def get_triggered_steps(self, builder, steps):
184 """Returns the steps on this builder that will get triggered by the given
185 builder and its steps."""
186 trigger_steps = []
187 if builder == self.trigger_name:
188 trigger_steps = [key for key, value in self.steps.iteritems()
189 if value in steps]
190
191 return (self.builder_name, sorted(trigger_steps))
192
193
194 class TryJobTriggeredOrNormalSteps(TryJobTriggeredSteps):
195 """This class assumes that the triggered names can be run
196 on the trigger bot with the same name that they appear with on
197 the triggered bot."""
198
199 # The list of steps that have to be run on the trigger bot.
200 trigger_bot_steps = list
201
202 # True if the triggered bot should try and run the missing tests.
203 use_triggered_bot = bool
204
205 @model.immutable
206 def need_to_trigger(self, try_jobs, now):
207 if self.unmet_prereqs(try_jobs):
208 return (self.builder_name, [])
209 name, steps = super(TryJobTriggeredOrNormalSteps,
210 self).need_to_trigger(try_jobs, now)
211
212 # Remove any tests where that could still be triggered by the trigger bot.
213 steps = need_to_trigger(self.trigger_name, steps, try_jobs.itervalues())
214
215 # Convert the trigger names to the triggered names.
216 steps = set(step for step, trigger
217 in self.steps.iteritems() if trigger in steps)
218
219 # Add the trigger bot only steps and remove ones that have passed.
220 steps = steps.union(self.trigger_bot_steps)
221 steps = need_to_trigger(self.trigger_name, steps, try_jobs.itervalues())
222
223 # If we want to use the triggered bot, convert the steps backs to their
224 # trigger name (where possible).
225 if self.use_triggered_bot:
226 # TODO(csharp): Remove this once the triggered bots should always handle
227 # retry (limit it to one attempt each to prevent too much breakage).
228 if any(try_job.builder == self.builder_name
229 for try_job in try_jobs.itervalues()):
230 return name, steps
231
232 steps = set(self.steps.get(step, step) for step in steps)
233
234 return name, steps
235
236 @model.immutable
237 def waiting_for(self, try_jobs):
238 steps = waiting_for(self.builder_name, self.steps,
239 self._triggered_try_jobs(try_jobs))
240
241 # Add the steps that can only run on the trigger bot and see what hasn't
242 # passed on the trigger bot yet.
243 steps = steps.union(self.trigger_bot_steps)
244
245 steps = waiting_for(self.trigger_name, steps, try_jobs.itervalues())
246
247 return self.trigger_name, steps
OLDNEW
« no previous file with comments | « commit-queue/verification/try_job_on_rietveld.py ('k') | commit-queue/verification/try_server.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698