Skip to content

Commit

Permalink
Prevent git from prompting for credentials
Browse files Browse the repository at this point in the history
There can be situations where git needs credentials and prompts the user,

* Trying to push to via http
* Trying to push via ssh but without having a key, or a key with a passphrase
* Trying to fetch from a private repo via http or ssh

This does not make sense in automated code and results in a hanging process
waitign for input.

We can prevent a prompt by setting the following two variables:

https://git-scm.com/docs/git#Documentation/git.txt-codeGITASKPASScode

GIT_ASKPASS
If this environment variable is set, then Git commands which need to acquire
passwords or passphrases (e.g. for HTTP or IMAP authentication) will call this
program with a suitable prompt as command-line argument and read the password
from its STDOUT. See also the core.askPass option in git-config[1].

https://git-scm.com/docs/git#Documentation/git.txt-codeGITTERMINALPROMPTcode
GIT_TERMINAL_PROMPT
If this Boolean environment variable is set to false, git will not prompt on
the terminal (e.g., when asking for HTTP authentication).

This way we will immediately get an error message.

Issue: https://progress.opensuse.org/issues/174592

In this case the error presented to the user is:
"Unable to push Git commit
(/path/to/needles): remote: Support
for password authentication was removed on August 13, 2021. remote: Please see
https://docs.github.com/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls
for information on currently recommended modes of authentication. fatal:
Authentication failed for
'https://github.com/perlpunk/os-autoinst-needles-openQA/'"

That can be improved in a followup by adding a link to our documentation.
  • Loading branch information
perlpunk committed Jan 28, 2025
1 parent 6b9b184 commit a42198e
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 14 deletions.
4 changes: 2 additions & 2 deletions lib/OpenQA/Git.pm
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ sub _run_cmd ($self, $args, $options = {}) {
my $include_git_path = $options->{include_git_path} // 1;
my $batchmode = $options->{batchmode} // 0;
my @cmd;
push @cmd, 'env', 'GIT_SSH_COMMAND=ssh -oBatchMode=yes' if $batchmode;
push @cmd, 'env', 'GIT_SSH_COMMAND=ssh -oBatchMode=yes', 'GIT_ASKPASS=echo', 'GIT_TERMINAL_PROMPT=false' if $batchmode;
push @cmd, $self->_prepare_git_command($include_git_path), @$args;

my $result = run_cmd_with_log_return_error(\@cmd);
Expand Down Expand Up @@ -97,7 +97,7 @@ sub commit ($self, $args = undef) {

# push changes
if (($self->config->{do_push} || '') eq 'yes') {
$res = $self->_run_cmd(['push']);
$res = $self->_run_cmd(['push'], {batchmode => 1});
return $self->_format_git_error($res, 'Unable to push Git commit') unless $res->{status};
}

Expand Down
23 changes: 12 additions & 11 deletions t/14-grutasks-git.t
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ subtest 'git clone' => sub {
run_cmd_with_log_return_error => sub ($cmd) {
push @mocked_git_calls, join(' ', map { tr/ // ? "'$_'" : $_ } @$cmd) =~ s/\Q$git_clones//r;
my $stdout = '';
splice @$cmd, 0, 2 if $cmd->[0] eq 'env';
splice @$cmd, 0, 4 if $cmd->[0] eq 'env';
my $path = '';
(undef, $path) = splice @$cmd, 1, 2 if $cmd->[1] eq '-C';
my $action = $cmd->[1];
Expand Down Expand Up @@ -109,6 +109,7 @@ subtest 'git clone' => sub {
});
my @gru_args = ($t->app, 'git_clone', $clone_dirs, {priority => 10});
my $res = run_gru_job(@gru_args);

is $res->{result}, 'Job successfully executed', 'minion job result indicates success';
#<<< no perltidy
my $expected_calls = [
Expand All @@ -121,31 +122,31 @@ subtest 'git clone' => sub {
['rev-parse' => 'git -C /sha2 rev-parse --verify -q def'],
['check dirty' => 'git -C /sha2 diff-index HEAD --exit-code'],
['current branch' => 'git -C /sha2 branch --show-current'],
['fetch branch' => "env 'GIT_SSH_COMMAND=ssh -oBatchMode=yes' git -C /sha2 fetch origin def"],
['fetch branch' => "env 'GIT_SSH_COMMAND=ssh -oBatchMode=yes' GIT_ASKPASS=echo GIT_TERMINAL_PROMPT=false git -C /sha2 fetch origin def"],

# /branch
['get-url' => 'git -C /branch/ remote get-url origin'],
['check dirty' => 'git -C /branch/ diff-index HEAD --exit-code'],
['current branch' => 'git -C /branch/ branch --show-current'],
['fetch branch' => "env 'GIT_SSH_COMMAND=ssh -oBatchMode=yes' git -C /branch/ fetch origin foobranch"],
['fetch branch' => "env 'GIT_SSH_COMMAND=ssh -oBatchMode=yes' GIT_ASKPASS=echo GIT_TERMINAL_PROMPT=false git -C /branch/ fetch origin foobranch"],

# /default/
['get-url' => 'git -C /default/ remote get-url origin'],
['check dirty' => 'git -C /default/ diff-index HEAD --exit-code'],
['default remote' => "env 'GIT_SSH_COMMAND=ssh -oBatchMode=yes' git ls-remote --symref http://localhost/foo.git HEAD"],
['default remote' => "env 'GIT_SSH_COMMAND=ssh -oBatchMode=yes' GIT_ASKPASS=echo GIT_TERMINAL_PROMPT=false git ls-remote --symref http://localhost/foo.git HEAD"],
['current branch' => 'git -C /default/ branch --show-current'],
['fetch default' => "env 'GIT_SSH_COMMAND=ssh -oBatchMode=yes' git -C /default/ fetch origin master"],
['fetch default' => "env 'GIT_SSH_COMMAND=ssh -oBatchMode=yes' GIT_ASKPASS=echo GIT_TERMINAL_PROMPT=false git -C /default/ fetch origin master"],
['reset' => 'git -C /default/ reset --hard origin/master'],

# /sha-branchname
['get-url' => 'git -C /sha-branchname remote get-url origin'],
['rev-parse' => 'git -C /sha-branchname rev-parse --verify -q a123'],
['check dirty' => 'git -C /sha-branchname diff-index HEAD --exit-code'],
['current branch' => 'git -C /sha-branchname branch --show-current'],
['fetch branch' => "env 'GIT_SSH_COMMAND=ssh -oBatchMode=yes' git -C /sha-branchname fetch origin a123"],
['fetch branch' => "env 'GIT_SSH_COMMAND=ssh -oBatchMode=yes' GIT_ASKPASS=echo GIT_TERMINAL_PROMPT=false git -C /sha-branchname fetch origin a123"],

# /this_directory_does_not_exist/
['clone' => "env 'GIT_SSH_COMMAND=ssh -oBatchMode=yes' git clone http://localhost/bar.git /this_directory_does_not_exist/"],
['clone' => "env 'GIT_SSH_COMMAND=ssh -oBatchMode=yes' GIT_ASKPASS=echo GIT_TERMINAL_PROMPT=false git clone http://localhost/bar.git /this_directory_does_not_exist/"],
];
#>>> no perltidy
for my $i (0 .. $#$expected_calls) {
Expand Down Expand Up @@ -222,17 +223,17 @@ subtest 'git clone' => sub {
# /opensuse
['get-url' => 'git -C /opensuse remote get-url origin'],
['check dirty' => 'git -C /opensuse diff-index HEAD --exit-code'],
['default remote' => "env 'GIT_SSH_COMMAND=ssh -oBatchMode=yes' git ls-remote --symref http://osado HEAD"],
['default remote' => "env 'GIT_SSH_COMMAND=ssh -oBatchMode=yes' GIT_ASKPASS=echo GIT_TERMINAL_PROMPT=false git ls-remote --symref http://osado HEAD"],
['current branch' => 'git -C /opensuse branch --show-current'],
['fetch default ' => "env 'GIT_SSH_COMMAND=ssh -oBatchMode=yes' git -C /opensuse fetch origin master"],
['fetch default ' => "env 'GIT_SSH_COMMAND=ssh -oBatchMode=yes' GIT_ASKPASS=echo GIT_TERMINAL_PROMPT=false git -C /opensuse fetch origin master"],
['reset' => 'git -C /opensuse reset --hard origin/master'],

# /opensuse/needles
['get-url' => 'git -C /opensuse/needles remote get-url origin'],
['check dirty' => 'git -C /opensuse/needles diff-index HEAD --exit-code'],
['default remote' => "env 'GIT_SSH_COMMAND=ssh -oBatchMode=yes' git ls-remote --symref http://osado HEAD"],
['default remote' => "env 'GIT_SSH_COMMAND=ssh -oBatchMode=yes' GIT_ASKPASS=echo GIT_TERMINAL_PROMPT=false git ls-remote --symref http://osado HEAD"],
['current branch' => 'git -C /opensuse/needles branch --show-current'],
['fetch branch' => "env 'GIT_SSH_COMMAND=ssh -oBatchMode=yes' git -C /opensuse/needles fetch origin master"],
['fetch branch' => "env 'GIT_SSH_COMMAND=ssh -oBatchMode=yes' GIT_ASKPASS=echo GIT_TERMINAL_PROMPT=false git -C /opensuse/needles fetch origin master"],
['reset' => 'git -C /opensuse/needles reset --hard origin/master'],
];
#>>> no perltidy
Expand Down
2 changes: 1 addition & 1 deletion t/16-utils-runcmd.t
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ subtest 'git commands with mocked run_cmd_with_log_return_error' => sub {
$utils_mock->redefine(
run_cmd_with_log_return_error => sub ($cmd) {
push @executed_commands, $cmd;
if ($cmd->[3] eq 'push') {
if ($cmd->[7] eq 'push') {
$mock_return_value{status} = 0;
}
return \%mock_return_value;
Expand Down

0 comments on commit a42198e

Please sign in to comment.