Giter Site home page Giter Site logo

tfnotify's Introduction

tfnotify

tfnotify parses Terraform commands' execution result and applies it to an arbitrary template and then notifies it to GitHub comments etc.

Motivation

There are commands such as plan and apply on Terraform command, but many developers think they would like to check if the execution of those commands succeeded. Terraform commands are often executed via CI like Circle CI, but in that case you need to go to the CI page to check it. This is very troublesome. It is very efficient if you can check it with GitHub comments or Slack etc. You can do this by using this command.

Installation

Grab the binary from GitHub Releases (Recommended)

or

$ go get -u github.com/mercari/tfnotify

What tfnotify does

  1. Parse the execution result of Terraform
  2. Bind parsed results to Go templates
  3. Notify it to any platform (e.g. GitHub) as you like

Detailed specifications such as templates and notification destinations can be customized from the configuration files (described later).

Usage

Basic

tfnotify is just CLI command. So you can run it from your local after grabbing the binary.

Basically tfnotify waits for the input from Stdin. So tfnotify needs to pipe the output of Terraform command like the following:

$ terraform plan | tfnotify plan

For plan command, you also need to specify plan as the argument of tfnotify. In the case of apply, you need to do apply. Currently supported commands can be checked with tfnotify --help.

Configurations

When running tfnotify, you can specify the configuration path via --config option (if it's omitted, it defaults to {.,}tfnotify.y{,a}ml).

The example settings of GitHub and GitHub Enterprise, Slack, Typetalk are as follows. Incidentally, there is no need to replace TOKEN string such as $GITHUB_TOKEN with the actual token. Instead, it must be defined as environment variables in CI settings.

template of Go can be used for template. The templates can be used in tfnotify.yaml are as follows:

Placeholder Usage
{{ .Title }} Like ## Plan result
{{ .Message }} A string that can be set from CLI with --message option
{{ .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

On GitHub, tfnotify can also put a warning message if the plan result contains resource deletion (optional).

Template Examples

For GitHub
---
ci: circleci
notifier:
  github:
    token: $GITHUB_TOKEN
    repository:
      owner: "mercari"
      name: "tfnotify"
terraform:
  fmt:
    template: |
      {{ .Title }}

      {{ .Message }}

      {{ .Result }}

      {{ .Body }}
  plan:
    template: |
      {{ .Title }} <sup>[CI link]( {{ .Link }} )</sup>
      {{ .Message }}
      {{if .Result}}
      <pre><code>{{ .Result }}
      </pre></code>
      {{end}}
      <details><summary>Details (Click me)</summary>

      <pre><code>{{ .Body }}
      </pre></code></details>
  apply:
    template: |
      {{ .Title }}
      {{ .Message }}
      {{if .Result}}
      <pre><code>{{ .Result }}
      </pre></code>
      {{end}}
      <details><summary>Details (Click me)</summary>

      <pre><code>{{ .Body }}
      </pre></code></details>

If you would like to let tfnotify warn the resource deletion, add when_destroy configuration as below.

---
# ...
terraform:
  # ...
  plan:
    template: |
      {{ .Title }} <sup>[CI link]( {{ .Link }} )</sup>
      {{ .Message }}
      {{if .Result}}
      <pre><code>{{ .Result }}
      </pre></code>
      {{end}}
      <details><summary>Details (Click me)</summary>

      <pre><code>{{ .Body }}
      </pre></code></details>
    when_destroy:
      template: |
        ## :warning: WARNING: Resource Deletion will happen :warning:

        This plan contains **resource deletion**. Please check the plan result very carefully!
  # ...

You can also let tfnotify add a label to PRs depending on the terraform plan output result. Currently, this feature is for Github labels only.

---
# ...
terraform:
  # ...
  plan:
    template: |
      {{ .Title }} <sup>[CI link]( {{ .Link }} )</sup>
      {{ .Message }}
      {{if .Result}}
      <pre><code>{{ .Result }}
      </pre></code>
      {{end}}
      <details><summary>Details (Click me)</summary>

      <pre><code>{{ .Body }}
      </pre></code></details>
    when_add_or_update_only:
      label: "add-or-update"
    when_destroy:
      label: "destroy"
    when_no_changes:
      label: "no-changes"
    when_plan_error:
      label: "error"
  # ...

Sometimes you may want not to HTML-escape Terraform command outputs. For example, when you use code block to print command output, it's better to use raw characters instead of character references (e.g. -/+ -> -/&#43;, " -> &#34;).

You can disable HTML escape by adding use_raw_output: true configuration. With this configuration, Terraform doesn't HTML-escape any Terraform output.

---
# ...
terraform:
  use_raw_output: true
  # ...
  plan:
    template: |
      {{ .Title }} <sup>[CI link]( {{ .Link }} )</sup>
      {{ .Message }}
      {{if .Result}}
      ```
      {{ .Result }}
      ```
      {{end}}
      <details><summary>Details (Click me)</summary>

      ```
      {{ .Body }}
      ```
  # ...
For GitHub Enterprise
---
ci: circleci
notifier:
  github:
    token: $GITHUB_TOKEN
    base_url: $GITHUB_BASE_URL # Example: https://github.example.com/api/v3
    repository:
      owner: "mercari"
      name: "tfnotify"
terraform:
  fmt:
    template: |
      {{ .Title }}

      {{ .Message }}

      {{ .Result }}

      {{ .Body }}
  plan:
    template: |
      {{ .Title }} <sup>[CI link]( {{ .Link }} )</sup>
      {{ .Message }}
      {{if .Result}}
      <pre><code>{{ .Result }}
      </pre></code>
      {{end}}
      <details><summary>Details (Click me)</summary>

      <pre><code>{{ .Body }}
      </pre></code></details>
  apply:
    template: |
      {{ .Title }}
      {{ .Message }}
      {{if .Result}}
      <pre><code>{{ .Result }}
      </pre></code>
      {{end}}
      <details><summary>Details (Click me)</summary>

      <pre><code>{{ .Body }}
      </pre></code></details>
For GitLab
---
ci: gitlabci
notifier:
  gitlab:
    token: $GITLAB_TOKEN
    base_url: $GITLAB_BASE_URL
    repository:
      owner: "mercari"
      name: "tfnotify"
terraform:
  fmt:
    template: |
      {{ .Title }}

      {{ .Message }}

      {{ .Result }}

      {{ .Body }}
  plan:
    template: |
      {{ .Title }} <sup>[CI link]( {{ .Link }} )</sup>
      {{ .Message }}
      {{if .Result}}
      <pre><code> {{ .Result }}
      </pre></code>
      {{end}}
      <details><summary>Details (Click me)</summary>
      <pre><code> {{ .Body }}
      </pre></code></details>
  apply:
    template: |
      {{ .Title }}
      {{ .Message }}
      {{if .Result}}
      <pre><code> {{ .Result }}
      </pre></code>
      {{end}}
      <details><summary>Details (Click me)</summary>
      <pre><code> {{ .Body }}
      </pre></code></details>
For Slack
---
ci: circleci
notifier:
  slack:
    token: $SLACK_TOKEN
    channel: $SLACK_CHANNEL_ID
    bot: $SLACK_BOT_NAME
terraform:
  plan:
    template: |
      {{ .Message }}
      {{if .Result}}
      ```
      {{ .Result }}
      ```
      {{end}}
      ```
      {{ .Body }}
      ```

Sometimes you may want not to HTML-escape Terraform command outputs. For example, when you use code block to print command output, it's better to use raw characters instead of character references (e.g. -/+ -> -/&#43;, " -> &#34;).

You can disable HTML escape by adding use_raw_output: true configuration. With this configuration, Terraform doesn't HTML-escape any Terraform output.

---
# ...
terraform:
  use_raw_output: true
  # ...
  plan:
  # ...
For Typetalk
---
ci: circleci
notifier:
  typetalk:
    token: $TYPETALK_TOKEN
    topic_id: $TYPETALK_TOPIC_ID
terraform:
  plan:
    template: |
      {{ .Message }}
      {{if .Result}}
      ```
      {{ .Result }}
      ```
      {{end}}
      ```
      {{ .Body }}
      ```

Supported CI

Currently, supported CI are here:

  • Circle CI
  • Travis CI
  • AWS CodeBuild
  • TeamCity
  • Drone
  • Jenkins
  • GitLab CI
  • GitHub Actions
  • Google Cloud Build

Private Repository Considerations

GitHub private repositories require the repo and write:discussion permissions.

Jenkins Considerations

  • Plugin
  • Environment Variable
    • PULL_REQUEST_NUMBER or PULL_REQUEST_URL are required to set by user for Pull Request Usage

Google Cloud Build Considerations

  • These environment variables are needed to be set using substitutions
    • COMMIT_SHA
    • BUILD_ID
    • PROJECT_ID
    • _PR_NUMBER
    • _REGION
  • Recommended trigger events
    • terraform plan: Pull request
    • terraform apply: Push to branch

Committers

Contribution

Please read the CLA below carefully before submitting your contribution.

https://www.mercari.com/cla/

License

Copyright 2018 Mercari, Inc.

Licensed under the MIT License.

tfnotify's People

Contributors

albertorm95 avatar andrescidoncha avatar b4b4r07 avatar babarot avatar baurmatt avatar chaspy avatar chroju avatar cicdguy avatar drlau avatar dtan4 avatar felvi-zzz avatar genert avatar htnosm avatar isaoshimizu avatar johejo avatar johnmanjiro13 avatar keisukeyamashita avatar mdolinin-chwy avatar mizzy avatar nownabe avatar ryok-0319 avatar shogo82148 avatar starefossen avatar takumin avatar tanakaworld avatar teraken0509 avatar tkak avatar tomfaulkner avatar tomoasleep avatar yuya-takeyama avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tfnotify's Issues

Document required GitHub permissions

It might be beneficial to include the required permissions in the readme. It seems to be that they are repo and write:discussion at least for private repos.

Conditional notification

I'd like to notify terraform cmd result to slack only when it fails. I think we can implement it as a conditional notification function, like below:

---
ci: circleci
notifier:
  slack:
    token: $SLACK_TOKEN
    channel: $SLACK_CHANNEL_ID
    bot: $SLACK_BOT_NAME
terraform:
  plan:
    filters:
      only:
        - failed  # notify when terraform-plan failed
    template: |
      {{ .Message }}
      {{if .Result}}
      ```
      {{ .Result }}
      ```
      {{end}}
      ```
      {{ .Body }}
      ```

Do you have any opinion? And I try to implement a patch as PoC if you have no problem.

Error while parsing the output only changes for Terraform `>=0.15`

WHY

From Terraform >= 0.15, if there no changes in the resources but changes on the output only, Terraform will only print

Changes to Outputs:

Steps to reproduce

Plan

>= 0.15 Plan result

I used the v1.1.4 Terraform version.

$  terraform plan

Changes to Outputs:
  + slack = "hoho"

You can apply this plan to save these new output values to the Terraform state, without changing any real infrastructure.

< 0.15 Plan result

I used the v0.14.10 Terraform version.

$ terraform plan

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:

Terraform will perform the following actions:

Plan: 0 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + slack = "hoho"

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

Apply

>= 0.15 Plan result

I used the v1.1.4 Terraform version.

$  terraform apply

Changes to Outputs:
  + slack = "hoho"

You can apply this plan to save these new output values to the Terraform state, without changing any real infrastructure.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes


Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

slack = "hoho"

< 0.15 Apply result

I used the v0.14.10 Terraform version.

$  terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:

Terraform will perform the following actions:

Plan: 0 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + slack = "hoho"

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes


Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

slack = "hoho"

ใ‚คใƒณใ‚นใƒˆใƒผใƒซใ‚จใƒฉใƒผ cannot use int(commentID) (type int) as type int64 in argument

$ go get -u github.com/mercari/tfnotify
# github.com/mercari/tfnotify/notifier/github
/home/vagrant/go/src/github.com/mercari/tfnotify/notifier/github/github.go:31:64: cannot use int(commentID) (type int) as type int64 in argument to g.Client.Issues.DeleteComment

$ cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)

$ uname -a
Linux dev 3.10.0-514.10.2.el7.x86_64 #1 SMP Fri Mar 3 00:04:05 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

$ go version
go version go1.9 linux/amd64

Windows 7 ไธŠใฎ Vagrant ใง VirtualBox ใง CentOS 7.3 ใง go get ใ—ใŸใ‚‰ใ‚จใƒฉใƒผใซใชใฃใฆใ—ใพใ„ใพใ™ใ€‚

ใพใ  go1.10 ใงใฏ่ฉฆใ—ใฆใ„ใพใ›ใ‚“ใ€‚

Gitlab comments don't work

WHAT

Hello, excellent project! I'm very excited to use it in gitlab, but unfortunately I can't. Comments can't be posted to any gitlab mr.

WHY

I think that error is here:

return g.Client.Notes.CreateMergeRequestNote(fmt.Sprintf("%s/%s", g.namespace, g.project), mergeRequest, opt, options...)

To be precise error-prone part is this:
fmt.Sprintf("%s/%s", g.namespace, g.project)

sprint here leads to incorrect api url:
https://gitlab.com/api/v4/projects/{namespace}/{project}/merge_requests/{mr}/notes

because gitlab doesn't have namespace and project, only project, so right url should look like this:

https://gitlab.com/api/v4/projects/{project}/merge_requests/{mr}/notes

also it should be mentioned that underlying gitlab client specifies this signature:
https://github.com/xanzy/go-gitlab/blob/41c6472d936a0ce5f919f7eb1afb8dc8ac46247a/notes.go#L477

func (s *NotesService) CreateMergeRequestNote(pid interface{}, mergeRequest int, opt *CreateMergeRequestNoteOptions, options ...RequestOptionFunc) (*Note, *Response, error) {

where pid is for project_id

terraform plan/apply result in GitHub comment is parsed as Markdown

WHAT

Make terraform plan|apply result output print in GitHub comment as it is, not to render as Markdown text.

WHY

Currently terraform plan|apply result notified as GitHub comment is parsed as Markdown text, not as plain text.
This causes transformation from some formatted text, e.g. plugin list, resources to diff and separator line, to HTML lists or separators.

Please look at the below examples.

enclose with <pre><code> (current state)

Details (Click me)

Initializing provider plugins...

  • Checking for available provider plugins on https://releases.hashicorp.com...
  • Downloading plugin for provider "pagerduty" (1.1.0)...
  • Downloading plugin for provider "aws" (1.16.0)...
  • Downloading plugin for provider "google" (1.10.0)...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

  • provider.aws: version = "~> 1.16"
  • provider.google: version = "~> 1.10"
  • provider.pagerduty: version = "~> 1.1"

Terraform has been successfully initialized!


An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
~ update in-place

Plan: 0 to add, 2 to change, 0 to destroy.


Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

enclose with backquotes

Since using the same body with above, HTML character entities are appeared as it is.

Details (Click me)

Initializing provider plugins...
- Checking for available provider plugins on https://releases.hashicorp.com...
- Downloading plugin for provider &#34;pagerduty&#34; (1.1.0)...
- Downloading plugin for provider &#34;aws&#34; (1.16.0)...
- Downloading plugin for provider &#34;google&#34; (1.10.0)...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = &#34;...&#34; constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.aws: version = &#34;~&gt; 1.16&#34;
* provider.google: version = &#34;~&gt; 1.10&#34;
* provider.pagerduty: version = &#34;~&gt; 1.1&#34;

Terraform has been successfully initialized!

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Plan: 0 to add, 2 to change, 0 to destroy.

------------------------------------------------------------------------

Note: You didn&#39;t specify an &#34;-out&#34; parameter to save this plan, so Terraform
can&#39;t guarantee that exactly these actions will be performed if
&#34;terraform apply&#34; is subsequently run.

One solution is using triple backquotes. I prefer this solution.
Another solution is replacing all special characters to HTML character entities.

New comment every time or updates to existing comments?

I am running 3 TF plans in a given PR workflow, and tfnotify is correctly giving me a new comment for each plan. However I get a set of 3 new comments every time the workflow runs. Is this expected behaviour or should it update/replace the comments on each run?

Possible to use this tool on local machine?

Hey there, nice project. From the looks of it, this tool is supposed to run on CI server. Just asking if it's possible to use this tool on local machine when running terraform plan/apply? Thanks!

Support Jenkins

Any plan to support Jenkins? What would it take to make this working?

Unable to use --config flag in v0.1.4

Using v0.1.4

running:
terraform plan -input=false | tfnotify plan --config ../tfnotify.yml

returns:

Incorrect Usage: flag provided but not defined: -config

NAME:
   tfnotify plan - Parse stdin as a plan result

USAGE:
   tfnotify plan [command options] [arguments...]

OPTIONS:
   --message value, -m value  Specify the message to use for notification
   
flag provided but not defined: -config

Tfnotify does not trace organization ownership transfer

WHAT

Expected behavior

Tfnotify posts comments to new organization's repositories PR after owernership transfer

Observed behavior

Tfnotify tries to post to old organization's repository link which does not exist anymore.

WHY

I have transferred the organization of the repository to another organization and tfnotify does not work since then.
Could be related to Drone's cache and not tfnotify's problem.
Checked that JSON webhook post message to Drone does not include any information from past owned organization.

Environment

CI: Drone
Code hosting: Github Enterprise

Support Gitlab CI

Is Gitlab CI support planned?
This is a popular CI so I think it will be interesting to do the support :)

Thanks for your work ๐Ÿ‘

`tfnotify` support custom environment variable

WHAT

Curretly, to read the GitHub Token from the environment variable, the $GITHUB_TOKEN is supported. It lookups the env var named GITHUB_TOKEN for the tokens.

if token == EnvToken {
token = os.Getenv(EnvToken)
}

But it would be nice if the tfnotify can support custom variables as below:

ci: circleci
notifier:
  github:
    token: $MY_CUSTOM_GITHUB_TOKEN  <-- not working, only $GITHUB_TOKEN is supported
    repository:
      owner: "mercari"
....

Note that this will not break existing users. The users that configure $GITHUB_TOKEN can still use the GITHUB_TOKEN env var on their runtime.

Too long comment

Error message from Github:

422 Validation Failed [{Resource:IssueComment Field:data Code:unprocessable Message:Body is too long (maximum is 65536 characters)}]

I know it is Github side thing but could tfnotify then don't post detailed plan if it exceeds limit and just provide link to build or something? Any other ideas?

Github apply notification not goes to the current commit

WHAT

My project uses tfnotify with Github and Travis as CI.
A CI execution for a specific commit also produces a plan and an apply results.
The plan result goes to the actual commit, that the CI was executed on, while the apply result goes to the previous commit. It would be good if an execution result would go to the same commit and this commit would be the actual commit.

WHY

To review back the CI execution results, it is easier to compare the plan and apply results, if it goes to the current commit.

I tried to create an image that depicts the current operation:

Screenshot 2021-07-26 at 16 06 40

fail go get current master HEAD ( b8bbe9b )

WHAT

I use tfnotify installed by go get on circleci like this:

commands:
  tfnotify:
    parameters:
      tf_type:
        type: string
    steps:
      - run:
          name: install tfnotify
          command: go get -u github.com/mercari/tfnotify
      - run:
          name: notify
          command: |
            for file in `ls -1 << parameters.tf_type >>.*`
            do
                cat ${file} | tfnotify << parameters.tf_type >> --title "## ${file} result"
            done

and the result of install tfnotify step now (2019-11-15T11:51:04+0900) bellows:

#!/bin/bash -eo pipefail
go get -u github.com/mercari/tfnotify
# github.com/mercari/tfnotify
/go/src/github.com/mercari/tfnotify/main.go:35:14: t.context.GlobalString undefined (type *cli.Context has no field or method GlobalString)
/go/src/github.com/mercari/tfnotify/main.go:36:21: t.context.GlobalString undefined (type *cli.Context has no field or method GlobalString)
/go/src/github.com/mercari/tfnotify/main.go:84:14: t.context.GlobalString undefined (type *cli.Context has no field or method GlobalString)
/go/src/github.com/mercari/tfnotify/main.go:85:31: t.context.GlobalString undefined (type *cli.Context has no field or method GlobalString)
/go/src/github.com/mercari/tfnotify/main.go:162:64: t.context.GlobalString undefined (type *cli.Context has no field or method GlobalString)
/go/src/github.com/mercari/tfnotify/main.go:178:17: cannot use cli.StringFlag literal (type cli.StringFlag) as type cli.Flag in array or slice literal:
	cli.StringFlag does not implement cli.Flag (Apply method has pointer receiver)
/go/src/github.com/mercari/tfnotify/main.go:179:17: cannot use cli.StringFlag literal (type cli.StringFlag) as type cli.Flag in array or slice literal:
	cli.StringFlag does not implement cli.Flag (Apply method has pointer receiver)
/go/src/github.com/mercari/tfnotify/main.go:180:17: cannot use cli.StringFlag literal (type cli.StringFlag) as type cli.Flag in array or slice literal:
	cli.StringFlag does not implement cli.Flag (Apply method has pointer receiver)
/go/src/github.com/mercari/tfnotify/main.go:188:19: cannot use cli.StringFlag literal (type cli.StringFlag) as type cli.Flag in array or slice literal:
	cli.StringFlag does not implement cli.Flag (Apply method has pointer receiver)
/go/src/github.com/mercari/tfnotify/main.go:192:19: cannot use cli.StringFlag literal (type cli.StringFlag) as type cli.Flag in array or slice literal:
	cli.StringFlag does not implement cli.Flag (Apply method has pointer receiver)
/go/src/github.com/mercari/tfnotify/main.go:192:19: too many errors
Exited with code 2
CircleCI received exit code 2

However, v0.3.3 looks no problems.

No Github comments from tfnotify

My issue:
Even though I set GITHUB_REF env var, I still get tfnotify comments attached to my commits instead of having them attached to related PR and what's more I do not get any labels attached to my PR.

My tfnotify.yml

ci: github-actions
notifier:
  github:
    token: <redacted>
    repository:
      owner: <redacted>
      name: <redacted>
terraform:
  plan:
    template: |
      {{ .Title }}
      {{ .Message }}
      {{if .Result}}
      <pre><code>{{ .Result }}
      </pre></code>
      {{end}}
      <details><summary>Details (Click me)</summary>
      <pre><code>{{ .Body }}
      </pre></code></details>
    when_add_or_update_only:
      label: "add-or-update"
    when_no_changes:
      label: "no-changes"
    when_plan_error:
      label: "error"
    when_destroy:
      label: "destroy"
      template: |
        ## :warning: WARNING: Resource Deletion will happen :warning:
        This plan contains **resource deletion**. Please check the plan result very carefully!

The command I run as part of my local tests:

export GITHUB_REF=refs/pull/240/merge
cat plan_result.temp | tfnotify --config tfnotify.yml plan --message "example tfnotify comment message"

I have a feeling tfnotify does not respect the GITHUB_REF env var I set and hence this code does not get executed.

Can not post an apply comment to the last commit

Hi,

I'd like to use tfnotify for a GitHub repository whose merging option is squash-and-merge, but tfnotify does not post an apply comment to the last commit (it always posts to one before the last commit).

https://github.com/mercari/tfnotify/blob/master/notifier/github/commits.go#L46

I think this code is a cause. The squash-and-merge commit history does not include the merge commit, so lastOne method does not return the correct one. Is it make sense?

It's implicit behavior, so I would like to configure it in tfnotify.yml if possible.

Thanks.

Parsing fails when only any output values are added

WHAT

When I add an output value only and run terraform plan, tfnotify caused an error and return exit code 1.

WHY

terraform version: 1.0.0

tfnotify checks texts with regular expression below.
https://github.com/mercari/tfnotify/blob/master/terraform/parser.go#L64
But when we ran plan adding any output values only, terraform's output didn't contain Plan: or No changes and tfnotify failed to parse.
Terraform's output result is a like below:

pagerduty_schedule.secondary: Refreshing state...
pagerduty_schedule.primary: Refreshing state...
pagerduty_team_membership.team[0]: Refreshing state...
pagerduty_team_membership.team[1]: Refreshing state...
pagerduty_escalation_policy.team: Refreshing state...
pagerduty_service.team: Refreshing state...
pagerduty_service_integration.datadog: Refreshing state...

------------------------------------------------------------------------

Changes to Outputs:
  + my_another_project_name = "my-another-project"

------------------------------------------------------------------------

Thanks!

terraform 0.12 planfile support

WHAT

Running terraform plan -out=planfile, and then in a later step terraform plan planfile | tfnotify plan no longer works in Terraform >=0.12

WHY

After Terraform 0.12 #19235 it is no longer possible to pass a saved plan file to terraform plan.
When attempting to pass terraform plan planfile to tfnotify, terraform throws the following error:

Error: Invalid configuration directory

Cannot pass a saved plan file to the 'terraform plan' command. To apply a
saved plan, use: terraform apply terraform-shared.plan

can we use markdown in template?

WHAT

Can we use markdown in the template for github, to make the output more clean? like below:

{{ .Title }} <sup>[CI link]( {{ .Link }} )</sup>
{{ .Message }}
{{if .Result}}
<pre><code> {{ .Result }}
</pre></code>
{{end}}
<details><summary>Details (Click me)</summary>
```hcl
 {{ .Body }}
```
</details>

Support Drone

WHAT

Add support for Drone

WHY

I want to execute terraform from Drone with tfnotify.

Support Terraform `0.15` or later

WHAT

As title, tfnotify only supports Terraform version under 0.14.x. Thus, I want to support the later >= 0.15.x Terraform releases.

WHY

Because Terraform changed the output format of the failure messages on plan or apply, the tfnotify runs into cannot parse plan result.

These are the sample failure messages emitted by Terraform for each versions

After 0.15

โ•ท
โ”‚ Error: expected rotation_days to be at least (1), got -1
โ”‚ 
โ”‚   with time_rotating.example,
โ”‚   on null_resource.tf line 14, in resource "time_rotating" "example":
โ”‚   14:   rotation_days = -1
โ”‚ 

Before 0.15

Error: expected rotation_days to be at least (1), got -1

  on null_resource.tf line 14, in resource "time_rotating" "example":
  14:   rotation_days = -1

Because there are | in the beginning, tfnotify can't parse it.

Broken private pool Cloud Build build result links

WHAT

The private pool (a.k.a private) Cloud Build build links are broken and the GCP will return 404

WHY

Because private pool Cloud Build build result links have ;region=<REGION> in the link like https://console.cloud.google.com/cloud-build/builds/build-id?project=gcp-project-id. Currently implementation doesn't have that, thus it will get considered as global's result link.

Since the Cloud Build build IDs are generated by regions, we need to add ;region=<REGION> for private pool builds.
For global regions, we can specify ;region=global.

Support to configure a label color

WHAT

Support to configure a label color.

WHY

It is useful and important to configure a label color properly.
We can know what is changed by color.
It is bothersome to configure label colors manually.
Especially, this feature is useful for Monorepo.

We use tfnotify at Monorepo and the number of Terraform states are over 60.
So the number of labels are 60 * 4 = 240.
It is bothersome to configure the label color manually.

HOW

Add optional color fields to the configuration file.

    when_add_or_update_only:
      label: "add-or-update"
      label_color: "1d76db" # blue
    when_destroy:
      label: "destroy"
      label_color: "d93f0b" # red
      template: |
        ## :warning: WARNING: Resource Deletion will happen :warning:
        This plan contains **resource deletion**. Please check the plan result very carefully!
    when_no_changes:
      label: "no-changes"
      label_color: "0e8a16" # green
    when_plan_error:
      label: "staging/error"

Add labels to an issue API returns labels.
If the color of returned label is different from the configuration, update the color by Update a label API.

tfnotify --version not working

WHAT

I got tfnotify binary from GitHub Releases, But tfnotify --version option doesn't seems to work.

$ wget https://github.com/mercari/tfnotify/releases/download/v0.7.0/tfnotify_darwin_amd64.tar.gz

$ tar xvf tfnotify_darwin_amd64.tar.gz

$ ./tfnotify --version
tfnotify version unset

Long plan output gives "cannot parse plan result"

WHAT

We have a very long Terraform Plan output with a lot of inline JSON that cuauses the following error:

$ terraform plan terraform-prod.plan | tfnotify plan 

The plan command received a saved plan file as input. This command
will output the saved plan. This will not modify the already-existing
plan. If you wish to generate a new plan, please pass in a configuration
directory as an argument.



An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create
  ~ update in-place

Terraform will perform the following actions:

  ~ module.apps.helm_release.prometheus-operator
      values.0:                     "global:\n  rbac:\n    enabled: true\ncommonLabels:\n  prometheus: default\ndefaultRules:\n  labels:\n    alertmanager: default\n  rules:\n    alertmanager: true\n    etcd: false\n    general: true\n    k8s: true\n    kubeApiserver: false\n    kubePrometheusNodeAlerting: true\n    kubePrometheusNodeRecording: true\n    kubeScheduler: false\n
โ€ฆ
(removed looooooooong output here)
โ€ฆ
eShift\": null,\n      \"title\": \"NATS Pending: Account Created\",\n      \"tooltip\": {\n        \"shared\": true,\n        \"sort\": 0,\n        \"value_type\": \"individual\"\n      },\n      \"type\": \"graph\",\n      \"xaxis\": {\n        \"buckets\": null,\n        \"mode\": \"time\",\n        \"name\": null,\n        \"show\": true,\n        \"values\": []\n      },\n      \"yaxes\": [\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        },\n        {\n          \"format\": \"short\",\n          \"label\": null,\n          \"logBase\": 1,\n          \"max\": null,\n          \"min\": null,\n          \"show\": true\n        }\n      ],\n      \"yaxis\": {\n        \"align\": false,\n        \"alignLevel\": null\n      }\n    }\n  ],\n  \"refresh\": \"5s\",\n  \"schemaVersion\": 18,\n  \"style\": \"dark\",\n  \"tags\": [],\n  \"templating\": {\n    \"list\": []\n  },\n  \"time\": {\n    \"from\": \"now-1h\",\n    \"to\": \"now\"\n  },\n  \"timepicker\": {\n    \"refresh_intervals\": [\n      \"5s\",\n      \"10s\",\n      \"30s\",\n      \"1m\",\n      \"5m\",\n      \"15m\",\n      \"30m\",\n      \"1h\",\n      \"2h\",\n      \"1d\"\n    ],\n    \"time_options\": [\n      \"5m\",\n      \"15m\",\n      \"1h\",\n      \"6h\",\n      \"12h\",\n      \"24h\",\n      \"2d\",\n      \"7d\",\n      \"30d\"\n    ]\n  },\n  \"timezone\": \"\",\n  \"title\": \"Onboarding\",\n  \"uid\": \"0_R1z5MWk\",\n  \"version\": 6\n}"
cannot parse plan result
Exited with code 1

From the looks of it tfnotify just gives up half way through and can not find what it is looking for in order to classify this as a valid plan.

$ terraform plan terraform-test.plan | wc
      86   20863  325582

As you can see the plan is quit big, this would definitly hit the GitHub comment limit #34, but this should still not fail in tfnotify, don't you think?

This is the latest version of tfnotify and the latest v0.11 version of Terraform.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.