summaryrefslogtreecommitdiffstats
path: root/WebKitTools/QueueStatusServer
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2010-09-29 17:32:26 +0100
committerSteve Block <steveblock@google.com>2010-09-29 17:35:08 +0100
commit68513a70bcd92384395513322f1b801e7bf9c729 (patch)
tree161b50f75a5921d61731bb25e730005994fcec85 /WebKitTools/QueueStatusServer
parentfd5c6425ce58eb75211be7718d5dee960842a37e (diff)
downloadexternal_webkit-68513a70bcd92384395513322f1b801e7bf9c729.zip
external_webkit-68513a70bcd92384395513322f1b801e7bf9c729.tar.gz
external_webkit-68513a70bcd92384395513322f1b801e7bf9c729.tar.bz2
Merge WebKit at r67908: Initial merge by Git
Change-Id: I43a553e7b3299b28cb6ee8aa035ed70fe342b972
Diffstat (limited to 'WebKitTools/QueueStatusServer')
-rw-r--r--WebKitTools/QueueStatusServer/app.yaml4
-rw-r--r--WebKitTools/QueueStatusServer/handlers/nextpatch.py61
-rw-r--r--WebKitTools/QueueStatusServer/handlers/queuestatus.py17
-rw-r--r--WebKitTools/QueueStatusServer/index.yaml5
-rw-r--r--WebKitTools/QueueStatusServer/main.py2
-rw-r--r--WebKitTools/QueueStatusServer/model/activeworkitems.py58
-rw-r--r--WebKitTools/QueueStatusServer/stylesheets/dashboard.css35
-rw-r--r--WebKitTools/QueueStatusServer/templates/dashboard.html6
-rw-r--r--WebKitTools/QueueStatusServer/templates/includes/singlequeuestatus.html5
-rw-r--r--WebKitTools/QueueStatusServer/templates/queuestatus.html37
10 files changed, 208 insertions, 22 deletions
diff --git a/WebKitTools/QueueStatusServer/app.yaml b/WebKitTools/QueueStatusServer/app.yaml
index f6ff870..76d8963 100644
--- a/WebKitTools/QueueStatusServer/app.yaml
+++ b/WebKitTools/QueueStatusServer/app.yaml
@@ -7,5 +7,9 @@ handlers:
- url: /stylesheets
static_dir: stylesheets
+- url: /remote_api
+ script: $PYTHON_LIB/google/appengine/ext/remote_api/handler.py
+ login: admin
+
- url: /.*
script: main.py
diff --git a/WebKitTools/QueueStatusServer/handlers/nextpatch.py b/WebKitTools/QueueStatusServer/handlers/nextpatch.py
new file mode 100644
index 0000000..edb702a
--- /dev/null
+++ b/WebKitTools/QueueStatusServer/handlers/nextpatch.py
@@ -0,0 +1,61 @@
+# Copyright (C) 2010 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from google.appengine.ext import db
+from google.appengine.ext import webapp
+
+from model.workitems import WorkItems
+from model.activeworkitems import ActiveWorkItems
+from model import queuestatus
+
+from datetime import datetime, timedelta
+
+
+class NextPatch(webapp.RequestHandler):
+ def _get_next_patch_id(self, queue_name):
+ work_items = WorkItems.all().filter("queue_name =", queue_name).get()
+ if not work_items:
+ return None
+ active_work_items = ActiveWorkItems.get_or_insert(key_name=queue_name, queue_name=queue_name)
+ return db.run_in_transaction(self._assign_patch, active_work_items.key(), work_items.item_ids)
+
+ def get(self, queue_name):
+ patch_id = self._get_next_patch_id(queue_name)
+ if not patch_id:
+ self.error(404)
+ return
+ self.response.out.write(patch_id)
+
+ @staticmethod
+ def _assign_patch(key, work_item_ids):
+ now = datetime.now()
+ active_work_items = db.get(key)
+ active_work_items.deactivate_expired(now)
+ next_item = active_work_items.next_item(work_item_ids, now)
+ active_work_items.put()
+ return next_item
diff --git a/WebKitTools/QueueStatusServer/handlers/queuestatus.py b/WebKitTools/QueueStatusServer/handlers/queuestatus.py
index 5295b17..f76157d 100644
--- a/WebKitTools/QueueStatusServer/handlers/queuestatus.py
+++ b/WebKitTools/QueueStatusServer/handlers/queuestatus.py
@@ -50,9 +50,24 @@ class QueueStatus(webapp.RequestHandler):
def get(self, queue_name):
work_items = WorkItems.all().filter("queue_name =", queue_name).get()
statuses = queuestatus.QueueStatus.all().filter("queue_name =", queue_name).order("-date").fetch(15)
+
+ status_groups = []
+ last_patch_id = None
+ synthetic_patch_id_counter = 0
+
+ for status in statuses:
+ patch_id = status.active_patch_id
+ if not patch_id or last_patch_id != patch_id:
+ status_group = []
+ status_groups.append(status_group)
+ else:
+ status_group = status_groups[-1]
+ status_group.append(status)
+ last_patch_id = patch_id
+
template_values = {
"display_queue_name": display_name_for_queue(queue_name),
"work_item_rows": self._rows_for_work_items(work_items),
- "statuses": statuses,
+ "status_groups": status_groups,
}
self.response.out.write(template.render("templates/queuestatus.html", template_values))
diff --git a/WebKitTools/QueueStatusServer/index.yaml b/WebKitTools/QueueStatusServer/index.yaml
index 94b6692..6c9a3b2 100644
--- a/WebKitTools/QueueStatusServer/index.yaml
+++ b/WebKitTools/QueueStatusServer/index.yaml
@@ -27,6 +27,11 @@ indexes:
properties:
- name: queue_name
- name: date
+
+- kind: QueueStatus
+ properties:
+ - name: queue_name
+ - name: date
direction: desc
- kind: SVNRevision
diff --git a/WebKitTools/QueueStatusServer/main.py b/WebKitTools/QueueStatusServer/main.py
index e550dc5..93227ca 100644
--- a/WebKitTools/QueueStatusServer/main.py
+++ b/WebKitTools/QueueStatusServer/main.py
@@ -35,6 +35,7 @@ from google.appengine.ext.webapp.util import run_wsgi_app
from handlers.dashboard import Dashboard
from handlers.gc import GC
+from handlers.nextpatch import NextPatch
from handlers.patch import Patch
from handlers.patchstatus import PatchStatus
from handlers.queuestatus import QueueStatus
@@ -59,6 +60,7 @@ routes = [
(r'/status-bubble/(.*)', StatusBubble),
(r'/svn-revision/(.*)', SVNRevision),
(r'/queue-status/(.*)', QueueStatus),
+ (r'/next-patch/(.*)', NextPatch),
('/update-status', UpdateStatus),
('/update-work-items', UpdateWorkItems),
('/update-svn-revision', UpdateSVNRevision),
diff --git a/WebKitTools/QueueStatusServer/model/activeworkitems.py b/WebKitTools/QueueStatusServer/model/activeworkitems.py
new file mode 100644
index 0000000..e24e6ca
--- /dev/null
+++ b/WebKitTools/QueueStatusServer/model/activeworkitems.py
@@ -0,0 +1,58 @@
+# Copyright (C) 2010 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from google.appengine.ext import db
+
+from datetime import timedelta
+import time
+
+
+class ActiveWorkItems(db.Model):
+ queue_name = db.StringProperty()
+ item_ids = db.ListProperty(int)
+ item_dates = db.ListProperty(float)
+ date = db.DateTimeProperty(auto_now_add=True)
+
+ def deactivate_expired(self, now):
+ one_hour_ago = time.mktime((now - timedelta(minutes=60)).timetuple())
+ nonexpired_item_ids = []
+ nonexpired_item_dates = []
+ for i in range(len(self.item_ids)):
+ if self.item_dates[i] > one_hour_ago:
+ nonexpired_item_ids.append(self.item_ids[i])
+ nonexpired_item_dates.append(self.item_dates[i])
+ self.item_ids = nonexpired_item_ids
+ self.item_dates = nonexpired_item_dates
+
+ def next_item(self, work_item_ids, now):
+ for item_id in work_item_ids:
+ if item_id not in self.item_ids:
+ self.item_ids.append(item_id)
+ self.item_dates.append(time.mktime(now.timetuple()))
+ return item_id
+ return None
diff --git a/WebKitTools/QueueStatusServer/stylesheets/dashboard.css b/WebKitTools/QueueStatusServer/stylesheets/dashboard.css
index 1ecf2eb..7b4f857 100644
--- a/WebKitTools/QueueStatusServer/stylesheets/dashboard.css
+++ b/WebKitTools/QueueStatusServer/stylesheets/dashboard.css
@@ -44,36 +44,59 @@ td {
tr:hover, li:hover {
background-color: #EEE;
}
+
+.status-group {
+ font-size: 90%;
+}
+
+.status-bug {
+ font-weight: bold;
+}
+
+.status-group ul {
+ font-size: 90%;
+}
+
+.status-group ul li {
+ padding: 2px 0 2px 7px;
+ overflow: hidden;
+}
+
+.status-group ul li:hover {
+ background: #ddd;
+}
+
.status-date {
color: #AAA;
float: right;
font-size: 8pt;
}
-.status {
+
+.status-cell {
margin: 1px;
padding: 1px 2px;
font-size: 9pt;
border: 1px solid transparent;
}
-.status:hover {
+.status-cell:hover {
border: 1px solid black;
}
-.pass {
+.status-cell.pass {
background-color: #8FDF5F;
cursor: pointer;
/* border: 1px solid #4F8530; */
}
-.fail {
+.status-cell.fail {
background-color: #E98080;
cursor: pointer;
/* border: 1px solid #A77272; */
}
-.pending {
+.status-cell.pending {
background-color: #FFFC6C;
cursor: pointer;
/* border: 1px solid #C5C56D; */
}
-.error {
+.status-cell.error {
background-color: #E0B0FF;
cursor: pointer;
/* border: 1px solid #ACA0B3; */
diff --git a/WebKitTools/QueueStatusServer/templates/dashboard.html b/WebKitTools/QueueStatusServer/templates/dashboard.html
index c5c2359..f88a5ea 100644
--- a/WebKitTools/QueueStatusServer/templates/dashboard.html
+++ b/WebKitTools/QueueStatusServer/templates/dashboard.html
@@ -24,14 +24,14 @@ function statusDetail(patch_id) {
</thead>
<tbody>{% for row in rows %}
<tr>
- <td class="status">
+ <td class="status-cell">
{{ row.bug_id|force_escape|webkit_bug_id|safe }}
</td>
- <td class="status">
+ <td class="status-cell">
{{ row.attachment_id|force_escape|webkit_attachment_id|safe }}
</td>
{% for bubble in row.bubbles %}
- <td class="status {{ bubble.status_class }}"
+ <td class="status-cell {{ bubble.status_class }}"
{% if bubble.status %}
onclick="statusDetail({{ row.attachment_id }})"
title="{{ bubble.status_date|timesince }}"
diff --git a/WebKitTools/QueueStatusServer/templates/includes/singlequeuestatus.html b/WebKitTools/QueueStatusServer/templates/includes/singlequeuestatus.html
new file mode 100644
index 0000000..075cd39
--- /dev/null
+++ b/WebKitTools/QueueStatusServer/templates/includes/singlequeuestatus.html
@@ -0,0 +1,5 @@
+<span class="status-date">{{ status.date|timesince }} ago</span>
+<span class="status-message">{{ status.message|force_escape|urlize|webkit_linkify|safe }}</span>
+{% if status.results_file %}
+ <span class="status-results">[{{ status.key.id|results_link|safe }}]</span>
+{% endif %}
diff --git a/WebKitTools/QueueStatusServer/templates/queuestatus.html b/WebKitTools/QueueStatusServer/templates/queuestatus.html
index 38c125f..d2d72c7 100644
--- a/WebKitTools/QueueStatusServer/templates/queuestatus.html
+++ b/WebKitTools/QueueStatusServer/templates/queuestatus.html
@@ -11,18 +11,31 @@
<div class="status-details">
<ul>
- {% for status in statuses %}
- <li>{% if status.active_bug_id %}
- <span class="status-bug">
- Patch {{ status.active_patch_id|force_escape|webkit_attachment_id|safe }} from bug
- {{ status.active_bug_id|force_escape|webkit_bug_id|safe }}:
- </span>{% endif %}
- <span class="status-message">{{ status.message|force_escape|urlize|webkit_linkify|safe }}</span>
- {% if status.results_file %}
- <span class="status-results">[{{ status.key.id|results_link|safe }}]</span>
- {% endif %}
- <span class="status-date">{{ status.date|timesince }} ago</span>
- </li>
+ {% for status_group in status_groups %}
+ {% with status_group.0 as title_status %}
+ <li class="status-group">
+ {% if title_status.active_bug_id %}
+ <span class="status-bug">
+ Patch {{ title_status.active_patch_id|force_escape|webkit_attachment_id|safe }} from bug
+ {{ title_status.active_bug_id|force_escape|webkit_bug_id|safe }}:
+ </span>
+ {% endif %}
+
+ {% ifequal status_group|length 1 %}
+ {% with title_status as status %}
+ {% include 'includes/singlequeuestatus.html' %}
+ {% endwith %}
+ {% else %}
+ <ul>
+ {% for status in status_group %}
+ <li class="status">
+ {% include 'includes/singlequeuestatus.html' %}
+ </li>
+ {% endfor %}
+ </ul>
+ {% endifequal %}
+ </li>
+ {% endwith %}
{% endfor %}
</ul>
</div>