[Buildbot-devel] Using "Branch to build: " in master.cfg

A.T.Hofkamp a.t.hofkamp at tue.nl
Tue Aug 5 08:56:46 UTC 2008


John Stile wrote:
> I think I'm close, but I have something wrong. 
> 
> my master.cfg looks for the options passed to "force build" form using
> buildbot.scripts.runner class ForceOptions.
> 
> The shell script called in factory.BuildFactory by shell.ShellCommand
> also prints out the rev and branch it was passed.
> 
> When I "Force Build", the "Branch to build:" or "Revision to build:" are
> not available using ForceOptions in master.cfg.
> 
> What object would have this?

Hello,

The following example may be of use:

I needed to fix entered SVN branches and revisions, branches other than 
'trunk' needed to have 'branches/' prepended, a sanity check was added (one 
should enter an existing branch-name), and the last revision of the branch was 
obtained if the user didn't enter one.


To implemente this, I derived a new class from shell.ShellCommand, along the 
lines of

http://buildbot.net/repos/release/docs/buildbot.html#Using-Build-Properties
and
http://buildbot.net/repos/release/docs/buildbot.html#Writing-New-BuildSteps

# ADD/DECIDE BRANCH AND REVISION
class DecideBranchRevision(shell.ShellCommand):

     _revision_pat = re.compile('\\d+$')
     _last_change_rev_pat = re.compile('Last Changed Rev: (\\d+)$')
     _svnURL = 'BASE_URL_TO_REPOSITORY'

     def __init__(self, **kwargs):
         kwargs['haltOnFailure'] = True
         kwargs['description'] = ['selecting', 'branch/rev']
         shell.ShellCommand.__init__(self, **kwargs)


     def _get_svnpath(self, branchname):
         """ Return a SVNurl suitable for querying revision of last 
modification """
         if branchname is None or branchname == '' or branchname == 'trunk':
             return self._svnURL + '/trunk'

         # Query open branches from svn
         fp = os.popen('svn ls --non-interactive ' + self._svnURL + 
'/branches', 'r')
         svn_branches = [line.strip() for line in fp.readlines()]
         code = fp.close()
         if code is not None:
             self.addCompleteLog('errors', "svn ls \'/branches\' failed 
(errorcode %r)\n"
  % code)
             self.finished(FAILURE)
             return None
         if branchname + "/" not in svn_branches:
             text = "Branch %r not in repository\n" % branchname
             text = text + "\n" + "Known branches:\n"
             for b in svn_branches:
                 assert b[-1] == '/'
                 text = text + "\t%r\n" % b[:-1]
             self.addCompleteLog('errors', text)

             self.finished(FAILURE)
             return None
         return self._svnURL + '/branches/' + branchname

     def _get_lastmod_revision(self, svnurl):
         """ Get revision number of last modification in L{svnurl} """
         fp = os.popen('svn info --non-interactive ' + svnurl, 'r')
         info_lines = [line.rstrip() for line in fp.readlines()]
         m = self._last_change_rev_pat.match(info_lines[7])
         if not m:
             self.addCompleteLog('errors', "Cannot retrieve last change 
revision of " + svnurl + '\n')
             self.finished(FAILURE)
             return None

         return m.group(1)

     def _rev_checking(self, rev):
         """ Verify that given revision is indeed a revision number """
         m = self._revision_pat.match(rev)
         if not m:
             self.addCompleteLog('errors', "%r is not a valid revision\n" % rev)
             self.finished(FAILURE)
             return None
         return rev


     def start(self):
         branch = self.getProperty('branch')
         revision = self.getProperty('revision')
         branch_modified = False
         revision_modified = False

         if branch is None or branch == '':
             branch = 'trunk'
             branch_modified = True

         svn_path = self._get_svnpath(branch)
         if svn_path is None:
             return None

         if revision is None or revision == '':
             revision = self._get_lastmod_revision(svn_path)
             revision_modified = True
         else:
             rev = self._rev_checking(revision)
             if rev is None:
                 return None
             assert rev == revision

         if branch_modified:
             self.setProperty('branch', branch)
         if revision_modified:
             self.setProperty('revision', revision)

         # always set 'got_revision'
         self.setProperty('got_revision', revision)

         self.descriptionDone = ['selected', branch, revision]

         text = "Building branch %r revision %s\n" % (branch, revision)
         self.addCompleteLog('stdout', text)
         self.finished(SUCCESS)

The starting point for an execution is at the 'start()' method. I added the 
other sub-routines mainly for completeness, you may not need them.


Add this class to the master.cfg, and add a buildstep

     step = DecideBranchRevision()
     f.addStep(step)






More information about the devel mailing list