diff --git a/server/events/command/project_result_test.go b/server/events/command/project_result_test.go index cd1e7bb67..0c917b9d3 100644 --- a/server/events/command/project_result_test.go +++ b/server/events/command/project_result_test.go @@ -225,3 +225,67 @@ func TestPlanSuccess_Summary(t *testing.T) { }) } } + +var Summary string + +func BenchmarkPlanSuccess_Summary(b *testing.B) { + var s string + + fixtures := map[string]string{ + "changes": ` + An execution plan has been generated and is shown below. + Resource actions are indicated with the following symbols: + - destroy + + Terraform will perform the following actions: + + - null_resource.hi[1] + + + Plan: 0 to add, 0 to change, 1 to destroy.`, + "no changes": ` + An execution plan has been generated and is shown below. + Resource actions are indicated with the following symbols: + + No changes. Infrastructure is up-to-date.`, + "changes outside Terraform": ` + Note: Objects have changed outside of Terraform + + Terraform detected the following changes made outside of Terraform since the + last "terraform apply": + + No changes. Your infrastructure matches the configuration.`, + "changes and changes outside": ` + Note: Objects have changed outside of Terraform + + Terraform detected the following changes made outside of Terraform since the + last "terraform apply": + + An execution plan has been generated and is shown below. + Resource actions are indicated with the following symbols: + - destroy + + Terraform will perform the following actions: + + - null_resource.hi[1] + + + Plan: 0 to add, 0 to change, 1 to destroy.`, + "empty summary, no matches": `No match, expect empty`, + } + + for name, output := range fixtures { + p := &models.PlanSuccess{ + TerraformOutput: output, + } + + b.Run(name, func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + s = p.Summary() + } + + Summary = s + }) + } +} diff --git a/server/events/markdown_renderer_test.go b/server/events/markdown_renderer_test.go index 094ef1c56..6a9151a3c 100644 --- a/server/events/markdown_renderer_test.go +++ b/server/events/markdown_renderer_test.go @@ -2214,8 +2214,7 @@ $$$ } } -func TestRenderProjectResultsWithEnableDiffMarkdownFormat(t *testing.T) { - tfOutput := `An execution plan has been generated and is shown below. +const tfOutput = `An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: ~ update in-place -/+ destroy and then create replacement @@ -2398,30 +2397,31 @@ Terraform will perform the following actions: Plan: 1 to add, 2 to change, 1 to destroy. ` - cases := []struct { - Description string - Command command.Name - ProjectResults []command.ProjectResult - VCSHost models.VCSHostType - Expected string - }{ - { - "single successful plan with diff markdown formatted", - command.Plan, - []command.ProjectResult{ - { - PlanSuccess: &models.PlanSuccess{ - TerraformOutput: tfOutput, - LockURL: "lock-url", - RePlanCmd: "atlantis plan -d path -w workspace", - ApplyCmd: "atlantis apply -d path -w workspace", - }, - Workspace: "workspace", - RepoRelDir: "path", + +var cases = []struct { + Description string + Command command.Name + ProjectResults []command.ProjectResult + VCSHost models.VCSHostType + Expected string +}{ + { + "single successful plan with diff markdown formatted", + command.Plan, + []command.ProjectResult{ + { + PlanSuccess: &models.PlanSuccess{ + TerraformOutput: tfOutput, + LockURL: "lock-url", + RePlanCmd: "atlantis plan -d path -w workspace", + ApplyCmd: "atlantis apply -d path -w workspace", }, + Workspace: "workspace", + RepoRelDir: "path", }, - models.Github, - `Ran Plan for dir: $path$ workspace: $workspace$ + }, + models.Github, + `Ran Plan for dir: $path$ workspace: $workspace$
Show Output @@ -2619,8 +2619,10 @@ Plan: 1 to add, 2 to change, 1 to destroy. `, - }, - } + }, +} + +func TestRenderProjectResultsWithEnableDiffMarkdownFormat(t *testing.T) { r := events.GetMarkdownRenderer( false, // GitlabSupportsCommonMark true, // DisableApplyAll @@ -2650,3 +2652,36 @@ Plan: 1 to add, 2 to change, 1 to destroy. }) } } + +var Render string + +func BenchmarkRenderProjectResultsWithEnableDiffMarkdownFormat(b *testing.B) { + var render string + + r := events.GetMarkdownRenderer( + false, // GitlabSupportsCommonMark + true, // DisableApplyAll + true, // DisableApply + false, // DisableMarkdownFolding + false, // DisableRepoLocking + true, // EnableDiffMarkdownFormat + "", // MarkdownTemplateOverridesDir + ) + + for _, c := range cases { + b.Run(c.Description, func(b *testing.B) { + res := command.Result{ + ProjectResults: c.ProjectResults, + } + for _, verbose := range []bool{true, false} { + b.Run(fmt.Sprintf("verbose %t", verbose), func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + render = r.Render(res, c.Command, "log", verbose, c.VCSHost) + } + Render = render + }) + } + }) + } +} diff --git a/server/events/models/models.go b/server/events/models/models.go index 0ca9e8d94..7ebcca65c 100644 --- a/server/events/models/models.go +++ b/server/events/models/models.go @@ -366,28 +366,34 @@ type PlanSuccess struct { HasDiverged bool } +// Summary regexes +var ( + reChangesOutside = regexp.MustCompile(`Note: Objects have changed outside of Terraform`) + rePlanChanges = regexp.MustCompile(`Plan: \d+ to add, \d+ to change, \d+ to destroy.`) + reNoChanges = regexp.MustCompile(`No changes. (Infrastructure is up-to-date|Your infrastructure matches the configuration).`) +) + // Summary extracts one line summary of plan changes from TerraformOutput. func (p *PlanSuccess) Summary() string { note := "" - r := regexp.MustCompile(`Note: Objects have changed outside of Terraform`) - if match := r.FindString(p.TerraformOutput); match != "" { - note = fmt.Sprintf("\n**%s**\n", match) + if match := reChangesOutside.FindString(p.TerraformOutput); match != "" { + note = "\n**" + match + "**\n" } - - r = regexp.MustCompile(`Plan: \d+ to add, \d+ to change, \d+ to destroy.`) - if match := r.FindString(p.TerraformOutput); match != "" { + if match := rePlanChanges.FindString(p.TerraformOutput); match != "" { return note + match } - r = regexp.MustCompile(`No changes. (Infrastructure is up-to-date|Your infrastructure matches the configuration).`) - return note + r.FindString(p.TerraformOutput) + return note + reNoChanges.FindString(p.TerraformOutput) } +// Diff Markdown regexes +var ( + diffKeywordRegex = regexp.MustCompile(`(?m)^( +)([-+~]\s)(.*)(\s=\s|\s->\s|<<|\{|\(known after apply\)| {2,}[^ ]+:.*)(.*)`) + diffListRegex = regexp.MustCompile(`(?m)^( +)([-+~]\s)(".*",)`) + diffTildeRegex = regexp.MustCompile(`(?m)^~`) +) + // DiffMarkdownFormattedTerraformOutput formats the Terraform output to match diff markdown format func (p PlanSuccess) DiffMarkdownFormattedTerraformOutput() string { - diffKeywordRegex := regexp.MustCompile(`(?m)^( +)([-+~]\s)(.*)(\s=\s|\s->\s|<<|\{|\(known after apply\)| {2,}[^ ]+:.*)(.*)`) - diffListRegex := regexp.MustCompile(`(?m)^( +)([-+~]\s)(".*",)`) - diffTildeRegex := regexp.MustCompile(`(?m)^~`) - formattedTerraformOutput := diffKeywordRegex.ReplaceAllString(p.TerraformOutput, "$2$1$3$4$5") formattedTerraformOutput = diffListRegex.ReplaceAllString(formattedTerraformOutput, "$2$1$3") formattedTerraformOutput = diffTildeRegex.ReplaceAllString(formattedTerraformOutput, "!")