github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/pkg/cmd/pr/checks/aggregate.go (about)

     1  package checks
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"time"
     7  
     8  	"github.com/ungtb10d/cli/v2/api"
     9  )
    10  
    11  type check struct {
    12  	Name        string    `json:"name"`
    13  	State       string    `json:"state"`
    14  	StartedAt   time.Time `json:"startedAt"`
    15  	CompletedAt time.Time `json:"completedAt"`
    16  	Link        string    `json:"link"`
    17  	Bucket      string    `json:"bucket"`
    18  }
    19  
    20  type checkCounts struct {
    21  	Failed   int
    22  	Passed   int
    23  	Pending  int
    24  	Skipping int
    25  }
    26  
    27  func aggregateChecks(checkContexts []api.CheckContext, requiredChecks bool) (checks []check, counts checkCounts) {
    28  	for _, c := range eliminateDuplicates(checkContexts) {
    29  		if requiredChecks && !c.IsRequired {
    30  			continue
    31  		}
    32  
    33  		state := c.State
    34  		if state == "" {
    35  			if c.Status == "COMPLETED" {
    36  				state = c.Conclusion
    37  			} else {
    38  				state = c.Status
    39  			}
    40  		}
    41  
    42  		link := c.DetailsURL
    43  		if link == "" {
    44  			link = c.TargetURL
    45  		}
    46  
    47  		name := c.Name
    48  		if name == "" {
    49  			name = c.Context
    50  		}
    51  
    52  		item := check{
    53  			Name:        name,
    54  			State:       state,
    55  			StartedAt:   c.StartedAt,
    56  			CompletedAt: c.CompletedAt,
    57  			Link:        link,
    58  		}
    59  		switch state {
    60  		case "SUCCESS":
    61  			item.Bucket = "pass"
    62  			counts.Passed++
    63  		case "SKIPPED", "NEUTRAL":
    64  			item.Bucket = "skipping"
    65  			counts.Skipping++
    66  		case "ERROR", "FAILURE", "CANCELLED", "TIMED_OUT", "ACTION_REQUIRED":
    67  			item.Bucket = "fail"
    68  			counts.Failed++
    69  		default: // "EXPECTED", "REQUESTED", "WAITING", "QUEUED", "PENDING", "IN_PROGRESS", "STALE"
    70  			item.Bucket = "pending"
    71  			counts.Pending++
    72  		}
    73  
    74  		checks = append(checks, item)
    75  	}
    76  	return
    77  }
    78  
    79  // eliminateDuplicates filters a set of checks to only the most recent ones if the set includes repeated runs
    80  func eliminateDuplicates(checkContexts []api.CheckContext) []api.CheckContext {
    81  	sort.Slice(checkContexts, func(i, j int) bool { return checkContexts[i].StartedAt.After(checkContexts[j].StartedAt) })
    82  
    83  	mapChecks := make(map[string]struct{})
    84  	mapContexts := make(map[string]struct{})
    85  	unique := make([]api.CheckContext, 0, len(checkContexts))
    86  
    87  	for _, ctx := range checkContexts {
    88  		if ctx.Context != "" {
    89  			if _, exists := mapContexts[ctx.Context]; exists {
    90  				continue
    91  			}
    92  			mapContexts[ctx.Context] = struct{}{}
    93  		} else {
    94  			key := fmt.Sprintf("%s/%s", ctx.Name, ctx.CheckSuite.WorkflowRun.Workflow.Name)
    95  			if _, exists := mapChecks[key]; exists {
    96  				continue
    97  			}
    98  			mapChecks[key] = struct{}{}
    99  		}
   100  		unique = append(unique, ctx)
   101  	}
   102  
   103  	return unique
   104  }