Is it possible to do a git push within a Gitlab-CI without SSH?

7.1k views Asked by At

We want to know if it's technically possible like in GitHub, to do a git push using https protocol and not ssh and without using directly an username and password in the curl request.

I have seen people that seem to think it is possible, we weren't able to prove it.

Is there any proof or witness out there than can confirm such a feature that allow you to push using a user access token or the gitlab-ci-token within the CI?

3

There are 3 answers

0
Dimitri Kopriwa On BEST ANSWER

I am giving my before_script.sh that can be used within any .gitlab-ci.yml

before_script:
  - ./before_script.sh

All you need is to set a protected environment variable called GL_TOKEN or GITLAB_TOKEN within your project.

if [[ -v "GL_TOKEN" || -v "GITLAB_TOKEN" ]]; then
  if [[ "${CI_PROJECT_URL}" =~ (([^/]*/){3}) ]]; then
    mkdir -p $HOME/.config/git
    echo "${BASH_REMATCH[1]/:\/\//://gitlab-ci-token:${GL_TOKEN:-$GITLAB_TOKEN}@}" > $HOME/.config/git/credentials
    git config --global credential.helper store
  fi
fi

It doesn't require to change the default git strategy and it will work fine with non protected branch using the default gitlab-ci-token.

On a protected branch, you can use the git push command as usual.

We stopped using SSH keys, Vít Kotačka answers helped us understand why it was failing before.

2
GoForth On

Just FYI, personal access tokens have account level access, which is generally too broad. The Deploy Key is better as it only has project-level access and can be given write permissions at the time of creation. You can provide the public SSH key as the deploy key and the private key can come from a CI/CD variable.

Here's basically the job I use for tagging:

release_tagging:
  stage: release
  image: ubuntu
  before_script:
    - mkdir -p ~/.ssh
    # Settings > Repository > Deploy Keys > "DEPLOY_KEY_PUBLIC" is the public key of the utitlized SSH pair
    # Settings > CI/CD > Variables > "DEPLOY_KEY_PRIVATE" is the private key of the utitlized SSH pair, type is 'File' and ends with empty line
    - mv "$DEPLOY_KEY_PRIVATE" ~/.ssh/id_rsa
    - chmod 600 ~/.ssh/id_rsa
    - 'which ssh-agent || (apt-get update -y && apt-get install openssh-client git -y) > /dev/null 2>&1'
    - eval "$(ssh-agent -s)"
    - ssh-add ~/.ssh/id_rsa > /dev/null 2>&1
    - (ssh-keyscan -H $CI_SERVER_HOST >> ~/.ssh/known_hosts) > /dev/null 2>&1
  script:
    # .gitconfig
    - touch ~/.gitconfig
    - git config --global user.name $GITLAB_USER_NAME
    - git config --global user.email $GITLAB_USER_EMAIL
    # fresh clone
    - mkdir ~/source && cd $_
    - git clone git@$CI_SERVER_HOST:$CI_PROJECT_PATH.git
    - cd $CI_PROJECT_NAME
    # Version tag
    - git tag -a "v$(cat version)" -m "version $(cat version)"
    - git push --tags
1
Vít Kotačka On

I was not able to push back via https from a Docker executor when I did changes in the repository which was cloned by gitlab-runner. Therefore, I use following workaround:

  1. Clone a repository to some temporary location via https with a user access token.
  2. Do some Git work (like merging, or tagging).
  3. Push changes back.

I have a job in the .gitlab-ci.yml:

tagMaster:
  stage: finalize
  script: ./tag_master.sh
  only:
  - master
  except:
  - tags

and then I have a shell script tag_master.sh with Git commands:

#!/usr/bin/env bash

OPC_VERSION=`gradle -q opcVersion`
CI_PIPELINE_ID=${CI_PIPELINE_ID:-00000}

mkdir /tmp/git-tag
cd /tmp/git-tag
git clone https://deployer-token:[email protected]/my-user/my-repo.git
cd my-repo
git config user.email [email protected]
git config user.name 'Deployer'
git checkout master
git pull
git tag -a -m "[GitLab Runner] Tag ${OPC_VERSION}-${CI_PIPELINE_ID}" ${OPC_VERSION}-${CI_PIPELINE_ID}
git push --tags

This works well.