source: trunk/forks/continutracplugin/continutrac/continuum.py @ 214

Revision 214, 18.3 KB checked in by cbalan, 5 years ago (diff)

Continutrac: - Added 'attach project' admin screen.

Line 
1import os
2from time import strftime, localtime
3import xmlrpclib
4
5class XmlRpcException(Exception):
6    def __init__( self, method, message, stackTrace ):
7        self.method = method
8        self.message = message
9        self.stackTrace = stackTrace
10
11    def __str__( self ):
12        return "Error while executing method." + os.linesep + \
13               "Method: " + self.method + os.linesep + \
14               "Message: " + self.message + os.linesep + \
15               "Stack trace: " + self.stackTrace + os.linesep
16
17def checkResult( map ):
18    if ( map.get( "result" ) == "ok" ):
19        return map
20
21    ex = XmlRpcException( map.get( "method" ), 
22                          map.get( "message" ), 
23                          map.get( "stackTrace" ) )
24    raise ex
25
26def decodeState( state ):
27    if ( state == Continuum.STATE_NEW ):
28        return "new"
29    elif ( state == Continuum.STATE_OK ):
30        return "ok"
31    elif ( state == Continuum.STATE_FAILED ):
32        return "failed"
33    elif ( state == Continuum.STATE_ERROR ):
34        return "error"
35#    elif ( state == 5 ):
36#        return Continuum.STATE_BUILD_SIGNALED
37    elif ( state == Continuum.STATE_BUILDING ):
38        return "building"
39    elif ( state == Continuum.STATE_CHECKING_OUT ):
40        return "checking out"
41    elif ( state == Continuum.STATE_UPDATING ):
42        return "updating"
43    elif ( state == Continuum.STATE_WARNED ):
44        return "warned"
45    else:
46        return "UNKNOWN STATE (" + str( state ) + ")."
47
48def decodeTrigger( trigger ):
49    if (trigger == Continuum.TRIGGER_FORCED):
50        return "forced"
51    elif (trigger == Continuum.TRIGGER_SCHEDULED):
52        return "scheduled"
53    else:
54        return "UNKNOWN TRIGGER (" + str( trigger ) + ")."
55def makeMailNotifier( address ):
56    notifier = ContinuumNotifier()
57
58    notifier.type = "mail"
59    notifier.configuration = { "address" : address }
60
61class Continuum:
62    STATE_NEW = 1
63    STATE_OK = 2
64    STATE_FAILED = 3
65    STATE_ERROR = 4
66    #STATE_BUILD_SIGNALED = "build signaled"
67    STATE_BUILDING = 6
68    STATE_CHECKING_OUT = 7
69    STATE_UPDATING = 8
70    STATE_WARNED = 9
71
72    TRIGGER_SCHEDULED = 0
73    TRIGGER_FORCED = 1
74   
75    def _get_service(self):
76        if self.__service is None:
77            self.__service = self.server.__getattr__(self.__handler) 
78        return self.__service
79         
80    def __init__( self, url, xmlrpc_handler = 'org.apache.maven.continuum.extras.xmlrpc.ContinuumExtrasService'):
81        self.server = xmlrpclib.Server(url, allow_none=True) 
82        self.__handler = xmlrpc_handler
83        self.__service = None
84       
85        # This will make sure the server is working
86        self._get_service().ping()
87
88    ####################################################################
89    # These methods correspods 1<=>1 with the ContinuumXmlRpc interface
90    ####################################################################
91
92    ####################################################################
93    # Projects
94    ####################################################################
95
96    def ping(self):
97        checkResult( self._get_service().ping() )
98
99    def removeProject( self, projectId ):
100        checkResult( self._get_service().removeProject( projectId ) )
101
102    #def updateProject( projectId, name, scmUrl, nagEmailAddress, version, arguments ):
103    #    checkResult( server.continuum.updateProject( projectId, name, scmUrl, nagEmailAddress, version, arguments ) )
104
105    #def updateProjectFromScm( projectId ):
106    #    checkResult( server.continuum.updateProjectFromScm( projectId ) )
107
108    #def updateProjectConfiguration( self, projectId, configuration ):
109    #    checkResult( self._get_service().updateProjectConfiguration( projectId, configuration ) )
110
111    def getProject( self, projectId ):
112        result = checkResult( self._get_service().getProject( projectId ) )
113
114        return self.makeProject( result[ "project" ] )
115
116    def getProjects( self, projectGroupId ):
117        result = checkResult( self._get_service().getProjects(projectGroupId) )
118
119        projects = []
120        for project in result[ "projects" ]:
121            projects.append( self.makeProject( project ) )
122
123        return projects
124
125    def getAllProjectGroups( self ):
126        result = checkResult(self._get_service().getAllProjectGroups())
127
128        projectGroups = []
129        for projectGroup in result[ "projectGroups" ]:
130            projectGroups.append( ProjectGroup( projectGroup ) )
131       
132        return projectGroups
133   
134    def getAllProjects( self ):       
135        projects = []
136        for pg in self.getAllProjectGroups():
137            projects+=pg.projects
138           
139        return projects
140
141    ####################################################################
142    # Builds
143    ####################################################################
144
145    def buildProject( self, projectId ):
146        checkResult( self._get_service().buildProject( projectId ) )
147
148    def getBuild( self, projectId, buildId ):
149        result = checkResult( self._get_service().getBuildResult( projectId, buildId ) )
150
151        return Build( result[ "build" ] )
152
153    def getBuildsForProject( self, projectId ):
154        result = checkResult( self._get_service().getBuildResultsForProject( projectId ) )
155
156        builds = []
157        for build in result[ "builds" ]:
158            builds.append( Build( build ) )
159
160        return builds
161
162    def getBuildOutput( self, projectId, buildId ):
163        return checkResult( self._get_service().getBuildOutput( projectId, buildId ) )[ "buildOutput" ]
164
165    def getBuildDefinitionsForProject(self, projectId):
166        result = checkResult( self._get_service().getBuildDefinitionsForProject( projectId ) )
167
168        buildDefinitions = []
169        for bd in result[ "buildDefinitions" ]:
170            buildDefinitions.append( BuildDefinition( bd ) )
171        return buildDefinitions
172
173   
174    def getChangedFilesForBuild( self, buildId ):
175        result = checkResult( self._get_service().getBuild( buildId ) )
176        scmResult = ScmResult( result[ "scmResult" ] )
177
178        return scmResult.changes
179
180    ####################################################################
181    # Maven 2.x projects
182    ####################################################################
183
184    def addMavenTwoProject( self, argument ):
185        result = checkResult( self._get_service().addMavenTwoProject( argument ) )
186
187        return result[ "projectIds" ]
188
189    def updateMavenTwoProject( self, mavenTwoProject ):
190        checkResult( self._get_service().updateaddMavenTwoProject( mavenTwoProject ) )
191
192    ####################################################################
193    # Maven 1.x projects
194    ####################################################################
195
196    def addMavenOneProject( self, argument ):
197        result = checkResult( self._get_service().addMavenOneProject( argument ) )
198
199        return result[ "projectIds" ]
200
201    def updateMavenOneProject( self, mavenOneProject ):
202        checkResult( self._get_service().updateMavenOneProject( mavenOneProject ) )
203
204    ####################################################################
205    # Ant projects
206    ####################################################################
207
208    def addAntProject( self, antProject ):
209        result = checkResult( self._get_service().addAntProject( antProject ) )
210
211        return result[ "projectIds" ]
212
213    def updateAntProject( self, antProject ):
214        checkResult( self._get_service().updateAntProject( antProject ) )
215
216    ####################################################################
217    # Shell projects
218    ####################################################################
219
220    def addShellProject( self, shellProject ):
221        result = checkResult( self._get_service().addShellProject( shellProject ) )
222
223        return result[ "projectIds" ]
224
225    def updateShellProject( self, shellProject ):
226        checkResult( self._get_service().updateShellProject( shellProject ) )
227
228    ####################################################################
229    #
230    ####################################################################
231
232    def makeProject( self, map ):
233        executorId = map.get( "executorId" )
234        if ( executorId == "maven2" ):
235            return MavenTwoProject( map )
236        elif ( executorId == "maven-1" ):
237            return MavenOneProject( map )
238        elif ( executorId == "ant" ):
239            return AntProject( map )
240        elif ( executorId == "shell" ):
241            return ShellProject( map )
242        else:
243            raise Exception( "Unknown executor id '" + executorId + "'." );
244
245
246####################################################################
247# Domain classes
248####################################################################
249class ProjectGroup:
250    def __init__(self, map):
251        self.description = map.get('description')
252        self.groupId = map.get('groupId')
253        self.id = map.get('id')
254        self.modelEncoding = map.get('modelEncoding')
255        self.name = map.get('name')
256       
257        self.projects = []
258        if map.has_key('projects'):
259            self.projects = [Project(p) for p in map.get('projects')]
260
261class Project:
262    def __init__( self, map ):
263        self.map = map;
264        self.dependencies = []
265        self.developers = []
266        self.notifiers = []
267
268        if ( map == None ):
269            return
270
271        self.id = map.get( "id" )
272        self.name = map.get( "name" )
273        self.scmUrl = map.get( "scmUrl" )
274        self.version = map.get( "version" )
275        self.build = map.get( "buildNumber" )
276        if ( map.has_key( "workingDirectory" ) ):
277            self.workingDirectory = map.get( "workingDirectory" )
278        else:
279            self.workingDirectory = ""
280        self.state = int( map.get( "state" ) )
281        self.executorId = map.get( "executorId" )
282        self.group = map.get("groupId")
283       
284        if ( map.has_key( "commandLineArguments" ) ):
285            self.commandLineArguments = map.get( "commandLineArguments" )
286        else:
287            self.commandLineArguments = ""
288
289        self.dependencies = list()
290        if ( map.has_key( "dependencies" ) ):
291            for f in map.get( "dependencies" ):
292                self.dependencies.append( ContinuumDependency( f ) )
293
294        self.developers = list()
295        if ( map.has_key( "developers" ) ):
296            for f in map.get( "developers" ):
297                self.developers.append( ContinuumDeveloper( f ) )
298
299        self.notifiers = list()
300        if ( map.has_key( "notifiers" ) ):
301            for f in map.get( "notifiers" ):
302                self.notifiers.append( ContinuumNotifier( f ) )
303
304    def __str__( self ):
305        s = "id: " + self.id + os.linesep +\
306            "name: " + self.name + os.linesep +\
307            "version: " + self.version + os.linesep +\
308            "executor id: " + self.executorId + os.linesep +\
309            "state: " + decodeState( self.state ) + os.linesep
310
311        return s
312
313class MavenTwoProject( Project ):
314    def __init__( self, map=None ):
315        Project.__init__( self, map )
316
317        if ( map == None ):
318            return
319   
320        self.goals = '' #map[ "goals" ]
321        self.group = map.get( "groupId" )
322
323    def __str__( self ):
324        return Project.__str__( self ) + os.linesep +\
325               "goals: " + self.goals + os.linesep
326
327class MavenOneProject( Project ):
328    def __init__( self, map=None ):
329        Project.__init__( self, map )
330
331        if ( map == None ):
332            return
333   
334        self.goals = '' #map[ "goals" ]
335        self.group = map.get( "groupId" )
336
337    def __str__( self ):
338        return Project.__str__( self ) + os.linesep +\
339               "goals: " + self.goals + os.linesep
340
341class AntProject( Project ):
342    def __init__( self, map=None ):
343        Project.__init__( self, map )
344
345        if ( map == None ):
346            return
347#        self.executable = map[ "executable" ]
348#        self.targets = map[ "goals" ]
349
350    def __str__( self ):
351        return Project.__str__( self ) + os.linesep +\
352               "executable: " + self.executable + os.linesep +\
353               "targets: " + self.targets + os.linesep
354
355class ShellProject( Project ):
356    def __init__( self, map=None ):
357        Project.__init__( self, map )
358
359        if ( map == None ):
360            return
361   
362        self.executable = map.get( "executable" )
363
364    def __str__( self ):
365        return Project.__str__( self ) + os.linesep +\
366               "executable: " + self.executable + os.linesep
367
368class Build:
369    def __init__( self, map ):
370        map[ "totalTime" ] = int( map.get( "endTime" ) )/ 1000 - int( map.get( "startTime" ) ) / 1000
371
372        self.id = map.get( "id" )
373        self.state = int( map.get( "state" ) )
374        self.buildNumber = map.get( "buildNumber" )
375        if ( self.state != Continuum.STATE_OK ):
376            self.buildNumber = ''
377        if ( map.has_key( "trigger" ) ):
378            self.forced = map.get( "trigger" ) == Continuum.TRIGGER_FORCED
379            self.trigger = int( map.get( "trigger" ) )
380        else:
381            self.forced = False
382            self.trigger = 0
383
384        self.startTime = localtime( int( map.get( "startTime" ) ) / 1000 )
385        self.endTime = localtime( int( map.get( "endTime" ) ) / 1000 )
386        self.totalTime = map.get( "totalTime" )
387        self.error = map.get( "error" )
388        self.map = map
389        if ( map.has_key( "scmResult" ) ):
390            self.scmResult = ScmResult( map.get( "scmResult" ) )
391        else:
392            self.scmResult = None
393
394        if ( self.error == None ):
395            self.error = ""
396            map[ "error" ] = ""
397
398        self.success = map.get( "success" ) == "true"
399        self.exitCode = int( map.get( "exitCode" ) )
400        if ( map.has_key( "standardOutput" ) ):
401            self.standardOutput = map.get( "standardOutput" )
402        else:
403            self.standardOutput = None
404        if ( map.has_key( "standardError" ) ):
405            self.standardError = map.get( "standardError" )
406        else:
407            self.standardError = None
408       
409        self.buildDefinition = BuildDefinition(map.get('buildDefinition'))
410       
411
412    def __str__( self ):
413        s = "Id: " + self.id + os.linesep +\
414            "State: " + decodeState( self.state ) + os.linesep +\
415            "End time: " + strftime( "%a, %d %b %Y %H:%M:%S +0000", self.endTime ) + os.linesep +\
416            "Build time: " + self.totalTime + os.linesep
417
418        if ( self.error != "" ):
419            s += "Error: %(error)s" % self.map
420        value = "Success: " + str( self.success )
421        value += os.linesep + "Exit code: " + str( self.exitCode )
422        if ( len( self.standardOutput ) > 0 ):
423              value += os.linesep + "Standard output: " + self.standardOutput
424        if ( len( self.standardError ) > 0 ):
425               value += os.linesep + "Standard error: " + self.standardError
426
427        return s
428
429class BuildDefinition:
430    def __init__(self, map):
431        self.arguments = map.get('arguments')
432        self.buildFile = map.get('buildFile')
433        self.buildFresh= map.get('buildFresh') == 'true'
434        self.defaultForProject = map.get('defaultForProject') == 'true'
435        self.goals = map.get('goals')
436        self.id = map.get('id')
437        self.modelEncoding = map.get('modelEncoding')
438        self.schedule = Schedule(map.get('schedule'))
439       
440class Schedule:
441    def __init__(self, map):
442        self.active = map.get('active') == 'true'
443        self.cronExpression = map.get('cronExpression')
444        self.delay = map.get('delay')
445        self.description = map.get('description')
446        self.id = map.get('id')
447        self.maxJobExecutionTime = map.get('maxJobExecutionTime')
448        self.modelEncoding = map.get('modelEncoding')
449        self.name = map.get('name')
450       
451class ScmResult:
452    def __init__( self, map ):
453        self.map = map
454        self.success = map.get( "success" ) == "true"
455
456        if ( map.has_key( "providerMessage" ) ):
457            self.providerMessage = map.get( "providerMessage" )
458        else:
459            self.providerMessage = ""
460
461        if ( map.has_key( "commandOutput" ) ):
462            self.commandOutput = map.get( "commandOutput" )
463        else:
464            self.commandOutput = ""
465
466        self.changes = list()
467        if ( map.has_key( "changes" ) ):
468            for f in map.get( "changes" ):
469                self.changes.append( ChangeSet( f ) )
470
471    def __str__( self ):
472        value = "Success: " + str( self.success ) + os.linesep +\
473                "Provider Message: " + self.providerMessage + os.linesep +\
474                "Command output: " + self.commandOutput
475
476        return value
477
478class ChangeSet:
479    def __init__( self, map ):
480        self.map = map
481        self.author = ""
482        if ( map.has_key( "author" ) ):
483          self.author = map.get( "author" )
484        self.comment = ""
485        if ( map.has_key( "comment" ) ):
486          self.comment = map.get( "comment" )
487        self.date = localtime( int( map.get( "date" ) ) / 1000 )
488
489        self.files = list()
490        for f in map.get( "files" ):
491            self.files.append( ChangeFile( f ) )
492
493    def __str__( self ):
494        value = "Author: " + self.author + os.linesep +\
495                "Comment: " + self.comment
496
497        return value
498
499class ChangeFile:
500    def __init__( self, map ):
501        self.map = map
502        self.name = map.get( "name" )
503        self.revision = ""
504        if ( map.has_key( "revision" ) ):
505          self.revision = map.get( "revision" )
506
507    def __str__( self ):
508        value = "File: " + self.name + " (" + self.revision + ")"
509
510        return value
511
512class ContinuumDependency:
513    def __init__( self, map ):
514        self.group = map.get( "groupId" )
515        self.artifact = map.get( "artifactId" )
516        self.version = map.get( "version" )
517
518    def __str__( self ):
519        value = self.group + ":" + self.artifact + ":" + self.version
520        return value
521
522class ContinuumDeveloper:
523    def __init__( self, map ):
524        self.id = map.get( "continuumId" )
525        self.name = map.get( "name" )
526        self.email = map.get( "email" )
527
528    def __str__( self ):
529        value = "id: " + self.id + os.linesep +\
530                "name: " + self.name + os.linesep +\
531                "email: " + self.email
532
533        return value
534
535class ContinuumNotifier:
536    def __init__( self, map=None ):
537        self.type = None
538        self.configuration = {}
539
540        if ( map == None ):
541            return
542
543        self.type = map.get("type")
544
545        if ( map.has_key( "configuration" ) ):
546            self.configuration = map.get( "configuration" )
547
548    def __str__( self ):
549        value = "type: " + self.type
550
551        return value
Note: See TracBrowser for help on using the repository browser.