2

We have a locally hosted Gitlab repository which I am trying to automate pushing and pulling with gitpython over ssh with the following script:

LOCAL_REPO_PATH = "/path/to/repository"

repo = Repo(LOCAL_REPO_PATH)

origin = repo.remotes[0]
origin.pull()

# Do some automated changes

index = repo.index

index.add(["*"])
index.commit("Removed/Added stuff")

author = Actor("Script","it@place.com)
committer = Actor("Script","it@place.com)

origin.push()

The config of the repo is

[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote "origin"]
        url = git@gitlab.<repo url>:<owner username>/<repository name>.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
        remote = origin
        merge = refs/heads/master

Whenever I try to run it, it reaches origin.pull() and stops execution to ask for git@gitlab.place.com in the following format:

Password: 
Password: 
Password: 
git@gitlab.<url>'s password: 
git@gitlab.<url>'s password:
git@gitlab.<url>'s password:

After incorrectly entering a password 6 times, it throws this error

Traceback (most recent call last):
  File "git-test.py", line 15, in <module>
    origin.pull()
  File "/usr/local/lib/python3.8/dist-packages/git/remote.py", line 910, in pull
    res = self._get_fetch_info_from_stderr(proc, progress,
  File "/usr/local/lib/python3.8/dist-packages/git/remote.py", line 750, in _get_fetch_info_from_stderr
    proc.wait(stderr=stderr_text)
  File "/usr/local/lib/python3.8/dist-packages/git/cmd.py", line 502, in wait
    raise GitCommandError(remove_password_if_present(self.args), status, errstr)
git.exc.GitCommandError: Cmd('git') failed due to: exit code(1)
  cmdline: git pull -v origin
  stderr: 'fatal: Could not read from remote repository.'

Is there any way to be able to automate this without having the password for the git user?

Edit 1

I have asked a new question here, as I have closer narrowed down what the issue is.

  • The `git@gitlab.:/.git` URL syntax, to Git, means the same as using `ssh://git@gitlab.//.git`, so Git will pass the entire `git@gitlab.` string to ssh. What *ssh* does with that is up to ssh, so see the ssh documentation. None of the rest is up to Python *or* Git *or* GitLab, it's all up to ssh. – torek Aug 05 '22 at 23:26
  • In general, using ssh here is the right thing, but you *must then set up a machine user for ssh access* (a deployment user or similar, not sure what GitLab call this), then *ensure that the user that runs the automated deployment scripts has password-free access to the deployment keys*. – torek Aug 05 '22 at 23:27

2 Answers2

3

The issue is not actually with GitPython, it is with the .git folder. I attempted to do a git pull from the command line, and it gave this error

error: cannot open .git/FETCH_HEAD: Permission denied

Consulting this link: Trying to git pull with error: cannot open .git/FETCH_HEAD: Permission denied, I ran chown myuser:mygroup -R .git, allowing me to git pull with no errors. This fixes the issue above while running the script. Apparently I had messed with the permissions and forgot about it.

I'm not sure why this would prompt me to ssh into git@gitlab, but the issue is now resolved

Edit 1:

I've done some experimentation, and running git fetch in sudo mode requires the git@gitlab user to execute. I'm working on a way of lowering the privileges for the one command

Since git pull is actually a combination of git fetch and git merge, the FETCH_HEAD file is created with the permissions of whoever ran the git fetch. I'm assuming that since the script must be run as sudo, the internal git fetch is also ran as sudo.

  • 2
    Good catch. Upvoted. Check what kind of remote URL you are using with `git remote -v`. – VonC Aug 08 '22 at 17:59
0

As explained in GitPython and SSH Keys?, you would need to start with a (gitpython) clone referencing the path to the private key, whose public key must be registered to the GitLab user account SSH keys settings page.

from git import Repo
Repo.clone_from("gitlab_ssh_url", 
                "path_where_you_want_to_clone_repo", 
                env={"GIT_SSH_COMMAND": 'ssh -i path_to_ssh_private_key'})

That way, GitLab will authenticate the actual user trying to clone said repository, and will determine if said user has the right to access the repository they want to clone.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250