<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[190900] trunk/Websites/perf.webkit.org</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/190900">190900</a></dd>
<dt>Author</dt> <dd>rniwa@webkit.org</dd>
<dt>Date</dt> <dd>2015-10-12 16:05:43 -0700 (Mon, 12 Oct 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Perf dashboard tools shouldn't require server credentials in multiple configuration files
https://bugs.webkit.org/show_bug.cgi?id=149994

Reviewed by Chris Dumez.

Made detect-changes.js and pull-svn.py pull username and passwords from the server config JSON to reduce
the number of JSON files that need to include credentials.

Also made each script reload the server config after sleep to allow dynamic credential updates.

In addition, change the server config JSON's format to include scheme, host, and port numbers separately
instead of a url since detect-changes.js needs each value separately.

This reduces the number of JSONs with credentials to two for our internal dashboard.

* tools/detect-changes.js:
(main): Added a property argument parsing. Now takes --server-config-json, --change-detection-config-json,
and --seconds-to-sleep like other scripts.
(parseArgument): Added.
(fetchManifestAndAnalyzeData): Reload the server config JSON.
(loadServerConfig): Added. Set settings.perfserver and settings.slave from the server config JSON. Also
add settings.perfserver.host to match the old format.
(configurationsForTesting): Fixed a bug that we throw an exception when a dashboard contains an empty cell.

* tools/pull-os-versions.py:
(main): Use load_server_config after each sleep.

* tools/pull-svn.py:
(main): Use load_server_config after each sleep.
(fetch_commits_and_submit): Use the perf dashboard's auth as subversion credential when useServerAuth is set.

* tools/sync-with-buildbot.py:
(main): Use load_server_config after each sleep.

* tools/util.py:
(load_server_config): Extracted from python scripts. Computes server's url from scheme, host, and port number
to match the old format python scripts except.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkWebsitesperfwebkitorgChangeLog">trunk/Websites/perf.webkit.org/ChangeLog</a></li>
<li><a href="#trunkWebsitesperfwebkitorgtoolsdetectchangesjs">trunk/Websites/perf.webkit.org/tools/detect-changes.js</a></li>
<li><a href="#trunkWebsitesperfwebkitorgtoolspullosversionspy">trunk/Websites/perf.webkit.org/tools/pull-os-versions.py</a></li>
<li><a href="#trunkWebsitesperfwebkitorgtoolspullsvnpy">trunk/Websites/perf.webkit.org/tools/pull-svn.py</a></li>
<li><a href="#trunkWebsitesperfwebkitorgtoolssyncwithbuildbotpy">trunk/Websites/perf.webkit.org/tools/sync-with-buildbot.py</a></li>
<li><a href="#trunkWebsitesperfwebkitorgtoolsutilpy">trunk/Websites/perf.webkit.org/tools/util.py</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkWebsitesperfwebkitorgChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/ChangeLog (190899 => 190900)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/ChangeLog        2015-10-12 22:51:59 UTC (rev 190899)
+++ trunk/Websites/perf.webkit.org/ChangeLog        2015-10-12 23:05:43 UTC (rev 190900)
</span><span class="lines">@@ -1,3 +1,43 @@
</span><ins>+2015-10-12  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        Perf dashboard tools shouldn't require server credentials in multiple configuration files
+        https://bugs.webkit.org/show_bug.cgi?id=149994
+
+        Reviewed by Chris Dumez.
+
+        Made detect-changes.js and pull-svn.py pull username and passwords from the server config JSON to reduce
+        the number of JSON files that need to include credentials.
+
+        Also made each script reload the server config after sleep to allow dynamic credential updates.
+
+        In addition, change the server config JSON's format to include scheme, host, and port numbers separately
+        instead of a url since detect-changes.js needs each value separately.
+
+        This reduces the number of JSONs with credentials to two for our internal dashboard.
+
+        * tools/detect-changes.js:
+        (main): Added a property argument parsing. Now takes --server-config-json, --change-detection-config-json,
+        and --seconds-to-sleep like other scripts.
+        (parseArgument): Added.
+        (fetchManifestAndAnalyzeData): Reload the server config JSON.
+        (loadServerConfig): Added. Set settings.perfserver and settings.slave from the server config JSON. Also
+        add settings.perfserver.host to match the old format.
+        (configurationsForTesting): Fixed a bug that we throw an exception when a dashboard contains an empty cell.
+
+        * tools/pull-os-versions.py:
+        (main): Use load_server_config after each sleep.
+
+        * tools/pull-svn.py:
+        (main): Use load_server_config after each sleep.
+        (fetch_commits_and_submit): Use the perf dashboard's auth as subversion credential when useServerAuth is set.
+
+        * tools/sync-with-buildbot.py:
+        (main): Use load_server_config after each sleep.
+
+        * tools/util.py:
+        (load_server_config): Extracted from python scripts. Computes server's url from scheme, host, and port number
+        to match the old format python scripts except.
+
</ins><span class="cx"> 2015-10-11  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Build fix after r190817.  Now that pull-os-versions store fake timestamps, we need to bypass timestamp
</span></span></pre></div>
<a id="trunkWebsitesperfwebkitorgtoolsdetectchangesjs"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/tools/detect-changes.js (190899 => 190900)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/tools/detect-changes.js        2015-10-12 22:51:59 UTC (rev 190899)
+++ trunk/Websites/perf.webkit.org/tools/detect-changes.js        2015-10-12 23:05:43 UTC (rev 190900)
</span><span class="lines">@@ -7,32 +7,84 @@
</span><span class="cx"> var RunsData = data.RunsData;
</span><span class="cx"> var Statistics = require('../public/v2/js/statistics.js');
</span><span class="cx"> 
</span><ins>+// FIXME: We shouldn't use a global variable like this.
</ins><span class="cx"> var settings;
</span><span class="cx"> function main(argv)
</span><span class="cx"> {
</span><del>-    if (argv.length &lt; 3) {
-        console.error('Please specify the settings JSON path');
-        return 1;
-    }
</del><ins>+    var options = parseArgument(argv, [
+        {name: '--server-config-json', required: true},
+        {name: '--change-detection-config-json', required: true},
+        {name: '--seconds-to-sleep', type: parseFloat, default: 1200},
+    ]);
+    if (!options)
+        return;
</ins><span class="cx"> 
</span><del>-    settings = JSON.parse(fs.readFileSync(argv[2], 'utf8'));
</del><ins>+    settings = JSON.parse(fs.readFileSync(options['--change-detection-config-json'], 'utf8'));
+    settings.secondsToSleep = options['--seconds-to-sleep'];
</ins><span class="cx"> 
</span><del>-    fetchManifestAndAnalyzeData();
</del><ins>+    fetchManifestAndAnalyzeData(options['--server-config-json']);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-function fetchManifestAndAnalyzeData()
</del><ins>+function parseArgument(argv, acceptedOptions) {
+    var args = argv.slice(2);
+    var options = {}
+    for (var i = 0; i &lt; args.length; i += 2) {
+        var current = args[i];
+        var next = args[i + 1];
+        for (var option of acceptedOptions) {
+            if (current == option['name']) {
+                options[option['name']] = next;
+                next = null;
+                break;
+            }
+        }
+        if (next) {
+            console.error('Invalid argument:', current);
+            return null;
+        }
+    }
+    for (var option of acceptedOptions) {
+        var name = option['name'];
+        if (option['required'] &amp;&amp; !(name in options)) {
+            console.log('Required argument', name, 'is missing');
+            return null;
+        }
+        var value = options[name] || option['default'];
+        var converter = option['type'];
+        options[name] = converter ? converter(value) : value;
+    }
+    return options;
+}
+
+function fetchManifestAndAnalyzeData(serverConfigJSON)
</ins><span class="cx"> {
</span><ins>+    loadServerConfig(serverConfigJSON);
+
</ins><span class="cx">     getJSON(settings.perfserver, '/data/manifest.json').then(function (manifest) {
</span><span class="cx">         return mapInOrder(configurationsForTesting(manifest), analyzeConfiguration);
</span><span class="cx">     }).catch(function (reason) {
</span><del>-        console.error('Failed to obtain the manifest file');
</del><ins>+        console.error('Failed to obtain the manifest file', reason);
</ins><span class="cx">     }).then(function () {
</span><span class="cx">         console.log('');
</span><span class="cx">         console.log('Sleeing for', settings.secondsToSleep, 'seconds');
</span><del>-        setTimeout(fetchManifestAndAnalyzeData, settings.secondsToSleep * 1000);
</del><ins>+        setTimeout(function () {
+            fetchManifestAndAnalyzeData(serverConfigJSON);
+        }, settings.secondsToSleep * 1000);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+function loadServerConfig(serverConfigJSON)
+{
+    var serverConfig = JSON.parse(fs.readFileSync(serverConfigJSON, 'utf8'));
+
+    var server = serverConfig['server'];
+    if ('auth' in server)
+        server['auth'] = server['auth']['username'] + ':' + server['auth']['password'];
+
+    settings.perfserver = server;
+    settings.slave = serverConfig['slave'];
+}
+
</ins><span class="cx"> function mapInOrder(array, callback, startIndex)
</span><span class="cx"> {
</span><span class="cx">     if (startIndex === undefined)
</span><span class="lines">@@ -54,8 +106,12 @@
</span><span class="cx">         var dashboard = manifest.dashboards[name];
</span><span class="cx">         for (var row of dashboard) {
</span><span class="cx">             for (var cell of row) {
</span><del>-                if (cell instanceof Array)
-                    configurations.push({platformId: parseInt(cell[0]), metricId: parseInt(cell[1])});
</del><ins>+                if (cell instanceof Array) {
+                    var platformId = parseInt(cell[0]);
+                    var metricId = parseInt(cell[1]);
+                    if (!isNaN(platformId) &amp;&amp; !isNaN(metricId))
+                        configurations.push({platformId: platformId, metricId: metricId});
+                }
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkWebsitesperfwebkitorgtoolspullosversionspy"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/tools/pull-os-versions.py (190899 => 190900)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/tools/pull-os-versions.py        2015-10-12 22:51:59 UTC (rev 190899)
+++ trunk/Websites/perf.webkit.org/tools/pull-os-versions.py        2015-10-12 23:05:43 UTC (rev 190900)
</span><span class="lines">@@ -14,7 +14,7 @@
</span><span class="cx"> from xml.dom.minidom import parseString as parseXmlString
</span><span class="cx"> from util import submit_commits
</span><span class="cx"> from util import text_content
</span><del>-from util import setup_auth
</del><ins>+from util import load_server_config
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> def main(argv):
</span><span class="lines">@@ -27,13 +27,10 @@
</span><span class="cx">     with open(args.os_config_json) as os_config_json:
</span><span class="cx">         os_config_list = json.load(os_config_json)
</span><span class="cx"> 
</span><del>-    with open(args.server_config_json) as server_config_json:
-        server_config = json.load(server_config_json)
-        setup_auth(server_config['server'])
-
</del><span class="cx">     fetchers = [OSBuildFetcher(os_config) for os_config in os_config_list]
</span><span class="cx"> 
</span><span class="cx">     while True:
</span><ins>+        server_config = load_server_config(args.server_config_json)
</ins><span class="cx">         for fetcher in fetchers:
</span><span class="cx">             fetcher.fetch_and_report_new_builds(server_config)
</span><span class="cx">         print &quot;Sleeping for %d seconds&quot; % args.seconds_to_sleep
</span></span></pre></div>
<a id="trunkWebsitesperfwebkitorgtoolspullsvnpy"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/tools/pull-svn.py (190899 => 190900)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/tools/pull-svn.py        2015-10-12 22:51:59 UTC (rev 190899)
+++ trunk/Websites/perf.webkit.org/tools/pull-svn.py        2015-10-12 23:05:43 UTC (rev 190900)
</span><span class="lines">@@ -9,7 +9,7 @@
</span><span class="cx"> import urllib2
</span><span class="cx"> 
</span><span class="cx"> from xml.dom.minidom import parseString as parseXmlString
</span><del>-from util import setup_auth
</del><ins>+from util import load_server_config
</ins><span class="cx"> from util import submit_commits
</span><span class="cx"> from util import text_content
</span><span class="cx"> 
</span><span class="lines">@@ -22,14 +22,11 @@
</span><span class="cx">     parser.add_argument('--max-fetch-count', type=int, default=10, help='The number of commits to fetch at once')
</span><span class="cx">     args = parser.parse_args()
</span><span class="cx"> 
</span><del>-    with open(args.server_config_json) as server_config_json:
-        server_config = json.load(server_config_json)
-        setup_auth(server_config['server'])
-
</del><span class="cx">     with open(args.svn_config_json) as svn_config_json:
</span><span class="cx">         svn_config = json.load(svn_config_json)
</span><span class="cx"> 
</span><span class="cx">     while True:
</span><ins>+        server_config = load_server_config(args.server_config_json)
</ins><span class="cx">         for repository_info in svn_config:
</span><span class="cx">             fetch_commits_and_submit(repository_info, server_config, args.max_fetch_count)
</span><span class="cx">         print &quot;Sleeping for %d seconds...&quot; % args.seconds_to_sleep
</span><span class="lines">@@ -44,6 +41,10 @@
</span><span class="cx">         print &quot;Determining the stating revision for %s&quot; % repository['name']
</span><span class="cx">         repository['revisionToFecth'] = determine_first_revision_to_fetch(server_config['server']['url'], repository['name'])
</span><span class="cx"> 
</span><ins>+    if 'useServerAuth' in repository:
+        repository['username'] = server_config['server']['auth']['username']
+        repository['password'] = server_config['server']['auth']['password']
+
</ins><span class="cx">     pending_commits = []
</span><span class="cx">     for unused in range(max_fetch_count):
</span><span class="cx">         commit = fetch_commit_and_resolve_author(repository, repository.get('accountNameFinderScript', None), repository['revisionToFecth'])
</span></span></pre></div>
<a id="trunkWebsitesperfwebkitorgtoolssyncwithbuildbotpy"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/tools/sync-with-buildbot.py (190899 => 190900)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/tools/sync-with-buildbot.py        2015-10-12 22:51:59 UTC (rev 190899)
+++ trunk/Websites/perf.webkit.org/tools/sync-with-buildbot.py        2015-10-12 23:05:43 UTC (rev 190900)
</span><span class="lines">@@ -9,7 +9,7 @@
</span><span class="cx"> import urllib
</span><span class="cx"> import urllib2
</span><span class="cx"> 
</span><del>-from util import setup_auth
</del><ins>+from util import load_server_config
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> def main():
</span><span class="lines">@@ -27,14 +27,9 @@
</span><span class="cx"> 
</span><span class="cx">     configurations = load_config(args.builder_config_json, args.buildbot_url.strip('/'))
</span><span class="cx"> 
</span><del>-    with open(args.server_config_json) as server_config_json:
-        server_config = json.load(server_config_json)
-        setup_auth(server_config['server'])
-
-    build_requests_url = server_config['server']['url'] + '/api/build-requests/' + args.triggerable
-
</del><span class="cx">     request_updates = {}
</span><span class="cx">     while True:
</span><ins>+        server_config = load_server_config(args.server_config_json)
</ins><span class="cx">         request_updates.update(find_request_updates(configurations, args.lookback_count))
</span><span class="cx">         if request_updates:
</span><span class="cx">             print 'Updating the build requests %s...' % ', '.join(map(str, request_updates.keys()))
</span><span class="lines">@@ -45,6 +40,8 @@
</span><span class="cx">             'buildRequestUpdates': request_updates,
</span><span class="cx">             'slaveName': server_config['slave']['name'],
</span><span class="cx">             'slavePassword': server_config['slave']['password']}
</span><ins>+
+        build_requests_url = server_config['server']['url'] + '/api/build-requests/' + args.triggerable
</ins><span class="cx">         response = update_and_fetch_build_requests(build_requests_url, payload)
</span><span class="cx">         open_requests = response.get('buildRequests', [])
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkWebsitesperfwebkitorgtoolsutilpy"></a>
<div class="modfile"><h4>Modified: trunk/Websites/perf.webkit.org/tools/util.py (190899 => 190900)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Websites/perf.webkit.org/tools/util.py        2015-10-12 22:51:59 UTC (rev 190899)
+++ trunk/Websites/perf.webkit.org/tools/util.py        2015-10-12 23:05:43 UTC (rev 190900)
</span><span class="lines">@@ -51,3 +51,12 @@
</span><span class="cx">     password_manager.add_password(realm=auth['realm'], uri=server['url'], user=auth['username'], passwd=auth['password'])
</span><span class="cx">     auth_handler = HTTP_AUTH_HANDLERS[auth['type']](password_manager)
</span><span class="cx">     urllib2.install_opener(urllib2.build_opener(auth_handler))
</span><ins>+
+
+def load_server_config(json_path):
+    with open(json_path) as server_config_json:
+        server_config = json.load(server_config_json)
+        server = server_config['server']
+        server['url'] = server['scheme'] + '://' + server['host'] + ':' + str(server['port'])
+        setup_auth(server)
+        return server_config
</ins></span></pre>
</div>
</div>

</body>
</html>