github.com/pulumi/terraform@v1.4.0/pkg/cloud/backend_taskStage_taskResults.go (about) 1 package cloud 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/hashicorp/go-tfe" 8 ) 9 10 type taskResultSummary struct { 11 unreachable bool 12 pending int 13 failed int 14 failedMandatory int 15 passed int 16 } 17 18 type taskResultSummarizer struct { 19 finished bool 20 cloud *Cloud 21 counter int 22 } 23 24 func newTaskResultSummarizer(b *Cloud, ts *tfe.TaskStage) taskStageSummarizer { 25 if len(ts.TaskResults) == 0 { 26 return nil 27 } 28 return &taskResultSummarizer{ 29 finished: false, 30 cloud: b, 31 } 32 } 33 34 func (trs *taskResultSummarizer) Summarize(context *IntegrationContext, output IntegrationOutputWriter, ts *tfe.TaskStage) (bool, *string, error) { 35 if trs.finished { 36 return false, nil, nil 37 } 38 trs.counter++ 39 40 counts := summarizeTaskResults(ts.TaskResults) 41 42 if counts.pending != 0 { 43 pendingMessage := "%d tasks still pending, %d passed, %d failed ... " 44 message := fmt.Sprintf(pendingMessage, counts.pending, counts.passed, counts.failed) 45 return true, &message, nil 46 } 47 if counts.unreachable { 48 output.Output("Skipping task results.") 49 output.End() 50 return false, nil, nil 51 } 52 53 // Print out the summary 54 trs.runTasksWithTaskResults(output, ts.TaskResults, counts) 55 56 // Mark as finished 57 trs.finished = true 58 59 return false, nil, nil 60 } 61 62 func summarizeTaskResults(taskResults []*tfe.TaskResult) *taskResultSummary { 63 var pendingCount, errCount, errMandatoryCount, passedCount int 64 for _, task := range taskResults { 65 if task.Status == tfe.TaskUnreachable { 66 return &taskResultSummary{ 67 unreachable: true, 68 } 69 } else if task.Status == tfe.TaskRunning || task.Status == tfe.TaskPending { 70 pendingCount++ 71 } else if task.Status == tfe.TaskPassed { 72 passedCount++ 73 } else { 74 // Everything else is a failure 75 errCount++ 76 if task.WorkspaceTaskEnforcementLevel == tfe.Mandatory { 77 errMandatoryCount++ 78 } 79 } 80 } 81 82 return &taskResultSummary{ 83 unreachable: false, 84 pending: pendingCount, 85 failed: errCount, 86 failedMandatory: errMandatoryCount, 87 passed: passedCount, 88 } 89 } 90 91 func (trs *taskResultSummarizer) runTasksWithTaskResults(output IntegrationOutputWriter, taskResults []*tfe.TaskResult, count *taskResultSummary) { 92 // Track the first task name that is a mandatory enforcement level breach. 93 var firstMandatoryTaskFailed *string = nil 94 95 if trs.counter == 0 { 96 output.Output(fmt.Sprintf("All tasks completed! %d passed, %d failed", count.passed, count.failed)) 97 } else { 98 output.OutputElapsed(fmt.Sprintf("All tasks completed! %d passed, %d failed", count.passed, count.failed), 50) 99 } 100 101 output.Output("") 102 103 for _, t := range taskResults { 104 capitalizedStatus := string(t.Status) 105 capitalizedStatus = strings.ToUpper(capitalizedStatus[:1]) + capitalizedStatus[1:] 106 107 status := "[green]" + capitalizedStatus 108 if t.Status != "passed" { 109 level := string(t.WorkspaceTaskEnforcementLevel) 110 level = strings.ToUpper(level[:1]) + level[1:] 111 status = fmt.Sprintf("[red]%s (%s)", capitalizedStatus, level) 112 113 if t.WorkspaceTaskEnforcementLevel == "mandatory" && firstMandatoryTaskFailed == nil { 114 firstMandatoryTaskFailed = &t.TaskName 115 } 116 } 117 118 title := fmt.Sprintf(`%s ⸺ %s`, t.TaskName, status) 119 output.SubOutput(title) 120 121 if len(t.Message) > 0 { 122 output.SubOutput(fmt.Sprintf("[dim]%s", t.Message)) 123 } 124 if len(t.URL) > 0 { 125 output.SubOutput(fmt.Sprintf("[dim]Details: %s", t.URL)) 126 } 127 output.SubOutput("") 128 } 129 130 // If a mandatory enforcement level is breached, return an error. 131 var overall string = "[green]Passed" 132 if firstMandatoryTaskFailed != nil { 133 overall = "[red]Failed" 134 if count.failedMandatory > 1 { 135 output.Output(fmt.Sprintf("[reset][bold][red]Error:[reset][bold]the run failed because %d mandatory tasks are required to succeed", count.failedMandatory)) 136 } else { 137 output.Output(fmt.Sprintf("[reset][bold][red]Error: [reset][bold]the run failed because the run task, %s, is required to succeed", *firstMandatoryTaskFailed)) 138 } 139 } else if count.failed > 0 { // we have failures but none of them mandatory 140 overall = "[green]Passed with advisory failures" 141 } 142 143 output.SubOutput("") 144 output.SubOutput("[bold]Overall Result: " + overall) 145 146 output.End() 147 }