@@ -453,6 +453,7 @@ def results(
453453 start_index = 0 ,
454454 max_results = 25 ,
455455 include_all_states = False ,
456+ build_state = None ,
456457 ):
457458 """
458459 Get results as generic method
@@ -468,6 +469,8 @@ def results(
468469 :param start_index:
469470 :param max_results:
470471 :param include_all_states:
472+ :param build_state: Optional Bamboo result state, such as
473+ ``Successful`` or ``Failed``.
471474 :return:
472475 """
473476 resource = "result"
@@ -485,6 +488,8 @@ def results(
485488 params ["issueKey" ] = issue_key
486489 if include_all_states :
487490 params ["includeAllStates" ] = include_all_states
491+ if build_state is not None :
492+ params ["buildstate" ] = build_state
488493 return self .base_list_call (
489494 resource ,
490495 expand = expand ,
@@ -581,6 +586,7 @@ def plan_results(
581586 start_index = 0 ,
582587 max_results = 25 ,
583588 include_all_states = False ,
589+ build_state = None ,
584590 ):
585591 """
586592 Get Plan results
@@ -594,6 +600,8 @@ def plan_results(
594600 :param start_index:
595601 :param max_results:
596602 :param include_all_states:
603+ :param build_state: Optional Bamboo result state, such as
604+ ``Successful`` or ``Failed``.
597605 :return:
598606 """
599607 return self .results (
@@ -607,8 +615,71 @@ def plan_results(
607615 start_index = start_index ,
608616 max_results = max_results ,
609617 include_all_states = include_all_states ,
618+ build_state = build_state ,
610619 )
611620
621+ def ordered_plan_results (
622+ self ,
623+ project_key ,
624+ plan_key ,
625+ order = "descending" ,
626+ build_state = None ,
627+ max_results = 25 ,
628+ ** kwargs ,
629+ ):
630+ """Return retrieved plan results ordered by completion time.
631+
632+ Bamboo's result API does not expose a server-side sort parameter. This
633+ helper orders the result page client-side by ``buildCompletedTime``.
634+ Set ``max_results`` high enough to include the history being compared;
635+ this method returns a list rather than the lazy generator returned by
636+ :meth:`plan_results`.
637+
638+ :param order: ``"ascending"`` for oldest first or ``"descending"``
639+ for newest first.
640+ :param build_state: Optional ``Successful`` or ``Failed`` filter.
641+ :param max_results: Number of results Bamboo should return to sort.
642+ :return: A list of build results ordered by completion time.
643+ """
644+ if order not in {"ascending" , "descending" }:
645+ raise ValueError ("order must be 'ascending' or 'descending'" )
646+
647+ results = self .plan_results (
648+ project_key ,
649+ plan_key ,
650+ build_state = build_state ,
651+ max_results = max_results ,
652+ ** kwargs ,
653+ )
654+ return sorted (
655+ results ,
656+ key = lambda result : result .get ("buildCompletedTime" ) or "" ,
657+ reverse = order == "descending" ,
658+ )
659+
660+ def latest_successful_plan_result (self , project_key , plan_key , max_results = 25 , ** kwargs ):
661+ """Return the newest successful plan result, or ``None`` when absent."""
662+ results = self .ordered_plan_results (
663+ project_key ,
664+ plan_key ,
665+ build_state = "Successful" ,
666+ max_results = max_results ,
667+ ** kwargs ,
668+ )
669+ return results [0 ] if results else None
670+
671+ def oldest_failed_plan_result (self , project_key , plan_key , max_results = 25 , ** kwargs ):
672+ """Return the oldest failed plan result, or ``None`` when absent."""
673+ results = self .ordered_plan_results (
674+ project_key ,
675+ plan_key ,
676+ order = "ascending" ,
677+ build_state = "Failed" ,
678+ max_results = max_results ,
679+ ** kwargs ,
680+ )
681+ return results [0 ] if results else None
682+
612683 def build_result (
613684 self ,
614685 build_key ,
0 commit comments