Search code examples
jsoncontinuous-integrationenvironment-variablesterraformgithub-actions

How to save Terraform output variable into a Github Action’s environment variable


My project uses Terraform for setting up the infrastructure and Github Actions for CI/CD. After running terraform apply I would like to save the value of a Terraform output variable as Github Action environment variable to be later used by the workflow.

According to Github Action's docs, this is the way to create or update environment variables using workflow commands.

Here is my simplified Github Action workflow:

name: Setup infrastructure
jobs:
  run-terraform:
    name: Apply infrastructure changes
    runs-on: ubuntu-latest
    steps:
      ...
      - run: terraform output vm_ip
      - run: echo TEST=$(terraform output vm_ip) >> $GITHUB_ENV
      - run: echo ${{ env.TEST }}

When running locally the command echo TEST_VAR=$(terraform output vm_ip) outputs exactly TEST="192.168.23.23" but from the Github Action CLI output I get something very strange:

enter image description here

I've tried with single quotes, double quotes. At some point I changed the strategy and tried to use jq. So I've added the following steps in order to export all Terraform Outputs to a json file and parse it using jq:

- run: terraform output -json >> /tmp/tf.out.json
- run: jq '.vm_ip.value' /tmp/tf.out.json

But now it throws the following error:

parse error: Invalid numeric literal at line 1, column 9

Even though the JSON generated is perfectly valid:

{
  "cc_host": {
    "sensitive": false,
    "type": "string",
    "value": "private.c.db.ondigitalocean.com"
  },
  "cc_port": {
    "sensitive": false,
    "type": "number",
    "value": 1234
  },
  "db_host": {
    "sensitive": false,
    "type": "string",
    "value": "private.b.db.ondigitalocean.com"
  },
  "db_name": {
    "sensitive": false,
    "type": "string",
    "value": "XXX"
  },
  "db_pass": {
    "sensitive": true,
    "type": "string",
    "value": "XXX"
  },
  "db_port": {
    "sensitive": false,
    "type": "number",
    "value": 1234
  },
  "db_user": {
    "sensitive": false,
    "type": "string",
    "value": "XXX"
  },
  "vm_ip": {
    "sensitive": false,
    "type": "string",
    "value": "206.189.15.70"
  }
}

The commands terraform output -json >> /tmp/tf.out.json and jq '.vm_ip.value' /tmp/tf.out.json work accordingly on local.


Solution

  • After hours searching I've finally figured it out.

    It seems that the Terraform's Github Action offers an additional parameter called terraform_wrapper which needs to be set to false if you plan using the output in commands. You can read a more in depth article here.

    Otherwise, they will be automatically exposed to the step's output and they can be accessed like steps.<step_id>.outputs.<variable>. You can read more about them here and here.