Bruno Bronosky
Bruno Bronosky

Reputation: 70329

How do you debug git credential helpers?

I have read:

Unfortunately, I cannot get the most basic Scientific Method™ test to work. I have used my stand-in command to try and log what happens when git calls the helper. Unfortunately, my command logs nothing. Therefore I'm forced to conclude that git is not calling its helper. What can I do?

Upvotes: 5

Views: 2234

Answers (1)

wheeler
wheeler

Reputation: 3241

I was trying to get the 1Password CLI to hand over my GitHub token to the gh command, and configure Git to use the gh command as a credential helper. But I was running into an issue when I would run gh auth git-credential from the command line and it would produce the correct credentials, but when I had the following in ~/.gitignore a git clone would still prompt me for my username and password:

[credential "https://github.com"]
    helper = /usr/bin/gh auth git-credential

To do some debugging, I first enabled trace logging in Git by setting the GIT_TRACE environment variable to true:

GIT_TRACE=true git clone https://github.com/wheelerlaw/some-private-repo

which would yield output that looked like this:

$ GIT_TRACE=true git clone https://github.com/Kong/khcp.git
15:19:00.344373 git.c:460               trace: built-in: git clone https://github.com/Kong/khcp.git
Cloning into 'khcp'...
15:19:00.347803 run-command.c:655       trace: run_command: git remote-https origin https://github.com/Kong/khcp.git
15:19:00.349893 git.c:750               trace: exec: git-remote-https origin https://github.com/Kong/khcp.git
15:19:00.349939 run-command.c:655       trace: run_command: git-remote-https origin https://github.com/Kong/khcp.git
15:19:00.625485 run-command.c:655       trace: run_command: '/usr/bin/gh auth git-credential get'

However, it wouldn't show any debugging output of the data passed to/from the credential helper. To do this, I wrote a small Python script that acted as a wrapper around the credential helper:

#!/usr/bin/env python3

import sys
import subprocess


def eprint(*args, **kwargs):
    print(*args, file=sys.stderr, **kwargs)

def etrace(str):
    eprint("[TRACE] ", str)


args = ['/usr/bin/gh', 'auth', 'git-credential'] + sys.argv[1:]

process = subprocess.Popen(args,
                           stdout=subprocess.PIPE,
                           stderr=sys.stderr,
                           stdin=subprocess.PIPE,
                           universal_newlines=True)

etrace(args)
for input in sys.stdin:
    etrace(input.strip())
    process.stdin.write(input)

process.stdin.close()

etrace("Done sending input...")

for output in process.stdout.readlines():
    etrace("Printing output...")
    etrace(output.strip())
    print(output.strip())

etrace("Done receiving output...")

return_code = process.poll()

etrace("Return code: " + str(return_code))

exit(return_code)

Then, I modified my ~/.gitconfig file to call the Python script as the credential helper:

[credential "https://github.com"]
    helper = /home/wheeler/wrapper.py

Now when I do the same git clone command with the trace debugging enabled, I can see how git and gh auth git-credential are talking to each other:

$ GIT_TRACE=true git clone https://github.com/Kong/khcp.git
15:54:33.973855 git.c:460               trace: built-in: git clone https://github.com/Kong/khcp.git
Cloning into 'khcp'...
15:54:33.987155 run-command.c:655       trace: run_command: git remote-https origin https://github.com/Kong/khcp.git
15:54:33.989509 git.c:750               trace: exec: git-remote-https origin https://github.com/Kong/khcp.git
15:54:33.989539 run-command.c:655       trace: run_command: git-remote-https origin https://github.com/Kong/khcp.git
15:54:34.191478 run-command.c:655       trace: run_command: '/home/wheeler/test.py get'
[TRACE]  ['/usr/bin/gh', 'auth', 'git-credential', 'get']
[TRACE]  protocol=https
[TRACE]  host=github.com
[TRACE]  Done sending input...
[TRACE]  Done receiving output...
[TRACE]  Return code: 1

This helped me realize that I needed to set my helper line to the following to allow the gh command to get the token from 1Password:

[credential "https://github.com"]
    helper = /usr/bin/op plugin run -- gh auth git-credential

Hope this helps

Upvotes: 2

Related Questions