action-terraform-report icon indicating copy to clipboard operation
action-terraform-report copied to clipboard

Unhandled error: Error: invalid Terraform Plan JSON data

Open pranav-advani opened this issue 1 year ago • 10 comments

The terraform.json is a valid json but still getting an error as - Unhandled error: Error: invalid Terraform Plan JSON data

How can we troubleshoot ?

pranav-advani avatar Sep 29 '23 11:09 pranav-advani

it uses the following JSON schema: https://github.com/ahmadnassri/node-terraform-unidiff/blob/master/schema.json

please download your JSON, test it against that schema and let me know what you find.

also, include your Terraform version (wondering in they changed anything in a recent release)

ahmadnassri avatar Sep 29 '23 14:09 ahmadnassri

Hi @ahmadnassri I am having this same error. I know for certain that in my case, the plan contains no items (i.e. no differences). Here is my data:

Stack trace:

Error: invalid Terraform Plan JSON data
    at terraformUnidiff (file:///home/runner/work/_actions/ahmadnassri/action-terraform-report/v3/dist/index.js:104806:11)
    at parse (file:///home/runner/work/_actions/ahmadnassri/action-terraform-report/v3/dist/index.js:104862:15)
    at async file:///home/runner/work/_actions/ahmadnassri/action-terraform-report/v3/dist/index.js:104975:1

terraform.text


No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration
and found no differences, so no changes are needed.

terraform.json

{
  "format_version": "1.2",
  "terraform_version": "1.6.3",
  "planned_values": {
    "root_module": {}
  },
  "configuration": {
    "provider_config": {
      "azurerm": {
        "name": "azurerm",
        "full_name": "registry.terraform.io/hashicorp/azurerm",
        "version_constraint": "~\u003e 3.65",
        "expressions": {
          "features": [
            {}
          ]
        }
      }
    },
    "root_module": {}
  },
  "timestamp": "2023-11-21T19:10:08Z",
  "errored": false
}

Do I need to check the status code on the plan and add an if conditional to your action in the case of an empty plan?

I am using v3 of your action.

mjcramer avatar Nov 21 '23 19:11 mjcramer

Yeah this failed too with something as simple as

terraform {
  # This module is now only being tested with Terraform 0.13.x. However, to make upgrading easier, we are setting
  # 0.12.26 as the minimum version, as that version added support for required_providers with source URLs, making it
  # forwards compatible with 0.13.x code.
  required_version = ">= 0.12.26"
}

# website::tag::1:: The simplest possible Terraform module: it just outputs "Hello, World!"
output "hello_world" {
  value = "Hello, World!"
}

to which the plan json looks like:

{
    "format_version": "1.2",
    "terraform_version": "1.6.0",
    "planned_values": {
        "outputs": {
            "hello_world": {
                "sensitive": false,
                "type": "string",
                "value": "Hello, World!"
            }
        },
        "root_module": {}
    },
    "output_changes": {
        "hello_world": {
            "actions": [
                "no-op"
            ],
            "before": "Hello, World!",
            "after": "Hello, World!",
            "after_unknown": false,
            "before_sensitive": false,
            "after_sensitive": false
        }
    },
    "prior_state": {
        "format_version": "1.0",
        "terraform_version": "1.6.0",
        "values": {
            "outputs": {
                "hello_world": {
                    "sensitive": false,
                    "value": "Hello, World!",
                    "type": "string"
                }
            },
            "root_module": {}
        }
    },
    "configuration": {
        "root_module": {
            "outputs": {
                "hello_world": {
                    "expression": {
                        "constant_value": "Hello, World!"
                    }
                }
            }
        }
    },
    "timestamp": "2023-12-19T16:29:59Z",
    "errored": false
}

I get it's a toy example, but it should work right?

danielloader avatar Dec 19 '23 16:12 danielloader

@danielloader If you are using v2 of the terraform setup try upgrading to hashicorp/setup-terraform@v3. It seems v2 with the wrapper includes standard error, standard out, etc appended to the json and text file even with just >. At least that helped in my case when I inspected the files.

Brian-Moritz avatar Dec 21 '23 00:12 Brian-Moritz

Oh okay, I see the problem. It looks like in the version that I'm using, terraform 1.6.3, when the plan has no changes, the top level key resource_changes is not present, but causes this plugin to throw an error because it's a required parameter in the schema.

mjcramer avatar Jan 08 '24 18:01 mjcramer

So you can crash-proof this action by doing the following after generating a plan in your workflow named terraform.plan:

terraform show -json terraform.plan | jq --argjson to_add '{"resource_changes":[]}' '. * $to_add' > terraform.json

This effectively ensures that the resource_changes key is present, even if it is empty. This, however, is NOT a fix because when there are changes, they are being reported as zero...

mjcramer avatar Jan 08 '24 21:01 mjcramer

bump?

mjcramer avatar Feb 15 '24 17:02 mjcramer

So you can crash-proof this action by doing the following after generating a plan in your workflow named terraform.plan:

terraform show -json terraform.plan | jq --argjson to_add '{"resource_changes":[]}' '. * $to_add' > terraform.json

This effectively ensures that the resource_changes key is present, even if it is empty. This, however, is NOT a fix because when there are changes, they are being reported as zero...

Thanks for that @mjcramer . I wrote this simple condition to check if resource_changes is empty, then add the missing field + array else, do nothing.

          terragrunt show -json tf.plan > tf-temp.json
          # check if the .resource_changes is null in the tf.plan file and if it is,
          # add an empty array to the json file else don't do anything.
            if [ "$(jq '.resource_changes' tf-temp.json)" == "null" ]; then
            echo "resource_changes is null"
            jq --argjson to_add '{"resource_changes":[]}' '. * $to_add' tf-temp.json > tf.json
          else
            echo "resource_changes is not null"
            cp tf-temp.json tf.json
          fi

Then I use that tf.json in the gh action to generate the report:

terraform-json: ${{ github.workspace }}/${{ matrix.directory }}/tf.json

marcossv9 avatar Apr 03 '24 17:04 marcossv9

Very nice! We should prolly find another github action, though, clearly this one has been abandoned...

mjcramer avatar Apr 05 '24 15:04 mjcramer

@mjcramer just an idea, I started using this as well to update the PR description. Haven't gotten the markdown so it doesn't look the best but it's been nice having the terraform changes in the description. I just feed it the changes txt file. https://github.com/nefrob/pr-description

Brian-Moritz avatar Apr 05 '24 16:04 Brian-Moritz