typicode / husky

Git hooks made easy 🐶 woof!
https://typicode.github.io/husky
MIT License
32.58k stars 1.03k forks source link

Why "lint-staged" log is different when is triggered by husky (v6)? #968

Open luquera opened 3 years ago

luquera commented 3 years ago

Everything is set up correctly, according to the documentation. I'm using Windows 10.

by husky: image

by npm script (running lint-staged): image

Thanks!

walkerrandolphsmith commented 3 years ago

I am experiencing this as well with lint staged 11.0.0 and husky v6. In addition, when I run yarn lint-staged it updates staged files, but when committing and relying on a hook to call yarn lint-staged the changes are left un-staged and a commit is made.

Running lint-staged with the following config:
$ HUSKY_DEBUG=1 git commit -m "fix some bug"
husky (debug) - starting pre-commit...
Running lint-staged with the following config:
{
  '*.{js,ts,tsx}': 'prettier --write'
}
[STARTED] Preparing...
[SUCCESS] Preparing...
[STARTED] Running tasks...
[STARTED] Running tasks for *.{js,ts,tsx}
[STARTED] prettier --write
[SUCCESS] prettier --write
[SUCCESS] Running tasks for *.{js,ts,tsx}
[SUCCESS] Running tasks...
[STARTED] Applying modifications...
[SUCCESS] Applying modifications...
[STARTED] Cleaning up...
[SUCCESS] Cleaning up...

ℹ prettier --write:
src\__tests__\utilities.test.ts 326ms
[story/5065410 9ee08d85a] fix
 1 file changed, 1 insertion(+), 1 deletion(-)
MineiToshio commented 3 years ago

Having the same issue, @luquera did you manage to solve it?

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

luquera commented 3 years ago

Having the same issue, @luquera did you manage to solve it?

Unfortunately not yet :(

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

FFdhorkin commented 2 years ago

Issue is still not solved

mukhlisakbr commented 2 years ago

it still not solved till now

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

typicode commented 2 years ago

Not sure, but I guess it detects that the terminal aren't capable of rendering the first version and renders the second one. I imagine it's done via an env variable. I would try passing some env variable to try if it's possible to "force" the first type of rendering.

And sometimes, it's better to avoid animation and have per-line information (for example logs in Git GUIs).

I would check the dependencies that lint-staged uses for rendering the results.

That said, as far as I know, I don't think there's anything that can be done in husky's code to help with that.

TrejGun commented 2 years ago

same here

acidcrash2005 commented 2 years ago

Has anyone found resolve?

Axedyson commented 2 years ago

It worked for me before, but since yesterday I've now bumped into the same exact issue. I'm using the windows terminal and running my project in WSL2

Axedyson commented 2 years ago

Okay it seems like this is working for me: https://github.com/AndysonDK/syncbase/blob/main/.husky/pre-commit But commitizen cli is still not rendered properly

valentinoli commented 2 years ago

Partially fixed in lint-staged https://github.com/okonet/lint-staged/issues/693#issuecomment-1079759224

iiroj commented 2 years ago

The issue seems to be that supports-color (code link) and colorette (code link) both use the tty.isatty(1) check from node:tty to test whether the current stdin is in fact a TTY. This is reported as false when running through a git hook (with husky), and true when directly running lint-staged.

I'm not sure what caused this to start happen, but I assume it is an update to one of:

  1. dependencies of lint-staged (colorette, supports-color..., listr2)
  2. husky
  3. git itself
iiroj commented 2 years ago

For a simple reproduction, try running in your terminal:

> node -e "console.log(require('tty').isatty(1))"
true

Putting this same script into the pre-commit sh script of Husky, will print false instead:

#!/usr/bin/env sh
. "$(dirname "$0")/_/husky.sh"

node -e "console.log(require('tty').isatty(1))"
axmrnv commented 2 years ago

TL;DR: Adding exec 1> /dev/tty or exec >/dev/tty 2>&1 to your git hook before npx lint-staged looks like a workaround:

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

exec >/dev/tty 2>&1

npx lint-staged

As @iiroj pointed out, tty.isatty(1) returns false if running in the git hook. In order to test it, we have a file ./.husky/pre-commit like this:

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

node -e "console.log(require('tty').isatty(1))"

When executing the file directly from bash, it returns true; but if it runs in the git hook, it returns false:

> bash ./.husky/pre-commit
true

> git hook run pre-commit
false

Let's redirect stdout (fd 1) to /dev/tty:

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

exec 1> /dev/tty

node -e "console.log(require('tty').isatty(1))"

Now it returns true in both cases:

> bash ./.husky/pre-commit
true

> git hook run pre-commit
true

So, adding exec 1> /dev/tty (to redirect stdout) or exec >/dev/tty 2>&1 (to redirect stdout and stderr) to git hook (before payload) looks like a workaround.

Ethorsen commented 2 years ago

@axmrnv Amazing discovery. We'll give it a try, thank you very much for this workaround

valentinoli commented 2 years ago

@axmrnv Thank you, it works!

iiroj commented 2 years ago

Can somebody open a PR for adding this to the README of lint-staged, maybe under Frequently Asked Questions? 🙏

Josh-Cena commented 2 years ago

It still appears largely like a bug to me—would appreciate it if anyone could dig out the actual reason why it's suddenly not a tty...

iiroj commented 2 years ago

It's not anything done directly in lint-staged, as @axmrnv explained pretty well.

I would like to fix it in lint-staged, but it would have to be pretty robust. Preferably it's something the git team would fix directly so that the default STDOUT would be a TTY.

EDIT: Hehe, I thought this issue was in the lint-staged project, not husky. In any case, that's my just my opinion.

axmrnv commented 2 years ago

Yes, it's git. I don't know why git hook's stdout is not a tty. Maybe there is a reason for that.

In theory, we could fix (workaround) it here by adding exec >/dev/tty 2>&1 redirection to husky's hook file template. It this case, the redirection would be added to any git hook created by husky. The template is in the followind listing, and redirection might be added beween lines 72 and 74:

https://github.com/typicode/husky/blob/840c4164d06d3c412caf63a9c9d7ca1af15f2165/src/index.ts#L71-L75

However, this redirection feels a bit hacky, and I'm not sure if it's ok to make it a part of out-of-a-box solution. It's better to tie it to optional CLI parameter (i. e. add redirection if some argument to husky add is set). But I don't know whether this solution is aligned to husky owner's vision. @typicode, what do you think?

ltbyce commented 2 years ago

@axmrnv Thank you very much!

valentinoli commented 2 years ago

I tried the above workaround in a lerna monorepo and lerna throws the following error for the lerna version command:

lerna ERR! Error: Command failed with exit code 1: git commit -F C:\Users\toto7\AppData\Local\Temp\4e4b3611-e84a-475c-b4ff-cb1e505a1c1c\lerna-commit.txt
lerna ERR! .husky/pre-commit: line 4: /dev/tty: No such device or address
lerna ERR! husky - pre-commit hook exited with code 1 (error)
lerna ERR!     at makeError (C:\Users\toto7\Documents\cours\EPFL\PDM\hestialabs\node_modules\execa\lib\error.js:60:11)
lerna ERR!     at handlePromise (C:\Users\toto7\Documents\cours\EPFL\PDM\hestialabs\node_modules\execa\index.js:118:26)
lerna ERR!     at processTicksAndRejections (node:internal/process/task_queues:96:5)
lerna ERR!     at async Promise.all (index 0)
lerna ERR! lerna Command failed with exit code 1: git commit -F C:\Users\toto7\AppData\Local\Temp\4e4b3611-e84a-475c-b4ff-cb1e505a1c1c\lerna-commit.txt
lerna ERR! lerna .husky/pre-commit: line 4: /dev/tty: No such device or address
lerna ERR! lerna husky - pre-commit hook exited with code 1 (error)

I worked around this by skipping commit hooks with

$ lerna version --no-commit-hooks
sanzhar-dan commented 2 years ago

Thank you @axmrnv ! It finally fixed that issue.

valentinoli commented 2 years ago

My colleague tried to commit in Magit in emacs with the above workaround and got the following error:

0 git.exe … "add" "-u" "--" "experiences/.husky/pre-commit"
  1 git.exe … "commit" "--"
experiences/.husky/pre-commit: line 5: /dev/tty: No such device or address
husky - pre-commit hook exited with code 1 (error)
sandumorari commented 2 years ago

My colleague tried to commit in Magit in emacs with the above workaround and got the following error:

0 git.exe … "add" "-u" "--" "experiences/.husky/pre-commit"
  1 git.exe … "commit" "--"
experiences/.husky/pre-commit: line 5: /dev/tty: No such device or address
husky - pre-commit hook exited with code 1 (error)

Same here

valentinoli commented 2 years ago

My colleague tried to commit in Magit in emacs with the above workaround and got the following error

I think we found a workaround for it, but might not work for all environments:

if [ -t 2 ]; then
  exec >/dev/tty 2>&1
fi

based on this answer

axmrnv commented 2 years ago

@valentinoli, thanks for pointing this out! However, this workaround may be improved. It should work most of the time as stdout & stderr often go hand in hand; but that's not always the case. If you're going to redirect stdout and stderr, it's better to test if both files are opened on a terminal:

if [[ -t 1 && -t 2 ]]; then exec >/dev/tty 2>&1; fi

If you want to redirect stdout (but not stderr), you need to test fd 1 only:

if [ -t 1 ]; then exec 1> /dev/tty; fi

You also may test and redirect stdout and stderr separately, but I believe it's an overkill:

if [ -t 1 ]; then exec 1> /dev/tty; fi
if [ -t 2 ]; then exec 2> /dev/tty; fi
ikrishagarwal commented 2 years ago

Would this work for windows powershell / cmd?

Chen-913 commented 2 years ago

TL;DR: Adding exec 1> /dev/tty or exec >/dev/tty 2>&1 to your git hook before npx lint-staged looks like a workaround:

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

exec >/dev/tty 2>&1

npx lint-staged

As @iiroj pointed out, tty.isatty(1) returns false if running in the git hook. In order to test it, we have a file ./.husky/pre-commit like this:

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

node -e "console.log(require('tty').isatty(1))"

When executing the file directly from bash, it returns true; but if it runs in the git hook, it returns false:

> bash ./.husky/pre-commit
true

> git hook run pre-commit
false

Let's redirect stdout (fd 1) to /dev/tty:

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

exec 1> /dev/tty

node -e "console.log(require('tty').isatty(1))"

Now it returns true in both cases:

> bash ./.husky/pre-commit
true

> git hook run pre-commit
true

So, adding exec 1> /dev/tty (to redirect stdout) or exec >/dev/tty 2>&1 (to redirect stdout and stderr) to git hook (before payload) looks like a workaround.

This is very useful to me, but how can I ensure that I can continue to use it properly at the end of the project?

silouanwright commented 2 years ago

One note, having debugged my own issue: you may run into commands ran with lint-staged that need specific flags added to those commands, to preserve the formatting of them.

For instance, if you run tsc commands through lint-staged, adding the --pretty flag (tsc --pretty) may fix your issue. It worked for me, and there may be similar commands you may run to run through lint-staged where you have to go expressly throw on a formatting flag that would normally run by default, but not with lint-staged.

jetersen commented 2 years ago

@axmrnv the conditional approach below does not work for windows or well it does but it forces lint-staged into non color mode 😓

if [[ -t 1 && -t 2 ]]; then exec >/dev/tty 2>&1; fi

Tried this one below but again non color mode.

if [ -t 1 ]; then exec 1> /dev/tty; fi
if [ -t 2 ]; then exec 2> /dev/tty; fi

The one below seems to work for windows and uses colors (imo prefer this as it is less verbose). I am not sure why this is the case

if [ -t 2 ]; then
  exec >/dev/tty 2>&1
fi
rszalski commented 2 years ago

Just ran into the same thing at work when upgrading husky. I noticed that the output of my hooks differs from that of my colleague.

Thanks to the prior comments hinting at the issue being that the git hooks are not attached to a TTY I wanted to check if git version mismatch was the issue. Turns out yes, I was running 2.37.1 and my colleague 2.36.1.

Git has fixed what I believe to be this exact issue in v 2.37.0: https://github.com/git/git/commit/a082345372e14ecd30a84a790eda0c38154e4602.

Also see: https://github.com/okonet/lint-staged/commit/20ab7e17ce52ce0e9e0f855095bdab8e1ccd985c

Release notes: https://github.com/git/git/blob/master/Documentation/RelNotes/2.37.0.txt#L285

akamfoad commented 2 years ago

Hi, I have a similar issue but in my case the terminal is being exploded with repeated log output.

OS: Windows
Shell: PowerShell 7.2.6
Git Version: 2.37.1.windows.1

running

yarn lint-staged

Through git hooks (added with husky):

https://user-images.githubusercontent.com/41629832/188649709-a61d2579-319a-487b-b2cf-abb89b75cace.mp4

Directly running the command:

https://user-images.githubusercontent.com/41629832/188650212-0fa8b4ea-bc04-43f7-9c88-1d68045e96a4.mp4

lalitlsg commented 2 years ago

If I make a commit from vscode UI, by keeping exec >/dev/tty 2>&1 in pre-commit script It gives below error:

.husky/pre-commit: line 4: /dev/tty: Device not configured

J4v4Scr1pt commented 2 years ago

Hi, I have a similar issue but in my case the terminal is being exploded with repeated log output.

OS: Windows
Shell: PowerShell 7.2.6
Git Version: 2.37.1.windows.1

running

yarn lint-staged

Through git hooks (added with husky):

PowerShell.2022-09-06.16-37-59.mp4

Directly running the command:

PowerShell.2022-09-06.16-39-07.mp4

Exactly the same thing happens to me and my team. Can't understand why and there seems to be no working solution from what I can find. If you check Task Manager you can also see that it spins up many Node.js instances. And the computer gets super slow. It even makes working js test to timeout.

I think this is a seroius issue that will affect usage. But Like I said I cant figure out why this accure.

Edit: I will reference you are excellent explanation in a new issue @akamfoad.

Nick-Hopps commented 2 years ago

image

seems they fix it in version 2.38?

vkrol commented 2 years ago

@Nick-Hopps No, I checked it.

wherehows commented 2 years ago

If I make a commit from vscode UI, by keeping exec >/dev/tty 2>&1 in pre-commit script It gives below error:

.husky/pre-commit: line 4: /dev/tty: Device not configured

@lalitlsg

i have the same problem but after i change /dev/tty to /dev/console it works

i dont know how it works exactly but anyway it works. (ㅠ.ㅠ)

cf: https://unix.stackexchange.com/questions/692257/why-no-such-device-or-address-when-open-dev-tty-in-the-first-process/

yangliguo7 commented 1 year ago

maybe you should run your command in terminal not in VSCODE or webStrom . @wherehows

akmaldira commented 1 year ago

Hi, I have a similar issue but in my case the terminal is being exploded with repeated log output.

OS: Windows
Shell: PowerShell 7.2.6
Git Version: 2.37.1.windows.1

running

yarn lint-staged

Through git hooks (added with husky):

PowerShell.2022-09-06.16-37-59.mp4

Directly running the command:

PowerShell.2022-09-06.16-39-07.mp4

Same problem here

MrFlyHouse commented 1 year ago

If I make a commit from vscode UI, by keeping exec >/dev/tty 2>&1 in pre-commit script It gives below error: .husky/pre-commit: line 4: /dev/tty: Device not configured

@lalitlsg

i have the same problem but after i change /dev/tty to /dev/console it works

i dont know how it works exactly but anyway it works. (ㅠ.ㅠ)

cf: https://unix.stackexchange.com/questions/692257/why-no-such-device-or-address-when-open-dev-tty-in-the-first-process/

@wherehows It works when I'm using terminal panel, but doesn't work when using the SOURCE CONTROL gui panel (commit by press 'Commit' button), do you have same problem, and do you solve it if so?

VSCode said .husky/pre-commit: line 4: /dev/console: No such device or address

wherehows commented 1 year ago

If I make a commit from vscode UI, by keeping exec >/dev/tty 2>&1 in pre-commit script It gives below error: .husky/pre-commit: line 4: /dev/tty: Device not configured

@lalitlsg i have the same problem but after i change /dev/tty to /dev/console it works i dont know how it works exactly but anyway it works. (ㅠ.ㅠ) cf: https://unix.stackexchange.com/questions/692257/why-no-such-device-or-address-when-open-dev-tty-in-the-first-process/

@wherehows It works when I'm using terminal panel, but doesn't work when using the SOURCE CONTROL gui panel (commit by press 'Commit' button), do you have same problem, and do you solve it if so?

VSCode said .husky/pre-commit: line 4: /dev/console: No such device or address

not only source control but also 'fork' tool doesnt work. i haven't solved it yet ㅠ.ㅠ

siarheiyelin commented 1 year ago

I managed to solve the issue by downgrading "lint-staged" from 13.x to 12.x

iiroj commented 1 year ago

@siarheiyelin Are you sure downgrading lint-staged fixes it? If so, I can take a look at the updates/changes in version 13 and try out if a culprit can be found.

iiroj commented 1 year ago

Can you try installing lint-staged@next (version 13.1.3) to see if it helps? I restored supports-color in place of colorette's isColorSupported util, a change that was introduced in 13.0.0.

loriswit commented 1 year ago

Can you try installing lint-staged@next (version 13.1.3) to see if it helps? I restored supports-color in place of colorette's isColorSupported util, a change that was introduced in 13.0.0.

@iiroj This fixes the repeated logs issue (as seen in https://github.com/typicode/husky/issues/968#issuecomment-1238185342), but shows instead the uncolored output as described in the original post. I guess this is better than the repeated outputs, but we're basically back to where we started.

Geczy commented 1 year ago

image

same problem here

VSCode said .husky/pre-commit: line 4: /dev/console: No such device or address