Skip to content

Commit 0f1f928

Browse files
authored
Merge pull request #1507 from diggerhq/feat/render-source-grouping
Update comments in group by source render mode
2 parents 6a1340b + df75384 commit 0f1f928

File tree

11 files changed

+118
-58
lines changed

11 files changed

+118
-58
lines changed

backend/controllers/github.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"fmt"
88
"github.com/diggerhq/digger/backend/segment"
99
"github.com/diggerhq/digger/backend/services"
10-
comment_updater "github.com/diggerhq/digger/libs/comment_utils/summary"
10+
comment_updater "github.com/diggerhq/digger/libs/comment_utils/reporting"
1111
orchestrator_scheduler "github.com/diggerhq/digger/libs/orchestrator/scheduler"
1212
"github.com/google/uuid"
1313
"log"

backend/controllers/projects.go

+50-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/diggerhq/digger/backend/models"
99
"github.com/diggerhq/digger/backend/services"
1010
"github.com/diggerhq/digger/backend/utils"
11+
"github.com/diggerhq/digger/libs/comment_utils/reporting"
1112
"github.com/diggerhq/digger/libs/digger_config"
1213
"github.com/diggerhq/digger/libs/orchestrator"
1314
orchestrator_scheduler "github.com/diggerhq/digger/libs/orchestrator/scheduler"
@@ -490,7 +491,8 @@ func SetJobStatusForProject(c *gin.Context) {
490491

491492
}
492493

493-
log.Printf("!!!Batch to json struct: %v", res)
494+
UpdateCommentsForBatchGroup(&utils.DiggerGithubRealClientProvider{}, batch, res.Jobs)
495+
494496
c.JSON(http.StatusOK, res)
495497
}
496498

@@ -570,6 +572,53 @@ func CreateRunForProject(c *gin.Context) {
570572
c.JSON(http.StatusOK, run.MapToJsonStruct())
571573
}
572574

575+
func UpdateCommentsForBatchGroup(gh utils.GithubClientProvider, batch *models.DiggerBatch, serializedJobs []orchestrator_scheduler.SerializedJob) error {
576+
diggerYmlString := batch.DiggerConfig
577+
diggerConfigYml, err := digger_config.LoadDiggerConfigYamlFromString(diggerYmlString)
578+
if err != nil {
579+
log.Printf("Error loading digger config from batch: %v", err)
580+
return fmt.Errorf("error loading digger config from batch: %v", err)
581+
}
582+
583+
if diggerConfigYml.CommentRenderMode != nil &&
584+
*diggerConfigYml.CommentRenderMode != digger_config.CommentRenderModeGroupByModule {
585+
log.Printf("render mode is not group_by_module, skipping")
586+
return nil
587+
}
588+
589+
ghService, _, err := utils.GetGithubService(
590+
gh,
591+
batch.GithubInstallationId,
592+
batch.RepoFullName,
593+
batch.RepoOwner,
594+
batch.RepoName,
595+
)
596+
597+
var sourceDetails []reporting.SourceDetails
598+
err = json.Unmarshal(batch.SourceDetails, &sourceDetails)
599+
if err != nil {
600+
log.Printf("failed to unmarshall sourceDetails: %v", err)
601+
return fmt.Errorf("failed to unmarshall sourceDetails: %v", err)
602+
}
603+
604+
// project_name => terraform output
605+
projectToTerraformOutput := make(map[string]string)
606+
// TODO: add projectName as a field of Job
607+
for _, serialJob := range serializedJobs {
608+
job, err := models.DB.GetDiggerJob(serialJob.DiggerJobId)
609+
if err != nil {
610+
return fmt.Errorf("Could not get digger job: %v", err)
611+
}
612+
projectToTerraformOutput[serialJob.ProjectName] = job.TerraformOutput
613+
}
614+
615+
for _, detail := range sourceDetails {
616+
reporter := reporting.SourceGroupingReporter{serializedJobs, batch.PrNumber, ghService}
617+
reporter.UpdateComment(sourceDetails, detail.SourceLocation, projectToTerraformOutput)
618+
}
619+
return nil
620+
}
621+
573622
func AutomergePRforBatchIfEnabled(gh utils.GithubClientProvider, batch *models.DiggerBatch) error {
574623
diggerYmlString := batch.DiggerConfig
575624
diggerConfigYml, err := digger_config.LoadDiggerConfigYamlFromString(diggerYmlString)

backend/models/scheduler.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ type GithubDiggerJobLink struct {
8585
Status DiggerJobLinkStatus
8686
}
8787

88-
func (j *DiggerJob) MapToJsonStruct() (interface{}, error) {
88+
func (j *DiggerJob) MapToJsonStruct() (orchestrator_scheduler.SerializedJob, error) {
8989
var job orchestrator.JobJson
9090
err := json.Unmarshal(j.SerializedJobSpec, &job)
9191
if err != nil {
@@ -104,7 +104,7 @@ func (j *DiggerJob) MapToJsonStruct() (interface{}, error) {
104104
ResourcesDeleted: j.DiggerJobSummary.ResourcesDeleted,
105105
}, nil
106106
}
107-
func (b *DiggerBatch) MapToJsonStruct() (interface{}, error) {
107+
func (b *DiggerBatch) MapToJsonStruct() (orchestrator_scheduler.SerializedBatch, error) {
108108
res := orchestrator_scheduler.SerializedBatch{
109109
ID: b.ID.String(),
110110
PrNumber: b.PrNumber,
@@ -119,14 +119,14 @@ func (b *DiggerBatch) MapToJsonStruct() (interface{}, error) {
119119
serializedJobs := make([]orchestrator_scheduler.SerializedJob, 0)
120120
jobs, err := DB.GetDiggerJobsForBatch(b.ID)
121121
if err != nil {
122-
return nil, fmt.Errorf("could not unmarshall digger batch: %v", err)
122+
return res, fmt.Errorf("could not unmarshall digger batch: %v", err)
123123
}
124124
for _, job := range jobs {
125125
jobJson, err := job.MapToJsonStruct()
126126
if err != nil {
127-
return nil, fmt.Errorf("error mapping job to struct (ID: %v); %v", job.ID, err)
127+
return res, fmt.Errorf("error mapping job to struct (ID: %v); %v", job.ID, err)
128128
}
129-
serializedJobs = append(serializedJobs, jobJson.(orchestrator_scheduler.SerializedJob))
129+
serializedJobs = append(serializedJobs, jobJson)
130130
}
131131
res.Jobs = serializedJobs
132132
return res, nil

cli/pkg/core/execution/execution.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package execution
22

33
import (
44
"fmt"
5+
"github.com/diggerhq/digger/libs/comment_utils/utils"
56
"github.com/diggerhq/digger/libs/terraform_utils"
67
"github.com/samber/lo"
78
"log"
@@ -15,7 +16,6 @@ import (
1516
"github.com/diggerhq/digger/cli/pkg/core/runners"
1617
"github.com/diggerhq/digger/cli/pkg/core/storage"
1718
"github.com/diggerhq/digger/cli/pkg/core/terraform"
18-
"github.com/diggerhq/digger/cli/pkg/core/utils"
1919
"github.com/diggerhq/digger/libs/comment_utils/reporting"
2020
configuration "github.com/diggerhq/digger/libs/digger_config"
2121
"github.com/diggerhq/digger/libs/orchestrator"

cli/pkg/digger/digger.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package digger
33
import (
44
"errors"
55
"fmt"
6+
coreutils "github.com/diggerhq/digger/libs/comment_utils/utils"
67
"log"
78
"os"
89
"path"
@@ -19,7 +20,6 @@ import (
1920
"github.com/diggerhq/digger/cli/pkg/core/runners"
2021
"github.com/diggerhq/digger/cli/pkg/core/storage"
2122
"github.com/diggerhq/digger/cli/pkg/core/terraform"
22-
coreutils "github.com/diggerhq/digger/cli/pkg/core/utils"
2323
"github.com/diggerhq/digger/cli/pkg/locking"
2424
"github.com/diggerhq/digger/cli/pkg/usage"
2525
utils "github.com/diggerhq/digger/cli/pkg/utils"

cli/pkg/digger/digger_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ func TestCorrectCommandExecutionWhenApplying(t *testing.T) {
281281

282282
commandStrings := allCommandsInOrderWithParams(terraformExecutor, commandRunner, prManager, lock, planStorage, planPathProvider)
283283

284-
assert.Equal(t, []string{"RetrievePlan plan", "Init ", "Apply -lock-timeout=3m", "PublishComment 1 <details open=\"false\"><summary>Apply output</summary>\n\n```terraform\n\n```\n</details>", "Run echo"}, commandStrings)
284+
assert.Equal(t, []string{"RetrievePlan plan", "Init ", "Apply -lock-timeout=3m", "PublishComment 1 <details ><summary>Apply output</summary>\n\n```terraform\n\n```\n</details>", "Run echo"}, commandStrings)
285285
}
286286

287287
func TestCorrectCommandExecutionWhenDestroying(t *testing.T) {

cli/pkg/locking/locking.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"errors"
66
"fmt"
7+
"github.com/diggerhq/digger/libs/comment_utils/utils"
78
"log"
89
"os"
910
"strconv"
@@ -13,7 +14,6 @@ import (
1314
"github.com/diggerhq/digger/cli/pkg/aws/envprovider"
1415
"github.com/diggerhq/digger/cli/pkg/azure"
1516
"github.com/diggerhq/digger/cli/pkg/core/locking"
16-
"github.com/diggerhq/digger/cli/pkg/core/utils"
1717
"github.com/diggerhq/digger/cli/pkg/gcp"
1818
"github.com/diggerhq/digger/libs/comment_utils/reporting"
1919
"github.com/diggerhq/digger/libs/orchestrator"

libs/comment_utils/reporting/reporting.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package reporting
22

33
import (
44
"fmt"
5-
"github.com/diggerhq/digger/cli/pkg/core/utils"
5+
"github.com/diggerhq/digger/libs/comment_utils/utils"
66
"github.com/diggerhq/digger/libs/orchestrator"
77
"log"
88
"strings"

libs/comment_utils/reporting/source_grouping.go

+46-40
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ package reporting
33
import (
44
"encoding/json"
55
"fmt"
6+
"github.com/diggerhq/digger/libs/comment_utils/utils"
67
"github.com/diggerhq/digger/libs/digger_config"
78
"github.com/diggerhq/digger/libs/orchestrator"
89
"github.com/diggerhq/digger/libs/orchestrator/scheduler"
910
"github.com/diggerhq/digger/libs/terraform_utils"
1011
"github.com/samber/lo"
1112
"log"
13+
"strconv"
1214
)
1315

1416
type ProjectNameSourceDetail struct {
@@ -25,24 +27,29 @@ type SourceGroupingReporter struct {
2527
PrService orchestrator.PullRequestService
2628
}
2729

28-
func (r SourceGroupingReporter) Report(report string, reportFormatting func(report string) string) (string, string, error) {
30+
func (r SourceGroupingReporter) UpdateComment(sourceDetails []SourceDetails, location string, terraformOutputs map[string]string) error {
2931
jobSpecs, err := scheduler.GetJobSpecs(r.Jobs)
3032
if err != nil {
31-
return "", "", fmt.Errorf("could not get job specs: %v", err)
33+
return fmt.Errorf("could not get job specs: %v", err)
3234
}
3335

34-
//impactedSources := jobSpecs[0].ImpactedSources
35-
// TODO: populate from batch field
36-
var impactedSources map[string]digger_config.ProjectToSourceMapping
36+
sourceDetaiItem, found := lo.Find(sourceDetails, func(item SourceDetails) bool {
37+
return item.SourceLocation == location
38+
})
39+
40+
if !found {
41+
log.Printf("location not found in sourcedetails list")
42+
return fmt.Errorf("location not found in sourcedetails list")
43+
}
3744

3845
projectNameToJobMap, err := scheduler.JobsToProjectMap(r.Jobs)
3946
if err != nil {
40-
return "", "", fmt.Errorf("could not convert jobs to map: %v", err)
47+
return fmt.Errorf("could not convert jobs to map: %v", err)
4148
}
4249

4350
projectNameToJobSpecMap, err := orchestrator.JobsSpecsToProjectMap(jobSpecs)
4451
if err != nil {
45-
return "", "", fmt.Errorf("could not convert jobs to map: %v", err)
52+
return fmt.Errorf("could not convert jobs to map: %v", err)
4653
}
4754

4855
projectNameToFootPrintMap := make(map[string]terraform_utils.TerraformPlanFootprint)
@@ -52,51 +59,50 @@ func (r SourceGroupingReporter) Report(report string, reportFormatting func(repo
5259
err := json.Unmarshal(job.PlanFootprint, &footprint)
5360
if err != nil {
5461
log.Printf("could not unmarshal footprint: %v", err)
55-
return "", "", fmt.Errorf("could not unmarshal footprint: %v", err)
62+
return fmt.Errorf("could not unmarshal footprint: %v", err)
5663
}
5764
} else {
5865
footprint = terraform_utils.TerraformPlanFootprint{}
5966
}
6067
projectNameToFootPrintMap[job.ProjectName] = footprint
6168
}
6269

63-
groupsToProjectMap := ImpactedSourcesMapToGroupMapping(impactedSources, projectNameToJobMap, projectNameToJobSpecMap, projectNameToFootPrintMap)
64-
65-
message := ":construction_worker: Jobs status:\n\n"
66-
for sourceLocation, projectSourceDetailList := range groupsToProjectMap {
67-
footprints := lo.Map(projectSourceDetailList, func(detail ProjectNameSourceDetail, i int) terraform_utils.TerraformPlanFootprint {
68-
return detail.PlanFootPrint
69-
})
70-
allSimilarInGroup, err := terraform_utils.SimilarityCheck(footprints)
71-
if err != nil {
72-
return "", "", fmt.Errorf("error performing similar check: %v", err)
70+
footprints := lo.FilterMap(sourceDetaiItem.Projects, func(project string, i int) (terraform_utils.TerraformPlanFootprint, bool) {
71+
if projectNameToJobMap[project].Status == scheduler.DiggerJobSucceeded {
72+
return projectNameToFootPrintMap[project], true
7373
}
74+
return terraform_utils.TerraformPlanFootprint{}, false
75+
})
76+
allSimilarInGroup, err := terraform_utils.SimilarityCheck(footprints)
77+
if err != nil {
78+
return fmt.Errorf("error performing similar check: %v", err)
79+
}
7480

75-
message = message + fmt.Sprintf("# Group: %v (similar: %v)", sourceLocation, allSimilarInGroup)
76-
for _, projectSourceDetail := range projectSourceDetailList {
77-
job := projectSourceDetail.Job
78-
jobSpec := projectSourceDetail.JobSpec
79-
isPlan := jobSpec.IsPlan()
80-
message = message + fmt.Sprintf("<!-- PROJECTHOLDER %v -->\n", job.ProjectName)
81-
message = message + fmt.Sprintf("%v **%v** <a href='%v'>%v</a>%v\n", job.Status.ToEmoji(), job.ProjectName, *job.WorkflowRunUrl, job.Status.ToString(), job.ResourcesSummaryString(isPlan))
82-
message = message + fmt.Sprintf("<!-- PROJECTHOLDEREND %v -->\n", job.ProjectName)
81+
message := ""
82+
message = message + fmt.Sprintf("# Group: %v (similar: %v)\n", location, allSimilarInGroup)
83+
for i, project := range sourceDetaiItem.Projects {
84+
job := projectNameToJobMap[project]
85+
if job.Status != scheduler.DiggerJobSucceeded {
86+
continue
8387
}
84-
88+
jobSpec := projectNameToJobSpecMap[project]
89+
isPlan := jobSpec.JobType == orchestrator.DiggerCommandPlan
90+
expanded := i == 0 || !allSimilarInGroup
91+
var commenter func(terraformOutput string) string
92+
if isPlan {
93+
commenter = utils.GetTerraformOutputAsCollapsibleComment(fmt.Sprintf("Plan for %v", project), expanded)
94+
} else {
95+
commenter = utils.GetTerraformOutputAsCollapsibleComment(fmt.Sprintf("Apply for %v", project), false)
96+
}
97+
message = message + commenter(terraformOutputs[project]) + "\n"
8598
}
8699

87-
r.PrService.PublishComment(r.PrNumber, message)
88-
return "", "", nil
89-
}
90-
91-
func (reporter SourceGroupingReporter) Flush() (string, string, error) {
92-
return "", "", nil
93-
}
94-
95-
func (reporter SourceGroupingReporter) SupportsMarkdown() bool {
96-
return false
97-
}
98-
99-
func (reporter SourceGroupingReporter) Suppress() error {
100+
CommentId, err := strconv.ParseInt(sourceDetaiItem.CommentId, 10, 64)
101+
if err != nil {
102+
log.Printf("Could not convert commentId to int64: %v", err)
103+
return fmt.Errorf("could not convert commentId to int64: %v", err)
104+
}
105+
r.PrService.EditComment(r.PrNumber, CommentId, message)
100106
return nil
101107
}
102108

libs/comment_utils/summary/utils.go libs/comment_utils/reporting/utils.go

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
package comment_updater
1+
package reporting
22

33
import (
44
"fmt"
5-
"github.com/diggerhq/digger/libs/comment_utils/reporting"
65
dg_configuration "github.com/diggerhq/digger/libs/digger_config"
76
dg_github "github.com/diggerhq/digger/libs/orchestrator/github"
87
"log"
@@ -26,10 +25,10 @@ func PostInitialSourceComments(ghService *dg_github.GithubService, prNumber int,
2625
}
2726
}
2827
for location, projects := range locations {
29-
reporter := reporting.CiReporter{
28+
reporter := CiReporter{
3029
PrNumber: prNumber,
3130
CiService: ghService,
32-
ReportStrategy: reporting.CommentPerRunStrategy{fmt.Sprintf("Report for location: %v", location), time.Now()},
31+
ReportStrategy: CommentPerRunStrategy{fmt.Sprintf("Report for location: %v", location), time.Now()},
3332
}
3433
commentId, _, err := reporter.Report("Comment Reporter", func(report string) string { return "" })
3534
if err != nil {

cli/pkg/core/utils/comments.go libs/comment_utils/utils/comments.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,20 @@ package utils
33
import "fmt"
44

55
func GetTerraformOutputAsCollapsibleComment(summary string, open bool) func(string) string {
6+
var openTag string
7+
if open {
8+
openTag = "open=\"true\""
9+
} else {
10+
openTag = ""
11+
}
612

713
return func(comment string) string {
8-
return fmt.Sprintf(`<details open="%v"><summary>`+summary+`</summary>
14+
return fmt.Sprintf(`<details %v><summary>`+summary+`</summary>
915
1016
`+"```terraform"+`
1117
`+comment+`
1218
`+"```"+`
13-
</details>`, open)
19+
</details>`, openTag)
1420
}
1521
}
1622

0 commit comments

Comments
 (0)