Next: , Previous: CVS, Up: Source Checkout


4.11.3.2 SVN

The SVN build step performs a Subversion checkout or update. There are two basic ways of setting up the checkout step, depending upon whether you are using multiple branches or not.

The most versatile way to create the SVN step is with the svnurl argument:

svnurl
(required): this specifies the URL argument that will be given to the svn checkout command. It dictates both where the repository is located and which sub-tree should be extracted. In this respect, it is like a combination of the CVS cvsroot and cvsmodule arguments. For example, if you are using a remote Subversion repository which is accessible through HTTP at a URL of http://svn.example.com/repos, and you wanted to check out the trunk/calc sub-tree, you would use svnurl="http://svn.example.com/repos/trunk/calc" as an argument to your SVN step.

The svnurl argument can be considered as a universal means to create the SVN step as it ignores the branch information in the SourceStamp.

Alternatively, if you are building from multiple branches, then you should preferentially create the SVN step with the baseURL and defaultBranch arguments instead:

baseURL
(required): this specifies the base repository URL, to which a branch name will be appended. Alternatively, baseURL can contain a %%BRANCH%% placeholder, which will be replaced with the branch name. baseURL should probably end in a slash.
defaultBranch
(optional): this specifies the name of the branch to use when a Build does not provide one of its own. This is a string that will be appended to baseURL to create the URL that will be passed to the svn checkout command. If you use baseURL without specifying defaultBranch every ChangeStamp must come with a valid (not None) branch.

It is possible to mix to have a mix of SVN steps that use either the svnurl or baseURL arguments but not both at the same time.

username
(optional): if specified, this will be passed to the svn binary with a --username option.
password
(optional): if specified, this will be passed to the svn binary with a --password option. The password itself will be suitably obfuscated in the logs.
extra_args
(optional): if specified, an array of strings that will be passed as extra arguments to the svn binary.
keep_on_purge
(optional): specific files or directories to keep between purges, like some build outputs that can be reused between builds.
ignore_ignores
(optional): when purging changes, don't use rules defined in svn:ignore properties and global-ignores in subversion/config.
always_purge
(optional): if set to True, always purge local changes before updating. This deletes unversioned files and reverts everything that would appear in a svn status.
depth
(optional): Specify depth argument to achieve sparse checkout. Only available if slave has Subversion 1.5 or higher.

If set to "empty" updates will not pull in any files or subdirectories not already present. If set to "files", updates will pull in any files not already present, but not directories. If set to "immediates", updates willl pull in any files or subdirectories not already present, the new subdirectories will have depth: empty. If set to "infinity", updates will pull in any files or subdirectories not already present; the new subdirectories will have depth-infinity. Infinity is equivalent to SVN default update behavior, without specifying any depth argument.

If you are using branches, you must also make sure your ChangeSource will report the correct branch names.

branch example

Let's suppose that the “MyProject” repository uses branches for the trunk, for various users' individual development efforts, and for several new features that will require some amount of work (involving multiple developers) before they are ready to merge onto the trunk. Such a repository might be organized as follows:

     svn://svn.example.org/MyProject/trunk
     svn://svn.example.org/MyProject/branches/User1/foo
     svn://svn.example.org/MyProject/branches/User1/bar
     svn://svn.example.org/MyProject/branches/User2/baz
     svn://svn.example.org/MyProject/features/newthing
     svn://svn.example.org/MyProject/features/otherthing

Further assume that we want the Buildbot to run tests against the trunk and against all the feature branches (i.e., do a checkout/compile/build of branch X when a file has been changed on branch X, when X is in the set [trunk, features/newthing, features/otherthing]). We do not want the Buildbot to automatically build any of the user branches, but it should be willing to build a user branch when explicitly requested (most likely by the user who owns that branch).

There are three things that need to be set up to accommodate this system. The first is a ChangeSource that is capable of identifying the branch which owns any given file. This depends upon a user-supplied function, in an external program that runs in the SVN commit hook and connects to the buildmaster's PBChangeSource over a TCP connection. (you can use the “buildbot sendchange” utility for this purpose, but you will still need an external program to decide what value should be passed to the --branch= argument). For example, a change to a file with the SVN URL of “svn://svn.example.org/MyProject/features/newthing/src/foo.c” should be broken down into a Change instance with branch='features/newthing' and file='src/foo.c'.

The second piece is an AnyBranchScheduler which will pay attention to the desired branches. It will not pay attention to the user branches, so it will not automatically start builds in response to changes there. The AnyBranchScheduler class requires you to explicitly list all the branches you want it to use, but it would not be difficult to write a subclass which used branch.startswith('features/' to remove the need for this explicit list. Or, if you want to build user branches too, you can use AnyBranchScheduler with branches=None to indicate that you want it to pay attention to all branches.

The third piece is an SVN checkout step that is configured to handle the branches correctly, with a baseURL value that matches the way the ChangeSource splits each file's URL into base, branch, and file.

     from buildbot.changes.pb import PBChangeSource
     from buildbot.scheduler import AnyBranchScheduler
     from buildbot.process import source, factory
     from buildbot.steps import source, shell
     
     c['change_source'] = PBChangeSource()
     s1 = AnyBranchScheduler('main',
                             ['trunk', 'features/newthing', 'features/otherthing'],
                             10*60, ['test-i386', 'test-ppc'])
     c['schedulers'] = [s1]
     
     f = factory.BuildFactory()
     f.addStep(source.SVN(mode='update',
                          baseURL='svn://svn.example.org/MyProject/',
                          defaultBranch='trunk'))
     f.addStep(shell.Compile(command="make all"))
     f.addStep(shell.Test(command="make test"))
     
     c['builders'] = [
       {'name':'test-i386', 'slavename':'bot-i386', 'builddir':'test-i386',
                            'factory':f },
       {'name':'test-ppc', 'slavename':'bot-ppc', 'builddir':'test-ppc',
                           'factory':f },
      ]

In this example, when a change arrives with a branch attribute of “trunk”, the resulting build will have a SVN step that concatenates “svn://svn.example.org/MyProject/” (the baseURL) with “trunk” (the branch name) to get the correct svn command. If the “newthing” branch has a change to “src/foo.c”, then the SVN step will concatenate “svn://svn.example.org/MyProject/” with “features/newthing” to get the svnurl for checkout.

For added flexibility, baseURL may contain a %%BRANCH%% placeholder, which will be replaced either by the branch in the SourceStamp or the default specified in defaultBranch.

     source.SVN( mode='update',
                 baseURL='svn://svn.example.org/svn/%%BRANCH%%/myproject',
                 defaultBranch='trunk' )