66
77
88class Bamboo (AtlassianRestAPI ):
9+
10+ """ Private methods """
11+
912 def _get_generator (self , path , elements_key = 'results' , element_key = 'result' , data = None , flags = None ,
1013 params = None , headers = None , max_results = None ):
1114 """
@@ -60,26 +63,8 @@ def base_list_call(self, resource, expand, favourite, clover_enabled, max_result
6063 max_results = max_results )
6164 params ['start-index' ] = start_index
6265 return self .get (self .resource_url (resource ), flags = flags , params = params )
63-
64- def get_custom_expiry (self , limit = 25 ):
65- """
66- Get list of all plans where user has admin permission and which override global expiry settings.
67- If global expiry is not enabled it returns empty response.
68- :param limit:
69- """
70- url = "rest/api/latest/admin/expiry/custom/plan?limit={}" .format (limit )
71- return self .get (url )
7266
73- def plan_directory_info (self , plan_key ):
74- """
75- Returns information about the directories where artifacts, build logs, and build results will be stored.
76- Disabled by default.
77- See https://confluence.atlassian.com/display/BAMBOO/Plan+directory+information+REST+API for more information.
78- :param plan_key:
79- :return:
80- """
81- resource = 'planDirectoryInfo/{}' .format (plan_key )
82- return self .get (self .resource_url (resource ))
67+ """ Projects & Plans """
8368
8469 def projects (self , expand = None , favourite = False , clover_enabled = False , max_results = 25 ):
8570 return self .base_list_call ('project' , expand , favourite , clover_enabled , max_results ,
@@ -102,6 +87,91 @@ def project_plans(self, project_key):
10287 def plans (self , expand = None , favourite = False , clover_enabled = False , start_index = 0 , max_results = 25 ):
10388 return self .base_list_call ("plan" , expand , favourite , clover_enabled , start_index , max_results ,
10489 elements_key = 'plans' , element_key = 'plan' )
90+
91+ def plan_directory_info (self , plan_key ):
92+ """
93+ Returns information about the directories where artifacts, build logs, and build results will be stored.
94+ Disabled by default.
95+ See https://confluence.atlassian.com/display/BAMBOO/Plan+directory+information+REST+API for more information.
96+ :param plan_key:
97+ :return:
98+ """
99+ resource = 'planDirectoryInfo/{}' .format (plan_key )
100+ return self .get (self .resource_url (resource ))
101+
102+ def delete_plan (self , plan_key ):
103+ """
104+ Marks plan for deletion. Plan will be deleted by a batch job.
105+ :param plan_key:
106+ :return:
107+ """
108+ resource = 'rest/api/latest/plan/{}' .format (plan_key )
109+ return self .delete (resource )
110+
111+ def enable_plan (self , plan_key ):
112+ """
113+ Enable plan.
114+ :param plan_key: str TST-BLD
115+ :return: POST request
116+ """
117+ resource = 'plan/{plan_key}/enable' .format (plan_key = plan_key )
118+ return self .post (self .resource_url (resource ))
119+
120+ """ Branches """
121+
122+ def search_branches (self , plan_key , include_default_branch = True , max_results = 25 ):
123+ params = {
124+ 'max-result' : max_results ,
125+ 'start-index' : 0 ,
126+ 'masterPlanKey' : plan_key ,
127+ 'includeMasterBranch' : include_default_branch
128+ }
129+ size = 1
130+ while params ['start-index' ] < size :
131+ results = self .get (self .resource_url ('search/branches' ), params = params )
132+ size = results ['size' ]
133+ for r in results ['searchResults' ]:
134+ yield r
135+ params ['start-index' ] += results ['max-result' ]
136+
137+ def plan_branches (self , plan_key , expand = None , favourite = False , clover_enabled = False , max_results = 25 ):
138+ """api/1.0/plan/{projectKey}-{buildKey}/branch"""
139+ resource = 'plan/{}/branch' .format (plan_key )
140+ return self .base_list_call (resource , expand , favourite , clover_enabled , max_results ,
141+ elements_key = 'branches' , element_key = 'branch' )
142+
143+ def get_branch_info (self , plan_key , branch_name ):
144+ """
145+ Get information about a plan branch
146+ :param plan_key:
147+ :param branch_name:
148+ :return:
149+ """
150+ resource = 'plan/{plan_key}/branch/{branch_name}' .format (plan_key = plan_key , branch_name = branch_name )
151+ return self .get (self .resource_url (resource ))
152+
153+ def create_branch (self , plan_key , branch_name , vcs_branch = None , enabled = False , cleanup_enabled = False ):
154+ """
155+ Method for creating branch for a specified plan.
156+ You can use vcsBranch query param to define which vcsBranch should newly created branch use.
157+ If not specified it will not override vcsBranch from the main plan.
158+
159+ :param plan_key: str TST-BLD
160+ :param branch_name: str new-shiny-branch
161+ :param vcs_branch: str feature/new-shiny-branch, /refs/heads/new-shiny-branch
162+ :param enabled: bool
163+ :param cleanup_enabled: bool
164+ :return: PUT request
165+ """
166+ resource = 'plan/{plan_key}/branch/{branch_name}' .format (plan_key = plan_key , branch_name = branch_name )
167+ params = {}
168+ if vcs_branch :
169+ params = dict (vcsBranch = vcs_branch ,
170+ enabled = 'true' if enabled else 'false' ,
171+ cleanupEnabled = 'true' if cleanup_enabled else 'false' )
172+ return self .put (self .resource_url (resource ), params = params )
173+
174+ """ Build results """
105175
106176 def results (self , project_key = None , plan_key = None , job_key = None , build_number = None , expand = None , favourite = False ,
107177 clover_enabled = False , issue_key = None , label = None , start_index = 0 , max_results = 25 , include_all_states = False ):
@@ -239,34 +309,33 @@ def delete_build_result(self, build_key):
239309 params = {'buildKey' : plan_key , 'buildNumber' : build_number }
240310 return self .post (custom_resource , params = params , headers = self .form_token_headers )
241311
242- def delete_plan (self , plan_key ):
312+ def execute_build (self , plan_key , stage = None , execute_all_stages = True , custom_revision = None , ** bamboo_variables ):
243313 """
244- Marks plan for deletion. Plan will be deleted by a batch job.
245- :param plan_key:
246- :return:
314+ Fire build execution for specified plan.
315+ !IMPORTANT! NOTE: for some reason, this method always execute all stages
316+ :param plan_key: str TST-BLD
317+ :param stage: str stage-name
318+ :param execute_all_stages: bool
319+ :param custom_revision: str revisionName
320+ :param bamboo_variables: dict {variable=value}
321+ :return: POST request
247322 """
248- resource = 'rest/api/latest/plan/{}' .format (plan_key )
249- return self .delete (resource )
323+ headers = self .form_token_headers
324+ resource = 'queue/{plan_key}' .format (plan_key = plan_key )
325+ params = {}
326+ if stage :
327+ execute_all_stages = False
328+ params ['stage' ] = stage
329+ if custom_revision :
330+ params ['customRevision' ] = custom_revision
331+ params ['executeAllStages' ] = 'true' if execute_all_stages else 'false'
332+ if bamboo_variables :
333+ for key , value in bamboo_variables .items ():
334+ params ['bamboo.variable.{}' .format (key )] = value
250335
251- def reports (self , max_results = 25 ):
252- params = {'max-results' : max_results }
253- return self ._get_generator (self .resource_url ('chart/reports' ), elements_key = 'reports' , element_key = 'report' ,
254- params = params )
336+ return self .post (self .resource_url (resource ), params = params , headers = headers )
255337
256- def chart (self , report_key , build_keys , group_by_period , date_filter = None , date_from = None , date_to = None ,
257- width = None , height = None , start_index = 9 , max_results = 25 ):
258- params = {'reportKey' : report_key , 'buildKeys' : build_keys , 'groupByPeriod' : group_by_period ,
259- 'start-index' : start_index , 'max-results' : max_results }
260- if date_filter :
261- params ['dateFilter' ] = date_filter
262- if date_filter == 'RANGE' :
263- params ['dateFrom' ] = date_from
264- params ['dateTo' ] = date_to
265- if width :
266- params ['width' ] = width
267- if height :
268- params ['height' ] = height
269- return self .get (self .resource_url ('chart' ), params = params )
338+ """ Comments & Labels """
270339
271340 def comments (self , project_key , plan_key , build_number , start_index = 0 , max_results = 25 ):
272341 resource = "result/{}-{}-{}/comment" .format (project_key , plan_key , build_number )
@@ -291,24 +360,17 @@ def delete_label(self, project_key, plan_key, build_number, label):
291360 resource = "result/{}-{}-{}/label/{}" .format (project_key , plan_key , build_number , label )
292361 return self .delete (self .resource_url (resource ))
293362
294- def server_info (self ):
295- return self .get (self .resource_url ('info' ))
296-
297- def agent_status (self ):
298- return self .get (self .resource_url ('agent' ))
299-
300- def activity (self ):
301- return self .get ('build/admin/ajax/getDashboardSummary.action' )
302-
303- def deployment_project (self , project_id ):
304- resource = 'deploy/project/{}' .format (project_id )
305- return self .get (self .resource_url (resource ))
363+ """ Deployments """
306364
307365 def deployment_projects (self ):
308366 resource = 'deploy/project/all'
309367 for project in self .get (self .resource_url (resource )):
310368 yield project
311369
370+ def deployment_project (self , project_id ):
371+ resource = 'deploy/project/{}' .format (project_id )
372+ return self .get (self .resource_url (resource ))
373+
312374 def deployment_environment_results (self , env_id , expand = None , max_results = 25 ):
313375 resource = 'deploy/environment/{environmentId}/results' .format (environmentId = env_id )
314376 params = {'max-result' : max_results , 'start-index' : 0 }
@@ -330,105 +392,7 @@ def deployment_dashboard(self, project_id=None):
330392 resource = 'deploy/dashboard/{}' .format (project_id ) if project_id else 'deploy/dashboard'
331393 return self .get (self .resource_url (resource ))
332394
333- def search_branches (self , plan_key , include_default_branch = True , max_results = 25 ):
334- params = {
335- 'max-result' : max_results ,
336- 'start-index' : 0 ,
337- 'masterPlanKey' : plan_key ,
338- 'includeMasterBranch' : include_default_branch
339- }
340- size = 1
341- while params ['start-index' ] < size :
342- results = self .get (self .resource_url ('search/branches' ), params = params )
343- size = results ['size' ]
344- for r in results ['searchResults' ]:
345- yield r
346- params ['start-index' ] += results ['max-result' ]
347-
348- def plan_branches (self , plan_key , expand = None , favourite = False , clover_enabled = False , max_results = 25 ):
349- """api/1.0/plan/{projectKey}-{buildKey}/branch"""
350- resource = 'plan/{}/branch' .format (plan_key )
351- return self .base_list_call (resource , expand , favourite , clover_enabled , max_results ,
352- elements_key = 'branches' , element_key = 'branch' )
353-
354- def create_branch (self , plan_key , branch_name , vcs_branch = None , enabled = False , cleanup_enabled = False ):
355- """
356- Method for creating branch for a specified plan.
357- You can use vcsBranch query param to define which vcsBranch should newly created branch use.
358- If not specified it will not override vcsBranch from the main plan.
359-
360- :param plan_key: str TST-BLD
361- :param branch_name: str new-shiny-branch
362- :param vcs_branch: str feature/new-shiny-branch, /refs/heads/new-shiny-branch
363- :param enabled: bool
364- :param cleanup_enabled: bool
365- :return: PUT request
366- """
367- resource = 'plan/{plan_key}/branch/{branch_name}' .format (plan_key = plan_key , branch_name = branch_name )
368- params = {}
369- if vcs_branch :
370- params = dict (vcsBranch = vcs_branch ,
371- enabled = 'true' if enabled else 'false' ,
372- cleanupEnabled = 'true' if cleanup_enabled else 'false' )
373- return self .put (self .resource_url (resource ), params = params )
374-
375- def get_branch_info (self , plan_key , branch_name ):
376- """
377- Get information about a plan branch
378- :param plan_key:
379- :param branch_name:
380- :return:
381- """
382- resource = 'plan/{plan_key}/branch/{branch_name}' .format (plan_key = plan_key , branch_name = branch_name )
383- return self .get (self .resource_url (resource ))
384-
385- def enable_plan (self , plan_key ):
386- """
387- Enable plan.
388- :param plan_key: str TST-BLD
389- :return: POST request
390- """
391- resource = 'plan/{plan_key}/enable' .format (plan_key = plan_key )
392- return self .post (self .resource_url (resource ))
393-
394- def execute_build (self , plan_key , stage = None , execute_all_stages = True , custom_revision = None , ** bamboo_variables ):
395- """
396- Fire build execution for specified plan.
397- !IMPORTANT! NOTE: for some reason, this method always execute all stages
398- :param plan_key: str TST-BLD
399- :param stage: str stage-name
400- :param execute_all_stages: bool
401- :param custom_revision: str revisionName
402- :param bamboo_variables: dict {variable=value}
403- :return: POST request
404- """
405- headers = self .form_token_headers
406- resource = 'queue/{plan_key}' .format (plan_key = plan_key )
407- params = {}
408- if stage :
409- execute_all_stages = False
410- params ['stage' ] = stage
411- if custom_revision :
412- params ['customRevision' ] = custom_revision
413- params ['executeAllStages' ] = 'true' if execute_all_stages else 'false'
414- if bamboo_variables :
415- for key , value in bamboo_variables .items ():
416- params ['bamboo.variable.{}' .format (key )] = value
417-
418- return self .post (self .resource_url (resource ), params = params , headers = headers )
419-
420- def health_check (self ):
421- """
422- Get health status
423- https://confluence.atlassian.com/jirakb/how-to-retrieve-health-check-results-using-rest-api-867195158.html
424- :return:
425- """
426- # check as Troubleshooting & Support Tools Plugin
427- response = self .get ('rest/troubleshooting/1.0/check/' )
428- if not response :
429- # check as support tools
430- response = self .get ('rest/supportHealthCheck/1.0/check/' )
431- return response
395+ """ Users & Groups """
432396
433397 def get_users_in_global_permissions (self , start = 0 , limit = 25 ):
434398 """
@@ -486,7 +450,7 @@ def add_users_into_group(self, group_name, users):
486450 url = 'rest/api/latest/admin/groups/{}/add-users' .format (group_name )
487451 return self .post (url , data = users )
488452
489- def remove_users_into_group (self , group_name , users ):
453+ def remove_users_from_group (self , group_name , users ):
490454 """
491455 Remove multiple users from a group.
492456 The list of usernames should be passed as request body.
@@ -540,6 +504,59 @@ def get_build_queue(self, expand='queuedBuilds'):
540504 params = {'expand' : expand }
541505 return self .get ('rest/api/latest/queue' , params = params )
542506
507+ """Other actions"""
508+
509+ def server_info (self ):
510+ return self .get (self .resource_url ('info' ))
511+
512+ def agent_status (self ):
513+ return self .get (self .resource_url ('agent' ))
514+
515+ def activity (self ):
516+ return self .get ('build/admin/ajax/getDashboardSummary.action' )
517+
518+ def get_custom_expiry (self , limit = 25 ):
519+ """
520+ Get list of all plans where user has admin permission and which override global expiry settings.
521+ If global expiry is not enabled it returns empty response.
522+ :param limit:
523+ """
524+ url = "rest/api/latest/admin/expiry/custom/plan?limit={}" .format (limit )
525+ return self .get (url )
526+
527+ def reports (self , max_results = 25 ):
528+ params = {'max-results' : max_results }
529+ return self ._get_generator (self .resource_url ('chart/reports' ), elements_key = 'reports' , element_key = 'report' ,
530+ params = params )
531+
532+ def chart (self , report_key , build_keys , group_by_period , date_filter = None , date_from = None , date_to = None ,
533+ width = None , height = None , start_index = 9 , max_results = 25 ):
534+ params = {'reportKey' : report_key , 'buildKeys' : build_keys , 'groupByPeriod' : group_by_period ,
535+ 'start-index' : start_index , 'max-results' : max_results }
536+ if date_filter :
537+ params ['dateFilter' ] = date_filter
538+ if date_filter == 'RANGE' :
539+ params ['dateFrom' ] = date_from
540+ params ['dateTo' ] = date_to
541+ if width :
542+ params ['width' ] = width
543+ if height :
544+ params ['height' ] = height
545+ return self .get (self .resource_url ('chart' ), params = params )
546+
547+ def health_check (self ):
548+ """
549+ Get health status
550+ https://confluence.atlassian.com/jirakb/how-to-retrieve-health-check-results-using-rest-api-867195158.html
551+ :return:
552+ """
553+ # check as Troubleshooting & Support Tools Plugin
554+ response = self .get ('rest/troubleshooting/1.0/check/' )
555+ if not response :
556+ # check as support tools
557+ response = self .get ('rest/supportHealthCheck/1.0/check/' )
558+ return response
559+
543560 def upload_plugin (self , plugin_path ):
544561 """
545562 Provide plugin path for upload into Jira e.g. useful for auto deploy
0 commit comments