threads / discuss / 58931

Issue with git > 2.36.1 and pre-commit hook on macOS M1

Subject: Issue with git > 2.36.1 and pre-commit hook on macOS M1

## tl;dr

6 messages between Dec 11, 2022 and Dec 17, 2022.

replies: 5people: 2as markdown or json

Piotrek· Dec 11, 2022, 21:11 UTC · lore
Hello.

On MacOS 12.6.1 with M1 chip, git >=2.37.0 (installed by homebrew) and pre-commit hook that is calling *make* target, that is calling *docker compose run* command, we get error:

     the input device is not a TTY
All works file with homebrew git version 2.36.1
* DETAILS OF PROBLEM *

There is pre-commit hook in place that is using bash script to call `make` command which is in turn calling `docker compose run` to run some check before commit. After upgrading git version from `2.36.1` to `>=2.37` we constantly get error:

 > the input device is not a TTY
Example pre-commit hook output:
 > docker compose run --rm --entrypoint "" app /code/test.sh
 > the input device is not a TTY
 > make: *** [Makefile:6: check] Error 1
 > !!! FAILING REGARDLESS OF CHECK RESULT !!!
(the latest error message is just so we don't actually commit anything)

AFAIK `docker compose` command is auto-detecting TTY because no `-t` or `-T` were set.

By doing some tests we managed to check that it is a problem with `git` version.

Latest version that it worked was `2.36.1`:
 > docker compose run --rm --entrypoint "" app /code/test.sh
 > =================== CHECK OK =================
 > !!! FAILING REGARDLESS OF CHECK RESULT !!!
Machine and software we were testing on:
 > make --version
 > GNU Make 3.81
 >
 > docker compose version
 > Docker Compose version v2.12.2
 >
 > git --version
 > git version 2.38.1
 >
 > which git
 > /opt/homebrew/bin/git

Also, we tested with linux Ubuntu and all git versions are working fine with same pre-commit hook. It seems related to `macOS` and `git` only.

* REPLICATING THIS PROBLEM *
Easiest way top replicate is to just clone sample repo I prepared here:
https://github.com/piotrekkr/git-tty-issue-macos
and go with replicate instructions from README.md.

If this is not okay then below I will copy and paste instruction with file contents.

* FILES *
* Makefile *
     COMPOSE_RUN = docker compose run --rm --entrypoint ""
     check:
     	$(COMPOSE_RUN) app /code/test.sh
* docker-compose.yml *
     version: "3.7"
     services:
     app:
         image: php:8.1.3-fpm-bullseye
         volumes:
         - "${PWD}:/code"
         working_dir: /code
* .git/hooks/pre-commit *
     #!/usr/bin/env bash
     make check
     echo "!!! FAILING REGARDLESS OF CHECK RESULT !!!"
     exit 1
* test.sh *
     #!/usr/bin/env bash
     echo "=================== CHECK OK ================="

(sorry for attaching like that, I'm not good with those plain text mail lists)

* INSTRUCTIONS *
1. have macOS with M1 chip (can be expensive)
2. install `docker`, `docker compose v2`, `make`
3. upgrade git with homebrew to version `>=2.37.0`
4. clone repo or manually create files (in same directory)
    - Makefile
    - docker-compose.yml
    - .git/hooks/pre-commit (with execute permissions)
    - test.sh
5. if using repo, copy pre commit script to `.git/hooks` directory
     cp pre-commit-hook.sh .git/hooks/pre-commit
     chmod +x .git/hooks/pre-commit
6. Try to commit and you should get TTY error
7. Switch git to `2.36.1` version (seems to be only possible by `brew 
extract`)
     brew tap-new --no-git $USER/local-tap
     brew extract --version=2.36.1 git $USER/local-tap
     brew install git@2.36.1
     brew link --overwrite git@2.36.1
8. Try committing again, TTY problem should be fixed
Let me know if you need more details etc.

Regards Piotrek

René Scharfe· Dec 12, 2022, 13:29 UTC · re: Piotrek · lore

Re: Issue with git > 2.36.1 and pre-commit hook on macOS M1

Am 11.12.22 um 22:11 schrieb Piotrek:
Show 9 quoted lines
> Hello.
>
> On MacOS 12.6.1 with M1 chip, git >=2.37.0 (installed by homebrew)
> and pre-commit hook that is calling *make* target, that is calling
> *docker compose run* command, we get error:
>
> the input device is not a TTY
>
> All works file with homebrew git version 2.36.1

Bisects to a082345372 (hook API: fix v2.36.0 regression: hooks should be connected to a TTY, 2022-06-07).

Adding "for fd in 0 1 2; do test -t $fd; printf %d $?; done; echo" to the shell script .git/hook/pre-commit yields 100 since a082345372, i.e. fd 1 (stdout) and fd 2 (stderr) are associated with a terminal, while fd 0 (stdin) is not. Before we got 111, i.e. none of the standard file descriptors were associated with a terminal.

v2.37.0 includes a082345372. v2.35.0 gives 100 as well, as expected, so older versions of Git should have "docker compose" complain as well.

While "docker compose" is right in that stdin is not a TTY, it never was. Redirecting the output its seems to help. So I guess it checks if stdout is connected to a terminal and then expects stdin to be a TTY as well. Try appending " | cat" to the command in the pre-commit hook, which breaks the connection for stdout.

René
Piotrek· Dec 13, 2022, 21:02 UTC · re: René Scharfe · lore

Re: Issue with git > 2.36.1 and pre-commit hook on macOS M1

On 12.12.2022 14:29, René Scharfe wrote:
Show 7 quoted lines
> While "docker compose" is right in that stdin is not a TTY, it never
> was.  Redirecting the output its seems to help.  So I guess it checks if
> stdout is connected to a terminal and then expects stdin to be a TTY as
> well.  Try appending " | cat" to the command in the pre-commit hook,
> which breaks the connection for stdout.
> 
> René

Just to be sure if I understand this correctly. It is probably a bug in docker compose expecting stdin to be a TTY, right? I'll write some bug report to them, maybe they will take care of this since it is only on MacOS and all works fine with Linux.

Thank you for checking this René.
René Scharfe· Dec 14, 2022, 22:23 UTC · re: Piotrek · lore

Re: Issue with git > 2.36.1 and pre-commit hook on macOS M1

Am 13.12.2022 um 22:02 schrieb Piotrek:
Show 14 quoted lines
> On 12.12.2022 14:29, René Scharfe wrote:
>
>> While "docker compose" is right in that stdin is not a TTY, it
>> never was.  Redirecting the output its seems to help.  So I guess
>> it checks if stdout is connected to a terminal and then expects
>> stdin to be a TTY as well.  Try appending " | cat" to the command
>> in the pre-commit hook, which breaks the connection for stdout.
>>
>> René
>
> Just to be sure if I understand this correctly. It is probably a bug
> in docker compose expecting stdin to be a TTY, right? I'll write some
> bug report to them, maybe they will take care of this since it is
> only on MacOS and all works fine with Linux.

I don't know "docker compose" well enough to say whether it's a bug, but it seems it turns on some kind of terminal mode that needs both stdin and stdout to be connected to a TTY after only checking that one of them actually is. Why not check both?

Curious that only macOS should be affected. Is stdin of a hook script a TTY on that platform? Or can "docker compose" handle stdin not being a TTY and stdout being one there?

René
Piotrek· Dec 17, 2022, 07:50 UTC · re: René Scharfe · lore

Re: Issue with git > 2.36.1 and pre-commit hook on macOS M1

On 14.12.2022 23:23, René Scharfe wrote:
Show 10 quoted lines
> I don't know "docker compose" well enough to say whether it's a bug,
> but it seems it turns on some kind of terminal mode that needs both
> stdin and stdout to be connected to a TTY after only checking that one
> of them actually is.  Why not check both?
> 
> Curious that only macOS should be affected.  Is stdin of a hook script a
> TTY on that platform?  Or can "docker compose" handle stdin not being a
> TTY and stdout being one there?
> 
> René

Well, seems like I somehow tested this wrong. Tried it again from scratch and on linux I also get this error. So this looks like not a bug. Docker compose CLI options page is a little confusing because of these:

 >--interactive , -i  true  Keep STDIN open even if not attached.
 >--no-TTY , -T 	     true  Disable pseudo-TTY allocation (default: 
auto-detected).
 >--tty , -t          true  Allocate a pseudo-TTY.

Second column with `true` values is titled `Default`, whatever it means. So `--tty` and `--no-TTY` is set by default? Anyway, seems like it is checking if at least one of stdout, stding, stderr is a tty and then tries to allocate a tty to all.

You can check docs here https://docs.docker.com/engine/reference/commandline/compose_run/#options

As a final solution I used makefile "magic" with `ifeq` and shell command like this:

     $(shell test -t 0)
     ifeq ($(.SHELLSTATUS), 1)
     ALLOCATE_TTY = --no-TTY
     endif
     docker compose run $(ALLOCATE_TTY) --rm --entrypoint "" app 
/code/test.sh

Maybe I'll just write to to them to clarify documentation on how those TTY options actually works by default.

Thanks for help with this. Piotr

René Scharfe· Dec 17, 2022, 08:34 UTC · re: Piotrek · lore

Re: Issue with git > 2.36.1 and pre-commit hook on macOS M1

Am 17.12.22 um 08:50 schrieb Piotrek:
Show 5 quoted lines
> On 14.12.2022 23:23, René Scharfe wrote:
>
>> Curious that only macOS should be affected.  Is stdin of a hook script a
>> TTY on that platform?  Or can "docker compose" handle stdin not being a
>> TTY and stdout being one there?
> Well, seems like I somehow tested this wrong. Tried it again from
> scratch and on linux I also get this error.
Ah, OK.
Show 14 quoted lines
> Docker compose CLI options page is a little confusing because of
> these:
>
>>--interactive , -i  true  Keep STDIN open even if not attached.
>>--no-TTY , -T          true  Disable pseudo-TTY allocation (default: auto-detected).
>>--tty , -t          true  Allocate a pseudo-TTY.
>
> Second column with `true` values is titled `Default`, whatever it means.
> So `--tty` and `--no-TTY` is set by default? Anyway, seems like it is
> checking if at least one of stdout, stding, stderr is a tty and then
> tries to allocate a tty to all.
>
> You can check docs here
> https://docs.docker.com/engine/reference/commandline/compose_run/#options

Yeah, having the last two both on by default seems impossible. Perhaps the text in the parenthesis means that "default" is actually to detect TTYs automatically? In any case the help text could be clearer.

Show 8 quoted lines
> As a final solution I used makefile "magic" with `ifeq` and shell command like this:
>
>     $(shell test -t 0)
>     ifeq ($(.SHELLSTATUS), 1)
>     ALLOCATE_TTY = --no-TTY
>     endif
>
>     docker compose run $(ALLOCATE_TTY) --rm --entrypoint "" app /code/test.sh

OK. Would be nice if "docker compose" could handle that case automatically, though, wouldn't it? :)

> Maybe I'll just write to to them to clarify documentation on how
> those TTY options actually works by default.
Good idea.
René

← back to recent threads