From 4dff81de7e5d5b20569d58e210da292d57815d51 Mon Sep 17 00:00:00 2001 From: Oliver Ford Date: Fri, 27 Oct 2023 18:05:58 +0000 Subject: [PATCH] Fix output malformed when wrapper enabled (#367) * Fix output malformed when wrapper enabled Presently using a command such as `terraform output -json | jq` does not work with the wrapper enabled, as it is by default. In order to consume terraform's output having set it up with this Action, it is necessary either to disable the wrapper (`with: terraform_wrapper: false`) or run it in its own Actions step with an explicit `id` (e.g. `id: foo`) so that it can be referred to and consumed (`${{steps.foo.outputs.stdout}}` et al.) in later steps. This seems to be the result of much confusion (issues passim) and is not at all easy (#338) to debug/diagnose and come to the realisation that it's due to the wrapper, or even that such a thing exists. @austinvalle identified the issue as being due to the `@actions/exec` package writing the spawned command to stdout (along with then its actual stdout). This has previously been reported upstream in actions/toolkit#649; I've proposed actions/toolkit#1573 to fix it. This commit aims to address the issue for `setup-terraform` in the meantime by silencing `@actions/exec` and then writing out to stdout & stderr from the listener buffers, which it writes to without this additional logging. Closes #20, #80, #85, #149, #338, and probably more. * add test for stdout with jq * update test name * remove debug lines and add changelog * add additional note about the bug fix to wrapper --------- Co-authored-by: Austin Valle --- .../unreleased/BUG FIXES-20231027-092614.yaml | 5 ++ .../unreleased/NOTES-20231027-134331.yaml | 10 +++ .github/workflows/data/local/main.tf | 8 +-- .github/workflows/setup-terraform.yml | 69 ++++++++++++++++++- dist/index1.js | 11 +-- wrapper/terraform.js | 11 +-- 6 files changed, 99 insertions(+), 15 deletions(-) create mode 100644 .changes/unreleased/BUG FIXES-20231027-092614.yaml create mode 100644 .changes/unreleased/NOTES-20231027-134331.yaml diff --git a/.changes/unreleased/BUG FIXES-20231027-092614.yaml b/.changes/unreleased/BUG FIXES-20231027-092614.yaml new file mode 100644 index 00000000..42020253 --- /dev/null +++ b/.changes/unreleased/BUG FIXES-20231027-092614.yaml @@ -0,0 +1,5 @@ +kind: BUG FIXES +body: Fixed malformed stdout when wrapper is enabled +time: 2023-10-27T09:26:14.675402-04:00 +custom: + Issue: "367" diff --git a/.changes/unreleased/NOTES-20231027-134331.yaml b/.changes/unreleased/NOTES-20231027-134331.yaml new file mode 100644 index 00000000..6833002c --- /dev/null +++ b/.changes/unreleased/NOTES-20231027-134331.yaml @@ -0,0 +1,10 @@ +kind: NOTES +body: The wrapper around the installed Terraform binary has been fixed to return the + exact STDOUT and STDERR from Terraform when executing commands. Previous versions + of setup-terraform may have required workarounds to process the STDOUT in bash, + such as filtering out the first line or selectively parsing STDOUT with jq. These + workarounds may need to be adjusted with `v3.0.0`, which will now return just the + STDOUT/STDERR from Terraform with no errant characters/statements. +time: 2023-10-27T13:43:31.430759-04:00 +custom: + Issue: "367" diff --git a/.github/workflows/data/local/main.tf b/.github/workflows/data/local/main.tf index 77ea07a9..81ea3447 100644 --- a/.github/workflows/data/local/main.tf +++ b/.github/workflows/data/local/main.tf @@ -1,5 +1,5 @@ -resource "null_resource" "null" { - triggers = { - value = timestamp() - } +resource "random_pet" "pet" {} + +output "pet" { + value = random_pet.pet.id } diff --git a/.github/workflows/setup-terraform.yml b/.github/workflows/setup-terraform.yml index 4dc826e8..ce77aac3 100644 --- a/.github/workflows/setup-terraform.yml +++ b/.github/workflows/setup-terraform.yml @@ -1,4 +1,4 @@ -name: 'Setup Terraform' +name: 'setup-terraform tests' on: push: @@ -303,3 +303,70 @@ jobs: - name: Terraform Plan id: plan run: terraform plan + + + terraform-stdout-wrapper: + name: 'Terraform STDOUT' + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + defaults: + run: + shell: bash + working-directory: ./.github/workflows/data/local + steps: + - name: Checkout + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + + - name: Setup Terraform + uses: ./ + with: + terraform_wrapper: true + + - name: Terraform Init + run: terraform init + + - name: Terraform Format + run: terraform fmt -check + + - name: Terraform Apply + id: apply + run: terraform apply -auto-approve + + - name: Terraform Output to JQ + id: output + run: terraform output -json | jq '.pet.value' + + terraform-stdout-no-wrapper: + name: 'Terraform STDOUT No Wrapper' + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + defaults: + run: + shell: bash + working-directory: ./.github/workflows/data/local + steps: + - name: Checkout + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + + - name: Setup Terraform + uses: ./ + with: + terraform_wrapper: false + + - name: Terraform Init + run: terraform init + + - name: Terraform Format + run: terraform fmt -check + + - name: Terraform Apply + id: apply + run: terraform apply -auto-approve + + - name: Terraform Output to JQ + id: output + run: terraform output -json | jq '.pet.value' diff --git a/dist/index1.js b/dist/index1.js index 42444df7..56af6568 100755 --- a/dist/index1.js +++ b/dist/index1.js @@ -27221,13 +27221,14 @@ async function checkTerraform () { const args = process.argv.slice(2); const options = { listeners, - ignoreReturnCode: true + ignoreReturnCode: true, + silent: true, // avoid printing command in stdout: https://github.com/actions/toolkit/issues/649 }; const exitCode = await exec(pathToCLI, args, options); - core.debug(`Terraform exited with code ${exitCode}.`); - core.debug(`stdout: ${stdout.contents}`); - core.debug(`stderr: ${stderr.contents}`); - core.debug(`exitcode: ${exitCode}`); + + // Pass-through stdout/err as `exec` won't due to `silent: true` option + process.stdout.write(stdout.contents); + process.stderr.write(stderr.contents); // Set outputs, result, exitcode, and stderr core.setOutput('stdout', stdout.contents); diff --git a/wrapper/terraform.js b/wrapper/terraform.js index eddcb35f..a64a4c22 100755 --- a/wrapper/terraform.js +++ b/wrapper/terraform.js @@ -33,13 +33,14 @@ async function checkTerraform () { const args = process.argv.slice(2); const options = { listeners, - ignoreReturnCode: true + ignoreReturnCode: true, + silent: true, // avoid printing command in stdout: https://github.com/actions/toolkit/issues/649 }; const exitCode = await exec(pathToCLI, args, options); - core.debug(`Terraform exited with code ${exitCode}.`); - core.debug(`stdout: ${stdout.contents}`); - core.debug(`stderr: ${stderr.contents}`); - core.debug(`exitcode: ${exitCode}`); + + // Pass-through stdout/err as `exec` won't due to `silent: true` option + process.stdout.write(stdout.contents); + process.stderr.write(stderr.contents); // Set outputs, result, exitcode, and stderr core.setOutput('stdout', stdout.contents);