github.com/diggerhq/digger/libs@v0.0.0-20240604170430-9d61cdf01cc5/comment_utils/reporting/source_grouping.go (about)

     1  package reporting
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"github.com/diggerhq/digger/libs/comment_utils/utils"
     7  	"github.com/diggerhq/digger/libs/digger_config"
     8  	"github.com/diggerhq/digger/libs/orchestrator"
     9  	"github.com/diggerhq/digger/libs/orchestrator/scheduler"
    10  	"github.com/diggerhq/digger/libs/terraform_utils"
    11  	"github.com/samber/lo"
    12  	"log"
    13  	"strconv"
    14  )
    15  
    16  type ProjectNameSourceDetail struct {
    17  	ProjectName   string
    18  	Source        string
    19  	Job           scheduler.SerializedJob
    20  	JobSpec       orchestrator.JobJson
    21  	PlanFootPrint terraform_utils.TerraformPlanFootprint
    22  }
    23  
    24  type SourceGroupingReporter struct {
    25  	Jobs      []scheduler.SerializedJob
    26  	PrNumber  int
    27  	PrService orchestrator.PullRequestService
    28  }
    29  
    30  func (r SourceGroupingReporter) UpdateComment(sourceDetails []SourceDetails, location string, terraformOutputs map[string]string) error {
    31  
    32  	sourceDetaiItem, found := lo.Find(sourceDetails, func(item SourceDetails) bool {
    33  		return item.SourceLocation == location
    34  	})
    35  
    36  	if !found {
    37  		log.Printf("location not found in sourcedetails list")
    38  		return fmt.Errorf("location not found in sourcedetails list")
    39  	}
    40  
    41  	projectNameToJobMap, err := scheduler.JobsToProjectMap(r.Jobs)
    42  	if err != nil {
    43  		return fmt.Errorf("could not convert jobs to map: %v", err)
    44  	}
    45  
    46  	projectNameToFootPrintMap := make(map[string]terraform_utils.TerraformPlanFootprint)
    47  	for _, job := range r.Jobs {
    48  		var footprint terraform_utils.TerraformPlanFootprint
    49  		if job.PlanFootprint != nil {
    50  			err := json.Unmarshal(job.PlanFootprint, &footprint)
    51  			if err != nil {
    52  				log.Printf("could not unmarshal footprint: %v", err)
    53  				return fmt.Errorf("could not unmarshal footprint: %v", err)
    54  			}
    55  		} else {
    56  			footprint = terraform_utils.TerraformPlanFootprint{}
    57  		}
    58  		projectNameToFootPrintMap[job.ProjectName] = footprint
    59  	}
    60  
    61  	footprints := lo.FilterMap(sourceDetaiItem.Projects, func(project string, i int) (terraform_utils.TerraformPlanFootprint, bool) {
    62  		if projectNameToJobMap[project].Status == scheduler.DiggerJobSucceeded {
    63  			return projectNameToFootPrintMap[project], true
    64  		}
    65  		return terraform_utils.TerraformPlanFootprint{}, false
    66  	})
    67  	allSimilarInGroup, err := terraform_utils.SimilarityCheck(footprints)
    68  	if err != nil {
    69  		return fmt.Errorf("error performing similar check: %v", err)
    70  	}
    71  
    72  	message := ""
    73  	message = message + fmt.Sprintf("# Group: %v (similar: %v)\n", location, allSimilarInGroup)
    74  	for i, project := range sourceDetaiItem.Projects {
    75  		job := projectNameToJobMap[project]
    76  		if job.Status != scheduler.DiggerJobSucceeded {
    77  			continue
    78  		}
    79  		expanded := i == 0 || !allSimilarInGroup
    80  		commenter := utils.GetTerraformOutputAsCollapsibleComment(fmt.Sprintf("Plan for %v", project), expanded)
    81  		message = message + commenter(terraformOutputs[project]) + "\n"
    82  	}
    83  
    84  	CommentId, err := strconv.ParseInt(sourceDetaiItem.CommentId, 10, 64)
    85  	if err != nil {
    86  		log.Printf("Could not convert commentId to int64: %v", err)
    87  		return fmt.Errorf("could not convert commentId to int64: %v", err)
    88  	}
    89  	r.PrService.EditComment(r.PrNumber, CommentId, message)
    90  	return nil
    91  }
    92  
    93  // returns a map inverting locations
    94  func ImpactedSourcesMapToGroupMapping(impactedSources map[string]digger_config.ProjectToSourceMapping, jobMapping map[string]scheduler.SerializedJob, jobSpecMapping map[string]orchestrator.JobJson, footprintsMap map[string]terraform_utils.TerraformPlanFootprint) map[string][]ProjectNameSourceDetail {
    95  
    96  	projectNameSourceList := make([]ProjectNameSourceDetail, 0)
    97  	for projectName, locations := range impactedSources {
    98  		for _, location := range locations.ImpactingLocations {
    99  			projectNameSourceList = append(projectNameSourceList, ProjectNameSourceDetail{
   100  				projectName,
   101  				location,
   102  				jobMapping[projectName],
   103  				jobSpecMapping[projectName],
   104  				footprintsMap[projectName],
   105  			})
   106  		}
   107  	}
   108  	res := lo.GroupBy(projectNameSourceList, func(t ProjectNameSourceDetail) string {
   109  		return t.Source
   110  	})
   111  	return res
   112  }