0

I'm trying to create my own hook (defined in terraform_plan.sh, can refer in terraform_plan.sh and .pre-commit-config.yaml below) and require user input to determine if this hook success or fail (This hook is about some checking by the user before commit). To activate user input function, I add exec < /dev/tty according to How do I prompt the user from within a commit-msg hook?.

The snippet code looks like this (terraform_plan.sh).

#!/bin/sh
location=$(pwd)
echo "location: ${location}"
cd ./tf_build/

project_id=$(gcloud config get-value project)
credentials=$(gcloud secrets versions access latest --secret="application-default-credentials")

echo "PROJECT_ID: ${project_id}"
echo "CREDENTIALS: ${credentials}"
terraform plan -var "PROJECT_ID=${project_id}" -var "APPLICATION_DEFAULT_CREDENTIALS=${credentials}"

exec < /dev/tty
read -p "Do yu agree this plan? (Y/N): " answer
echo "answer: ${answer}"

# for testing purpose, assign 0 directly
exit 0

I expect that the prompt Do you agree this plan? (Y/N) should appear before I can enter my answer. But actually nothing shown and it just hangs there waiting for the input.

(.venv) ➜ ✗ git commit -m "test"
sqlfluff-lint........................................(no files to check)Skipped
sqlfluff-fix.........................................(no files to check)Skipped
black................................................(no files to check)Skipped
isort................................................(no files to check)Skipped
docformatter.........................................(no files to check)Skipped
flake8...............................................(no files to check)Skipped
blackdoc.............................................(no files to check)Skipped
Terraform plan...........................................................

Only after I give an input "Y", all output strings defined in this hook (ex: output string through echo, terraform plan) comes out.

Terraform plan...........................................................Y
Passed
- hook id: terraform_plan
- duration: 222.33s

location: [remove due to privacy]
PROJECT_ID: [remove due to privacy]
CREDENTIALS: [remove due to privacy]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # google_bigquery_table.bar will be created
  + resource "google_bigquery_table" "bar" {
      + creation_time       = (known after apply)
      + dataset_id          = "default_dataset"
      + deletion_protection = true
...

I also try read -p "Do yu agree this plan? (Y/N): " answer < /dev/tty, but get the same issue.

Here is my part of .pre-commit-config.yaml config file.

repos:
  - repo: local
    hooks:
      # there are other hooks above, remove them for easy to read
      - id: terraform_plan
        name: Terraform plan
        entry: hooks/terraform_plan.sh
        language: script
        verbose: true
        files: (\.tf|\.tfvars)$
        exclude: \.terraform\/.*$
  - repo: ../pre-commit-terraform
    rev: d7e049d0b72eebcb09b719bb296589a47f4fa806
    hooks:
     - id: terraform_fmt
     - id: terraform_tflint
     - id: terraform_validate
       args: [--args=-no-color]

So far I do not know what the root cause is and how to solve it. Seek for someone's help and suggestion. Thanks.

hlovdal
  • 26,565
  • 10
  • 94
  • 165
  • 2
    Generating a plan is typically part of the pull request to branches that apply. You probably do not want to do that in a pre-commit hook. – Matthew Schuchard Aug 08 '22 at 13:03

1 Answers1

2

pre-commit intentionally does not allow interactivity so there is no working solution within the framework. you can sidestep the framework and utilize a legacy shell script (.git/hooks/pre-commit.legacy) but I would also not recommend that:

terraform plan is also kind of a poor choice for a pre-commit hook -- especially if you are blocking the user to confirm it. they are likely to be either surprised by such a hook or fatigued by it and will ignore the output (mash yes) or ignore the entire process (SKIP / --no-verify).


disclaimer: I wrote pre-commit

anthony sottile
  • 61,815
  • 15
  • 148
  • 207