[Buildbot-devel] Force Page, Default values for WithProperties Patch
Minesh Patel
mpatel at 2wire.com
Tue Jan 9 19:55:24 UTC 2007
Minor tweaks to the force page patch from Paul Gain, give him all the
credit for a great idea. Added default values to the WithProperties as
well as username to the sourcestamp and build_status.properties so that
it can be retrieved by the WithProperties class.
Here is an example of how to use the default values:
WithProperties("%s", "test", test='foo')
diff -Nuar buildbot-0.7.5.orig/buildbot/master.py
buildbot-0.7.5/buildbot/master.py
--- buildbot-0.7.5.orig/buildbot/master.py 2006-12-10 21:40:11.000000000
-0800
+++ buildbot-0.7.5/buildbot/master.py 2007-01-09 10:36:15.000000000 -0800
@@ -500,6 +500,7 @@
projectURL = None
buildbotURL = None
change_svc = None
+ customBuildProperties = None
def __init__(self, basedir, configFileName="master.cfg"):
service.MultiService.__init__(self)
@@ -653,7 +654,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:
@@ -674,6 +676,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")
@@ -777,6 +780,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,
diff -Nuar buildbot-0.7.5.orig/buildbot/process/base.py
buildbot-0.7.5/buildbot/process/base.py
--- buildbot-0.7.5.orig/buildbot/process/base.py 2006-12-10
21:40:11.000000000 -0800
+++ buildbot-0.7.5/buildbot/process/base.py 2007-01-09
11:20:44.000000000 -0800
@@ -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, builderName=None, custom_props=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
@@ -202,8 +213,10 @@
self.build_status.setProperty(propname, value)
def getProperty(self, propname):
- return self.build_status.properties[propname]
-
+ if self.build_status.properties.has_key(propname):
+ return self.build_status.properties[propname]
+ else:
+ return None
def allChanges(self):
return self.source.changes
@@ -267,8 +280,13 @@
self.build_status = build_status
self.setProperty("buildername", self.builder.name)
self.setProperty("buildnumber", self.build_status.number)
+ self.setProperty("username", self.source.username)
self.setProperty("branch", self.source.branch)
self.setProperty("revision", self.source.revision)
+ cp = self.custom_properties
+ if cp:
+ for key,userProp in cp.iteritems():
+ self.setProperty(key,userProp)
def setupSlaveBuilder(self, slavebuilder):
self.slavebuilder = slavebuilder
diff -Nuar buildbot-0.7.5.orig/buildbot/sourcestamp.py
buildbot-0.7.5/buildbot/sourcestamp.py
--- buildbot-0.7.5.orig/buildbot/sourcestamp.py 2006-12-10
21:40:11.000000000 -0800
+++ buildbot-0.7.5/buildbot/sourcestamp.py 2007-01-03 14:54:33.000000000
-0800
@@ -32,8 +32,9 @@
else:
__implements__ = interfaces.ISourceStamp,
- def __init__(self, branch=None, revision=None, patch=None,
- changes=None):
+ def __init__(self, branch=None, revision=None,
+ patch=None, changes=None, username=None):
+ self.username = username
self.branch = branch
self.revision = revision
self.patch = patch
@@ -77,7 +78,8 @@
for req in others:
assert self.canBeMergedWith(req) # should have been checked already
changes.extend(req.changes)
- newsource = SourceStamp(branch=self.branch,
+ newsource = SourceStamp(username=self.username,
+ branch=self.branch,
revision=self.revision,
patch=self.patch,
changes=changes)
diff -Nuar buildbot-0.7.5.orig/buildbot/status/builder.py
buildbot-0.7.5/buildbot/status/builder.py
--- buildbot-0.7.5.orig/buildbot/status/builder.py 2006-12-10
21:40:11.000000000 -0800
+++ buildbot-0.7.5/buildbot/status/builder.py 2006-12-18
17:00:26.000000000 -0800
@@ -1786,6 +1786,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()
diff -Nuar buildbot-0.7.5.orig/buildbot/status/html.py
buildbot-0.7.5/buildbot/status/html.py
--- buildbot-0.7.5.orig/buildbot/status/html.py 2006-12-10
21:40:11.000000000 -0800
+++ buildbot-0.7.5/buildbot/status/html.py 2006-12-21 16:08:26.000000000
-0800
@@ -3,6 +3,7 @@
from __future__ import generators
from twisted.python import log, components
+from twisted.python.util import sibpath
import urllib, re
from twisted.internet import defer, reactor
@@ -538,6 +539,7 @@
"<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,46 @@
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()
+ if customBuildProperties:
+ for property in customBuildProperties:
+ name = property['propertyName']
+ type = property['propertyType']
+ label = property['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)
+
+ 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()
+ if forceBuildProperties:
+ 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'"
@@ -592,8 +628,8 @@
# TODO: if we can authenticate that a particular User pushed the
# 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())
+ s = SourceStamp(username=name, branch=branch, revision=revision)
+ req = BuildRequest(r, s, self.builder.getName(), custom_props)
try:
self.control.requestBuildSoon(req)
except interfaces.NoSlaveError:
diff -Nuar buildbot-0.7.5.orig/buildbot/steps/shell.py
buildbot-0.7.5/buildbot/steps/shell.py
--- buildbot-0.7.5.orig/buildbot/steps/shell.py 2006-12-10
21:40:12.000000000 -0800
+++ buildbot-0.7.5/buildbot/steps/shell.py 2007-01-09 11:40:42.000000000
-0800
@@ -22,16 +22,19 @@
compare_attrs = ('fmtstring', 'args')
- def __init__(self, fmtstring, *args):
+ def __init__(self, fmtstring, *args, **kwargs):
self.fmtstring = fmtstring
self.args = args
+ self.kwargs = kwargs
def render(self, build):
if self.args:
strings = []
for name in self.args:
p = build.getProperty(name)
- if p is None:
+ if p is None and self.kwargs.has_key(name):
+ p = self.kwargs[name]
+ elif p is None:
p = ""
strings.append(p)
s = self.fmtstring % tuple(strings)
Thanks,
Minesh Patel
buildbot-devel-request at lists.sourceforge.net wrote:
> Send Buildbot-devel mailing list submissions to
> buildbot-devel at lists.sourceforge.net
>
> To subscribe or unsubscribe via the World Wide Web, visit
> https://lists.sourceforge.net/lists/listinfo/buildbot-devel
> or, via email, send a message with subject or body 'help' to
> buildbot-devel-request at lists.sourceforge.net
>
> You can reach the person managing the list at
> buildbot-devel-owner at lists.sourceforge.net
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of Buildbot-devel digest..."
>
>
> Today's Topics:
>
> 1. Accessing Build Parameters from LogObserver (Tim Flink)
> 2. parallel steps (christian unger)
> 3. [patch] user build properties (paul.gain at virgin.net)
> 4. Patch for custom build properties (Paul Gain)
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Wed, 15 Nov 2006 13:24:42 +0900
> From: Tim Flink <tim at mail.mew.co.jp>
> Subject: [Buildbot-devel] Accessing Build Parameters from LogObserver
> To: buildbot-devel at lists.sourceforge.net
> Message-ID: <455A968A.7050905 at mail.mew.co.jp>
> Content-Type: text/plain; charset=ISO-8859-1; format=flowed
>
> I am using Buildbot 0.7.4 on a C++ project with unit tests and I would
> like to have a new bug created in my bug tracking system when a test
> fails on the build. I have been able to add a bug when a test fails but
> I would like to include more information about the build like the build
> number, the user responsible for the build and the SVN revision number
> but I'm having trouble accessing that information from the LogLineObserver.
>
> Is there a good way to access these properties from the LogLineObserver?
> If not, is there a way to pass non-standard parameters into the
> LogLineObserver without changing the buildbot source?
>
> Thanks in advance for your time,
>
> Tim
>
>
>
> from buildbot.process.step import ShellCommand, LogLineObserver,
> WithProperties
> from makeFailureTicket import makeTicket
>
> class TracIssueReporter(LogLineObserver):
> buildNumber = 0
> properties = ""
>
> def outLineReceived(self, line):
> if "error:" in line:
>
> makeTicket('/etc/tracTest.conf',self.buildNumber,self.properties)
>
> def setProperties(self,args):
> self.properties = args['properties']
>
>
> class RunUtppTests(ShellCommand):
> command = ["scons test"]
> properties = "not changed"
> name = "utppTest"
> warnOnFailure = 1
> description = ["Running UTPP Tests"]
> descriptionDone = ["UTPP Tests"]
>
> def __init__(self, **kwargs):
> ShellCommand.__init__(self, **kwargs) # always upcall!
> reporter = TracIssueReporter()
> self.addLogObserver('stdio', reporter)
>
>
>
> ------------------------------
>
> Message: 2
> Date: Wed, 15 Nov 2006 11:47:05 +0100
> From: christian unger <christian_unger at mac.com>
> Subject: [Buildbot-devel] parallel steps
> To: buildbot-devel <buildbot-devel at lists.sourceforge.net>
> Message-ID: <B03AA941-C132-41B8-BEFE-197378C97AFD at mac.com>
> Content-Type: text/plain; charset=US-ASCII; delsp=yes; format=flowed
>
>
> Hi,
>
> is it possible to checkout multiple modules from a repository in
> parallel?
>
> how can I work with build phases such that I create a dependency
> table which detemines which projects are able to build in parallel?
>
>
> Is there a way to have two builders work in the same directory when
> using dependent schedulers?
>
> cu
> christian unger
> ______________
>
>
>
> ------------------------------
>
> Message: 3
> Date: Wed, 15 Nov 2006 16:00:59 +0000 (UTC)
> From: "paul.gain at virgin.net" <paul.gain at virgin.net>
> Subject: [Buildbot-devel] [patch] user build properties
> To: buildbot-devel at lists.sourceforge.net
> Message-ID: <49900.1163606459074.JavaMail.?@fh1006.dia.cp.net>
> Content-Type: text/plain;charset="UTF-8"
>
> 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
>
>
>
>
>
>
>
> ------------------------------
>
> Message: 4
> Date: Wed, 15 Nov 2006 19:45:35 -0000
> From: "Paul Gain" <paul.gain at virgin.net>
> Subject: [Buildbot-devel] Patch for custom build properties
> To: <Buildbot-devel at lists.sourceforge.net>
> Message-ID: <009001c708ee$9f418b60$37560352 at paul>
> Content-Type: text/plain; charset="iso-8859-1"
>
> 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
> -------------- next part --------------
> An HTML attachment was scrubbed...
> URL: http://sourceforge.net/mailarchive/forum.php?forum=buildbot-devel/attachments/20061115/5b55e574/attachment.html
>
> ------------------------------
>
> -------------------------------------------------------------------------
> Take Surveys. Earn Cash. Influence the Future of IT
> Join SourceForge.net's Techsay panel and you'll get the chance to share your
> opinions on IT & business topics through brief surveys - and earn cash
> http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
>
> ------------------------------
>
> _______________________________________________
> Buildbot-devel mailing list
> Buildbot-devel at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/buildbot-devel
>
>
> End of Buildbot-devel Digest, Vol 7, Issue 17
> *********************************************
>
More information about the devel
mailing list