[Buildbot-devel] [patch] user build properties

paul.gain at virgin.net paul.gain at virgin.net
Wed Nov 15 16:00:59 UTC 2006


Hi 

I have a patch below that enables users to easily add widgets (e.g. text fields, 
radio buttons and check boxes) to the slave/force build page.  Once the 
user has added their properties they can easily be retrieved via a build 
step such as a clean build step (e.g. extend buildbot.process.step.Compile) 
with the following method call(s).

ticked = self.getProperty('check_box')
message = self.getProperty('text_field')
maleFemale = self.getProperty('radio_group')


For testing I used the following class:

from buildbot.process.step import Compile

class CleanBuild(Compile):

	name = "Clean Build"
        description = ["Clean Build"]
        descriptionDone = ["Done"]

        def getText(self, cmd, results):

		cb = ["Clean Build"]                
                
		ticked = self.getProperty('check_box')
		if ticked == 'on':
                	cb.append('Yes')
                else:
                	cb.append('No')

                message = self.getProperty('text_field')
                cb.append(message)
                                
                mf = self.getProperty('radio_group')                
                if mf == 'm':
                    cb.append('male')              	
                if mf == 'f':
                    cb.append('female')
        
                return cb

Here is the patch:

### Eclipse Workspace Patch 1.0
#P buildbot_new
Index: buildbot/status/html.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/status/html.py,v
retrieving revision 1.92
diff -u -r1.92 html.py
--- buildbot/status/html.py	2 Oct 2006 00:13:32 -0000	1.92
+++ buildbot/status/html.py	15 Nov 2006 15:21:32 -0000
@@ -538,6 +538,8 @@
                            "<input type='text' name='branch' />")
                 + make_row("Revision to build:",
                            "<input type='text' name='revision' />")
+                + self.make_user_defined_rows()
+
                 + """
                 <input type='submit' value='Force Build' />
                 </form>
@@ -560,12 +562,45 @@
 
         return data
 
+    # Providing the users custom properties are set in the master.cfg file 
+    # this method will generate custom widgets (text fields, radio buttons 
and
+    # check boxes) for the slave build page. The method returns a html string 
+    # representing the widgets. This string is added to the body of the 
slave 
+    # build page.
+    def make_user_defined_rows(self):
+        userDefRows = name = type = label = value = ""
+        customBuildProperties = self.status.getCustomBuildProperties()    
+        for properties in customBuildProperties:
+            name = properties['propertyName']
+            type = properties['propertyType']
+            label = properties['propertyLabel']                
+            if type == 'radio':                
+                value = properties['groupValue']
+                field = "<input type=" + "\'" + type + "\'" + "name=" 
+ "\'" + \
+                                name + "\'" + "value=" + "\'" + value 
+ "\'" + " />"
+            else:
+                field = "<input type=" + "\'" + type + "\'" +  \
+                                "name=" + "\'" + name + "\'" + " />"
+
+            userDefRows += make_row(label, field)
+            name = type = label = value = ""
+
+        return userDefRows
+
     def force(self, request):
         name = request.args.get("username", ["<unknown>"])[0]
         reason = request.args.get("comments", ["<no reason specified>"])
[0]
         branch = request.args.get("branch", [""])[0]
         revision = request.args.get("revision", [""])[0]
 
+        # Custom properties.
+        custom_props = {}           
+        forceBuildProperties = self.status.getCustomBuildProperties()    
+        for dict in forceBuildProperties:
+            for key, value in dict.iteritems():            	
+               if key == 'propertyName':
+                   custom_props[value] = request.args.get(value, [""])
[0]
+
         r = "The web-page 'force build' button was pressed by '%s': %s\n" 
\
             % (name, reason)
         log.msg("web forcebuild of builder '%s', branch='%s', revision='%
s'"
@@ -593,7 +628,7 @@
         # button, use their name instead of None, so they'll be informed 
of
         # the results.
         s = SourceStamp(branch=branch, revision=revision)
-        req = BuildRequest(r, s, self.builder.getName())
+        req = BuildRequest(r, s, custom_props, self.builder.getName())
         try:
             self.control.requestBuildSoon(req)
         except interfaces.NoSlaveError:
Index: buildbot/status/builder.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/status/builder.py,v
retrieving revision 1.88
diff -u -r1.88 builder.py
--- buildbot/status/builder.py	15 Sep 2006 14:48:53 -0000	1.88
+++ buildbot/status/builder.py	15 Nov 2006 15:21:31 -0000
@@ -1777,6 +1777,8 @@
         return self.botmaster.parent.projectURL
     def getBuildbotURL(self):
         return self.botmaster.parent.buildbotURL
+    def getCustomBuildProperties(self):
+    	return self.botmaster.parent.customBuildProperties
 
     def getURLForThing(self, thing):
         prefix = self.getBuildbotURL()
Index: buildbot/process/base.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/process/base.py,v
retrieving revision 1.71
diff -u -r1.71 base.py
--- buildbot/process/base.py	25 Sep 2006 02:43:56 -0000	1.71
+++ buildbot/process/base.py	15 Nov 2006 15:21:31 -0000
@@ -39,6 +39,9 @@
                   provide this, but for forced builds the user requesting 
the
                   build will provide a string.
 
+    @type custom_props: dictionary.
+    @ivar custom_props: custom user properties.
+
     @ivar status: the IBuildStatus object which tracks our status
 
     @ivar submittedAt: a timestamp (seconds since epoch) when this request
@@ -49,18 +52,20 @@
     source = None
     builder = None
     startCount = 0 # how many times we have tried to start this build
+    custom_props = {}
 
     if implements:
         implements(interfaces.IBuildRequestControl)
     else:
         __implements__ = interfaces.IBuildRequestControl,
 
-    def __init__(self, reason, source, builderName=None):
+    def __init__(self, reason, source, custom_props, builderName=None):
         # TODO: remove the =None on builderName, it is there so I don't 
have
         # to change a lot of tests that create BuildRequest objects
         assert interfaces.ISourceStamp(source, None)
         self.reason = reason
         self.source = source
+        self.custom_props = custom_props
         self.start_watchers = []
         self.finish_watchers = []
         self.status = BuildRequestStatus(source, builderName)
@@ -87,6 +92,9 @@
         self.finish_watchers.append(d)
         return d
 
+    def customProps(self):
+    	return self.custom_props;
+
     # these are called by the Builder
 
     def requestSubmitted(self, builder):
@@ -175,6 +183,9 @@
         self.source = requests[0].mergeWith(requests[1:])
         self.reason = requests[0].mergeReasons(requests[1:])
 
+        # Set custom properties.
+        self.custom_properties = requests[0].customProps()
+
         #self.abandoned = False
 
         self.progress = None
@@ -269,6 +280,9 @@
         self.setProperty("buildnumber", self.build_status.number)
         self.setProperty("branch", self.source.branch)
         self.setProperty("revision", self.source.revision)
+        cp = self.custom_properties
+        for key,userProp in cp.iteritems():
+        	self.setProperty(key,userProp)
 
     def setupSlaveBuilder(self, slavebuilder):
         self.slavebuilder = slavebuilder
Index: buildbot/master.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/master.py,v
retrieving revision 1.97
diff -u -r1.97 master.py
--- buildbot/master.py	17 Sep 2006 20:43:39 -0000	1.97
+++ buildbot/master.py	15 Nov 2006 15:21:31 -0000
@@ -543,6 +543,7 @@
     projectURL = None
     buildbotURL = None
     change_svc = None
+    customBuildProperties = None
 
     def __init__(self, basedir, configFileName="master.cfg"):
         service.MultiService.__init__(self)
@@ -694,7 +695,8 @@
 
         known_keys = "bots sources schedulers builders slavePortnum " 
+ \
                      "debugPassword manhole " + \
-                     "status projectName projectURL buildbotURL"
+                     "status projectName projectURL buildbotURL " + \
+                     "customBuildProperties"
         known_keys = known_keys.split()
         for k in config.keys():
             if k not in known_keys:
@@ -715,6 +717,7 @@
             projectName = config.get('projectName')
             projectURL = config.get('projectURL')
             buildbotURL = config.get('buildbotURL')
+            customBuildProperties = config.get('customBuildProperties')
 
         except KeyError, e:
             log.msg("config dictionary is missing a required parameter")
@@ -818,6 +821,7 @@
         self.projectName = projectName
         self.projectURL = projectURL
         self.buildbotURL = buildbotURL
+        self.customBuildProperties = customBuildProperties
 
         # self.bots: Disconnect any that were attached and removed from the
         # list. Update self.checker with the new list of passwords,
Index: buildbot/scripts/sample.cfg
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/scripts/sample.cfg,v
retrieving revision 1.12
diff -u -r1.12 sample.cfg
--- buildbot/scripts/sample.cfg	22 Sep 2006 05:46:28 -0000	1.12
+++ buildbot/scripts/sample.cfg	15 Nov 2006 15:21:31 -0000
@@ -173,3 +173,31 @@
 # without some help.
 
 c['buildbotURL'] = "http://localhost:8010/"
+
+###### CUSTOM BUILD PROPERTIES FOR THE SLAVE BUILD PAGE.
+
+"""
+textField = {'propertyName' : 'text_field',
+             'propertyType' : 'text',
+             'propertyLabel': 'Text Label',
+             }
+
+checkBox = {'propertyName' : 'check_box',
+            'propertyType' : 'checkbox',
+            'propertyLabel': 'Check Box',
+            }
+
+radio1 = {'propertyName' : 'radio_group',
+          'propertyType' : 'radio',
+          'propertyLabel': 'Male',
+          'groupValue'   : 'm',
+          }
+
+radio2 = {'propertyName' : 'radio_group',
+          'propertyType' : 'radio',
+          'propertyLabel': 'Female',
+          'groupValue'   : 'f',
+          }
+
+c['customBuildProperties'] = [textField, checkBox, radio1, radio2]
+"""

I'm fairly new to Python to if you spot an error please let me know.

Regards

Paul Gain








More information about the devel mailing list