diff --git a/README.md b/README.md index e53603f..ced1ea7 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ Placeholder | Usage ---|--- `{{ .Title }}` | Like `## Plan result` `{{ .Message }}` | A string that can be set from CLI with `--message` option +`{{ .Action }}` | Using in terraform plan, and matched leading message by parsing like `Terraform will perform the following actions:` `{{ .Result }}` | Matched result by parsing like `Plan: 1 to add` or `No changes` `{{ .Body }}` | The entire of Terraform execution result `{{ .Link }}` | The link of the build page on CI diff --git a/terraform/parser.go b/terraform/parser.go index 1c6926a..35e7f97 100644 --- a/terraform/parser.go +++ b/terraform/parser.go @@ -15,6 +15,7 @@ type Parser interface { type ParseResult struct { Result string HasDestroy bool + Action string ExitCode int Error error } @@ -32,6 +33,7 @@ type FmtParser struct { // PlanParser is a parser for terraform plan type PlanParser struct { Pass *regexp.Regexp + Action *regexp.Regexp Fail *regexp.Regexp HasDestroy *regexp.Regexp } @@ -57,8 +59,9 @@ func NewFmtParser() *FmtParser { // NewPlanParser is PlanParser initialized with its Regexp func NewPlanParser() *PlanParser { return &PlanParser{ - Pass: regexp.MustCompile(`(?m)^(Plan: \d|No changes.)`), - Fail: regexp.MustCompile(`(?m)^(Error: )`), + Pass: regexp.MustCompile(`(?m)^(Plan: \d|No changes.)`), + Action: regexp.MustCompile(`(?m)^(An execution plan has been generated)`), + Fail: regexp.MustCompile(`(?m)^(Error: )`), // "0 to destroy" should be treated as "no destroy" HasDestroy: regexp.MustCompile(`(?m)([1-9][0-9]* to destroy.)`), } @@ -107,9 +110,13 @@ func (p *PlanParser) Parse(body string) ParseResult { } } lines := strings.Split(body, "\n") - var i int - var result, line string + var i, actionStartIdx int + var result, action, line string for i, line = range lines { + if p.Action.MatchString(line) { + // action starts with the line: An execution plan... + actionStartIdx = i + } if p.Pass.MatchString(line) || p.Fail.MatchString(line) { break } @@ -117,6 +124,10 @@ func (p *PlanParser) Parse(body string) ParseResult { switch { case p.Pass.MatchString(line): result = lines[i] + if actionStartIdx != 0 { + // action ends with the line above summary + action = strings.Join(trimLastNewline(lines[actionStartIdx:i]), "\n") + } case p.Fail.MatchString(line): result = strings.Join(trimLastNewline(lines[i:]), "\n") } @@ -126,6 +137,7 @@ func (p *PlanParser) Parse(body string) ParseResult { return ParseResult{ Result: result, HasDestroy: hasDestroy, + Action: action, ExitCode: exitCode, Error: nil, } diff --git a/terraform/parser_test.go b/terraform/parser_test.go index c7f964e..882b510 100644 --- a/terraform/parser_test.go +++ b/terraform/parser_test.go @@ -35,7 +35,7 @@ versions.tf --- old/versions.tf +++ new/versions.tf @@ -1,4 +1,4 @@ - + terraform { - required_version = ">= 0.12" + required_version = ">= 0.12" @@ -309,8 +309,22 @@ func TestPlanParserParse(t *testing.T) { result: ParseResult{ Result: "Plan: 1 to add, 0 to change, 0 to destroy.", HasDestroy: false, - ExitCode: 0, - Error: nil, + Action: `An execution plan has been generated and is shown below. +Resource actions are indicated with the following symbols: + + create + +Terraform will perform the following actions: + + + google_compute_global_address.my_another_project + id: + address: + ip_version: "IPV4" + name: "my-another-project" + project: "my-project" + self_link: +`, + ExitCode: 0, + Error: nil, }, }, { diff --git a/terraform/template.go b/terraform/template.go index 490b946..d92a0f6 100644 --- a/terraform/template.go +++ b/terraform/template.go @@ -102,11 +102,12 @@ type Template interface { // CommonTemplate represents template entities type CommonTemplate struct { - Title string - Message string - Result string - Body string - Link string + Title string + Message string + Action string + Result string + Body string + Link string UseRawOutput bool } @@ -278,6 +279,7 @@ func (t *DestroyWarningTemplate) Execute() (string, error) { data := map[string]interface{}{ "Title": t.Title, "Message": t.Message, + "Action": t.Action, "Result": t.Result, "Body": t.Body, "Link": t.Link, diff --git a/terraform/template_test.go b/terraform/template_test.go index c947061..c0e0e0b 100644 --- a/terraform/template_test.go +++ b/terraform/template_test.go @@ -450,6 +450,17 @@ message }, resp: `a-b-c-d`, }, + { + template: `{{ .Title }}-{{ .Message }}-{{ .Action }}-{{ .Result }}-{{ .Body }}`, + value: CommonTemplate{ + Title: "a", + Message: "b", + Action: "action", + Result: "c", + Body: "d", + }, + resp: `a-b-action-c-d`, + }, } for _, testCase := range testCases { template := NewPlanTemplate(testCase.template)