1# This file is part of Buildbot.  Buildbot is free software: you can
2# redistribute it and/or modify it under the terms of the GNU General Public
3# License as published by the Free Software Foundation, version 2.
4#
5# This program is distributed in the hope that it will be useful, but WITHOUT
6# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
7# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
8# details.
9#
10# You should have received a copy of the GNU General Public License along with
11# this program; if not, write to the Free Software Foundation, Inc., 51
12# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
13#
14# Copyright Buildbot Team Members
15
16"""Interface documentation.
17
18Define the interfaces that are implemented by various buildbot classes.
19"""
20
21# disable pylint warnings triggered by interface definitions
22# pylint: disable=no-self-argument
23# pylint: disable=no-method-argument
24# pylint: disable=inherit-non-class
25
26from twisted.python.deprecate import deprecatedModuleAttribute
27from twisted.python.versions import Version
28from zope.interface import Attribute
29from zope.interface import Interface
30
31# exceptions that can be raised while trying to start a build
32
33
34class BuilderInUseError(Exception):
35    pass
36
37
38class WorkerSetupError(Exception):
39    pass
40
41
42WorkerTooOldError = WorkerSetupError
43deprecatedModuleAttribute(
44    Version("buildbot", 2, 9, 0),
45    message="Use WorkerSetupError instead.",
46    moduleName="buildbot.interfaces",
47    name="WorkerTooOldError",
48)
49
50
51class LatentWorkerFailedToSubstantiate(Exception):
52    pass
53
54
55class LatentWorkerCannotSubstantiate(Exception):
56    pass
57
58
59class LatentWorkerSubstantiatiationCancelled(Exception):
60    pass
61
62
63class IPlugin(Interface):
64
65    """
66    Base interface for all Buildbot plugins
67    """
68
69
70class IChangeSource(IPlugin):
71
72    """
73    Service which feeds Change objects to the changemaster. When files or
74    directories are changed in version control, this object should represent
75    the changes as a change dictionary and call::
76
77      self.master.data.updates.addChange(who=.., rev=.., ..)
78
79    See 'Writing Change Sources' in the manual for more information.
80    """
81    master = Attribute('master',
82                       'Pointer to BuildMaster, automatically set when started.')
83
84    def describe():
85        """Return a string which briefly describes this source."""
86
87
88class ISourceStamp(Interface):
89
90    """
91    @cvar branch: branch from which source was drawn
92    @type branch: string or None
93
94    @cvar revision: revision of the source, or None to use CHANGES
95    @type revision: varies depending on VC
96
97    @cvar patch: patch applied to the source, or None if no patch
98    @type patch: None or tuple (level diff)
99
100    @cvar changes: the source step should check out the latest revision
101                   in the given changes
102    @type changes: tuple of L{buildbot.changes.changes.Change} instances,
103                   all of which are on the same branch
104
105    @cvar project: project this source code represents
106    @type project: string
107
108    @cvar repository: repository from which source was drawn
109    @type repository: string
110    """
111
112    def canBeMergedWith(self, other):
113        """
114        Can this SourceStamp be merged with OTHER?
115        """
116
117    def mergeWith(self, others):
118        """Generate a SourceStamp for the merger of me and all the other
119        SourceStamps. This is called by a Build when it starts, to figure
120        out what its sourceStamp should be."""
121
122    def getAbsoluteSourceStamp(self, got_revision):
123        """Get a new SourceStamp object reflecting the actual revision found
124        by a Source step."""
125
126    def getText(self):
127        """Returns a list of strings to describe the stamp. These are
128        intended to be displayed in a narrow column. If more space is
129        available, the caller should join them together with spaces before
130        presenting them to the user."""
131
132
133class IEmailSender(Interface):
134
135    """I know how to send email, and can be used by other parts of the
136    Buildbot to contact developers."""
137
138
139class IEmailLookup(Interface):
140
141    def getAddress(user):
142        """Turn a User-name string into a valid email address. Either return
143        a string (with an @ in it), None (to indicate that the user cannot
144        be reached by email), or a Deferred which will fire with the same."""
145
146
147class ILogObserver(Interface):
148
149    """Objects which provide this interface can be used in a BuildStep to
150    watch the output of a LogFile and parse it incrementally.
151    """
152
153    # internal methods
154    def setStep(step):
155        pass
156
157    def setLog(log):
158        pass
159
160    # methods called by the LogFile
161    def logChunk(build, step, log, channel, text):
162        pass
163
164
165class IWorker(IPlugin):
166    # callback methods from the manager
167    pass
168
169
170class ILatentWorker(IWorker):
171
172    """A worker that is not always running, but can run when requested.
173    """
174    substantiated = Attribute('Substantiated',
175                              'Whether the latent worker is currently '
176                              'substantiated with a real instance.')
177
178    def substantiate():
179        """Request that the worker substantiate with a real instance.
180
181        Returns a deferred that will callback when a real instance has
182        attached."""
183
184    # there is an insubstantiate too, but that is not used externally ATM.
185
186    def buildStarted(wfb):
187        """Inform the latent worker that a build has started.
188
189        @param wfb: a L{LatentWorkerForBuilder}.  The wfb is the one for whom the
190        build finished.
191        """
192
193    def buildFinished(wfb):
194        """Inform the latent worker that a build has finished.
195
196        @param wfb: a L{LatentWorkerForBuilder}.  The wfb is the one for whom the
197        build finished.
198        """
199
200
201class IMachine(Interface):
202    pass
203
204
205class IMachineAction(Interface):
206    def perform(self, manager):
207        """ Perform an action on the machine managed by manager. Returns a
208            deferred evaluating to True if it was possible to execute the
209            action.
210        """
211
212
213class ILatentMachine(IMachine):
214    """ A machine that is not always running, but can be started when requested.
215    """
216
217
218class IRenderable(Interface):
219
220    """An object that can be interpolated with properties from a build.
221    """
222
223    def getRenderingFor(iprops):
224        """Return a deferred that fires with interpolation with the given properties
225
226        @param iprops: the L{IProperties} provider supplying the properties.
227        """
228
229
230class IProperties(Interface):
231
232    """
233    An object providing access to build properties
234    """
235
236    def getProperty(name, default=None):
237        """Get the named property, returning the default if the property does
238        not exist.
239
240        @param name: property name
241        @type name: string
242
243        @param default: default value (default: @code{None})
244
245        @returns: property value
246        """
247
248    def hasProperty(name):
249        """Return true if the named property exists.
250
251        @param name: property name
252        @type name: string
253        @returns: boolean
254        """
255
256    def has_key(name):
257        """Deprecated name for L{hasProperty}."""
258
259    def setProperty(name, value, source, runtime=False):
260        """Set the given property, overwriting any existing value.  The source
261        describes the source of the value for human interpretation.
262
263        @param name: property name
264        @type name: string
265
266        @param value: property value
267        @type value: JSON-able value
268
269        @param source: property source
270        @type source: string
271
272        @param runtime: (optional) whether this property was set during the
273        build's runtime: usually left at its default value
274        @type runtime: boolean
275        """
276
277    def getProperties():
278        """Get the L{buildbot.process.properties.Properties} instance storing
279        these properties.  Note that the interface for this class is not
280        stable, so where possible the other methods of this interface should be
281        used.
282
283        @returns: L{buildbot.process.properties.Properties} instance
284        """
285
286    def getBuild():
287        """Get the L{buildbot.process.build.Build} instance for the current
288        build.  Note that this object is not available after the build is
289        complete, at which point this method will return None.
290
291        Try to avoid using this method, as the API of L{Build} instances is not
292        well-defined.
293
294        @returns L{buildbot.process.build.Build} instance
295        """
296
297    def render(value):
298        """Render @code{value} as an L{IRenderable}.  This essentially coerces
299        @code{value} to an L{IRenderable} and calls its @L{getRenderingFor}
300        method.
301
302        @name value: value to render
303        @returns: rendered value
304        """
305
306
307class IScheduler(IPlugin):
308    pass
309
310
311class ITriggerableScheduler(Interface):
312
313    """
314    A scheduler that can be triggered by buildsteps.
315    """
316
317    def trigger(waited_for, sourcestamps=None, set_props=None,
318                parent_buildid=None, parent_relationship=None):
319        """Trigger a build with the given source stamp and properties.
320        """
321
322
323class IBuildStepFactory(Interface):
324
325    def buildStep():
326        pass
327
328
329class IBuildStep(IPlugin):
330
331    """
332    A build step
333    """
334    # Currently has nothing
335
336
337class IConfigured(Interface):
338
339    def getConfigDict():
340        pass
341
342
343class IReportGenerator(Interface):
344
345    def generate(self, master, reporter, key, build):
346        pass
347
348
349class IConfigLoader(Interface):
350
351    def loadConfig():
352        """
353        Load the specified configuration.
354
355        :return MasterConfig:
356        """
357
358
359class IHttpResponse(Interface):
360
361    def content():
362        """
363        :returns: raw (``bytes``) content of the response via deferred
364        """
365    def json():
366        """
367        :returns: json decoded content of the response via deferred
368        """
369    code = Attribute('code',
370                     "http status code of the request's response (e.g 200)")
371    url = Attribute('url',
372                    "request's url (e.g https://api.github.com/endpoint')")
373
374
375class IConfigurator(Interface):
376
377    def configure(config_dict):
378        """
379        Alter the buildbot config_dict, as defined in master.cfg
380
381        like the master.cfg, this is run out of the main reactor thread, so this can block, but
382        this can't call most Buildbot facilities.
383
384        :returns: None
385        """
386