I've got a simple Node.js script that executes an external command (in this case terraform apply
) using spawn
like this:
const spawnOptions = {
shell: true,
stdio: ['pipe', 'pipe', 'pipe'],
};
const childProcess = spawn('terraform', ['apply'], spawnOptions);
And then it tries to read input from other channels and feeds it into the stdin of childProcess
:
// wait for the process to start!
childProcess.stdin.write('yes\n');
The script works just fine on local machine, but it doesn't work inside GitHub workflow runner (see the logs). When the data gets written into the stdin, nothing happens, as in terraform
doesn't receive the "yes"
.
I also tried different options for the stdin (like pipe
vs inherit
) but no success. Also tried cork
/uncork
but it didn't work.
What's the correct way of doing this in environments like GH workflow runners?
The full source code is here.
My objective is to have a simple manual approval step for applying terraform stacks, so passing -auto-approve
is not option.
It turns out that the issue is not with the JS code, but it's with it's the way terraform
which tries hard to detect if "Stdin is a terminal
" (You can see this if you enable the trace logs)hashicorp/setup-terraform
sets up terraform
command, which is not the actual terraform
binary executable, but a Nodejs script wrapper that doesn't pass the stdin to terraform
binary, hence it always says "Stdin is not a terminal". Using the binary terraform
works with any of the solutions (e.g. expect
, script
, node-pty, etc). In fact, even executing the actual binary with the builtin child_process of Nodejs, Terraform still says "Stdin is not a terminal", but you can write to it and it'll work as expected.