Skip to content

Commit

Permalink
publish ai summaries (#1864)
Browse files Browse the repository at this point in the history
* publish ai summaries
  • Loading branch information
motatoes authored Dec 30, 2024
1 parent 34d1db1 commit 9599562
Show file tree
Hide file tree
Showing 27 changed files with 531 additions and 700 deletions.
40 changes: 34 additions & 6 deletions backend/controllers/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import (
"net/http"
"net/url"
"os"
"path"
"path/filepath"
"reflect"
"runtime/debug"
Expand Down Expand Up @@ -511,7 +510,19 @@ func handlePullRequestEvent(gh utils.GithubClientProvider, payload *github.PullR
log.Printf("strconv.ParseInt error: %v", err)
commentReporterManager.UpdateComment(fmt.Sprintf(":x: could not handle commentId: %v", err))
}
batchId, _, err := utils.ConvertJobsToDiggerJobs(*diggerCommand, models.DiggerVCSGithub, organisationId, impactedJobsMap, impactedProjectsMap, projectsGraph, installationId, branch, prNumber, repoOwner, repoName, repoFullName, commitSha, commentId, diggerYmlStr, 0)

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
}

batchId, _, err := utils.ConvertJobsToDiggerJobs(*diggerCommand, models.DiggerVCSGithub, organisationId, impactedJobsMap, impactedProjectsMap, projectsGraph, installationId, branch, prNumber, repoOwner, repoName, repoFullName, commitSha, commentId, diggerYmlStr, 0, aiSummaryCommentId, config.ReportTerraformOutputs)
if err != nil {
log.Printf("ConvertJobsToDiggerJobs error: %v", err)
commentReporterManager.UpdateComment(fmt.Sprintf(":x: ConvertJobsToDiggerJobs error: %v", err))
Expand Down Expand Up @@ -585,8 +596,11 @@ func GetDiggerConfigForBranch(gh utils.GithubClientProvider, installationId int6
var dependencyGraph graph.Graph[string, dg_configuration.Project]

err = utils.CloneGitRepoAndDoAction(cloneUrl, branch, "", *token, func(dir string) error {
diggerYmlBytes, err := os.ReadFile(path.Join(dir, "digger.yml"))
diggerYmlStr = string(diggerYmlBytes)
diggerYmlStr, err = dg_configuration.ReadDiggerYmlFileContents(dir)
if err != nil {
log.Printf("could not load digger config: %v", err)
return err
}
config, _, dependencyGraph, err = dg_configuration.LoadDiggerConfig(dir, true, changedFiles)
if err != nil {
log.Printf("Error loading digger config: %v", err)
Expand Down Expand Up @@ -768,7 +782,10 @@ func handleIssueCommentEvent(gh utils.GithubClientProvider, payload *github.Issu
// terraform code generator
if os.Getenv("DIGGER_GENERATION_ENABLED") == "1" {
err = GenerateTerraformFromCode(payload, commentReporterManager, config, defaultBranch, ghService, repoOwner, repoName, commitSha, issueNumber, branch)
return err
if err != nil {
log.Printf("terraform generation failed: %v", err)
return err
}
}

commentIdStr := strconv.FormatInt(userCommentId, 10)
Expand Down Expand Up @@ -902,7 +919,18 @@ func handleIssueCommentEvent(gh utils.GithubClientProvider, payload *github.Issu
return fmt.Errorf("comment reporter error: %v", err)
}

batchId, _, err := utils.ConvertJobsToDiggerJobs(*diggerCommand, "github", orgId, impactedProjectsJobMap, impactedProjectsMap, projectsGraph, installationId, *branch, issueNumber, repoOwner, repoName, repoFullName, *commitSha, reporterCommentId, diggerYmlStr, 0)
var aiSummaryCommentId = ""
if config.Reporting.AiSummary {
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)
}
aiSummaryCommentId = aiSummaryComment.Id
}

batchId, _, err := utils.ConvertJobsToDiggerJobs(*diggerCommand, "github", orgId, impactedProjectsJobMap, impactedProjectsMap, projectsGraph, installationId, *branch, issueNumber, repoOwner, repoName, repoFullName, *commitSha, reporterCommentId, diggerYmlStr, 0, aiSummaryCommentId, config.ReportTerraformOutputs)
if err != nil {
log.Printf("ConvertJobsToDiggerJobs error: %v", err)
commentReporterManager.UpdateComment(fmt.Sprintf(":x: ConvertJobsToDiggerJobs error: %v", err))
Expand Down
8 changes: 4 additions & 4 deletions backend/controllers/github_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -731,7 +731,7 @@ func TestJobsTreeWithOneJobsAndTwoProjects(t *testing.T) {
graph, err := configuration.CreateProjectDependencyGraph(projects)
assert.NoError(t, err)

_, result, err := utils.ConvertJobsToDiggerJobs("", "github", 1, jobs, projectMap, graph, 41584295, "", 2, "diggerhq", "parallel_jobs_demo", "diggerhq/parallel_jobs_demo", "", 123, "test", 0)
_, result, err := utils.ConvertJobsToDiggerJobs("", "github", 1, jobs, projectMap, graph, 41584295, "", 2, "diggerhq", "parallel_jobs_demo", "diggerhq/parallel_jobs_demo", "", 123, "test", 0, "", false)
assert.NoError(t, err)
assert.Equal(t, 1, len(result))
parentLinks, err := models.DB.GetDiggerJobParentLinksChildId(&result["dev"].DiggerJobID)
Expand Down Expand Up @@ -760,7 +760,7 @@ func TestJobsTreeWithTwoDependantJobs(t *testing.T) {
projectMap["dev"] = project1
projectMap["prod"] = project2

_, result, err := utils.ConvertJobsToDiggerJobs("", "github", 1, jobs, projectMap, graph, 123, "", 2, "", "", "test", "", 123, "test", 0)
_, result, err := utils.ConvertJobsToDiggerJobs("", "github", 1, jobs, projectMap, graph, 123, "", 2, "", "", "test", "", 123, "test", 0, "", false)
assert.NoError(t, err)
assert.Equal(t, 2, len(result))

Expand Down Expand Up @@ -793,7 +793,7 @@ func TestJobsTreeWithTwoIndependentJobs(t *testing.T) {
projectMap["dev"] = project1
projectMap["prod"] = project2

_, result, err := utils.ConvertJobsToDiggerJobs("", "github", 1, jobs, projectMap, graph, 123, "", 2, "", "", "test", "", 123, "test", 0)
_, result, err := utils.ConvertJobsToDiggerJobs("", "github", 1, jobs, projectMap, graph, 123, "", 2, "", "", "test", "", 123, "test", 0, "", false)
assert.NoError(t, err)
assert.Equal(t, 2, len(result))
parentLinks, err := models.DB.GetDiggerJobParentLinksChildId(&result["dev"].DiggerJobID)
Expand Down Expand Up @@ -838,7 +838,7 @@ func TestJobsTreeWithThreeLevels(t *testing.T) {
projectMap["555"] = project5
projectMap["666"] = project6

_, result, err := utils.ConvertJobsToDiggerJobs("", "github", 1, jobs, projectMap, graph, 123, "", 2, "", "", "test", "", 123, "test", 0)
_, result, err := utils.ConvertJobsToDiggerJobs("", "github", 1, jobs, projectMap, graph, 123, "", 2, "", "", "test", "", 123, "test", 0, "", false)
assert.NoError(t, err)
assert.Equal(t, 6, len(result))
parentLinks, err := models.DB.GetDiggerJobParentLinksChildId(&result["111"].DiggerJobID)
Expand Down
78 changes: 69 additions & 9 deletions backend/controllers/projects.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"gorm.io/gorm"
"log"
"net/http"
"os"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -323,7 +324,6 @@ type SetJobStatusRequest struct {
Footprint *iac_utils.IacPlanFootprint `json:"job_plan_footprint"`
PrCommentUrl string `json:"pr_comment_url"`
TerraformOutput string `json:"terraform_output"`

}

func (d DiggerController) SetJobStatusForProject(c *gin.Context) {
Expand Down Expand Up @@ -482,6 +482,11 @@ func (d DiggerController) SetJobStatusForProject(c *gin.Context) {
return
}

err = CreateTerraformOutputsSummary(d.GithubClientProvider, batch)
if err != nil {
log.Printf("could not generate terraform plans summary: %v", err)
}

err = AutomergePRforBatchIfEnabled(d.GithubClientProvider, batch)
if err != nil {
log.Printf("Error merging PR with automerge option: %v", err)
Expand All @@ -493,7 +498,6 @@ func (d DiggerController) SetJobStatusForProject(c *gin.Context) {
if err != nil {
log.Printf("Error getting batch details: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Error getting batch details"})

}

UpdateCommentsForBatchGroup(d.GithubClientProvider, batch, res.Jobs)
Expand Down Expand Up @@ -648,6 +652,69 @@ func GetPrServiceFromBatch(batch *models.DiggerBatch, gh utils.GithubClientProvi
return nil, fmt.Errorf("could not retrieive a service for %v", batch.VCS)
}

func CreateTerraformOutputsSummary(gh utils.GithubClientProvider, batch *models.DiggerBatch) error {
diggerYmlString := batch.DiggerConfig
diggerConfigYml, err := digger_config.LoadDiggerConfigYamlFromString(diggerYmlString)
if err != nil {
log.Printf("Error loading digger config from batch: %v", err)
return fmt.Errorf("error loading digger config from batch: %v", err)
}

config, _, err := digger_config.ConvertDiggerYamlToConfig(diggerConfigYml)

if batch.Status == orchestrator_scheduler.BatchJobSucceeded && config.Reporting.AiSummary == true {
prService, err := GetPrServiceFromBatch(batch, gh)
if err != nil {
log.Printf("Error getting github service: %v", err)
prService.EditComment(batch.PrNumber, batch.AiSummaryCommentId, ":x: could not generate AI summary \n\n could not communicate with github")
return fmt.Errorf("error getting github service: %v", err)
}

if batch.AiSummaryCommentId == "" {
log.Printf("could not post summary comment, initial comment not found")
prService.PublishComment(batch.PrNumber, ":x: could not generate AI summary \n\n could not communicate with github")
return fmt.Errorf("could not post summary comment, initial comment not found")
}

summaryEndpoint := os.Getenv("DIGGER_AI_SUMMARY_ENDPOINT")
if summaryEndpoint == "" {
log.Printf("could not generate AI summary, ai summary endpoint missing")
prService.EditComment(batch.PrNumber, batch.AiSummaryCommentId, ":x: could not generate AI summary \n\n comment ID is missing ")
return fmt.Errorf("could not generate AI summary, ai summary endpoint missing")
}
apiToken := os.Getenv("DIGGER_AI_SUMMARY_API_TOKEN")

jobs, err := models.DB.GetDiggerJobsForBatch(batch.ID)
if err != nil {
log.Printf("could not get jobs for batch: %v", err)
prService.EditComment(batch.PrNumber, batch.AiSummaryCommentId, ":x: could not generate AI summary \n\n error fetching jobs ")
return fmt.Errorf("could not get jobs for batch: %v", err)
}

var terraformOutputs = "## AI Summary for terraform runs\n\n"
for _, job := range jobs {
var jobSpec orchestrator_scheduler.JobJson
err := json.Unmarshal(job.SerializedJobSpec, &jobSpec)
if err != nil {
log.Printf("could not summarise plans due to unmarshalling error: %v", err)
prService.EditComment(batch.PrNumber, batch.AiSummaryCommentId, ":x: could not generate AI summary \n\n error fetching job spec")
return fmt.Errorf("could not summarise plans due to unmarshalling error: %v", err)
}
projectName := jobSpec.ProjectName
terraformOutputs += fmt.Sprintf("terraform output for %v \n\n", projectName) + job.TerraformOutput
}
summary, err := utils.GetAiSummaryFromTerraformPlans(terraformOutputs, summaryEndpoint, apiToken)
if err != nil {
log.Printf("could not summarise terraform outputs: %v", err)
prService.EditComment(batch.PrNumber, batch.AiSummaryCommentId, ":x: could not generate AI summary \n\n error generating summary from plans")
return fmt.Errorf("could not summarise terraform outputs: %v", err)
}

prService.EditComment(batch.PrNumber, batch.AiSummaryCommentId, summary)
}
return nil
}

func AutomergePRforBatchIfEnabled(gh utils.GithubClientProvider, batch *models.DiggerBatch) error {
diggerYmlString := batch.DiggerConfig
diggerConfigYml, err := digger_config.LoadDiggerConfigYamlFromString(diggerYmlString)
Expand All @@ -663,13 +730,6 @@ func AutomergePRforBatchIfEnabled(gh utils.GithubClientProvider, batch *models.D
automerge = false
}
if batch.Status == orchestrator_scheduler.BatchJobSucceeded && batch.BatchType == orchestrator_scheduler.DiggerCommandApply && automerge == true {
//ghService, _, err := utils.GetGithubService(
// gh,
// batch.GithubInstallationId,
// batch.RepoFullName,
// batch.RepoOwner,
// batch.RepoName,
//)
prService, err := GetPrServiceFromBatch(batch, gh)
if err != nil {
log.Printf("Error getting github service: %v", err)
Expand Down
2 changes: 2 additions & 0 deletions backend/migrations/20241229112312.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- Modify "digger_batches" table
ALTER TABLE "public"."digger_batches" ADD COLUMN "ai_summary_comment_id" text NULL, ADD COLUMN "report_terraform_outputs" boolean NULL;
3 changes: 2 additions & 1 deletion backend/migrations/atlas.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
h1:+aJac+1voE00wJ5clz52DJ/fLljzr4l1KNsP8e3ZZYA=
h1:kHWmqYJMe9ZbdcztvM02SVEs5lyw/RFbKzZmqgbmSIk=
20231227132525.sql h1:43xn7XC0GoJsCnXIMczGXWis9d504FAWi4F1gViTIcw=
20240115170600.sql h1:IW8fF/8vc40+eWqP/xDK+R4K9jHJ9QBSGO6rN9LtfSA=
20240116123649.sql h1:R1JlUIgxxF6Cyob9HdtMqiKmx/BfnsctTl5rvOqssQw=
Expand Down Expand Up @@ -34,3 +34,4 @@ h1:+aJac+1voE00wJ5clz52DJ/fLljzr4l1KNsP8e3ZZYA=
20241107163722.sql h1:D5+D4TJxs80GIYrKbf70P1Vc2FUuiFVGxlu424kxYbg=
20241107172343.sql h1:E1j+7R5TZlyCKEpyYmH1mJ2zh+y5hVbtQ/PuEMJR7us=
20241114202249.sql h1:P2DhJK8MLe8gSAAz+Y5KNmsvKVw8KfLQPCncynYXEfM=
20241229112312.sql h1:Fr06uwt7LcQoLh6bjGzKB+uy9i8+uk8m6jfi+OBBbP4=
28 changes: 15 additions & 13 deletions backend/models/scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,21 @@ const DiggerVCSGithub DiggerVCSType = "github"
const DiggerVCSGitlab DiggerVCSType = "gitlab"

type DiggerBatch struct {
ID uuid.UUID `gorm:"primary_key"`
VCS DiggerVCSType
PrNumber int
CommentId *int64
Status orchestrator_scheduler.DiggerBatchStatus
BranchName string
DiggerConfig string
GithubInstallationId int64
GitlabProjectId int
RepoFullName string
RepoOwner string
RepoName string
BatchType orchestrator_scheduler.DiggerCommand
ID uuid.UUID `gorm:"primary_key"`
VCS DiggerVCSType
PrNumber int
CommentId *int64
AiSummaryCommentId string
Status orchestrator_scheduler.DiggerBatchStatus
BranchName string
DiggerConfig string
GithubInstallationId int64
GitlabProjectId int
RepoFullName string
RepoOwner string
RepoName string
BatchType orchestrator_scheduler.DiggerCommand
ReportTerraformOutputs bool
// used for module source grouping comments
SourceDetails []byte
}
Expand Down
30 changes: 16 additions & 14 deletions backend/models/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -617,22 +617,24 @@ func (db *Database) GetDiggerBatch(batchId *uuid.UUID) (*DiggerBatch, error) {
return batch, nil
}

func (db *Database) CreateDiggerBatch(vcsType DiggerVCSType, githubInstallationId int64, repoOwner string, repoName string, repoFullname string, PRNumber int, diggerConfig string, branchName string, batchType scheduler.DiggerCommand, commentId *int64, gitlabProjectId int) (*DiggerBatch, error) {
func (db *Database) CreateDiggerBatch(vcsType DiggerVCSType, githubInstallationId int64, repoOwner string, repoName string, repoFullname string, PRNumber int, diggerConfig string, branchName string, batchType scheduler.DiggerCommand, commentId *int64, gitlabProjectId int, aiSummaryCommentId string, reportTerraformOutputs bool) (*DiggerBatch, error) {
uid := uuid.New()
batch := &DiggerBatch{
ID: uid,
VCS: vcsType,
GithubInstallationId: githubInstallationId,
RepoOwner: repoOwner,
RepoName: repoName,
RepoFullName: repoFullname,
PrNumber: PRNumber,
CommentId: commentId,
Status: scheduler.BatchJobCreated,
BranchName: branchName,
DiggerConfig: diggerConfig,
BatchType: batchType,
GitlabProjectId: gitlabProjectId,
ID: uid,
VCS: vcsType,
GithubInstallationId: githubInstallationId,
RepoOwner: repoOwner,
RepoName: repoName,
RepoFullName: repoFullname,
PrNumber: PRNumber,
CommentId: commentId,
Status: scheduler.BatchJobCreated,
BranchName: branchName,
DiggerConfig: diggerConfig,
BatchType: batchType,
GitlabProjectId: gitlabProjectId,
AiSummaryCommentId: aiSummaryCommentId,
ReportTerraformOutputs: reportTerraformOutputs,
}
result := db.GormDB.Save(batch)
if result.Error != nil {
Expand Down
2 changes: 1 addition & 1 deletion backend/models/storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func TestGetDiggerJobsForBatchPreloadsSummary(t *testing.T) {
resourcesUpdated := uint(2)
resourcesDeleted := uint(3)

batch, err := DB.CreateDiggerBatch(DiggerVCSGithub, 123, repoOwner, repoName, repoFullName, prNumber, diggerconfig, branchName, batchType, &commentId, 0)
batch, err := DB.CreateDiggerBatch(DiggerVCSGithub, 123, repoOwner, repoName, repoFullName, prNumber, diggerconfig, branchName, batchType, &commentId, 0, "", false)
assert.NoError(t, err)

job, err := DB.CreateDiggerJob(batch.ID, []byte(jobSpec), "workflow_file.yml")
Expand Down
5 changes: 3 additions & 2 deletions backend/services/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ func GetSpecFromJob(job models.DiggerJob) (*spec.Spec, error) {
CommentId: strconv.FormatInt(*batch.CommentId, 10),
Job: jobSpec,
Reporter: spec.ReporterSpec{
ReportingStrategy: "comments_per_run",
ReporterType: "lazy",
ReportingStrategy: "comments_per_run",
ReporterType: "lazy",
ReportTerraformOutput: batch.ReportTerraformOutputs,
},
Lock: spec.LockSpec{
LockType: "noop",
Expand Down
2 changes: 1 addition & 1 deletion backend/tasks/runs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ func TestThatRunQueueItemMovesFromQueuedToPlanningAfterPickup(t *testing.T) {

for i, testParam := range testParameters {
ciService := github2.MockCiService{}
batch, _ := models.DB.CreateDiggerBatch(models.DiggerVCSGithub, 123, "", "", "", 22, "", "", "", nil, 0)
batch, _ := models.DB.CreateDiggerBatch(models.DiggerVCSGithub, 123, "", "", "", 22, "", "", "", nil, 0, "", false)
project, _ := models.DB.CreateProject(fmt.Sprintf("test%v", i), nil, nil, false, false)
planStage, _ := models.DB.CreateDiggerRunStage(batch.ID.String())
applyStage, _ := models.DB.CreateDiggerRunStage(batch.ID.String())
Expand Down
Loading

0 comments on commit 9599562

Please sign in to comment.