3 Implement EWS real-time patch status updates and tail logging
4 https://bugs.webkit.org/show_bug.cgi?id=186823
5
6 Reviewed by NOBODY (OOPS!).
7
8 Makes the patch status page (e.g. https://webkit-queues.webkit.org/patch/342789/mac-ews) display
9 real-time status updates, including a tail(1) of the standard output and standard error streams
10 from the bot as it runs commands to build and test a patch. You can either access the patch status
11 page directly using a URL similar to the example one above or, even easier, just click on the EWS
12 bubble of the queue you want to view on the Bugzilla bug page the patch was uploaded to.
13
14 Real-time updates are written to a TailLog, which is implemented using the AppEngine Channel API.
15 Each TailLog stores the Channel API token (used by the patch status page to connect to the back-end)
16 in memcache keyed off the queue name and attachment id. We use memcache to store this association
17 instead of storing it in the database to complement the transient nature of the Channel API. Memcache
18 may be flushed or items may be evicted from it at any time.
19
20 A side effect of this change this that the patch status patch now lists events in chronological
21 order from oldest to newest. Currently it lists status updates in reverse chronological order.
22 The change in ordering was made so that the standard output and standard error streams are
23 written as a person would expect in a terminal.
24
25 * QueueStatusServer/handlers/patch.py:
26 (Patch.get): Always order the status messages in chronological order from oldest to newest.
27 If we have an existing tail log for the specified queue and attachment then include its token
28 as a template variable so that the rendered web page will be able to connect to the stream.
29 * QueueStatusServer/handlers/releaselock.py:
30 (ReleaseLock.post): Expire the tail log when we release the lock for the patch.
31 * QueueStatusServer/handlers/releasepatch.py:
32 (ReleasePatch.post): Expire the tail log when the patch is released from the queue.
33 * QueueStatusServer/handlers/updatestatus.py:
34 (UpdateStatus.post): Create a tail log for the specified queue and attachment if one does not
35 already exist and write the status details to it. We only persist the status details to the
36 database (disk) if the update is not is transient. Transient updates are only written to the
37 tail log and are best used for data that is unnecessary to keep around. We use transient
38 update for streamed standard output and standard error text because the value of such text
39 is time-sensitive (usually only valuable while iterating on a patch before it lands) and
40 the output can be excessive (tens of MBs). EWS will persist a trailing portion of these
41 streams to the database if a patch fails to build of causes tests failures.
42 * QueueStatusServer/index.yaml: Remove the sort order from the database index.
43 * QueueStatusServer/model/taillog.py: Added.
44 (TailLog):
45 (TailLog.__init__):
46 (TailLog.lookup_or_create): Query memcache for an existing channel token. Otherwise, create
47 a new channel and store the token in memcache.
48 (TailLog.lookup): Query memcache for the channel token.
49 (TailLog.expire): Remove the key from memcache.
50 (TailLog.write_message): Writes a message to the channel.
51 (TailLog._generate_key): Compute a key from the name of the queue and the attachment id.
52 * QueueStatusServer/stylesheets/common.css:
53 (.code): Stylize transient messages using a monospace font to resemble console output.
54 * QueueStatusServer/templates/patch.html: Connect to to the underlying Channel API to stream
55 tail log updates.
56 * QueueStatusServer/templates/updatestatus.html: Add a checkbox as to whether the update is
57 considered transient and should only appear in the tail log.
58 * Scripts/webkitpy/common/net/statusserver.py:
59 (StatusServer._post_status_to_server): Modified to take a boolean, is_transient, as to whether
60 the status is considered transient.
61 (StatusServer.update_status): Ditto.
62
63 (WritableStatusServerStatusFileObject):
64 (WritableStatusServerStatusFileObject.__init__):
65 (WritableStatusServerStatusFileObject.__eq__):
66 (WritableStatusServerStatusFileObject.write):
67 File-like object that forwards writes to the status
68 server as transient status updates.
69
70 * Scripts/webkitpy/common/net/statusserver_mock.py:
71 (MockStatusServer.update_status):
72 * Scripts/webkitpy/common/net/web_mock.py:
73 (MockBrowser.find_control): Added.
74 * Scripts/webkitpy/common/system/executive.py:
75 (Executive.run_and_throw_if_fail): Extract out logic into run_with_teed_output_and_throw_if_fail()
76 and write this function in terms of it.
77 (Executive.run_with_teed_output_and_throw_if_fail): Extracted from Executive.run_and_throw_if_fail().
78 * Scripts/webkitpy/common/system/executive_mock.py:
79 (MockExecutive.run_with_teed_output_and_throw_if_fail): Added.
80
81 * Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py:
82 (MockCommitQueue.run_command):
83 (FailingTestCommitQueue.run_command):
84 (MockSimpleTestPlanCommitQueue.run_command):
85 * Scripts/webkitpy/tool/bot/patchanalysistask.py:
86 (PatchAnalysisTaskDelegate.run_command):
87 (PatchAnalysisTask._run_command):
88 * Scripts/webkitpy/tool/commands/earlywarningsystem.py:
89 (AbstractEarlyWarningSystem.run_command):
90 Pass the Attachment object through so that we can log the output of the command with respect to a particular patch.
91
92 * Scripts/webkitpy/tool/commands/earlywarningsystem_unittest.py:
93 (EarlyWarningSystemTest._default_expected_logs): Update expected result now that we send updates for transient events.
94 * Scripts/webkitpy/tool/commands/perfalizer.py:
95 (PerfalizerTask.run_command): Pass the Attachment object through so that we can log the output of the command with
96 respect to a particular patch.
97 * Scripts/webkitpy/tool/commands/queues.py:
98 (AbstractQueue.run_webkit_patch):
99 (CommitQueue.run_command): Pass the Attachment object through so that we can log the output of the command with respect
100 to a particular patch.
101 (StyleQueue.run_command): Ditto.
102 * Scripts/webkitpy/tool/commands/queues_unittest.py:
103 (AbstractQueueTest._assert_run_webkit_patch): Update test now that we send updates for transient events.
104
1052018-06-19 Daniel Bates <dabates@apple.com>
106