OLD | NEW |
| (Empty) |
1 # -*- test-case-name: buildbot.test.test_step -*- | |
2 | |
3 from buildbot import util | |
4 from buildbot.process.base import Build | |
5 from buildbot.process.buildstep import BuildStep | |
6 from buildbot.steps.source import CVS, SVN | |
7 from buildbot.steps.shell import Configure, Compile, Test, PerlModuleTest | |
8 | |
9 # deprecated, use BuildFactory.addStep | |
10 def s(steptype, **kwargs): | |
11 # convenience function for master.cfg files, to create step | |
12 # specification tuples | |
13 return (steptype, kwargs) | |
14 | |
15 class ArgumentsInTheWrongPlace(Exception): | |
16 """When calling BuildFactory.addStep(stepinstance), addStep() only takes | |
17 one argument. You passed extra arguments to addStep(), which you probably | |
18 intended to pass to your BuildStep constructor instead. For example, you | |
19 should do:: | |
20 | |
21 f.addStep(ShellCommand(command=['echo','stuff'], haltOnFailure=True)) | |
22 | |
23 instead of:: | |
24 | |
25 f.addStep(ShellCommand(command=['echo','stuff']), haltOnFailure=True) | |
26 """ | |
27 | |
28 class BuildFactory(util.ComparableMixin): | |
29 """ | |
30 @cvar buildClass: class to use when creating builds | |
31 @type buildClass: L{buildbot.process.base.Build} | |
32 """ | |
33 buildClass = Build | |
34 useProgress = 1 | |
35 compare_attrs = ['buildClass', 'steps', 'useProgress'] | |
36 | |
37 def __init__(self, steps=None): | |
38 if steps is None: | |
39 steps = [] | |
40 self.steps = [self._makeStepFactory(s) for s in steps] | |
41 | |
42 def _makeStepFactory(self, step_or_factory): | |
43 if isinstance(step_or_factory, BuildStep): | |
44 return step_or_factory.getStepFactory() | |
45 return step_or_factory | |
46 | |
47 def newBuild(self, request): | |
48 """Create a new Build instance. | |
49 @param request: a L{base.BuildRequest} describing what is to be built | |
50 """ | |
51 b = self.buildClass(request) | |
52 b.useProgress = self.useProgress | |
53 b.setStepFactories(self.steps) | |
54 return b | |
55 | |
56 def addStep(self, step_or_factory, **kwargs): | |
57 if isinstance(step_or_factory, BuildStep): | |
58 if kwargs: | |
59 raise ArgumentsInTheWrongPlace() | |
60 s = step_or_factory.getStepFactory() | |
61 else: | |
62 s = (step_or_factory, dict(kwargs)) | |
63 self.steps.append(s) | |
64 | |
65 def addSteps(self, steps): | |
66 self.steps.extend([ s.getStepFactory() for s in steps ]) | |
67 | |
68 # BuildFactory subclasses for common build tools | |
69 | |
70 class GNUAutoconf(BuildFactory): | |
71 def __init__(self, source, configure="./configure", | |
72 configureEnv={}, | |
73 configureFlags=[], | |
74 compile=["make", "all"], | |
75 test=["make", "check"]): | |
76 BuildFactory.__init__(self, [source]) | |
77 if configure is not None: | |
78 # we either need to wind up with a string (which will be | |
79 # space-split), or with a list of strings (which will not). The | |
80 # list of strings is the preferred form. | |
81 if type(configure) is str: | |
82 if configureFlags: | |
83 assert not " " in configure # please use list instead | |
84 command = [configure] + configureFlags | |
85 else: | |
86 command = configure | |
87 else: | |
88 assert isinstance(configure, (list, tuple)) | |
89 command = configure + configureFlags | |
90 self.addStep(Configure, command=command, env=configureEnv) | |
91 if compile is not None: | |
92 self.addStep(Compile, command=compile) | |
93 if test is not None: | |
94 self.addStep(Test, command=test) | |
95 | |
96 class CPAN(BuildFactory): | |
97 def __init__(self, source, perl="perl"): | |
98 BuildFactory.__init__(self, [source]) | |
99 self.addStep(Configure, command=[perl, "Makefile.PL"]) | |
100 self.addStep(Compile, command=["make"]) | |
101 self.addStep(PerlModuleTest, command=["make", "test"]) | |
102 | |
103 class Distutils(BuildFactory): | |
104 def __init__(self, source, python="python", test=None): | |
105 BuildFactory.__init__(self, [source]) | |
106 self.addStep(Compile, command=[python, "./setup.py", "build"]) | |
107 if test is not None: | |
108 self.addStep(Test, command=test) | |
109 | |
110 class Trial(BuildFactory): | |
111 """Build a python module that uses distutils and trial. Set 'tests' to | |
112 the module in which the tests can be found, or set useTestCaseNames=True | |
113 to always have trial figure out which tests to run (based upon which | |
114 files have been changed). | |
115 | |
116 See docs/factories.xhtml for usage samples. Not all of the Trial | |
117 BuildStep options are available here, only the most commonly used ones. | |
118 To get complete access, you will need to create a custom | |
119 BuildFactory.""" | |
120 | |
121 trial = "trial" | |
122 randomly = False | |
123 recurse = False | |
124 | |
125 def __init__(self, source, | |
126 buildpython=["python"], trialpython=[], trial=None, | |
127 testpath=".", randomly=None, recurse=None, | |
128 tests=None, useTestCaseNames=False, env=None): | |
129 BuildFactory.__init__(self, [source]) | |
130 assert tests or useTestCaseNames, "must use one or the other" | |
131 if trial is not None: | |
132 self.trial = trial | |
133 if randomly is not None: | |
134 self.randomly = randomly | |
135 if recurse is not None: | |
136 self.recurse = recurse | |
137 | |
138 from buildbot.steps.python_twisted import Trial | |
139 buildcommand = buildpython + ["./setup.py", "build"] | |
140 self.addStep(Compile, command=buildcommand, env=env) | |
141 self.addStep(Trial, | |
142 python=trialpython, trial=self.trial, | |
143 testpath=testpath, | |
144 tests=tests, testChanges=useTestCaseNames, | |
145 randomly=self.randomly, | |
146 recurse=self.recurse, | |
147 env=env, | |
148 ) | |
149 | |
150 | |
151 # compatibility classes, will go away. Note that these only offer | |
152 # compatibility at the constructor level: if you have subclassed these | |
153 # factories, your subclasses are unlikely to still work correctly. | |
154 | |
155 ConfigurableBuildFactory = BuildFactory | |
156 | |
157 class BasicBuildFactory(GNUAutoconf): | |
158 # really a "GNU Autoconf-created tarball -in-CVS tree" builder | |
159 | |
160 def __init__(self, cvsroot, cvsmodule, | |
161 configure=None, configureEnv={}, | |
162 compile="make all", | |
163 test="make check", cvsCopy=False): | |
164 mode = "clobber" | |
165 if cvsCopy: | |
166 mode = "copy" | |
167 source = s(CVS, cvsroot=cvsroot, cvsmodule=cvsmodule, mode=mode) | |
168 GNUAutoconf.__init__(self, source, | |
169 configure=configure, configureEnv=configureEnv, | |
170 compile=compile, | |
171 test=test) | |
172 | |
173 class QuickBuildFactory(BasicBuildFactory): | |
174 useProgress = False | |
175 | |
176 def __init__(self, cvsroot, cvsmodule, | |
177 configure=None, configureEnv={}, | |
178 compile="make all", | |
179 test="make check", cvsCopy=False): | |
180 mode = "update" | |
181 source = s(CVS, cvsroot=cvsroot, cvsmodule=cvsmodule, mode=mode) | |
182 GNUAutoconf.__init__(self, source, | |
183 configure=configure, configureEnv=configureEnv, | |
184 compile=compile, | |
185 test=test) | |
186 | |
187 class BasicSVN(GNUAutoconf): | |
188 | |
189 def __init__(self, svnurl, | |
190 configure=None, configureEnv={}, | |
191 compile="make all", | |
192 test="make check"): | |
193 source = s(SVN, svnurl=svnurl, mode="update") | |
194 GNUAutoconf.__init__(self, source, | |
195 configure=configure, configureEnv=configureEnv, | |
196 compile=compile, | |
197 test=test) | |
OLD | NEW |