-
Notifications
You must be signed in to change notification settings - Fork 563
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: support single comment summary with orchestrator mode #1850
base: develop
Are you sure you want to change the base?
Conversation
WalkthroughThe pull request introduces significant enhancements to Digger's reporting and commenting mechanisms across multiple components. The changes primarily focus on improving error handling, reporting strategies, and comment management. Key modifications include updating reporting interfaces, refining comment strategies, and adding new fields to track placeholder comments and report details. The changes streamline the reporting process, provide more flexibility in comment handling, and enhance error tracking across GitHub and GitLab integrations. Changes
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Outside diff range and nitpick comments (5)
libs/comment_utils/reporting/reporting.go (1)
110-114
: Use 'ID' instead of 'Id' in struct field namesIn Go, it's standard practice to use 'ID' instead of 'Id' in struct field names. Consider renaming
CommentId
toCommentID
inAlwaysSameCommentStrategy
for consistency.type AlwaysSameCommentStrategy struct { Title string - CommentId string + CommentID string TimeOfRun time.Time }backend/controllers/github.go (2)
503-508
: Fix typo in placeholder comment textThere's a typo in the placeholder comment text: "placehoder" should be "placeholder".
placeholderComment, err := ghService.PublishComment(prNumber, "<digger report placehoder>") +placeholderComment, err := ghService.PublishComment(prNumber, "<digger report placeholder>")
885-890
: Correct typo in placeholder comment textThe comment text contains a typo: "placehoder" should be "placeholder".
placeholderComment, err := ghService.PublishComment(issueNumber, "<digger report placehoder>") +placeholderComment, err := ghService.PublishComment(issueNumber, "<digger report placeholder>")
libs/spec/models.go (1)
8-11
: Use 'ID' instead of 'Id' in struct field namesIt's conventional in Go to use 'ID' instead of 'Id' for identifiers. Consider renaming
ReportCommentId
toReportCommentID
inReporterSpec
.type ReporterSpec struct { ReporterType string `json:"reporter_type"` ReportingStrategy string `json:"reporting_strategy"` ReportTerraformOutput bool `json:"report_terraform_output"` - ReportCommentId *string `json:"report_comment_id,omitempty"` + ReportCommentID *string `json:"report_comment_id,omitempty"` }backend/models/scheduler.go (1)
25-38
: Use 'ID' instead of 'Id' in struct field namesFor consistency with Go naming conventions, consider renaming
PlaceholderCommentIdForReport
toPlaceholderCommentIDForReport
inDiggerBatch
.type DiggerBatch struct { ID uuid.UUID `gorm:"primary_key"` VCS DiggerVCSType PrNumber int CommentId *int64 - PlaceholderCommentIdForReport *string + PlaceholderCommentIDForReport *string Status orchestrator_scheduler.DiggerBatchStatus BranchName string DiggerConfig string GithubInstallationId int64 GitlabProjectId int RepoFullName string RepoOwner string RepoName string BatchType orchestrator_scheduler.DiggerCommand // used for module source grouping comments SourceDetails []byte }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (10)
backend/controllers/github.go
(2 hunks)backend/models/scheduler.go
(1 hunks)backend/models/storage.go
(1 hunks)backend/services/spec.go
(1 hunks)backend/utils/graphs.go
(2 hunks)ee/backend/controllers/gitlab.go
(2 hunks)ee/backend/hooks/github.go
(1 hunks)libs/comment_utils/reporting/reporting.go
(2 hunks)libs/spec/models.go
(1 hunks)libs/spec/providers.go
(1 hunks)
🔇 Additional comments (7)
ee/backend/controllers/gitlab.go (2)
336-339
: Changes appear correct for updated function signature
The updated call to ConvertJobsToDiggerJobs
reflects the new function signature. Parameters are adjusted appropriately.
527-530
: Function call updated appropriately
The changes to ConvertJobsToDiggerJobs
parameters align with the updated function definition.
backend/services/spec.go (1)
119-122
: Verify the impact of changing the reporting strategy
The change from comments_per_run
to always_same_comment
represents a significant shift in how comments are handled. This could affect existing integrations and workflows.
Consider:
- Adding a feature flag to gradually roll out this change
- Documenting the new behavior in the codebase
- Ensuring backward compatibility for existing integrations
backend/utils/graphs.go (1)
17-17
:
Verify all callers of ConvertJobsToDiggerJobs are updated
The function signature has been modified to include placeholderCommentIdForReport *string
. This is a breaking change that requires updates to all callers.
Consider:
- Adding a version suffix to the function name (e.g.,
ConvertJobsToDiggerJobsV2
) - Providing a wrapper function with the old signature for backward compatibility
- Adding migration documentation
Also applies to: 46-46
✅ Verification successful
All callers have been properly updated with the new parameter
Based on the search results, all callers of ConvertJobsToDiggerJobs
are passing the new placeholderCommentIdForReport
parameter correctly:
- In
backend/controllers/github.go
, it's passing&placeholderComment.Id
- In
ee/backend/hooks/github.go
andee/backend/controllers/gitlab.go
, it's passingnil
- In test files, it's passing
"test"
as a placeholder - In
next/services/scheduler.go
, it's passing an empty string""
The breaking change has been properly handled across the codebase, and there's no need for versioning or backward compatibility measures.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Find all callers of ConvertJobsToDiggerJobs
echo "Checking for all callers..."
rg "ConvertJobsToDiggerJobs\(" --type go -A 3
# Look for potential missed updates
echo "Checking for potential missed updates..."
ast-grep --pattern 'ConvertJobsToDiggerJobs($$$)'
Length of output: 7767
ee/backend/hooks/github.go (1)
154-154
: 🛠️ Refactor suggestion
Clarify the intention behind passing nil for placeholderCommentIdForReport
While the code has been updated to match the new function signature, passing nil
for placeholderCommentIdForReport
needs clarification:
- Is this intentional for drift reconciliation?
- Should we fall back to a default behavior?
Consider:
- Adding a comment explaining why nil is acceptable here
- Using a default value if appropriate
- Adding error handling for the nil case in the reporting logic
✅ Verification successful
Passing nil for placeholderCommentIdForReport is correct in this context
Based on the code analysis, passing nil
for placeholderCommentIdForReport
in the drift reconciliation hook is intentional and correct:
- The parameter is properly typed as
*string
in the function signature, explicitly allowing nil values - It's used consistently across different VCS implementations (both GitHub and GitLab handlers)
- The parameter is simply passed through to
CreateDiggerBatch
for storage, with no validation requirements - This parameter is specifically for placeholder comment IDs in reporting, which isn't relevant for drift reconciliation workflows
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check for similar patterns in other handlers
echo "Checking for similar patterns in other handlers..."
rg "ConvertJobsToDiggerJobs.*nil.*diggerYmlStr" --type go
# Look for documentation or comments about this behavior
echo "Checking for related documentation..."
rg "placeholderCommentIdForReport" --type md
Length of output: 906
Script:
#!/bin/bash
# Let's check the ConvertJobsToDiggerJobs function definition and usage context
ast-grep --pattern 'func ConvertJobsToDiggerJobs($$$)'
# Check for any comments or documentation around the parameter
rg -B 2 -A 2 "placeholderCommentIdForReport" --type go
# Look for any error handling related to this parameter
rg "if.*placeholderCommentIdForReport.*nil" --type go
rg "placeholderCommentIdForReport.*==.*nil" --type go
Length of output: 12328
libs/spec/providers.go (1)
128-134
: LGTM! Clean implementation of the new reporting strategy
The new case for "always_same_comment" follows the existing pattern and integrates well with the reporting system.
backend/models/storage.go (1)
620-636
: LGTM! Clean implementation of the placeholder comment ID
The changes properly integrate the new placeholderCommentIdForReport
field into the batch creation process, maintaining consistency with the existing codebase structure.
func appendToExistingComment(ciService ci.PullRequestService, prNumber int, existingCommentBody string, reportToAppend string, reportTitle string, commentId string, supportsCollapsible bool) error { | ||
|
||
// strip first and last lines | ||
lines := strings.Split(commentBody, "\n") | ||
lines := strings.Split(existingCommentBody, "\n") | ||
lines = lines[1 : len(lines)-1] | ||
commentBody = strings.Join(lines, "\n") | ||
existingCommentBody = strings.Join(lines, "\n") | ||
|
||
commentBody = commentBody + "\n\n" + report + "\n" | ||
existingCommentBody = existingCommentBody + "\n\n" + reportToAppend + "\n" | ||
|
||
var completeComment string | ||
if !supportsCollapsible { | ||
completeComment = utils.AsComment(reportTitle)(commentBody) | ||
completeComment = utils.AsComment(reportTitle)(existingCommentBody) | ||
} else { | ||
completeComment = utils.AsCollapsibleComment(reportTitle, false)(commentBody) | ||
completeComment = utils.AsCollapsibleComment(reportTitle, false)(existingCommentBody) | ||
} | ||
|
||
err := ciService.EditComment(PrNumber, commentIdForThisRun, completeComment) | ||
err := ciService.EditComment(prNumber, commentId, completeComment) | ||
|
||
if err != nil { | ||
return "", "", fmt.Errorf("error editing comment: %v", err) | ||
return fmt.Errorf("error editing comment: %v", err) | ||
} | ||
return fmt.Sprintf("%v", commentIdForThisRun), commentUrl, nil | ||
return nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prevent slice bounds out of range in appendToExistingComment
If existingCommentBody
has fewer than two lines, slicing lines[1:len(lines)-1]
will cause a panic. Ensure that lines
has at least two elements before slicing.
// strip first and last lines
lines := strings.Split(existingCommentBody, "\n")
+ if len(lines) >= 2 {
lines = lines[1 : len(lines)-1]
+ } else {
+ lines = []string{}
+ }
existingCommentBody = strings.Join(lines, "\n")
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func appendToExistingComment(ciService ci.PullRequestService, prNumber int, existingCommentBody string, reportToAppend string, reportTitle string, commentId string, supportsCollapsible bool) error { | |
// strip first and last lines | |
lines := strings.Split(commentBody, "\n") | |
lines := strings.Split(existingCommentBody, "\n") | |
lines = lines[1 : len(lines)-1] | |
commentBody = strings.Join(lines, "\n") | |
existingCommentBody = strings.Join(lines, "\n") | |
commentBody = commentBody + "\n\n" + report + "\n" | |
existingCommentBody = existingCommentBody + "\n\n" + reportToAppend + "\n" | |
var completeComment string | |
if !supportsCollapsible { | |
completeComment = utils.AsComment(reportTitle)(commentBody) | |
completeComment = utils.AsComment(reportTitle)(existingCommentBody) | |
} else { | |
completeComment = utils.AsCollapsibleComment(reportTitle, false)(commentBody) | |
completeComment = utils.AsCollapsibleComment(reportTitle, false)(existingCommentBody) | |
} | |
err := ciService.EditComment(PrNumber, commentIdForThisRun, completeComment) | |
err := ciService.EditComment(prNumber, commentId, completeComment) | |
if err != nil { | |
return "", "", fmt.Errorf("error editing comment: %v", err) | |
return fmt.Errorf("error editing comment: %v", err) | |
} | |
return fmt.Sprintf("%v", commentIdForThisRun), commentUrl, nil | |
return nil | |
func appendToExistingComment(ciService ci.PullRequestService, prNumber int, existingCommentBody string, reportToAppend string, reportTitle string, commentId string, supportsCollapsible bool) error { | |
// strip first and last lines | |
lines := strings.Split(existingCommentBody, "\n") | |
if len(lines) >= 2 { | |
lines = lines[1 : len(lines)-1] | |
} else { | |
lines = []string{} | |
} | |
existingCommentBody = strings.Join(lines, "\n") | |
existingCommentBody = existingCommentBody + "\n\n" + reportToAppend + "\n" | |
var completeComment string | |
if !supportsCollapsible { | |
completeComment = utils.AsComment(reportTitle)(existingCommentBody) | |
} else { | |
completeComment = utils.AsCollapsibleComment(reportTitle, false)(existingCommentBody) | |
} | |
err := ciService.EditComment(prNumber, commentId, completeComment) | |
if err != nil { | |
return fmt.Errorf("error editing comment: %v", err) | |
} | |
return nil |
func (strategy AlwaysSameCommentStrategy) Report(ciService ci.PullRequestService, PrNumber int, report string, reportFormatter func(report string) string, supportsCollapsibleComment bool) (string, string, error) { | ||
comments, err := ciService.GetComments(PrNumber) | ||
if err != nil { | ||
return "", "", fmt.Errorf("error getting comments: %v", err) | ||
} | ||
|
||
var commentBody *string | ||
var commentUrl string | ||
for _, comment := range comments { | ||
if comment.Id == strategy.CommentId { | ||
commentBody = comment.Body | ||
commentUrl = comment.Url | ||
} | ||
} | ||
|
||
var reportTitle string | ||
if strategy.Title != "" { | ||
reportTitle = strategy.Title + " " + strategy.TimeOfRun.Format("2006-01-02 15:04:05 (MST)") | ||
} else { | ||
reportTitle = "Digger run report at " + strategy.TimeOfRun.Format("2006-01-02 15:04:05 (MST)") | ||
} | ||
|
||
err = appendToExistingComment(ciService, PrNumber, *commentBody, report, reportTitle, strategy.CommentId, supportsCollapsibleComment) | ||
if err != nil { | ||
return "", "", fmt.Errorf("error while adding to existing comment: %v", err) | ||
} | ||
|
||
return strategy.CommentId, commentUrl, err | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix potential nil pointer dereference in AlwaysSameCommentStrategy.Report
method
If no comment matching strategy.CommentId
is found, commentBody
remains nil
. Dereferencing it at line 138 will cause a panic. Ensure commentBody
is not nil
before dereferencing.
for _, comment := range comments {
if comment.Id == strategy.CommentId {
commentBody = comment.Body
commentUrl = comment.Url
}
}
+ if commentBody == nil {
+ return "", "", fmt.Errorf("no comment found with CommentId: %v", strategy.CommentId)
+ }
err = appendToExistingComment(ciService, PrNumber, *commentBody, report, reportTitle, strategy.CommentId, supportsCollapsibleComment)
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func (strategy AlwaysSameCommentStrategy) Report(ciService ci.PullRequestService, PrNumber int, report string, reportFormatter func(report string) string, supportsCollapsibleComment bool) (string, string, error) { | |
comments, err := ciService.GetComments(PrNumber) | |
if err != nil { | |
return "", "", fmt.Errorf("error getting comments: %v", err) | |
} | |
var commentBody *string | |
var commentUrl string | |
for _, comment := range comments { | |
if comment.Id == strategy.CommentId { | |
commentBody = comment.Body | |
commentUrl = comment.Url | |
} | |
} | |
var reportTitle string | |
if strategy.Title != "" { | |
reportTitle = strategy.Title + " " + strategy.TimeOfRun.Format("2006-01-02 15:04:05 (MST)") | |
} else { | |
reportTitle = "Digger run report at " + strategy.TimeOfRun.Format("2006-01-02 15:04:05 (MST)") | |
} | |
err = appendToExistingComment(ciService, PrNumber, *commentBody, report, reportTitle, strategy.CommentId, supportsCollapsibleComment) | |
if err != nil { | |
return "", "", fmt.Errorf("error while adding to existing comment: %v", err) | |
} | |
return strategy.CommentId, commentUrl, err | |
} | |
func (strategy AlwaysSameCommentStrategy) Report(ciService ci.PullRequestService, PrNumber int, report string, reportFormatter func(report string) string, supportsCollapsibleComment bool) (string, string, error) { | |
comments, err := ciService.GetComments(PrNumber) | |
if err != nil { | |
return "", "", fmt.Errorf("error getting comments: %v", err) | |
} | |
var commentBody *string | |
var commentUrl string | |
for _, comment := range comments { | |
if comment.Id == strategy.CommentId { | |
commentBody = comment.Body | |
commentUrl = comment.Url | |
} | |
} | |
var reportTitle string | |
if strategy.Title != "" { | |
reportTitle = strategy.Title + " " + strategy.TimeOfRun.Format("2006-01-02 15:04:05 (MST)") | |
} else { | |
reportTitle = "Digger run report at " + strategy.TimeOfRun.Format("2006-01-02 15:04:05 (MST)") | |
} | |
if commentBody == nil { | |
return "", "", fmt.Errorf("no comment found with CommentId: %v", strategy.CommentId) | |
} | |
err = appendToExistingComment(ciService, PrNumber, *commentBody, report, reportTitle, strategy.CommentId, supportsCollapsibleComment) | |
if err != nil { | |
return "", "", fmt.Errorf("error while adding to existing comment: %v", err) | |
} | |
return strategy.CommentId, commentUrl, err | |
} |
libs/spec/providers.go
Outdated
case "always_same_comment": | ||
return reporting.AlwaysSameCommentStrategy{ | ||
Title: title, | ||
TimeOfRun: time.Now(), | ||
CommentId: *reporterSpec.ReportCommentId, | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add nil check for ReportCommentId
The code dereferences reporterSpec.ReportCommentId
without checking if it's nil, which could lead to a panic.
Add a nil check before using the pointer:
case "always_same_comment":
+ if reporterSpec.ReportCommentId == nil {
+ return reporting.MultipleCommentsStrategy{}
+ }
return reporting.AlwaysSameCommentStrategy{
Title: title,
TimeOfRun: time.Now(),
CommentId: *reporterSpec.ReportCommentId,
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
case "always_same_comment": | |
return reporting.AlwaysSameCommentStrategy{ | |
Title: title, | |
TimeOfRun: time.Now(), | |
CommentId: *reporterSpec.ReportCommentId, | |
} | |
case "always_same_comment": | |
if reporterSpec.ReportCommentId == nil { | |
return reporting.MultipleCommentsStrategy{} | |
} | |
return reporting.AlwaysSameCommentStrategy{ | |
Title: title, | |
TimeOfRun: time.Now(), | |
CommentId: *reporterSpec.ReportCommentId, | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (2)
libs/comment_utils/reporting/reporting.go (2)
131-136
: Consider extracting time format constantThe time format string "2006-01-02 15:04:05 (MST)" is hardcoded in multiple places. Consider extracting it to a package-level constant.
+const ( + TimeFormat = "2006-01-02 15:04:05 (MST)" +) + if strategy.Title != "" { - reportTitle = strategy.Title + " " + strategy.TimeOfRun.Format("2006-01-02 15:04:05 (MST)") + reportTitle = strategy.Title + " " + strategy.TimeOfRun.Format(TimeFormat) } else { - reportTitle = "Digger run report at " + strategy.TimeOfRun.Format("2006-01-02 15:04:05 (MST)") + reportTitle = "Digger run report at " + strategy.TimeOfRun.Format(TimeFormat) }
204-227
: Add function documentation and improve error handlingThe function lacks documentation and could benefit from more specific error handling.
Add documentation and improve error handling:
+// appendToExistingComment appends a new report to an existing comment while maintaining its formatting. +// It strips the comment markers, appends the new report, and re-applies the formatting. +// Parameters: +// - ciService: Service for interacting with the CI platform +// - prNumber: Pull request number +// - existingCommentBody: Current content of the comment +// - reportToAppend: New report to append +// - reportTitle: Title for the comment +// - commentId: ID of the comment to edit +// - supportsCollapsible: Whether to use collapsible comment formatting +// Returns an error if the comment update fails func appendToExistingComment(ciService ci.PullRequestService, prNumber int, existingCommentBody string, reportToAppend string, reportTitle string, commentId string, supportsCollapsible bool) error { // strip first and last lines lines := strings.Split(existingCommentBody, "\n") if len(lines) > 1 { lines = lines[1 : len(lines)-1] } existingCommentBody = strings.Join(lines, "\n") existingCommentBody = existingCommentBody + "\n\n" + reportToAppend + "\n" var completeComment string if !supportsCollapsible { completeComment = utils.AsComment(reportTitle)(existingCommentBody) } else { completeComment = utils.AsCollapsibleComment(reportTitle, false)(existingCommentBody) } err := ciService.EditComment(prNumber, commentId, completeComment) if err != nil { - return fmt.Errorf("error editing comment: %v", err) + return fmt.Errorf("failed to edit comment %s: %w", commentId, err) } return nil }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
⛔ Files ignored due to path filters (1)
backend/migrations/atlas.sum
is excluded by!**/*.sum
📒 Files selected for processing (2)
backend/migrations/20241204194016.sql
(1 hunks)libs/comment_utils/reporting/reporting.go
(2 hunks)
✅ Files skipped from review due to trivial changes (1)
- backend/migrations/20241204194016.sql
🔇 Additional comments (3)
libs/comment_utils/reporting/reporting.go (3)
110-114
: LGTM: Well-structured struct definition
The struct fields are appropriately named and typed, following Go conventions.
195-202
: LGTM: Clean error handling and consistent approach
The changes maintain good error handling practices and integrate well with the new append functionality.
116-144
:
Fix potential nil pointer dereference
The code dereferences commentBody
at line 138 without checking if it's nil. This could cause a panic if no matching comment is found.
Apply this fix:
var commentBody *string
var commentUrl string
for _, comment := range comments {
if comment.Id == strategy.CommentId {
commentBody = comment.Body
commentUrl = comment.Url
}
}
+
+ if commentBody == nil {
+ return "", "", fmt.Errorf("no comment found with ID %s", strategy.CommentId)
+ }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (1)
backend/controllers/github.go (1)
503-503
: Fix typo in placeholder comment messageThe word "placeholder" is misspelled as "placehoder" in both locations.
Apply this fix:
- placeholderComment, err := ghService.PublishComment(prNumber, "digger report placehoder") + placeholderComment, err := ghService.PublishComment(prNumber, "digger report placeholder")Also applies to: 886-886
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
backend/controllers/github.go
(2 hunks)libs/comment_utils/reporting/reporting.go
(2 hunks)
🔇 Additional comments (3)
libs/comment_utils/reporting/reporting.go (2)
110-114
: LGTM: Clear and well-structured struct definition
The struct fields are appropriately named and have clear purposes for managing comment updates.
116-144
:
Fix potential nil pointer dereference in Report method
The code dereferences commentBody
at line 138 without checking if it's nil, which could happen if no comment with the matching ID is found.
Apply this fix:
var commentBody *string
var commentUrl string
for _, comment := range comments {
if comment.Id == strategy.CommentId {
commentBody = comment.Body
commentUrl = comment.Url
}
}
+
+ if commentBody == nil {
+ return "", "", fmt.Errorf("no comment found with ID: %s", strategy.CommentId)
+ }
Likely invalid or redundant comment.
backend/controllers/github.go (1)
885-890
:
Fix incorrect error message in placeholder comment creation (duplicate)
The same error message issue exists in the issue comment event handler.
Apply the same fix as above to correct the error message.
func appendToExistingComment(ciService ci.PullRequestService, prNumber int, existingCommentBody string, reportToAppend string, reportTitle string, commentId string, supportsCollapsible bool) error { | ||
|
||
// strip first and last lines | ||
lines := strings.Split(commentBody, "\n") | ||
lines = lines[1 : len(lines)-1] | ||
commentBody = strings.Join(lines, "\n") | ||
lines := strings.Split(existingCommentBody, "\n") | ||
//if len(lines) > 1 { | ||
// lines = lines[1 : len(lines)-1] | ||
//} | ||
existingCommentBody = strings.Join(lines, "\n") | ||
|
||
commentBody = commentBody + "\n\n" + report + "\n" | ||
existingCommentBody = existingCommentBody + "\n\n" + reportToAppend + "\n" | ||
|
||
var completeComment string | ||
if !supportsCollapsible { | ||
completeComment = utils.AsComment(reportTitle)(commentBody) | ||
completeComment = utils.AsComment(reportTitle)(existingCommentBody) | ||
} else { | ||
completeComment = utils.AsCollapsibleComment(reportTitle, false)(commentBody) | ||
completeComment = utils.AsCollapsibleComment(reportTitle, false)(existingCommentBody) | ||
} | ||
|
||
err := ciService.EditComment(PrNumber, commentIdForThisRun, completeComment) | ||
err := ciService.EditComment(prNumber, commentId, completeComment) | ||
|
||
if err != nil { | ||
return "", "", fmt.Errorf("error editing comment: %v", err) | ||
return fmt.Errorf("error editing comment: %v", err) | ||
} | ||
return fmt.Sprintf("%v", commentIdForThisRun), commentUrl, nil | ||
return nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Clean up commented code and improve error handling
- The commented out code for stripping lines should either be implemented or removed
- The error message could be more descriptive by including the comment ID
Apply these improvements:
func appendToExistingComment(ciService ci.PullRequestService, prNumber int, existingCommentBody string, reportToAppend string, reportTitle string, commentId string, supportsCollapsible bool) error {
// strip first and last lines
lines := strings.Split(existingCommentBody, "\n")
- //if len(lines) > 1 {
- // lines = lines[1 : len(lines)-1]
- //}
existingCommentBody = strings.Join(lines, "\n")
existingCommentBody = existingCommentBody + "\n\n" + reportToAppend + "\n"
var completeComment string
if !supportsCollapsible {
completeComment = utils.AsComment(reportTitle)(existingCommentBody)
} else {
completeComment = utils.AsCollapsibleComment(reportTitle, false)(existingCommentBody)
}
err := ciService.EditComment(prNumber, commentId, completeComment)
if err != nil {
- return fmt.Errorf("error editing comment: %v", err)
+ return fmt.Errorf("error editing comment %s: %v", commentId, err)
}
return nil
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func appendToExistingComment(ciService ci.PullRequestService, prNumber int, existingCommentBody string, reportToAppend string, reportTitle string, commentId string, supportsCollapsible bool) error { | |
// strip first and last lines | |
lines := strings.Split(commentBody, "\n") | |
lines = lines[1 : len(lines)-1] | |
commentBody = strings.Join(lines, "\n") | |
lines := strings.Split(existingCommentBody, "\n") | |
//if len(lines) > 1 { | |
// lines = lines[1 : len(lines)-1] | |
//} | |
existingCommentBody = strings.Join(lines, "\n") | |
commentBody = commentBody + "\n\n" + report + "\n" | |
existingCommentBody = existingCommentBody + "\n\n" + reportToAppend + "\n" | |
var completeComment string | |
if !supportsCollapsible { | |
completeComment = utils.AsComment(reportTitle)(commentBody) | |
completeComment = utils.AsComment(reportTitle)(existingCommentBody) | |
} else { | |
completeComment = utils.AsCollapsibleComment(reportTitle, false)(commentBody) | |
completeComment = utils.AsCollapsibleComment(reportTitle, false)(existingCommentBody) | |
} | |
err := ciService.EditComment(PrNumber, commentIdForThisRun, completeComment) | |
err := ciService.EditComment(prNumber, commentId, completeComment) | |
if err != nil { | |
return "", "", fmt.Errorf("error editing comment: %v", err) | |
return fmt.Errorf("error editing comment: %v", err) | |
} | |
return fmt.Sprintf("%v", commentIdForThisRun), commentUrl, nil | |
return nil | |
func appendToExistingComment(ciService ci.PullRequestService, prNumber int, existingCommentBody string, reportToAppend string, reportTitle string, commentId string, supportsCollapsible bool) error { | |
// strip first and last lines | |
lines := strings.Split(existingCommentBody, "\n") | |
existingCommentBody = strings.Join(lines, "\n") | |
existingCommentBody = existingCommentBody + "\n\n" + reportToAppend + "\n" | |
var completeComment string | |
if !supportsCollapsible { | |
completeComment = utils.AsComment(reportTitle)(existingCommentBody) | |
} else { | |
completeComment = utils.AsCollapsibleComment(reportTitle, false)(existingCommentBody) | |
} | |
err := ciService.EditComment(prNumber, commentId, completeComment) | |
if err != nil { | |
return fmt.Errorf("error editing comment %s: %v", commentId, err) | |
} | |
return nil | |
} |
|
||
placeholderComment, err := ghService.PublishComment(prNumber, "digger report placehoder") | ||
if err != nil { | ||
log.Printf("strconv.ParseInt error: %v", err) | ||
commentReporterManager.UpdateComment(fmt.Sprintf(":x: could not create placeholder commentId for report: %v", err)) | ||
return fmt.Errorf("comment reporter error: %v", err) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix incorrect error message in placeholder comment creation
The error message incorrectly references "strconv.ParseInt" when the error is from publishing a comment.
Apply this fix:
placeholderComment, err := ghService.PublishComment(prNumber, "digger report placehoder")
if err != nil {
- log.Printf("strconv.ParseInt error: %v", err)
+ log.Printf("failed to publish placeholder comment: %v", err)
commentReporterManager.UpdateComment(fmt.Sprintf(":x: could not create placeholder commentId for report: %v", err))
return fmt.Errorf("comment reporter error: %v", err)
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
placeholderComment, err := ghService.PublishComment(prNumber, "digger report placehoder") | |
if err != nil { | |
log.Printf("strconv.ParseInt error: %v", err) | |
commentReporterManager.UpdateComment(fmt.Sprintf(":x: could not create placeholder commentId for report: %v", err)) | |
return fmt.Errorf("comment reporter error: %v", err) | |
} | |
placeholderComment, err := ghService.PublishComment(prNumber, "digger report placehoder") | |
if err != nil { | |
log.Printf("failed to publish placeholder comment: %v", err) | |
commentReporterManager.UpdateComment(fmt.Sprintf(":x: could not create placeholder commentId for report: %v", err)) | |
return fmt.Errorf("comment reporter error: %v", err) | |
} |
✅ No security or compliance issues detected. Reviewed everything up to 5a33821. Security Overview
Detected Code Changes
Diagnostics
Reply to this PR with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (13)
libs/comment_utils/reporting/mock.go (1)
7-9
: Consider enhancing test coverage for comment ID handlingWhile the implementation correctly follows the new interface, consider adding test cases to verify the new placeholder comment mechanism works correctly with this mock implementation.
Consider adding a field to track comment IDs for testing:
type MockReporter struct { commands []string + // Add fields to track placeholder comment IDs for testing + placeholderCommentId string } func (mockReporter *MockReporter) Report(report string, reportFormatting func(report string) string) error { mockReporter.commands = append(mockReporter.commands, "Report") + // Track the placeholder comment ID if needed for tests return nil }libs/comment_utils/reporting/utils.go (2)
33-37
: Consider adding context to error wrappingWhile the error handling is correct, consider adding more context when wrapping the error to aid in debugging.
- return nil, fmt.Errorf("error reporting source module comment: %v", err) + return nil, fmt.Errorf("error reporting source module comment for location %v: %v", location, err)
33-39
: Potential race condition in Report-then-Flush patternThe new pattern of calling Report followed by Flush introduces a potential race condition. Between these calls, another process could modify the comment, causing the Flush to operate on an inconsistent state.
Consider either:
- Making the Report-Flush operation atomic within the CiReporter
- Adding a mechanism to detect and handle concurrent modifications
libs/comment_utils/reporting/reporting.go (3)
19-21
: Simplify error handling in Report methodThe error handling can be simplified further since we're just passing through the error.
func (ciReporter CiReporter) Report(report string, reportFormatting func(report string) string) error { - _, _, err := ciReporter.ReportStrategy.Report(ciReporter.CiService, ciReporter.PrNumber, report, reportFormatting, ciReporter.SupportsMarkdown()) - return err + return ciReporter.ReportStrategy.Report(ciReporter.CiService, ciReporter.PrNumber, report, reportFormatting, ciReporter.SupportsMarkdown()) }
81-83
: Empty Flush implementations need documentationThe empty Flush implementations in both strategies need documentation explaining why they return empty values. This is especially important as it's part of the interface contract.
Add documentation comments explaining the empty implementations:
+// Flush returns empty values as CommentPerRunStrategy doesn't buffer comments func (s CommentPerRunStrategy) Flush() (string, string, error) { return "", "", nil } +// Flush returns empty values as MultipleCommentsStrategy doesn't buffer comments func (s MultipleCommentsStrategy) Flush() (string, string, error) { return "", "", nil }Also applies to: 142-144
57-57
: Document the Flush method in ReportStrategy interfaceThe new Flush method in the ReportStrategy interface lacks documentation explaining its purpose and contract.
Add interface documentation:
type ReportStrategy interface { Report(ciService ci.PullRequestService, PrNumber int, report string, reportFormatter func(report string) string, supportsCollapsibleComment bool) (commentId string, commentUrl string, error error) + // Flush finalizes any buffered comments and returns the last comment's ID and URL Flush() (string, string, error) }
libs/execution/execution.go (5)
297-304
: Enhance error logging messageConsider improving the error logging message to include more context about where the error occurred and what was being reported.
- log.Printf("error publishing comment: %v", commentErr) + log.Printf("error publishing init error comment: %v", commentErr)
399-402
: Enhance apply output error loggingConsider improving the error logging message to include more context.
- log.Printf("error publishing comment: %v", commentErr) + log.Printf("error publishing terraform apply output comment: %v", commentErr)
407-415
: Enhance terraform error loggingConsider improving the error logging message to include more context.
- log.Printf("error publishing comment: %v", commentErr) + log.Printf("error publishing terraform init error comment: %v", commentErr)
431-434
: Enhance additional output error loggingConsider improving the error logging message to include more context.
- log.Printf("error publishing comment: %v", commentErr) + log.Printf("error publishing additional output comment: %v", commentErr)
Line range hint
297-434
: Consider refactoring reporting functions to reduce duplicationThe reporting functions share similar patterns and could be refactored into a common helper function to reduce code duplication and ensure consistent error handling.
Example implementation:
func reportWithFormat(r reporting.Reporter, content string, title string, isCollapsible bool) { var formatter func(string) string if r.SupportsMarkdown() { formatter = utils.AsCollapsibleComment(title, isCollapsible) } else { formatter = utils.AsComment(title) } if err := r.Report(content, formatter); err != nil { log.Printf("error publishing %s comment: %v", title, err) } }This helper function could be used to simplify all the reporting functions while maintaining consistent error handling and logging.
cli/pkg/digger/digger.go (2)
173-181
: Refactor error handling for consistency and reusability.The error handling pattern is duplicated across multiple reporting functions. Consider creating a helper function to handle the common pattern.
+func handleReportError(err error, context string) { + if err != nil { + log.Printf("Error publishing %s: %v", context, err) + } +} func reportPolicyError(projectName string, command string, requestedBy string, reporter reporting.Reporter) string { msg := fmt.Sprintf("User %s is not allowed to perform action: %s. Check your policies :x:", requestedBy, command) if reporter.SupportsMarkdown() { - err := reporter.Report(msg, coreutils.AsCollapsibleComment(fmt.Sprintf("Policy violation for <b>%v - %v</b>", projectName, command), false)) - if err != nil { - log.Printf("Error publishing comment: %v", err) - } + err := reporter.Report(msg, coreutils.AsCollapsibleComment(fmt.Sprintf("Policy violation for <b>%v - %v</b>", projectName, command), false)) + handleReportError(err, "policy violation") } else { // Similar changes for the else block } return msg }Also applies to: 499-507, 521-524, 536-539, 546-551
Line range hint
314-327
: Enhance plan validation reporting with structured messages.The plan validation reporting could be improved to provide more structured and informative messages.
- planReportMessage := "Terraform plan failed validation checks :x:<br>" - preformattedMessaged := make([]string, 0) - for _, message := range messages { - preformattedMessaged = append(preformattedMessaged, fmt.Sprintf(" %v", message)) - } - planReportMessage = planReportMessage + strings.Join(preformattedMessaged, "<br>") + planReportMessage := strings.Builder{} + planReportMessage.WriteString("### Terraform Plan Validation Results :x:\n\n") + planReportMessage.WriteString("The following policy violations were found:\n\n") + for _, message := range messages { + planReportMessage.WriteString(fmt.Sprintf("- %v\n", message)) + } + planReportMessage.WriteString("\nPlease address these violations before proceeding.") err = reporter.Report(planReportMessage, planPolicyFormatter)Also, enhance the success message to include validation details:
- err := reporter.Report("Terraform plan validation checks succeeded :white_check_mark:", planPolicyFormatter) + successMsg := fmt.Sprintf("### Terraform Plan Validation Succeeded :white_check_mark:\n\n" + + "- All policy checks passed\n" + + "- Project: %s\n" + + "- Validation time: %s\n", + job.ProjectName, + time.Now().Format(time.RFC3339)) + err := reporter.Report(successMsg, planPolicyFormatter)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
cli/cmd/digger/root.go
(0 hunks)cli/pkg/digger/digger.go
(7 hunks)ee/cli/cmd/digger/root.go
(0 hunks)libs/comment_utils/reporting/core.go
(1 hunks)libs/comment_utils/reporting/mock.go
(1 hunks)libs/comment_utils/reporting/noop.go
(1 hunks)libs/comment_utils/reporting/reporting.go
(5 hunks)libs/comment_utils/reporting/utils.go
(1 hunks)libs/execution/execution.go
(4 hunks)libs/locking/locking.go
(3 hunks)libs/spec/providers.go
(1 hunks)
💤 Files with no reviewable changes (2)
- ee/cli/cmd/digger/root.go
- cli/cmd/digger/root.go
✅ Files skipped from review due to trivial changes (1)
- libs/locking/locking.go
🚧 Files skipped from review as they are similar to previous changes (1)
- libs/spec/providers.go
🔇 Additional comments (4)
libs/comment_utils/reporting/core.go (1)
4-4
: Verify the impact of removing commentId and commentUrl returns
The simplified signature suggests a change in how comment references are managed. Please ensure that:
- Consumers of this interface aren't relying on the removed return values
- Comment ID tracking is handled elsewhere in the codebase
- The change aligns with the new placeholder comment mechanism mentioned in the PR summary
✅ Verification successful
Based on the search results, I can now generate the final response:
The removal of commentId and commentUrl returns is safe
The codebase search reveals that:
- All Reporter interface implementations (CiReporter, StdOutReporter, NoopReporter, MockReporter) already discard these values, returning empty strings or nil
- No direct consumers are extracting or using the commentId/commentUrl from Report() method calls
- The actual comment ID management is handled at a lower level by the ReportStrategy interface in reporting.go
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for any remaining uses of the old signature pattern
rg -A 2 "Report.*string.*string.*error" --type go
# Look for potential consumers that might expect comment IDs
ast-grep --pattern 'Report($$$).($id|$url)'
Length of output: 9247
libs/comment_utils/reporting/noop.go (1)
5-6
: LGTM! Implementation correctly follows the new interface
The NoopReporter maintains its purpose while adhering to the simplified interface.
libs/comment_utils/reporting/reporting.go (1)
Line range hint 115-117
: Prevent slice bounds out of range in comment processing
The slice operation lines[1 : len(lines)-1]
will panic if lines
has fewer than 2 elements.
This issue was previously reported and needs to be addressed. The fix involves adding a length check before slicing:
lines := strings.Split(commentBody, "\n")
+ if len(lines) >= 2 {
lines = lines[1 : len(lines)-1]
+ } else {
+ lines = []string{}
+ }
commentBody = strings.Join(lines, "\n")
cli/pkg/digger/digger.go (1)
Line range hint 595-597
: Review AWS credentials handling for security best practices.
The PopulateAwsCredentialsEnvVarsForJob
function is handling AWS credentials. Ensure that:
- Credentials are not logged or exposed in error messages
- Credentials are properly rotated and managed
- The minimum required IAM permissions are used
✅ Verification successful
Let me analyze the AWS credentials handling in the codebase based on the search results. I can now generate the final response:
AWS credentials are handled securely with appropriate safeguards in place
The codebase demonstrates secure AWS credentials handling practices:
- Uses AWS SDK's recommended credential providers and configuration patterns
- Credentials are not logged or exposed in error messages
- Supports multiple authentication methods including environment variables, OIDC, and role assumption
- Implements proper credential rotation through session tokens and temporary credentials
- Uses AWS SDK's secure credential chain for resolving credentials
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check for potential credential exposure in logs
rg -i "aws.*key|secret.*key|password|credential" -A 5 -B 5
Length of output: 78483
libs/execution/execution.go
Outdated
commentErr := r.Report(err.Error(), utils.AsCollapsibleComment("Error during applying.", false)) | ||
if commentErr != nil { | ||
log.Printf("error publishing comment: %v", err) | ||
} | ||
} else { | ||
_, _, commentErr := r.Report(err.Error(), utils.AsComment("Error during applying.")) | ||
commentErr := r.Report(err.Error(), utils.AsComment("Error during applying.")) | ||
if commentErr != nil { | ||
log.Printf("error publishing comment: %v", err) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix incorrect error variable in log message
There's a bug in the error logging where it uses the wrong error variable.
- log.Printf("error publishing comment: %v", err)
+ log.Printf("error publishing apply error comment: %v", commentErr)
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
commentErr := r.Report(err.Error(), utils.AsCollapsibleComment("Error during applying.", false)) | |
if commentErr != nil { | |
log.Printf("error publishing comment: %v", err) | |
} | |
} else { | |
_, _, commentErr := r.Report(err.Error(), utils.AsComment("Error during applying.")) | |
commentErr := r.Report(err.Error(), utils.AsComment("Error during applying.")) | |
if commentErr != nil { | |
log.Printf("error publishing comment: %v", err) | |
} | |
commentErr := r.Report(err.Error(), utils.AsCollapsibleComment("Error during applying.", false)) | |
if commentErr != nil { | |
log.Printf("error publishing apply error comment: %v", commentErr) | |
} | |
} else { | |
commentErr := r.Report(err.Error(), utils.AsComment("Error during applying.")) | |
if commentErr != nil { | |
log.Printf("error publishing apply error comment: %v", commentErr) | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (2)
libs/comment_utils/reporting/reporting.go (2)
19-21
: Simplify error handling in Report methodThe method unnecessarily discards two return values from ReportStrategy.Report. Consider updating the interface to match the simplified error-only return type.
- _, _, err := ciReporter.ReportStrategy.Report("", ciReporter.CiService, ciReporter.PrNumber, report, reportFormatting, ciReporter.SupportsMarkdown()) + return ciReporter.ReportStrategy.Report("", ciReporter.CiService, ciReporter.PrNumber, report, reportFormatting, ciReporter.SupportsMarkdown())
60-63
: Add validation for ReportFormat fieldsThe ReportFormat struct lacks validation for required fields. Consider adding validation to ensure ReportFormatter is not nil.
+func NewReportFormat(title string, formatter func(report string) string) (*ReportFormat, error) { + if formatter == nil { + return nil, fmt.Errorf("formatter cannot be nil") + } + return &ReportFormat{ + ReportTitle: title, + ReportFormatter: formatter, + }, nil +}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
cli/cmd/digger/root.go
(1 hunks)ee/cli/cmd/digger/root.go
(1 hunks)libs/comment_utils/reporting/reporting.go
(5 hunks)libs/comment_utils/reporting/utils.go
(1 hunks)libs/spec/providers.go
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- ee/cli/cmd/digger/root.go
- libs/spec/providers.go
- cli/cmd/digger/root.go
🔇 Additional comments (2)
libs/comment_utils/reporting/utils.go (1)
33-37
: 🛠️ Refactor suggestion
Improve error handling and resource cleanup
The error handling could be improved by:
- Adding more context to the error message
- Ensuring proper cleanup of resources on error
- err := reporter.Report("Comment Reporter", func(report string) string { return "" })
- if err != nil {
- log.Printf("Error reporting source module comment: %v", err)
- return nil, fmt.Errorf("error reporting source module comment: %v", err)
- }
+ if err := reporter.Report("Comment Reporter", func(report string) string { return "" }); err != nil {
+ log.Printf("Error reporting source module comment for location %v: %v", location, err)
+ return nil, fmt.Errorf("error reporting source module comment for location %v: %v", location, err)
+ }
Likely invalid or redundant comment.
libs/comment_utils/reporting/reporting.go (1)
93-93
:
Remove unreachable code in SingleCommentStrategy.Flush
Line 93 contains unreachable code as it follows a return statement.
- return "", "", nil
Likely invalid or redundant comment.
@@ -28,9 +28,15 @@ func PostInitialSourceComments(ghService ci.PullRequestService, prNumber int, im | |||
reporter := CiReporter{ | |||
PrNumber: prNumber, | |||
CiService: ghService, | |||
ReportStrategy: CommentPerRunStrategy{fmt.Sprintf("Report for location: %v", location), time.Now()}, | |||
ReportStrategy: SingleCommentStrategy{fmt.Sprintf("Report for location: %v", location), time.Now()}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider initializing the Formatters map in SingleCommentStrategy
The SingleCommentStrategy struct requires a Formatters map, but it's not being initialized here. This could lead to a nil map panic when Report is called.
- ReportStrategy: SingleCommentStrategy{fmt.Sprintf("Report for location: %v", location), time.Now()},
+ ReportStrategy: SingleCommentStrategy{
+ Title: fmt.Sprintf("Report for location: %v", location),
+ TimeOfRun: time.Now(),
+ Formatters: make(map[string]ReportFormat),
+ },
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
ReportStrategy: SingleCommentStrategy{fmt.Sprintf("Report for location: %v", location), time.Now()}, | |
ReportStrategy: SingleCommentStrategy{ | |
Title: fmt.Sprintf("Report for location: %v", location), | |
TimeOfRun: time.Now(), | |
Formatters: make(map[string]ReportFormat), | |
}, |
func (strategy MultipleCommentsStrategy) Report(projectName string, report string, reportFormatter func(report string) string) error { | ||
strategy.Formatters[projectName] = ReportFormat{ | ||
ReportTitle: report, | ||
ReportFormatter: reportFormatter, | ||
} | ||
|
||
reportTitle := "Digger latest run report" | ||
commentId, commentUrl, err := upsertComment(ciService, PrNumber, report, reportFormatter, comments, reportTitle, supportsCollapsibleComment) | ||
return commentId, commentUrl, err | ||
return nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add thread safety to map access in MultipleCommentsStrategy
Similar to SingleCommentStrategy, the Formatters map in MultipleCommentsStrategy needs synchronization.
+type MultipleCommentsStrategy struct {
+ Formatters map[string]ReportFormat
+ mu sync.RWMutex
+}
func (strategy MultipleCommentsStrategy) Report(projectName string, report string, reportFormatter func(report string) string) error {
+ strategy.mu.Lock()
+ defer strategy.mu.Unlock()
strategy.Formatters[projectName] = ReportFormat{
ReportTitle: report,
ReportFormatter: reportFormatter,
}
return nil
}
Committable suggestion skipped: line range outside the PR's diff.
func (strategy MultipleCommentsStrategy) Flush(ciService ci.PullRequestService, PrNumber int, supportsCollapsibleComment bool) (string, string, error) { | ||
return "", "", nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implement proper Flush behavior in MultipleCommentsStrategy
The Flush method currently returns empty values without any implementation. Consider implementing proper behavior or documenting why it's intentionally empty.
Either implement the method properly:
func (strategy MultipleCommentsStrategy) Flush(ciService ci.PullRequestService, PrNumber int, supportsCollapsibleComment bool) (string, string, error) {
- return "", "", nil
+ strategy.mu.RLock()
+ defer strategy.mu.RUnlock()
+
+ var errors []error
+ for projectName, format := range strategy.Formatters {
+ // Implement flushing logic for each project
+ if err := flushProject(ciService, PrNumber, projectName, format, supportsCollapsibleComment); err != nil {
+ errors = append(errors, err)
+ }
+ }
+
+ if len(errors) > 0 {
+ return "", "", fmt.Errorf("multiple flush errors: %v", errors)
+ }
+ return "", "", nil
}
Or document the intentional no-op:
+// Flush is a no-op for MultipleCommentsStrategy as comments are posted immediately in Report
func (strategy MultipleCommentsStrategy) Flush(ciService ci.PullRequestService, PrNumber int, supportsCollapsibleComment bool) (string, string, error) {
return "", "", nil
}
Committable suggestion skipped: line range outside the PR's diff.
func (strategy SingleCommentStrategy) Report(projectName string, report string, reportFormatter func(report string) string, supportsCollapsibleComment bool) error { | ||
strategy.Formatters[projectName] = ReportFormat{ | ||
ReportTitle: report, | ||
ReportFormatter: reportFormatter, | ||
} | ||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add thread safety to map access in SingleCommentStrategy
The Formatters map is accessed without synchronization, which could lead to race conditions in concurrent usage.
+type SingleCommentStrategy struct {
+ Title string
+ TimeOfRun time.Time
+ Formatters map[string]ReportFormat
+ mu sync.RWMutex
+}
func (strategy SingleCommentStrategy) Report(projectName string, report string, reportFormatter func(report string) string, supportsCollapsibleComment bool) error {
+ strategy.mu.Lock()
+ defer strategy.mu.Unlock()
strategy.Formatters[projectName] = ReportFormat{
ReportTitle: report,
ReportFormatter: reportFormatter,
}
return nil
}
Committable suggestion skipped: line range outside the PR's diff.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (7)
cli/cmd/digger/main_test.go (1)
929-933
: Maintain consistent field ordering in struct initializationThe field ordering in this CiReporter initialization differs from the one in
TestGitHubNewPullRequestContext
. Also, like the previous instance, it usesMultipleCommentsStrategy
when the PR aims to support single comment summary.reporter := &reporting.CiReporter{ CiService: &prManager, PrNumber: prNumber, - ReportStrategy: reporting.NewMultipleCommentsStrategy(), - IsSuppressed: false, IsSupportMarkdown: true, + IsSuppressed: false, + ReportStrategy: reporting.NewSingleCommentStrategy(), }libs/comment_utils/reporting/noop.go (1)
17-17
: Name the parameter in Suppress methodThe parameter in the Suppress method should be named for better code readability.
-func (reporter NoopReporter) Suppress(string) error { +func (reporter NoopReporter) Suppress(projectName string) error {libs/comment_utils/reporting/mock.go (1)
4-6
: Consider documenting the new reporting architectureThe interface changes suggest a significant architectural shift in how comments are handled. Consider:
- Adding documentation explaining the new comment lifecycle
- Providing examples of how the batch processing works
- Documenting the relationship between
projectName
and comment handlingWould you like me to help draft the documentation for these architectural changes?
libs/comment_utils/reporting/reporting.go (4)
15-15
: Add documentation for the new IsSuppressed fieldThe purpose and usage of this new field should be documented to help other developers understand when and how to use it.
+ // IsSuppressed indicates whether reporting should be suppressed for this reporter IsSuppressed bool
62-65
: Document the ReportFormat structAdd documentation to explain the purpose of this struct and its fields.
+// ReportFormat encapsulates a report's content and its formatting function type ReportFormat struct { + // Report contains the raw report content Report string + // ReportFormatter is a function that formats the report content ReportFormatter func(report string) string }
116-119
: Implement the Suppress methodThe TODO comment should be addressed by implementing the suppression logic.
Would you like me to help implement the suppression logic for this method?
145-183
: Improve error handling in Flush methodThe current error handling approach using boolean flags and a single error variable could be improved:
- Consider using error groups for concurrent operations
- Return early on errors instead of continuing with placeholders
func (strategy MultipleCommentsStrategy) Flush(ciService ci.PullRequestService, PrNumber int, supportsCollapsibleComment bool) ([]string, []string, error) { + var commentIds []string + var commentUrls []string - hasError := false - var latestError error = nil - commentIds := make([]string, 0) - commentUrls := make([]string, 0) for projectName, projectFormatters := range strategy.formatters { projectTitle := "Digger run report for " + projectName + " " + strategy.TimeOfRun.Format("2006-01-02 15:04:05 (MST)") var projectComment = "" for _, f := range projectFormatters { report := f.ReportFormatter(f.Report) projectComment = projectComment + "\n" + report } if !supportsCollapsibleComment { projectComment = utils.AsComment(projectTitle)(projectComment) } else { projectComment = utils.AsCollapsibleComment(projectTitle, false)(projectComment) } c, err := ciService.PublishComment(PrNumber, projectComment) if err != nil { log.Printf("error while publishing reporter comment: %v", err) - hasError = true - latestError = err - // append placeholders - commentIds = append(commentIds, "0") - commentUrls = append(commentUrls, "") + return commentIds, commentUrls, fmt.Errorf("failed to publish comment for project %s: %v", projectName, err) } else { commentIds = append(commentIds, c.Id) commentUrls = append(commentUrls, c.Url) } } - if hasError { - log.Printf("could not publish all comments") - return commentIds, commentUrls, latestError - } return commentIds, commentUrls, nil }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
cli/cmd/digger/main_test.go
(2 hunks)cli/cmd/digger/root.go
(1 hunks)cli/pkg/digger/digger.go
(9 hunks)cli/pkg/digger/digger_test.go
(2 hunks)cli/pkg/integration/integration_test.go
(1 hunks)ee/cli/cmd/digger/root.go
(1 hunks)libs/comment_utils/reporting/core.go
(1 hunks)libs/comment_utils/reporting/mock.go
(1 hunks)libs/comment_utils/reporting/noop.go
(1 hunks)libs/comment_utils/reporting/reporting.go
(1 hunks)libs/comment_utils/reporting/utils.go
(1 hunks)libs/execution/execution.go
(6 hunks)libs/locking/locking.go
(6 hunks)libs/spec/providers.go
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
- libs/comment_utils/reporting/utils.go
- libs/spec/providers.go
- ee/cli/cmd/digger/root.go
- libs/locking/locking.go
- cli/cmd/digger/root.go
- libs/execution/execution.go
🧰 Additional context used
🪛 golangci-lint (1.62.2)
cli/pkg/digger/digger.go
549-549: Error return value of reporter.Suppress
is not checked
(errcheck)
🔇 Additional comments (8)
cli/pkg/digger/digger.go (2)
174-179
: LGTM! Consistent error handling pattern
The error handling pattern is well-implemented across all reporting functions. Errors are properly logged without interrupting the execution flow, which is appropriate for a reporting system.
Also applies to: 288-328, 331-331, 374-374
Line range hint 495-542
: LGTM! Well-structured reporting functions
The reporting functions are well-structured with consistent patterns for:
- Markdown support checking
- Error handling
- Message formatting
libs/comment_utils/reporting/core.go (1)
4-6
: Verify the impact of Reporter interface changes across the codebase
The interface changes suggest a significant architectural shift:
- Addition of
projectName
parameter indicates multi-project support - Return type changes in
Flush()
suggest batch processing of comments - Removal of
commentId
andcommentUrl
fromReport()
implies a different comment handling strategy
Let's verify the impact of these changes:
✅ Verification successful
Let me generate additional scripts to verify the interface implementations and their usage patterns:
Let me try one more search pattern to find the implementations:
Interface changes are properly implemented across the codebase
Based on the verification results:
- All implementations (
NoopReporter
,CiReporter
,StdOutReporter
,SingleCommentStrategy
,MultipleCommentsStrategy
,MockReporter
) correctly implement the updated interface with the new signatures - All callers of these methods (from previous search) are using the new parameter structure
- The
Flush()
return type change to([]string, []string, error)
is consistently implemented - The
projectName
parameter is properly handled in all implementations
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for all implementations of the Reporter interface
ast-grep --pattern 'type $_ struct {
$$$
}
func ($_ $_) Report($$$) $_ {
$$$
}
func ($_ $_) Flush() ($$$) {
$$$
}
func ($_ $_) Suppress($$$) $_ {
$$$
}'
# Search for existing calls to these methods that might need updates
rg -A 2 '\.(Report|Flush|Suppress)\('
Length of output: 7628
Script:
#!/bin/bash
# Search for Reporter interface implementations
ast-grep --pattern 'type $name struct {
$$$
}
func ($r $_) Report(projectName string, report string, reportFormatting func(report string) string) error {
$$$
}'
# Search for Flush implementations to verify return type changes
ast-grep --pattern 'func ($r $_) Flush() ([]string, []string, error) {
$$$
}'
# Search for old interface signatures that might need updates
rg 'func.*Report.*\(.*\).*\(string,\s*string,\s*error\)'
rg 'func.*Flush.*\(.*\).*\(string,\s*string,\s*error\)'
Length of output: 366
Script:
#!/bin/bash
# Search for struct types that might implement Reporter
ast-grep --pattern 'type $name struct {
$$$
}'
# Search for all Report method implementations
rg -A 5 '^func.*Report\('
# Search for all Flush method implementations
rg -A 5 '^func.*Flush\('
# Search for all Suppress method implementations
rg -A 5 '^func.*Suppress\('
Length of output: 8860
libs/comment_utils/reporting/reporting.go (2)
121-123
:
Add mutex for thread-safe map access
Similar to SingleCommentStrategy, the formatters
map needs synchronization.
type MultipleCommentsStrategy struct {
+ mu sync.RWMutex
formatters map[string][]ReportFormat
TimeOfRun time.Time
}
Likely invalid or redundant comment.
67-70
:
Add mutex for thread-safe map access
The formatters
map is accessed from multiple methods without synchronization, which could lead to race conditions.
type SingleCommentStrategy struct {
TimeOfRun time.Time
+ mu sync.RWMutex
formatters map[string][]ReportFormat
}
Likely invalid or redundant comment.
cli/pkg/digger/digger_test.go (2)
250-256
: LGTM!
The changes correctly initialize the MultipleCommentsStrategy for testing.
301-306
: LGTM!
The changes correctly initialize the MultipleCommentsStrategy for the destroy test case.
cli/pkg/integration/integration_test.go (1)
47-52
: LGTM!
The changes correctly initialize the MultipleCommentsStrategy for integration testing.
func reportEmptyPlanOutput(projectName string, reporter reporting.Reporter, projectId string) { | ||
identityFormatter := func(comment string) string { | ||
return comment | ||
} | ||
_, _, err := reporter.Report("→ No changes in terraform output for "+projectId, identityFormatter) | ||
err := reporter.Report(projectName, "→ No changes in terraform output for "+projectId, identityFormatter) | ||
// suppress the comment (if reporter is suppressible) | ||
reporter.Suppress() | ||
reporter.Suppress("") | ||
if err != nil { | ||
log.Printf("Failed to report plan. %v", err) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handle error return value from reporter.Suppress
The error return value from reporter.Suppress
is not checked, which could hide important errors.
Add error handling:
func reportEmptyPlanOutput(projectName string, reporter reporting.Reporter, projectId string) {
identityFormatter := func(comment string) string {
return comment
}
err := reporter.Report(projectName, "→ No changes in terraform output for "+projectId, identityFormatter)
- reporter.Suppress("")
+ if err := reporter.Suppress(""); err != nil {
+ log.Printf("Failed to suppress report: %v", err)
+ }
if err != nil {
log.Printf("Failed to report plan. %v", err)
}
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
func reportEmptyPlanOutput(projectName string, reporter reporting.Reporter, projectId string) { | |
identityFormatter := func(comment string) string { | |
return comment | |
} | |
_, _, err := reporter.Report("→ No changes in terraform output for "+projectId, identityFormatter) | |
err := reporter.Report(projectName, "→ No changes in terraform output for "+projectId, identityFormatter) | |
// suppress the comment (if reporter is suppressible) | |
reporter.Suppress() | |
reporter.Suppress("") | |
if err != nil { | |
log.Printf("Failed to report plan. %v", err) | |
} | |
func reportEmptyPlanOutput(projectName string, reporter reporting.Reporter, projectId string) { | |
identityFormatter := func(comment string) string { | |
return comment | |
} | |
err := reporter.Report(projectName, "→ No changes in terraform output for "+projectId, identityFormatter) | |
// suppress the comment (if reporter is suppressible) | |
if err := reporter.Suppress(""); err != nil { | |
log.Printf("Failed to suppress report: %v", err) | |
} | |
if err != nil { | |
log.Printf("Failed to report plan. %v", err) | |
} |
🧰 Tools
🪛 golangci-lint (1.62.2)
549-549: Error return value of reporter.Suppress
is not checked
(errcheck)
_, jobPrCommentUrls, err := reporter.Flush() | ||
if err != nil { | ||
log.Printf("error while sending job comments %v", err) | ||
return false, false, fmt.Errorf("error while sending job comments %v", err) | ||
} | ||
|
||
currentJob := jobs[0] | ||
jobPrCommentUrl := jobPrCommentUrls[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add bounds checking for jobPrCommentUrls array
The code assumes jobPrCommentUrls has at least one element. This could lead to a panic if the array is empty.
Add a bounds check before accessing the first element:
_, jobPrCommentUrls, err := reporter.Flush()
if err != nil {
log.Printf("error while sending job comments %v", err)
return false, false, fmt.Errorf("error while sending job comments %v", err)
}
+if len(jobPrCommentUrls) == 0 {
+ return false, false, fmt.Errorf("no comment URLs returned from reporter")
+}
currentJob := jobs[0]
jobPrCommentUrl := jobPrCommentUrls[0]
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
_, jobPrCommentUrls, err := reporter.Flush() | |
if err != nil { | |
log.Printf("error while sending job comments %v", err) | |
return false, false, fmt.Errorf("error while sending job comments %v", err) | |
} | |
currentJob := jobs[0] | |
jobPrCommentUrl := jobPrCommentUrls[0] | |
_, jobPrCommentUrls, err := reporter.Flush() | |
if err != nil { | |
log.Printf("error while sending job comments %v", err) | |
return false, false, fmt.Errorf("error while sending job comments %v", err) | |
} | |
if len(jobPrCommentUrls) == 0 { | |
return false, false, fmt.Errorf("no comment URLs returned from reporter") | |
} | |
currentJob := jobs[0] | |
jobPrCommentUrl := jobPrCommentUrls[0] |
CiService: &prManager, | ||
PrNumber: prNumber, | ||
IsSupportMarkdown: true, | ||
IsSuppressed: false, | ||
ReportStrategy: reporting.NewMultipleCommentsStrategy(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add test coverage for single comment strategy
The PR aims to support single comment summary, but the test initializes MultipleCommentsStrategy
. Consider:
- Adding test cases that verify the single comment strategy
- Validating the reporting behavior with different strategies
reporter := &reporting.CiReporter{
CiService: &prManager,
PrNumber: prNumber,
IsSupportMarkdown: true,
IsSuppressed: false,
- ReportStrategy: reporting.NewMultipleCommentsStrategy(),
+ ReportStrategy: reporting.NewSingleCommentStrategy(),
}
+func TestGitHubNewPullRequestContextWithSingleComment(t *testing.T) {
+ // Add test case for single comment strategy
+ // Verify the reporting behavior
+}
Committable suggestion skipped: line range outside the PR's diff.
func (mockReporter *MockReporter) Report(projectName string, report string, reportFormatting func(report string) string) error { | ||
mockReporter.commands = append(mockReporter.commands, "Report") | ||
return "", "", nil | ||
return nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enhance mock implementation consistency
The mock implementation has several areas for improvement:
- Command tracking is inconsistent across methods
- The Suppress method parameter is unnamed
- Flush method should track command execution
func (mockReporter *MockReporter) Report(projectName string, report string, reportFormatting func(report string) string) error {
mockReporter.commands = append(mockReporter.commands, "Report")
return nil
}
func (mockReporter *MockReporter) Flush() ([]string, []string, error) {
+ mockReporter.commands = append(mockReporter.commands, "Flush")
return []string{}, []string{}, nil
}
-func (mockReporter *MockReporter) Suppress(string) error {
+func (mockReporter *MockReporter) Suppress(projectName string) error {
+ mockReporter.commands = append(mockReporter.commands, "Suppress")
return nil
}
Also applies to: 12-13, 16-16
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
backend/controllers/github.go (1)
503-509
:⚠️ Potential issueFix incorrect error message in placeholder comment creation
The error message incorrectly references "strconv.ParseInt" when the error is from publishing a comment.
Apply this fix:
placeholderComment, err := ghService.PublishComment(prNumber, "digger report placehoder") if err != nil { - log.Printf("strconv.ParseInt error: %v", err) + log.Printf("failed to publish placeholder comment: %v", err) commentReporterManager.UpdateComment(fmt.Sprintf(":x: could not create placeholder commentId for report: %v", err)) return fmt.Errorf("comment reporter error: %v", err) }
🧹 Nitpick comments (1)
backend/controllers/github.go (1)
504-504
: Fix typo in placeholder comment textThe word "placehoder" is misspelled in the placeholder comment text. It should be "placeholder".
Apply this fix in both locations:
- placeholderComment, err := ghService.PublishComment(prNumber, "digger report placehoder") + placeholderComment, err := ghService.PublishComment(prNumber, "digger report placeholder")Also applies to: 887-887
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
backend/controllers/github.go
(3 hunks)backend/services/spec.go
(1 hunks)libs/spec/providers.go
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- libs/spec/providers.go
- backend/services/spec.go
placeholderComment, err := ghService.PublishComment(issueNumber, "digger report placehoder") | ||
if err != nil { | ||
log.Printf("strconv.ParseInt error: %v", err) | ||
commentReporterManager.UpdateComment(fmt.Sprintf(":x: could not create placeholder commentId for report: %v", err)) | ||
return fmt.Errorf("comment reporter error: %v", err) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Fix incorrect error message and consider refactoring duplicated code
- The error message incorrectly references "strconv.ParseInt" when the error is from publishing a comment.
- This code block is duplicated from the handlePullRequestEvent function.
First, fix the error message:
placeholderComment, err := ghService.PublishComment(issueNumber, "digger report placehoder")
if err != nil {
- log.Printf("strconv.ParseInt error: %v", err)
+ log.Printf("failed to publish placeholder comment: %v", err)
commentReporterManager.UpdateComment(fmt.Sprintf(":x: could not create placeholder commentId for report: %v", err))
return fmt.Errorf("comment reporter error: %v", err)
}
Consider extracting the placeholder comment creation into a shared helper function to avoid code duplication:
func createPlaceholderComment(ghService *dg_github.GithubService, number int, commentReporterManager *utils.CommentReporterManager) (*github.IssueComment, error) {
placeholderComment, err := ghService.PublishComment(number, "digger report placeholder")
if err != nil {
log.Printf("failed to publish placeholder comment: %v", err)
commentReporterManager.UpdateComment(fmt.Sprintf(":x: could not create placeholder commentId for report: %v", err))
return nil, fmt.Errorf("comment reporter error: %v", err)
}
return placeholderComment, nil
}
This reverts commit f552996.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
♻️ Duplicate comments (1)
backend/controllers/github.go (1)
531-536
:⚠️ Potential issueFix incorrect error message and duplicate code
- The error message incorrectly references "strconv.ParseInt" when the error is from publishing a comment
- This code block is duplicated between handlePullRequestEvent and handleIssueCommentEvent
Also applies to: 951-956
🧹 Nitpick comments (22)
backend/utils/ai.go (5)
12-16
: Ensure HTTP client timeouts are set for reliabilityYou might want to provide a custom
http.Client
with a timeout to avoid hanging indefinitely on slow or unresponsive servers.func GenerateTerraformCode(appCode string, generationEndpoint string, apiToken string) (string, error) { payload := map[string]string{ "code": appCode, } + client := &http.Client{ + Timeout: 30 * time.Second, + }
49-55
: Differentiate between 4xx/5xx errors or handle them gracefullyCurrently, a 400 response is singled out, and all other non-200 responses return a generic error message. Distinguishing between client (4xx) and server (5xx) errors could improve observability and debugging.
57-67
: Leverage a singleGeneratorResponse
type across both functionsConsider placing
GeneratorResponse
in a shared scope if you’re using it in both methods. This reduces duplication and eases maintenance.
72-99
: Reuse client between functionsSimilar to the first function, consider reusing the same
http.Client
instance or introduce a shared helper method to avoid duplicating request handling logic.
109-112
: Include response details when logging 400 errorsIn addition to logging the raw body, consider adding more contextual information about the error to help diagnose user input issues or server validation failures.
backend/controllers/projects.go (1)
655-717
: Graceful handling of missing AI summary parametersConsider adding more structured logging for each error scenario. In particular, if
ai summary endpoint
orapiToken
is missing, you might store a structured error in the database or post a more user-friendly comment in the PR.libs/digger_config/terragrunt/atlantis/generate.go (6)
142-142
: Populate error detail proactivelyYou’re setting a cached result with
err
before fully parsing dependencies. If subsequent logic modifies this error, consider storing more detailed data.
259-259
: Cascading dependencies edge caseWhen
cascadeDependencies
is true, failures to retrieve child dependencies are silently ignored (continue
). Consider adding logs or fallback logic to improve traceability.
366-382
: Guard the return early for short-circuited logicWhen
triggerProjectsFromDirOnly
istrue
andrelativeSourceDir == "."
, it simply returnsnil
. This is valid, but consider logging the scenario for debugging consistency.
480-480
: Add test coverage forcreateHclProject
logicUnit tests for various local overrides or skipping with
atlantis_skip
might help prevent regressions.
553-553
: Skipping project logic clarityBecause
getDependencies(...)
can return nil to indicate a project skip, consider documenting that behavior clearly to avoid confusion in future.
706-706
: Clarify concurrency settings
Parse(...)
uses a semaphore with a weight of 10. Is this a chosen concurrency limit for all calls, or should it be configurable based on environment constraints?backend/tasks/runs_test.go (1)
146-146
: Added parameters for AI summary in the testBe cautious about always passing empty string and
false
. You may want to add a test scenario that sets them to a non-default value to verify that logic in downstream methods works as intended.libs/digger_config/digger_config.go (2)
33-45
: Robust file loading approach.Using separate cases for
digger.yml
vs.digger.yaml
is good. Consider adding more granular logs or telemetry (if relevant) to assist in debugging file-not-found scenarios.
579-579
: Potential edge cases in path normalization.When normalizing patterns for
Autoplan.WhenModified
, be mindful of unusual directory structures or symbolic links. The logic here is acceptable, but additional checks might be warranted if you support more complex setups.backend/migrations/20241229112312.sql (1)
1-2
: Add down migration for rollback support.While the migration adds the necessary columns correctly, consider adding a down migration to support rollbacks:
-- Up migration ALTER TABLE "public"."digger_batches" ADD COLUMN "ai_summary_comment_id" text NULL, ADD COLUMN "report_terraform_outputs" boolean NULL; -- Down migration ALTER TABLE "public"."digger_batches" DROP COLUMN "ai_summary_comment_id", DROP COLUMN "report_terraform_outputs";backend/scripts/curl_bootstrap.sh (1)
22-26
: Pin the web service image version.Using
latest
tag can lead to unexpected behavior. Consider pinning to a specific version:- image: "registry.digger.dev/diggerhq/digger_backend:latest" + image: "registry.digger.dev/diggerhq/digger_backend:v1.x.x"libs/digger_config/config.go (3)
18-20
: Add documentation for new configuration fields.Please add documentation comments for the new fields to explain their purpose and expected values:
+ // Reporting contains configuration for various reporting features Reporting ReporterConfig + // ReportTerraformOutputs when true, includes Terraform outputs in the report ReportTerraformOutputs bool
22-24
: Document ReporterConfig struct and add validation.Add documentation and consider adding validation for the AiSummary field:
+// ReporterConfig contains settings for different types of reporting features type ReporterConfig struct { + // AiSummary when true, enables AI-powered summary generation AiSummary bool } +// Validate ensures the reporter configuration is valid +func (r *ReporterConfig) Validate() error { + // Add validation logic if needed + return nil +}
37-52
: Consider adding validation for Project configuration.The Project struct contains critical configuration. Consider adding validation to ensure required fields are properly set:
func (p *Project) Validate() error { if p.Name == "" { return fmt.Errorf("project name is required") } if p.Dir == "" { return fmt.Errorf("project directory is required") } // Add more validation as needed return nil }backend/utils/graphs.go (1)
17-17
: Consider breaking down the long parameter list.The function signature has grown quite long with 19 parameters, which could make it harder to maintain and use correctly.
Consider introducing a configuration struct to group related parameters:
type JobConversionConfig struct { JobType scheduler.DiggerCommand VCSType models.DiggerVCSType OrganisationId uint GithubInstallationId int64 GitlabProjectId int Branch string PRNumber int RepoInfo struct { Owner string Name string FullName string CommitSha string } Comments struct { CommentId int64 PlaceholderCommentIdForReport *string AiSummaryCommentId string } Config struct { DiggerConfigStr string ReportTerraformOutput bool } } func ConvertJobsToDiggerJobs(config JobConversionConfig, jobsMap map[string]scheduler.Job, projectMap map[string]configuration.Project, projectsGraph graph.Graph[string, configuration.Project]) (*uuid.UUID, map[string]*models.DiggerJob, error)action.yml (1)
431-433
: Remove trailing spacesThe cache configuration has trailing spaces on line 433 that should be removed.
path: ${{ github.workspace }}/cache key: digger-cache-${{ hashFiles('**/cache') }} - +🧰 Tools
🪛 yamllint (1.35.1)
[error] 433-433: trailing spaces
(trailing-spaces)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (6)
backend/migrations/atlas.sum
is excluded by!**/*.sum
cli/go.sum
is excluded by!**/*.sum
ee/backend/go.sum
is excluded by!**/*.sum
ee/cli/go.sum
is excluded by!**/*.sum
go.work.sum
is excluded by!**/*.sum
libs/go.sum
is excluded by!**/*.sum
📒 Files selected for processing (25)
action.yml
(2 hunks)backend/controllers/github.go
(10 hunks)backend/controllers/github_test.go
(4 hunks)backend/controllers/projects.go
(3 hunks)backend/migrations/20240403155357_drop_dup_idx.sql
(1 hunks)backend/migrations/20241229112312.sql
(1 hunks)backend/models/scheduler.go
(1 hunks)backend/models/storage.go
(1 hunks)backend/models/storage_test.go
(1 hunks)backend/scripts/curl_bootstrap.sh
(1 hunks)backend/tasks/runs_test.go
(1 hunks)backend/utils/ai.go
(1 hunks)backend/utils/graphs.go
(2 hunks)cli/go.mod
(2 hunks)docs/mint.json
(0 hunks)ee/backend/controllers/gitlab.go
(2 hunks)ee/backend/go.mod
(8 hunks)ee/backend/hooks/github.go
(1 hunks)ee/cli/go.mod
(1 hunks)libs/digger_config/config.go
(2 hunks)libs/digger_config/converters.go
(3 hunks)libs/digger_config/digger_config.go
(3 hunks)libs/digger_config/terragrunt/atlantis/generate.go
(11 hunks)libs/digger_config/yaml.go
(2 hunks)libs/go.mod
(0 hunks)
💤 Files with no reviewable changes (2)
- docs/mint.json
- libs/go.mod
✅ Files skipped from review due to trivial changes (1)
- backend/migrations/20240403155357_drop_dup_idx.sql
🚧 Files skipped from review as they are similar to previous changes (4)
- backend/models/scheduler.go
- backend/models/storage.go
- ee/backend/hooks/github.go
- ee/backend/controllers/gitlab.go
🧰 Additional context used
🪛 Shellcheck (0.10.0)
backend/scripts/curl_bootstrap.sh
[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.
(SC2148)
🪛 golangci-lint (1.62.2)
backend/controllers/github.go
538-538: no new variables on left side of :=
(typecheck)
958-958: no new variables on left side of :=
(typecheck)
🪛 yamllint (1.35.1)
action.yml
[error] 433-433: trailing spaces
(trailing-spaces)
🔇 Additional comments (23)
backend/controllers/projects.go (2)
20-20
: OS import usageThe addition of the
"os"
import is valid for retrieving environment variables (e.g.,os.Getenv
). Ensure safe handling of sensitive data from environment variables when logging or storing.
485-489
: Verify post-job summary creationYou're calling
CreateTerraformOutputsSummary
immediately after updating the batch status. Ensure that any partial failures withinCreateTerraformOutputsSummary
do not block other routine tasks, like final notifications or auto-merge.libs/digger_config/terragrunt/atlantis/generate.go (4)
Line range hint
121-125
: Caching dependencies locallyThe use of
requestGroup.Do
andgetDependenciesCache
is an effective approach. Ensure threading is safe around all shared state (which it appears to be).
315-339
: Design promotes clean reuse withcreateBaseProject
Good approach extracting common Atlantis project initialization here. Ensures consistency across different creation workflows.
352-356
: Add top-level directory checksThe lines create
relativeDependencies
always. Be mindful that “.tf” may inadvertently pick up hidden or extraneous files.
444-453
: Project naming collisionsYou rely on
projectNameFromDir
to name both the project and workspace. In large monorepos, different subdirectories might somehow yield the same sanitized name. Consider checking for collisions or retaining additional path segments.backend/models/storage_test.go (1)
154-154
: New parameters inCreateDiggerBatch
You’ve introduced
aiSummaryCommentId
as an empty string andreportTerraformOutputs
asfalse
. If future tests require verifying these fields, consider adding more explicit coverage that sets different values.libs/digger_config/converters.go (3)
50-58
: Prefer consistent initialization style.The conditional pointer assignment and subsequent block for
awsCognitoOidc
look consistent. Ensure you consistently initialize and assign default regions or fallback values for all supported providers if the code evolves to support new fields.
172-183
: Concise utility addition looks good.The
copyReporterConfig
function provides a neat way to handle default vs. provided values. If additional fields are introduced in the future, ensure you expand this copier function to safely handle them without overshadowing defaults.
198-205
: New reporting logic is coherent.Good approach in setting
ReportTerraformOutputs
defaults and callingcopyReporterConfig
. This maintains backward compatibility and ensures new reporting fields are exposed effectively.libs/digger_config/yaml.go (3)
22-24
: Clarity in naming the new reporting fields.Adding
ReportTerraformOutputs
andReporting
with a pointer toReportingConfigYaml
is clear and semantically consistent. Ensure that usage downstream handles nil pointers correctly.
25-27
: Good introduction of theReportingConfigYaml
struct.This is straightforward. In future expansions, consider the possibility that more reporting-related fields might be added to reduce repeated structures.
146-163
: Ensure Terragrunt parsing logic consistently uses the newTriggerProjectsFromDirOnly
field.The newly added fields in
TerragruntParsingConfig
appear coherent with the file’s structure. Verify that the rest of the codebase properly interprets this option to avoid partial application of filters.libs/digger_config/digger_config.go (1)
553-553
: AddingTriggerProjectsFromDirOnly
parameter recognized.Looks consistent with the logic in
hydrateDiggerConfigYamlWithTerragrunt
. Verify that tests capture scenarios whenTriggerProjectsFromDirOnly
is enabled to confirm correct project detection.backend/controllers/github_test.go (4)
734-734
: Extra parameter integration is seamless.This test demonstrates how the new boolean parameter is passed to
ConvertJobsToDiggerJobs
. The usage looks straightforward.
763-763
: Parameter expansion maintained consistency.Ensuring that all necessary parameters (
aiSummaryCommentId
,reportTerraformOutput
, etc.) are captured in test scenarios is crucial. This looks correct.
796-796
: Multiple projects scenario well-covered.Again, passing the new parameter in a multi-project test ensures consistency across job creation logic. Good job.
841-841
: Three-level dependency scenario remains valid.Including the new parameter also for this deeper dependency test ensures no breakage. The coverage is thorough.
cli/go.mod (1)
Line range hint
58-84
: Verify AWS SDK version compatibility across packages.The AWS SDK packages have been updated to newer versions. While the updates appear consistent, it's important to verify compatibility with the rest of the codebase.
Run the following script to check for any version mismatches:
✅ Verification successful
AWS SDK dependencies are correctly updated and used consistently
The verification shows that AWS SDK packages are used consistently across the codebase in various components:
- Storage components (S3)
- Authentication (Cognito, STS)
- DynamoDB operations
- Configuration and credentials management
All imports are using the same AWS SDK v2 family (
aws-sdk-go-v2
), and the updated versions ingo.mod
maintain compatibility across these packages. The dependencies marked as "indirect" are correctly labeled as they are transitive dependencies required by the directly used AWS packages.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check for AWS SDK version consistency across the codebase # Search for AWS SDK imports and their versions rg --type go "github.com/aws/aws-sdk-go-v2" -A 1Length of output: 4040
ee/cli/go.mod (1)
61-84
: LGTM! Dependencies are consistent with cli/go.mod.The AWS SDK version updates and go-gitlab addition mirror the changes in cli/go.mod, maintaining consistency across modules.
action.yml (1)
278-278
: LGTM: OpenTofu setup action version updateThe update from v1.0.3 to v1.0.5 is a minor version bump that likely includes bug fixes and improvements.
ee/backend/go.mod (1)
14-14
: LGTM: Dependency updatesThe changes include:
- Version updates for existing dependencies (e.g., github.com/samber/lo to v1.46.0)
- New dependencies added (e.g., github.com/diggerhq/digger/ee/drift)
- Database-related dependencies added (e.g., gorm.io/datatypes, gorm.io/driver/mysql)
These changes align with the PR's objectives for supporting AI summary functionality.
Also applies to: 20-20, 36-36, 96-96, 118-119, 129-130, 186-188, 303-309
backend/controllers/github.go (1)
312-320
: LGTM: Added panic recovery to event handlersGood addition of panic recovery in both handlePullRequestEvent and handleIssueCommentEvent handlers. This improves the robustness of the application by preventing crashes and logging panic details for debugging.
Also applies to: 727-735
backend/scripts/curl_bootstrap.sh
Outdated
echo "GITHUB_ORG=${GITHUB_ORG:-your_github_org} | ||
HOSTNAME=http://DIGGER_HOSTNAME | ||
BEARER_AUTH_TOKEN=$(openssl rand -base64 12) | ||
DATABASE_URL=postgres://postgres:root@postgres:5432/postgres?sslmode=disable | ||
HTTP_BASIC_AUTH=1 | ||
HTTP_BASIC_AUTH_USERNAME=myorg | ||
HTTP_BASIC_AUTH_PASSWORD=$(openssl rand -base64 12) | ||
ALLOW_DIRTY=false" > .env && \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enhance environment variable security.
- Consider using a
.env.example
file for template values - Add input validation for critical environment variables
- Document the required environment variables
Would you like me to generate a more secure environment variable handling implementation?
backend/scripts/curl_bootstrap.sh
Outdated
@@ -0,0 +1,36 @@ | |||
echo 'version: '"'"'3.7'"'"' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add shebang line for shell script.
Add a shebang line at the beginning of the script to specify the shell:
+#!/bin/bash
echo 'version: '"'"'3.7'"'"'
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
echo 'version: '"'"'3.7'"'"' | |
#!/bin/bash | |
echo 'version: '"'"'3.7'"'"' |
🧰 Tools
🪛 Shellcheck (0.10.0)
[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.
(SC2148)
backend/scripts/curl_bootstrap.sh
Outdated
image: postgres:alpine | ||
ports: | ||
- "5432:5432" | ||
environment: | ||
- POSTGRES_PASSWORD=root |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enhance PostgreSQL container security and persistence.
Consider these improvements for the PostgreSQL service:
- Use a specific version tag instead of
alpine
for better reproducibility - Use environment variables for sensitive data
- Add volume persistence for data
postgres:
- image: postgres:alpine
+ image: postgres:15-alpine
ports:
- "5432:5432"
environment:
- - POSTGRES_PASSWORD=root
+ - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-root}
+ volumes:
+ - postgres_data:/var/lib/postgresql/data
+
+volumes:
+ postgres_data:
Committable suggestion skipped: line range outside the PR's diff.
backend/utils/graphs.go
Outdated
@@ -43,7 +43,7 @@ func ConvertJobsToDiggerJobs(jobType scheduler.DiggerCommand, vcsType models.Dig | |||
|
|||
log.Printf("marshalledJobsMap: %v\n", marshalledJobsMap) | |||
|
|||
batch, err := models.DB.CreateDiggerBatch(vcsType, githubInstallationId, repoOwner, repoName, repoFullName, prNumber, diggerConfigStr, branch, jobType, &commentId, gitlabProjectId) | |||
batch, err := models.DB.CreateDiggerBatch(vcsType, githubInstallationId, repoOwner, repoName, repoFullName, prNumber, diggerConfigStr, branch, jobType, &commentId,placeholderCommentIdForReport, gitlabProjectId, aiSummaryCommentId, reportTerraformOutput) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix parameter ordering in CreateDiggerBatch call.
The parameter ordering in the CreateDiggerBatch call appears incorrect. The placeholderCommentIdForReport
parameter is placed between commentId
and gitlabProjectId
, breaking the logical grouping of related parameters.
Apply this diff to fix the parameter ordering:
- batch, err := models.DB.CreateDiggerBatch(vcsType, githubInstallationId, repoOwner, repoName, repoFullName, prNumber, diggerConfigStr, branch, jobType, &commentId,placeholderCommentIdForReport, gitlabProjectId, aiSummaryCommentId, reportTerraformOutput)
+ batch, err := models.DB.CreateDiggerBatch(vcsType, githubInstallationId, repoOwner, repoName, repoFullName, prNumber, diggerConfigStr, branch, jobType, &commentId, gitlabProjectId, aiSummaryCommentId, placeholderCommentIdForReport, reportTerraformOutput)
Committable suggestion skipped: line range outside the PR's diff.
backend/controllers/github.go
Outdated
var aiSummaryCommentId = "" | ||
if config.Reporting.AiSummary { | ||
aiSummaryComment, err := ghService.PublishComment(prNumber, "AI Summary will be posted here after completion") | ||
if err != nil { | ||
log.Printf("could not post ai summary comment: %v", err) | ||
commentReporterManager.UpdateComment(fmt.Sprintf(":x: could not post ai comment summary comment id: %v", err)) | ||
return fmt.Errorf("could not post ai summary comment: %v", err) | ||
} | ||
aiSummaryCommentId = aiSummaryComment.Id | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Fix duplicate AI summary implementation
The AI summary comment creation logic is duplicated between handlePullRequestEvent and handleIssueCommentEvent. Consider extracting this into a shared helper function.
func createAiSummaryComment(ghService *dg_github.GithubService, issueNumber int, commentReporterManager utils.CommentReporterManager) (string, error) {
if !config.Reporting.AiSummary {
return "", nil
}
aiSummaryComment, err := ghService.PublishComment(issueNumber, "AI Summary will be posted here after completion")
if err != nil {
log.Printf("could not post ai summary comment: %v", err)
commentReporterManager.UpdateComment(fmt.Sprintf(":x: could not post ai comment summary comment id: %v", err))
return "", fmt.Errorf("could not post ai summary comment: %v", err)
}
return aiSummaryComment.Id, nil
}
Also applies to: 938-947
return fmt.Errorf("comment reporter error: %v", err) | ||
} | ||
|
||
batchId, _, err := utils.ConvertJobsToDiggerJobs(*diggerCommand, models.DiggerVCSGithub, organisationId, impactedJobsMap, impactedProjectsMap, projectsGraph, installationId, branch, prNumber, repoOwner, repoName, repoFullName, commitSha, commentId, &placeholderComment.Id, diggerYmlStr, 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix redeclaration of batchId variable
The batchId variable is redeclared using := operator when it's already defined. This will cause a compilation error.
-batchId, _, err := utils.ConvertJobsToDiggerJobs(
+batchId, _, err = utils.ConvertJobsToDiggerJobs(
Also applies to: 958-958
🧰 Tools
🪛 golangci-lint (1.62.2)
538-538: no new variables on left side of :=
(typecheck)
backend/controllers/github.go
Outdated
for _, line := range lines { | ||
if strings.HasPrefix(line, "+") && !strings.HasPrefix(line, "+++") { | ||
appCode.WriteString(strings.TrimPrefix(line, "+")) | ||
appCode.WriteString("\n") | ||
} | ||
} | ||
} | ||
appCode.WriteString("\n") | ||
} | ||
|
||
if appCode.Len() == 0 { | ||
return "", fmt.Errorf("no code changes found in commit %s. Please ensure the PR contains added or modified code", *commitSha) | ||
} | ||
|
||
return appCode.String(), nil | ||
} | ||
|
||
appCode, err := getCodeFromCommit(ghService, repoOwner, repoName, commitSha, project.Dir) | ||
if err != nil { | ||
commentReporterManager.UpdateComment(fmt.Sprintf(":x: Failed to get code content: %v", err)) | ||
log.Printf("Error getting code content: %v", err) | ||
return fmt.Errorf("error getting code content: %v", err) | ||
} | ||
|
||
commentReporterManager.UpdateComment(fmt.Sprintf(":white_check_mark: Successfully loaded code from commit")) | ||
|
||
log.Printf("the app code is: %v", appCode) | ||
|
||
commentReporterManager.UpdateComment(fmt.Sprintf("Generating terraform...")) | ||
terraformCode, err := utils.GenerateTerraformCode(appCode, generationEndpoint, apiToken) | ||
if err != nil { | ||
commentReporterManager.UpdateComment(fmt.Sprintf(":x: could not generate terraform code: %v", err)) | ||
log.Printf("could not generate terraform code: %v", err) | ||
return fmt.Errorf("could not generate terraform code: %v", err) | ||
} | ||
|
||
commentReporterManager.UpdateComment(fmt.Sprintf(":white_check_mark: Generated terraform")) | ||
|
||
// comment terraform code to project dir | ||
//project.Dir | ||
log.Printf("terraform code is %v", terraformCode) | ||
|
||
baseTree, _, err := ghService.Client.Git.GetTree(context.Background(), repoOwner, repoName, *commitSha, false) | ||
if err != nil { | ||
commentReporterManager.UpdateComment(fmt.Sprintf(":x: Failed to get base tree: %v", err)) | ||
log.Printf("Error getting base tree: %v", err) | ||
return fmt.Errorf("error getting base tree: %v", err) | ||
} | ||
|
||
// Create a new tree with the new file | ||
treeEntries := []*github.TreeEntry{ | ||
{ | ||
Path: github.String(filepath.Join(project.Dir, fmt.Sprintf("generated_%v.tf", issueNumber))), | ||
Mode: github.String("100644"), | ||
Type: github.String("blob"), | ||
Content: github.String(terraformCode), | ||
}, | ||
} | ||
|
||
newTree, _, err := ghService.Client.Git.CreateTree(context.Background(), repoOwner, repoName, *baseTree.SHA, treeEntries) | ||
if err != nil { | ||
commentReporterManager.UpdateComment(fmt.Sprintf(":x: Failed to create new tree: %v", err)) | ||
log.Printf("Error creating new tree: %v", err) | ||
return fmt.Errorf("error creating new tree: %v", err) | ||
} | ||
|
||
// Create the commit | ||
commitMsg := fmt.Sprintf("Add generated Terraform code for %v", projectName) | ||
commit := &github.Commit{ | ||
Message: &commitMsg, | ||
Tree: newTree, | ||
Parents: []*github.Commit{{SHA: commitSha}}, | ||
} | ||
|
||
newCommit, _, err := ghService.Client.Git.CreateCommit(context.Background(), repoOwner, repoName, commit, nil) | ||
if err != nil { | ||
commentReporterManager.UpdateComment(fmt.Sprintf(":x: Failed to commit Terraform file: %v", err)) | ||
log.Printf("Error committing Terraform file: %v", err) | ||
return fmt.Errorf("error committing Terraform file: %v", err) | ||
} | ||
|
||
// Update the reference to point to the new commit | ||
ref := &github.Reference{ | ||
Ref: github.String(fmt.Sprintf("refs/heads/%s", *branch)), | ||
Object: &github.GitObject{ | ||
SHA: newCommit.SHA, | ||
}, | ||
} | ||
_, _, err = ghService.Client.Git.UpdateRef(context.Background(), repoOwner, repoName, ref, false) | ||
if err != nil { | ||
commentReporterManager.UpdateComment(fmt.Sprintf(":x: Failed to update branch reference: %v", err)) | ||
log.Printf("Error updating branch reference: %v", err) | ||
return fmt.Errorf("error updating branch reference: %v", err) | ||
} | ||
|
||
commentReporterManager.UpdateComment(":white_check_mark: Successfully generated and committed Terraform code") | ||
return nil | ||
} | ||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
Security review of code generation implementation
The code generation implementation has several security concerns that need to be addressed:
- The API token is used without any validation of its presence or format
- The HTTP client lacks important security configurations:
- No timeout settings, which could lead to hung connections
- No TLS configuration validation
- The response handling could be improved:
- Large response bodies are not limited, risking memory issues
- Generic error message for non-200 responses could mask security issues
- The generated code is committed without any validation of its content or size
Recommendations:
- Add validation for the API token's presence and format
- Configure HTTP client with appropriate timeouts and TLS settings
- Implement response size limits
- Add proper validation of the generated Terraform code before committing
- Consider adding rate limiting for the generation endpoint
- Improve error handling with more specific error messages for different failure scenarios
🔗 Analysis chain
Review the GenerateTerraformFromCode implementation
The implementation has several areas that could be improved:
- Consider adding rate limiting for API calls
- The 1MB patch size limit should be configurable
- Consider adding retry logic for GitHub API calls
- Add validation for the generated Terraform code before committing
Also, verify the security implications:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check for potential security issues in the code generation endpoint configuration
rg -A 5 "DIGGER_GENERATION_ENDPOINT|DIGGER_GENERATION_API_TOKEN" --type yaml
Length of output: 78
Script:
#!/bin/bash
# Let's check for environment variables and configuration in other file types
rg -A 5 "DIGGER_GENERATION_ENDPOINT|DIGGER_GENERATION_API_TOKEN"
# Check how these variables are used in the codebase
ast-grep --pattern 'os.Getenv("DIGGER_GENERATION_ENDPOINT")'
ast-grep --pattern 'os.Getenv("DIGGER_GENERATION_API_TOKEN")'
# Check the GenerateTerraformCode function implementation for security measures
ast-grep --pattern 'func GenerateTerraformCode($$$)'
Length of output: 4192
# Conflicts: # backend/controllers/github.go # backend/migrations/atlas.sum # backend/models/scheduler.go # backend/models/storage.go # backend/services/spec.go # backend/utils/graphs.go # ee/backend/controllers/gitlab.go # ee/backend/hooks/github.go
60dbc32
to
1d3bc41
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🔭 Outside diff range comments (2)
backend/controllers/github.go (2)
Line range hint
315-315
: Add missing import for 'runtime/debug' packageThe code uses
debug.Stack()
but theruntime/debug
package is not imported. This causes compilation failures.Add this import to fix the compilation error:
+"runtime/debug"
Security improvements needed in code generation implementation
Based on the verification results, several security concerns in the code generation implementation are confirmed:
HTTP client configuration in
GenerateTerraformCode
:
- No timeout settings for HTTP requests
- No TLS configuration validation
- No response size limits (only patch size is limited to 1MB in a different context)
API token handling:
- While the token's presence is checked, there's no validation of its format or strength
- Token is used directly in the Authorization header without any sanitization
Response handling:
io.ReadAll
is used without size limits, potentially leading to memory exhaustion- Error messages at lines 49-55 are too generic and could mask security issues
- No validation of generated code content before using it
Recommendations:
- Add request timeout settings
- Implement response size limits
- Add proper TLS configuration
- Validate and sanitize API token
- Implement content validation for generated code
- Improve error handling with more specific messages
🔗 Analysis chain
Line range hint
1066-1067
: Improve security in code generation implementationThe code generation implementation has several security concerns that need to be addressed:
- The API token is used without any validation of its presence or format
- The HTTP client lacks important security configurations:
- No timeout settings
- No TLS configuration validation
- The response handling could be improved:
- Large response bodies are not limited
- Generic error message for non-200 responses could mask security issues
- The generated code is committed without any validation of its content or size
Run this script to check for potential security issues:
Also applies to: 1073-1074
Let me gather more information about the security measures in place.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Check for potential security issues in the code generation endpoint configuration rg -A 5 "DIGGER_GENERATION_ENDPOINT|DIGGER_GENERATION_API_TOKEN" --type yaml # Let's check for environment variables and configuration in other file types rg -A 5 "DIGGER_GENERATION_ENDPOINT|DIGGER_GENERATION_API_TOKEN" # Check the GenerateTerraformCode function implementation for security measures ast-grep --pattern 'func GenerateTerraformCode($$$)'Length of output: 4144
Script:
#!/bin/bash # Check for any size limits or validation in the code rg -A 5 "MaxPatchSize|MaxFileSize|MaxBodySize" backend/ # Check for timeout configurations rg -A 5 "Timeout|timeout" backend/utils/ # Check for TLS configuration rg -A 5 "TLSConfig|tls" backend/utils/ # Check for any validation of generated code rg -A 5 "validate|sanitize|check" backend/utils/ai.goLength of output: 1466
♻️ Duplicate comments (2)
backend/controllers/github.go (2)
528-529
:⚠️ Potential issueFix incorrect error message in placeholder comment creation
The error message incorrectly references "strconv.ParseInt" when the error is from publishing a comment.
Apply this fix:
-log.Printf("strconv.ParseInt error: %v", err) +log.Printf("failed to publish placeholder comment: %v", err)Also applies to: 944-945
533-533
:⚠️ Potential issueFix redeclaration of batchId variable
The batchId variable is redeclared using := operator when it's already defined. This will cause a compilation error.
Apply this fix:
-batchId, _, err := utils.ConvertJobsToDiggerJobs( +batchId, _, err = utils.ConvertJobsToDiggerJobs(Also applies to: 949-949
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
backend/controllers/github.go
(3 hunks)backend/models/scheduler.go
(1 hunks)backend/models/storage.go
(2 hunks)backend/utils/graphs.go
(2 hunks)ee/backend/controllers/gitlab.go
(2 hunks)ee/backend/hooks/github.go
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
- ee/backend/hooks/github.go
- backend/models/storage.go
- backend/models/scheduler.go
- ee/backend/controllers/gitlab.go
- backend/utils/graphs.go
🧰 Additional context used
🪛 GitHub Actions: EE Backend Go Tests
backend/controllers/github.go
[error] 315-315: Undefined variable 'debug' referenced in code
🪛 GitHub Actions: Backend Go Tests
backend/controllers/github.go
[error] 315-315: Undefined variable 'debug' used in code
|
||
placeholderComment, err := ghService.PublishComment(prNumber, "digger report placehoder") | ||
if err != nil { | ||
log.Printf("strconv.ParseInt error: %v", err) | ||
commentReporterManager.UpdateComment(fmt.Sprintf(":x: could not create placeholder commentId for report: %v", err)) | ||
return fmt.Errorf("comment reporter error: %v", err) | ||
} | ||
|
||
batchId, _, err := utils.ConvertJobsToDiggerJobs(*diggerCommand, models.DiggerVCSGithub, organisationId, impactedJobsMap, impactedProjectsMap, projectsGraph, installationId, branch, prNumber, repoOwner, repoName, repoFullName, commitSha, commentId, &placeholderComment.Id, diggerYmlStr, 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Extract duplicate placeholder comment logic into a helper function
The placeholder comment creation logic is duplicated between handlePullRequestEvent
and handleIssueCommentEvent
. This violates the DRY principle.
Extract the logic into a helper function:
func createPlaceholderComment(ghService *dg_github.GithubService, number int, commentReporterManager utils.CommentReporterManager) (*github.IssueComment, error) {
placeholderComment, err := ghService.PublishComment(number, "digger report placeholder")
if err != nil {
log.Printf("failed to publish placeholder comment: %v", err)
commentReporterManager.UpdateComment(fmt.Sprintf(":x: could not create placeholder commentId for report: %v", err))
return nil, fmt.Errorf("comment reporter error: %v", err)
}
return placeholderComment, nil
}
Also applies to: 942-949
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
backend/migrations/20250102194016.sql (1)
1-2
: Consider adding these maintainability improvements.
- Add a column description to document its purpose:
COMMENT ON COLUMN "public"."digger_batches"."placeholder_comment_id_for_report" IS 'Stores the ID of the placeholder comment created for AI summary during job processing';
- Add a DOWN migration for rollback capability:
-- Add to a separate rollback file or section: ALTER TABLE "public"."digger_batches" DROP COLUMN "placeholder_comment_id_for_report";
- Consider adding an index if this column will be frequently queried:
CREATE INDEX idx_digger_batches_placeholder_comment ON "public"."digger_batches" ("placeholder_comment_id_for_report");
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
backend/migrations/atlas.sum
is excluded by!**/*.sum
📒 Files selected for processing (1)
backend/migrations/20250102194016.sql
(1 hunks)
🔇 Additional comments (1)
backend/migrations/20250102194016.sql (1)
1-2
: LGTM! Safe schema change.The migration adds a nullable text column which is a non-blocking operation. The column type and nullability are appropriate for storing comment IDs.
Summary by CodeRabbit
Based on the comprehensive summary, here are the release notes:
New Features
Improvements
Bug Fixes
Technical Updates