GitLab runner, error on push whereas same thing works on git bash or python from a console

gluttony :

Context

We're trying to do a GitLab runner job that, on a certain tag, modifies a version header file and add a release branch/tag to this changeset.

The GitLab runner server is on my machine, launched as a service by my user (that is properly registered to our GitLab server).

The GitLab runner job basically launches a python script that uses gitpython to du the job, there are just a few changes in runner yml file (added before_script part to be able to have upload permission, got it from there: https://stackoverflow.com/a/55344804/11159476), here is full .gitlab-ci.yml file:

variables:
  GIT_SUBMODULE_STRATEGY: recursive

stages: [ build, publish, release ]

release_tag:
  stage: build
  before_script:
    - git config --global user.name ${GITLAB_USER_NAME}
    - git config --global user.email ${GITLAB_USER_EMAIL}
  script:
    - python .\scripts\release_gitlab_runner.py
  only:
    # Trigger on specific regex...
    - /^Src_V[0-9]+\.[0-9]+\.[0-9]+$/
  except:
    # .. only for tags then except branches, see doc (https://docs.gitlab.com/ee/ci/yaml/#regular-expressions): "Only the tag or branch name can be matched by a regular expression."
    - branches

Also added trick in the python URL when pushing (push with user:personal_access_token@repo_URL instead of default runner URL, got it from same answer as above, and token has been generated from company gitlab => user "Settings" => "Access Tokens" => "Add a personal access token" with all rights and never expiring), and here is, not the actual scripts\release_gitlab_runner.py python script but one simplified to have a git flow as much standard as possible for what we want (fetch all, create local branch with random name so that it does not exist, modify a file, stage, commit and finally push):

# -*-coding:utf-8 -*

import uuid
import git
import sys
import os

# Since we are in <git root path>/scripts folder, git root path is this file's path parent path
GIT_ROOT_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
try:
    # Get user login and URL from GITLAB_USER_LOGIN and CI_REPOSITORY_URL gitlab environment variables
    gitlabUserLogin = os.environ["GITLAB_USER_LOGIN"]
    gitlabFullURL = os.environ["CI_REPOSITORY_URL"]
    # Push at "https://${GITLAB_USER_NAME}:${PERSONAL_ACCESS_TOKEN}@gitlab.companyname.net/demo/demo.git")
    # generatedPersonalAccessToken has been generated with full rights from https://gitlab.companyname.net/profile/personal_access_tokens and set in a variable not seen here
    gitlabPushURL = "https://{}:{}@{}".format(gitlabUserLogin, generatedPersonalAccessToken, gitlabFullURL.split("@")[-1])
    print("gitlabFullURL is [{}]".format(gitlabFullURL))
    print("gitlabPushURL is [{}]".format(gitlabPushURL))

    branchName = str(uuid.uuid1())

    print("Build git.Repo object with [{}] root path".format(GIT_ROOT_PATH))
    repo = git.Repo(GIT_ROOT_PATH)

    print("Fetch all")
    repo.git.fetch("-a")

    print("Create new local branch [{}]".format(branchName))
    repo.git.checkout("-b", branchName)

    print("Modify file")
    versionFile = os.path.join(GIT_ROOT_PATH, "public", "include" , "Version.h")
    patchedVersionFileContent = ""
    with open(versionFile, 'r') as versionFileContent:
        patchedVersionFileContent = versionFileContent.read()
        patchedVersionFileContent = re.sub("#define VERSION_MAJOR 0", "#define VERSION_MAJOR {}".format(75145), patchedVersionFileContent)
    with open(versionFile, 'w') as versionFileContent:
        versionFileContent.write(patchedVersionFileContent)

    print("Stage file")
    repo.git.add("-u")

    print("Commit file")
    repo.git.commit("-m", "New version file in new branch {}".format(branchName))

    print("Push new branch [{}] remotely".format(branchName))
    # The error is at below line:
    repo.git.push(gitlabPushURL, "origin", branchName)

    sys.exit(0)
except Exception as e:
    print("Exception: {}".format(e))

    sys.exit(-1)

Problem

Even with the trick to have rights, when we try to push from GitLab runner following error is raised:

Cmd('git') failed due to: exit code(1)
  cmdline: git push https://user:[email protected]/demo/repo.git origin 85a3fa6e-690a-11ea-a07d-e454e8696d31
  stderr: 'error: src refspec origin does not match any
error: failed to push some refs to 'https://user:[email protected]/demo/repo.git''

What works

If I open a Git Bash, I successfully run manual commands:

git fetch -a
git checkout -b newBranch
vim public/include/Version.h
=> At this point file has been modified
git add -u
git commit -m "New version file in new branch"
git push origin newBranch

Here if we fetch all from elsewhere we can see newBranch with version file modifications

And same if we run script content (without URL modification) from a python command line (assuming all imports as in script have been performed):

GIT_ROOT_PATH = "E:\\path\\to\\workspace\\repo"
branchName = str(uuid.uuid1())
repo = git.Repo(GIT_ROOT_PATH)
repo.git.fetch("-a")
repo.git.checkout("-b", branchName)
versionFile = os.path.join(GIT_ROOT_PATH, "public", "include" , "Version.h")
patchedVersionFileContent = ""
with open(versionFile, 'r') as versionFileContent:
    patchedVersionFileContent = versionFileContent.read()
    patchedVersionFileContent = re.sub("#define VERSION_MAJOR 0", "#define VERSION_MAJOR {}".format(75145), patchedVersionFileContent)
with open(versionFile, 'w') as versionFileContent:
    versionFileContent.write(patchedVersionFileContent)
repo.git.add("-u")
repo.git.commit("-m", "New version file in new branch {}".format(branchName))
repo.git.push("origin", branchName)

Conclusion

I can't find what I do wrong when running from GitLab runner, is there something I'm missing ?

The only thing that I can see different when running from GitLab runner is that after fetch I can see I'm on a detached head (listing repo.git.branch('-a').split('\n') gives for example ['* (HEAD detached at 560976b)', 'branchName', 'remotes/origin/otherExistingBranch', ...]), but this should not be a problem since I create a new branch where to push, right ?

frost-nzcr4 :

Git said that you used the wrong refspec. When you need to push in other remote you have to make it first gitlab = repo.create_remote("gitlab", gitlabPushURL) and push to it like repo.push("gitlab", branchName).

Edit from @gluttony to not break on next git run with "remote already exists":

remote_name = "gitlab"
if remote_name not in repo.remotes:
    repo.create_remote(remote_name, gitlabPushURL)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=346433&siteId=1