Add Buildbot configuration for Opensource EWS
authoraakash_jain@apple.com <aakash_jain@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 23 May 2018 23:41:43 +0000 (23:41 +0000)
committeraakash_jain@apple.com <aakash_jain@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 23 May 2018 23:41:43 +0000 (23:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=185484

Rubber-stamped by Alexey Proskuryakov.

* BuildSlaveSupport/ews-build/config.json: Added, config file.
* BuildSlaveSupport/ews-build/factories.py: Added, basic template for factories.
* BuildSlaveSupport/ews-build/loadConfig.py: Added.
(loadBuilderConfig): Loads the configuration.
(checkValidWorker): Checks if the worker is valid.
(checkValidBuilder): Checks if the builder is valid.
(checkWorkersAndBuildersForConsistency): Check if workers and builders are consistent.
(checkWorkersAndBuildersForConsistency._find_worker_with_name):
(getBlackListedTags): Returns a list of keywords which should not be listed as tags.
(getValidTags): Returns a list of valid tags.
(getTagsForBuilder): Return a list of tags for given builder.
* BuildSlaveSupport/ews-build/loadConfig_unittest.py: unit-tests for loadConfig.py.
* BuildSlaveSupport/ews-build/master.cfg: Configuration for buildbot.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232135 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Tools/BuildSlaveSupport/ews-build/config.json [new file with mode: 0644]
Tools/BuildSlaveSupport/ews-build/factories.py [new file with mode: 0644]
Tools/BuildSlaveSupport/ews-build/loadConfig.py [new file with mode: 0644]
Tools/BuildSlaveSupport/ews-build/loadConfig_unittest.py [new file with mode: 0644]
Tools/BuildSlaveSupport/ews-build/master.cfg [new file with mode: 0644]
Tools/ChangeLog

diff --git a/Tools/BuildSlaveSupport/ews-build/config.json b/Tools/BuildSlaveSupport/ews-build/config.json
new file mode 100644 (file)
index 0000000..3d58e6e
--- /dev/null
@@ -0,0 +1,280 @@
+{
+  "workers": [
+    {
+      "name": "webkit-misc",
+      "platform": "*"
+    },
+    {
+      "name": "tanty-gtk-wk2-ews",
+      "platform": "gtk"
+    },
+    {
+      "name": "ltilve-gtk-wk2-ews",
+      "platform": "gtk"
+    },
+    {
+      "name": "igalia-wpe-ews",
+      "platform": "wpe"
+    },
+    {
+      "name": "aperez-wpe-gcc5-ews",
+      "platform": "wpe"
+    },
+    {
+      "name": "aperez-wpe-gcc6-ews",
+      "platform": "wpe"
+    },
+    {
+      "name": "wincairo-ews-001",
+      "platform": "wincairo"
+    },
+    {
+      "name": "wincairo-ews-002",
+      "platform": "wincairo"
+    },
+    {
+      "name": "wincairo-ews-003",
+      "platform": "wincairo"
+    },
+    {
+      "name": "wincairo-ews-004",
+      "platform": "wincairo"
+    },
+    {
+      "name": "ews100",
+      "platform": "mac-sierra"
+    },
+    {
+      "name": "ews101",
+      "platform": "mac-sierra"
+    },
+    {
+      "name": "ews102",
+      "platform": "mac-sierra"
+    },
+    {
+      "name": "ews103",
+      "platform": "mac-sierra"
+    },
+    {
+      "name": "ews104",
+      "platform": "mac-sierra"
+    },
+    {
+      "name": "ews105",
+      "platform": "mac-sierra"
+    },
+    {
+      "name": "ews106",
+      "platform": "mac-sierra"
+    },
+    {
+      "name": "ews107",
+      "platform": "mac-sierra"
+    },
+    {
+      "name": "ews108",
+      "platform": "ios-11"
+    },
+    {
+      "name": "ews109",
+      "platform": "ios-11"
+    },
+    {
+      "name": "ews112",
+      "platform": "mac-sierra"
+    },
+    {
+      "name": "ews113",
+      "platform": "mac-sierra"
+    },
+    {
+      "name": "ews114",
+      "platform": "mac-sierra"
+    },
+    {
+      "name": "ews115",
+      "platform": "mac-sierra"
+    },
+    {
+      "name": "ews116",
+      "platform": "mac-sierra"
+    },
+    {
+      "name": "ews117",
+      "platform": "mac-sierra"
+    },
+    {
+      "name": "ews118",
+      "platform": "mac-high-sierra"
+    },
+    {
+      "name": "ews119",
+      "platform": "mac-high-sierra"
+    },
+    {
+      "name": "ews120",
+      "platform": "mac-high-sierra"
+    },
+    {
+      "name": "ews123",
+      "platform": "ios-11-simulator"
+    },
+    {
+      "name": "ews124",
+      "platform": "ios-11-simulator"
+    },
+    {
+      "name": "ews125",
+      "platform": "ios-11-simulator"
+    },
+    {
+      "name": "ews126",
+      "platform": "ios-11-simulator"
+    },
+    {
+      "name": "ews127",
+      "platform": "*"
+    },
+    {
+      "name": "ews128",
+      "platform": "*"
+    },
+    {
+      "name": "ews200",
+      "platform": "win"
+    },
+    {
+      "name": "ews201",
+      "platform": "win"
+    },
+    {
+      "name": "ews202",
+      "platform": "win"
+    },
+    {
+      "name": "ews203",
+      "platform": "win"
+    },
+    {
+      "name": "ews204",
+      "platform": "win"
+    },
+    {
+      "name": "ews205",
+      "platform": "win"
+    },
+    {
+      "name": "ews206",
+      "platform": "win"
+    },
+    {
+      "name": "ews207",
+      "platform": "win"
+    },
+    {
+      "name": "ews208",
+      "platform": "win"
+    }
+  ],
+  "builders": [
+    {
+      "name": "Style-EWS",
+      "factory": "StyleFactory",
+      "platform": "*",
+      "workernames": ["webkit-misc"]
+    },
+    {
+      "name": "GTK-Webkit2-EWS",
+      "factory": "GTKFactory",
+      "platform": "gtk",
+      "workernames": ["tanty-gtk-wk2-ews", "ltilve-gtk-wk2-ews"]
+    },
+    {
+      "name": "iOS-11-EWS",
+      "factory": "iOSFactory",
+      "platform": "ios-11",
+      "workernames": ["ews108", "ews109"]
+    },
+    {
+      "name": "iOS-11-Simulator-EWS",
+      "factory": "iOSSimulatorFactory",
+      "platform": "ios-11-simulator",
+      "workernames": ["ews123", "ews124", "ews125", "ews126"]
+    },
+    {
+      "name": "macOS-Sierra-Release-WK1-EWS",
+      "factory": "MacWK1Factory",
+      "platform": "mac-sierra",
+      "configuration": "Release",
+      "workernames": ["ews100", "ews101", "ews102", "ews103"]
+    },
+    {
+      "name": "macOS-Sierra-Release-WK2-EWS",
+      "factory": "MacWK2Factory",
+      "platform": "mac-sierra",
+      "configuration": "Release",
+      "workernames": ["ews104", "ews105", "ews106", "ews107"]
+    },
+    {
+      "name": "macOS-Sierra-Debug-WK1-EWS",
+      "factory": "MacWK1Factory",
+      "platform": "mac-sierra",
+      "configuration": "Debug",
+      "workernames": ["ews112", "ews113", "ews114", "ews115", "ews116"]
+    },
+    {
+      "name": "macOS-High-Sierra-Release-32bit-WK2-EWS",
+      "factory": "MacWK2Factory",
+      "platform": "mac-high-sierra",
+      "configuration": "Release",
+      "workernames": ["ews118", "ews119", "ews120"]
+    },
+    {
+      "name": "Windows-EWS",
+      "factory": "WindowsFactory",
+      "platform": "win",
+      "workernames": ["ews200", "ews201", "ews202", "ews203", "ews204", "ews205", "ews206", "ews207", "ews208"]
+    },
+    {
+      "name": "WinCairo-EWS",
+      "factory": "WinCairoFactory",
+      "platform": "wincairo",
+      "workernames": ["wincairo-ews-001", "wincairo-ews-002", "wincairo-ews-003", "wincairo-ews-004"]
+    },
+    {
+      "name": "WPE-EWS",
+      "factory": "WPEFactory",
+      "platform": "wpe",
+      "workernames": ["igalia-wpe-ews", "aperez-wpe-gcc5-ews", "aperez-wpe-gcc6-ews"]
+    },
+    {
+      "name": "JSC-tests-EWS",
+      "factory": "JSCTestsFactory",
+      "platform": "*",
+      "workernames": ["ews127", "ews128"]
+    },
+    {
+      "name": "Bindings-tests-EWS",
+      "factory": "BindingsFactory",
+      "platform": "*",
+      "workernames": ["webkit-misc"]
+    },
+    {
+      "name": "Webkitpy-tests-EWS",
+      "factory": "WebkitpyFactory",
+      "platform": "*",
+      "workernames": ["webkit-misc"]
+    }
+  ],
+  "schedulers": [
+    {
+      "type": "AnyBranchScheduler",
+      "name": "misc-trigger",
+      "treeStableTimer": 0,
+      "builderNames": ["Style-EWS", "JSC-tests-EWS", "macOS-Sierra-Release-WK1-EWS", "GTK-Webkit2-EWS", "macOS-Sierra-Release-WK2-EWS",
+                       "macOS-High-Sierra-Release-32bit-WK2-EWS", "WPE-EWS", "Windows-EWS", "iOS-11-EWS", "WinCairo-EWS", "iOS-11-Simulator-EWS",
+                       "Webkitpy-tests-EWS", "macOS-Sierra-Debug-WK1-EWS", "Bindings-tests-EWS"]
+    }
+  ]
+}
diff --git a/Tools/BuildSlaveSupport/ews-build/factories.py b/Tools/BuildSlaveSupport/ews-build/factories.py
new file mode 100644 (file)
index 0000000..0621133
--- /dev/null
@@ -0,0 +1,72 @@
+# Copyright (C) 2018 Apple 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:
+# 1.  Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+# 2.  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.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 buildbot.process import factory
+
+
+class StyleFactory(factory.BuildFactory):
+    pass
+
+
+class GTKFactory(factory.BuildFactory):
+    pass
+
+
+class iOSFactory(factory.BuildFactory):
+    pass
+
+
+class iOSSimulatorFactory(factory.BuildFactory):
+    pass
+
+
+class MacWK1Factory(factory.BuildFactory):
+    pass
+
+
+class MacWK2Factory(factory.BuildFactory):
+    pass
+
+
+class WindowsFactory(factory.BuildFactory):
+    pass
+
+
+class WinCairoFactory(factory.BuildFactory):
+    pass
+
+
+class WPEFactory(factory.BuildFactory):
+    pass
+
+
+class JSCTestsFactory(factory.BuildFactory):
+    pass
+
+
+class BindingsFactory(factory.BuildFactory):
+    pass
+
+
+class WebkitpyFactory(factory.BuildFactory):
+    pass
diff --git a/Tools/BuildSlaveSupport/ews-build/loadConfig.py b/Tools/BuildSlaveSupport/ews-build/loadConfig.py
new file mode 100644 (file)
index 0000000..aa03b84
--- /dev/null
@@ -0,0 +1,136 @@
+# Copyright (C) 2018 Apple 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:
+# 1.  Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+# 2.  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.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+
+
+import json
+import re
+
+from buildbot.scheduler import AnyBranchScheduler, Periodic, Dependent, Triggerable, Nightly
+from buildbot.worker import Worker
+from buildbot.util import identifiers as buildbot_identifiers
+
+from factories import *
+
+BUILDER_NAME_LENGTH_LIMIT = 70
+STEP_NAME_LENGTH_LIMIT = 50
+
+
+def loadBuilderConfig(c):
+    config = json.load(open('config.json'))
+    passwords = json.load(open('passwords.json'))
+    checkWorkersAndBuildersForConsistency(config['workers'], config['builders'])
+
+    c['workers'] = [Worker(worker['name'], passwords.get(worker['name'], 'password')) for worker in config['workers']]
+    c['builders'] = []
+    for builder in config['builders']:
+        builder['tags'] = getTagsForBuilder(builder)
+        factory = globals()[builder['factory']]
+        builder['factory'] = factory()
+        del builder['platform']
+        if 'configuration' in builder:
+            del builder['configuration']
+        c['builders'].append(builder)
+
+    c['schedulers'] = []
+    for scheduler in config['schedulers']:
+        schedulerType = globals()[scheduler.pop('type')]
+        # Python 2.6 can't handle unicode keys as keyword arguments:
+        # http://bugs.python.org/issue2646.  Modern versions of json return
+        # unicode strings from json.load, so we map all keys to str objects.
+        scheduler = dict(map(lambda key_value_pair: (str(key_value_pair[0]), key_value_pair[1]), scheduler.items()))
+        c['schedulers'].append(schedulerType(**scheduler))
+
+
+def checkValidWorker(worker):
+    if not worker:
+        raise Exception('Worker is None or Empty.')
+
+    if not worker.get('name'):
+        raise Exception('Worker "{}" does not have name defined.'.format(worker))
+
+    if not worker.get('platform'):
+        raise Exception('Worker {} does not have platform defined.'.format(worker['name']))
+
+
+def checkValidBuilder(builder):
+    if not builder:
+        raise Exception('Builder is None or Empty.')
+
+    if not builder.get('name'):
+        raise Exception('Builder "{}" does not have name defined.'.format(builder))
+
+    if not buildbot_identifiers.ident_re.match(builder['name']):
+        raise Exception('Builder name {} is not a valid buildbot identifier.'.format(builder['name']))
+
+    if len(builder['name']) > BUILDER_NAME_LENGTH_LIMIT:
+        raise Exception('Builder name {} is longer than maximum allowed by Buildbot ({} characters).'.format(builder['name'], BUILDER_NAME_LENGTH_LIMIT))
+
+    if 'configuration' in builder and builder['configuration'] not in ['Debug', 'Production', 'Release']:
+        raise Exception('Invalid configuration: {} for builder: {}'.format(builder.get('configuration'), builder.get('name')))
+
+    if not builder.get('factory'):
+        raise Exception('Builder {} does not have factory defined.'.format(builder['name']))
+
+    if not builder.get('platform'):
+        raise Exception('Builder {} does not have platform defined.'.format(builder['name']))
+
+
+def checkWorkersAndBuildersForConsistency(workers, builders):
+    def _find_worker_with_name(workers, worker_name):
+        for worker in workers:
+            if worker['name'] == worker_name:
+                return worker
+        return None
+
+    for worker in workers:
+        checkValidWorker(worker)
+
+    for builder in builders:
+        checkValidBuilder(builder)
+        for worker_name in builder['workernames']:
+            worker = _find_worker_with_name(workers, worker_name)
+            if worker is None:
+                raise Exception('Builder {} has worker {}, which is not defined in workers list!'.format(builder['name'], worker_name))
+
+            if worker['platform'] != builder['platform']:
+                raise Exception('Builder {0} is for platform {1}, but has worker {2} for platform {3}!'.format(
+                    builder['name'], builder['platform'], worker['name'], worker['platform']))
+
+
+def getBlackListedTags():
+    """
+    We maintain a blacklist of words which we do not want to display as tag in buildbot.
+    We generate a list of tags by splitting the builder name. We do not want certain words as tag.
+    For e.g. we don't want '11'as tag for builder iOS-11-Simulator-EWS
+    """
+    tags_blacklist = [str(i) for i in xrange(0, 20)]
+    tags_blacklist.extend(['EWS', 'TryBot'])
+    return tags_blacklist
+
+
+def getValidTags(tags):
+    return list(set(tags) - set(getBlackListedTags()))
+
+
+def getTagsForBuilder(builder):
+    keywords = filter(None, re.split('[, \-_:()]+', str(builder['name'])))
+    return getValidTags(keywords)
diff --git a/Tools/BuildSlaveSupport/ews-build/loadConfig_unittest.py b/Tools/BuildSlaveSupport/ews-build/loadConfig_unittest.py
new file mode 100644 (file)
index 0000000..d0ae457
--- /dev/null
@@ -0,0 +1,149 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2018 Apple 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:
+# 1.  Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+# 2.  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.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
+
+
+import unittest
+
+import loadConfig
+
+
+class ConfigDotJSONTest(unittest.TestCase):
+    def test_configuration(self):
+        loadConfig.loadBuilderConfig({})
+
+
+class TagsForBuilderTeest(unittest.TestCase):
+    def verifyTags(self, builderName, expectedTags):
+        tags = loadConfig.getTagsForBuilder({'name': builderName})
+        self.assertEqual(sorted(tags), sorted(expectedTags))
+
+    def test_getTagsForBuilder(self):
+        self.verifyTags('EWS', [])
+        self.verifyTags('TryBot-10-EWS', [])
+        self.verifyTags('11-EWS', [])
+        self.verifyTags('32-EWS', ['32'])
+        self.verifyTags('iOS-11-EWS', ['iOS'])
+        self.verifyTags('iOS(11),(test)-EWS', ['iOS', 'test'])
+        self.verifyTags('Windows-EWS', ['Windows'])
+        self.verifyTags('Windows_Windows', ['Windows'])
+        self.verifyTags('GTK-Webkit2-EWS', ['GTK', 'Webkit2'])
+        self.verifyTags('macOS-Sierra-Release-WK1-EWS', ['Sierra', 'Release', 'macOS', 'WK1'])
+        self.verifyTags('macOS-High-Sierra-Release-32bit-WK2-EWS', ['macOS', 'High', 'Sierra', 'Release', 'WK2', '32bit'])
+
+    def test_tags_type(self):
+        tags = loadConfig.getTagsForBuilder({'name': u'iOS-11-EWS'})
+        self.assertEqual(tags, ['iOS'])
+        self.assertEqual(type(tags[0]), str)
+
+    def test_getBlackListedTags(self):
+        blacklistedTags = loadConfig.getBlackListedTags()
+        expectedTags = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
+                        '11', '12', '13', '14', '15', '16', '17', '18', '19', 'EWS', 'TryBot']
+        self.assertEqual(blacklistedTags, expectedTags)
+
+
+class TestcheckValidWorker(unittest.TestCase):
+    def test_invalid_worker(self):
+        with self.assertRaises(Exception) as context:
+            loadConfig.checkValidWorker({})
+        self.assertEqual(context.exception.args, ('Worker is None or Empty.',))
+
+    def test_worker_with_missing_name(self):
+        with self.assertRaises(Exception) as context:
+            loadConfig.checkValidWorker({'platform': 'mac-sierra'})
+        self.assertEqual(context.exception.args, ('Worker "{\'platform\': \'mac-sierra\'}" does not have name defined.',))
+
+    def test_worker_with_missing_platName(self):
+        with self.assertRaises(Exception) as context:
+            loadConfig.checkValidWorker({'name': 'ews101'})
+        self.assertEqual(context.exception.args, ('Worker ews101 does not have platform defined.',))
+
+    def test_valid_worker(self):
+        loadConfig.checkValidWorker({'name': 'ews101', 'platform': 'mac-sierra'})
+
+
+class TestcheckValidBuilder(unittest.TestCase):
+    def test_invalid_builder(self):
+        with self.assertRaises(Exception) as context:
+            loadConfig.checkValidBuilder({})
+        self.assertEqual(context.exception.args, ('Builder is None or Empty.',))
+
+    def test_builder_with_missing_name(self):
+        with self.assertRaises(Exception) as context:
+            loadConfig.checkValidBuilder({'platform': 'mac-sierra'})
+        self.assertEqual(context.exception.args, ('Builder "{\'platform\': \'mac-sierra\'}" does not have name defined.',))
+
+    def test_builder_with_invalid_identifier(self):
+        with self.assertRaises(Exception) as context:
+            loadConfig.checkValidBuilder({'name': 'mac-wk2(test)'})
+        self.assertEqual(context.exception.args, ('Builder name mac-wk2(test) is not a valid buildbot identifier.',))
+
+    def test_builder_with_extra_long_name(self):
+        longName = 'a' * 71
+        with self.assertRaises(Exception) as context:
+            loadConfig.checkValidBuilder({'name': longName})
+        self.assertEqual(context.exception.args, ('Builder name {} is longer than maximum allowed by Buildbot (70 characters).'.format(longName),))
+
+    def test_builder_with_invalid_configuration(self):
+        with self.assertRaises(Exception) as context:
+            loadConfig.checkValidBuilder({'name': 'mac-wk2', 'configuration': 'asan'})
+        self.assertEqual(context.exception.args, ('Invalid configuration: asan for builder: mac-wk2',))
+
+    def test_builder_with_missing_factory(self):
+        with self.assertRaises(Exception) as context:
+            loadConfig.checkValidBuilder({'name': 'mac-wk2', 'configuration': 'Release'})
+        self.assertEqual(context.exception.args, ('Builder mac-wk2 does not have factory defined.',))
+
+    def test_builder_with_missing_platform(self):
+        with self.assertRaises(Exception) as context:
+            loadConfig.checkValidBuilder({'name': 'mac-wk2', 'configuration': 'Release', 'factory': 'WK2Factory'})
+        self.assertEqual(context.exception.args, ('Builder mac-wk2 does not have platform defined.',))
+
+    def test_valid_builder(self):
+        loadConfig.checkValidBuilder({'name': 'mac-wk2', 'configuration': 'Release', 'factory': 'WK2Factory', 'platform': 'mac-sierra'})
+
+
+class TestcheckWorkersAndBuildersForConsistency(unittest.TestCase):
+    def __init__(self, *args, **kwargs):
+        self.WK2Builder = {'name': 'mac-wk2', 'factory': 'WK2Factory', 'platform': 'mac-sierra', 'workernames': ['ews101', 'ews102']}
+        self.ews101 = {'name': 'ews101', 'platform': 'mac-sierra'}
+        self.ews102 = {'name': 'ews102', 'platform': 'ios-11'}
+        super(TestcheckWorkersAndBuildersForConsistency, self).__init__(*args, **kwargs)
+
+    def test_checkWorkersAndBuildersForConsistency(self):
+        with self.assertRaises(Exception) as context:
+            loadConfig.checkWorkersAndBuildersForConsistency([], [self.WK2Builder])
+        self.assertEqual(context.exception.args, ('Builder mac-wk2 has worker ews101, which is not defined in workers list!',))
+
+    def test_checkWorkersAndBuildersForConsistency1(self):
+        with self.assertRaises(Exception) as context:
+            loadConfig.checkWorkersAndBuildersForConsistency([self.ews101, self.ews102], [self.WK2Builder])
+        self.assertEqual(context.exception.args, ('Builder mac-wk2 is for platform mac-sierra, but has worker ews102 for platform ios-11!',))
+
+    def test_success(self):
+        loadConfig.checkWorkersAndBuildersForConsistency([self.ews101, {'name': 'ews102', 'platform': 'mac-sierra'}], [self.WK2Builder])
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/Tools/BuildSlaveSupport/ews-build/master.cfg b/Tools/BuildSlaveSupport/ews-build/master.cfg
new file mode 100644 (file)
index 0000000..b1c35c9
--- /dev/null
@@ -0,0 +1,23 @@
+import loadConfig
+
+
+c = BuildmasterConfig = {}
+
+c['www'] = dict(port=8010,
+                plugins=dict(waterfall_view={}, console_view={}))
+
+c['www']['ui_default_config'] = { 
+    'Builders.show_workers_name': True,
+    'Builders.buildFetchLimit': 1000,
+    'Workers.showWorkerBuilders': True,
+}
+
+c['protocols'] = {'pb': {'port': 9989}}
+
+c['projectName'] = 'WebKit EWS'
+c['projectURL'] = 'https://ews-build.webkit.org/'
+c['buildbotURL'] = 'https://ews-build.webkit.org/'
+
+c['buildbotNetUsageData'] = None
+
+loadConfig.loadBuilderConfig(c)
index b913a22..7ccf513 100644 (file)
@@ -1,3 +1,24 @@
+2018-05-23  Aakash Jain  <aakash_jain@apple.com>
+
+        Add Buildbot configuration for Opensource EWS
+        https://bugs.webkit.org/show_bug.cgi?id=185484
+
+        Rubber-stamped by Alexey Proskuryakov.
+
+        * BuildSlaveSupport/ews-build/config.json: Added, config file.
+        * BuildSlaveSupport/ews-build/factories.py: Added, basic template for factories.
+        * BuildSlaveSupport/ews-build/loadConfig.py: Added.
+        (loadBuilderConfig): Loads the configuration.
+        (checkValidWorker): Checks if the worker is valid.
+        (checkValidBuilder): Checks if the builder is valid.
+        (checkWorkersAndBuildersForConsistency): Check if workers and builders are consistent.
+        (checkWorkersAndBuildersForConsistency._find_worker_with_name):
+        (getBlackListedTags): Returns a list of keywords which should not be listed as tags.
+        (getValidTags): Returns a list of valid tags.
+        (getTagsForBuilder): Return a list of tags for given builder.
+        * BuildSlaveSupport/ews-build/loadConfig_unittest.py: unit-tests for loadConfig.py.
+        * BuildSlaveSupport/ews-build/master.cfg: Configuration for buildbot.
+
 2018-05-23  Michael Catanzaro  <mcatanzaro@igalia.com>
 
         [GTK] Silence GCC 8 warnings