DEV Community

loading...
Cover image for How to push to a Git repository from a GitLab CI pipeline πŸ‘·

How to push to a Git repository from a GitLab CI pipeline πŸ‘·

ranb2002 profile image Benjamin Rancourt Originally published at benjaminrancourt.ca on ・3 min read

As my website is a Jamstack project, I completely own its build process (using Eleventy as my generator and Ghost CMS as my backend). One of the heavy steps of my build process is downloading external images and making them responsive for my blog. πŸ–ΌοΈ

But, as I keep adding content every week, my website has started to take longer and longer to built... Often, the generated files do not change from a build to another, so why should I recreate them from scratch each time? It may be fine for small websites, but it was no longer a viable option for me. 🀯

So I decided to commit and push some of the results files created into my Git repository and I improved my GitLab CI pipeline to do that as well. Today, I am sharing that part with you in the hope of helping you someday. πŸ•ŠοΈ

If you have already read my GitLab CI predefined variables post last month, you will see that I may have use them too much. You will understand why in the next few minutes.

As usual, I add a lot of comments to help everyone (including myself) to understand it fully. Enough talk, let's see what this step looks like. πŸ§™

variables:
  # https://hub.docker.com/r/alpine/git/tags
  GIT_VERSION: v2.30.1

# Description
# This script allows to store the artefacts of a step into the current
# repository, to improve the efficiency of the next build process.

# Set up this script
# 1. Create a new personal access token (https://gitlab.com/-/profile/personal_access_tokens)
# with the following scopes:
# - read_repository
# - write_repository
# 2. Inside Settings -> CI / CD -> Variables, create the following variables:
#
# GITLAB_TOKEN Personal access token previously created. XGE2-k445hd5fbs94v9d
# (masked)
# GITLAB_USERNAME Username associated with the personal access token. ranb2002
# COMMIT_MESSAGE Commit message Automatic update from the weekly schedule

# Other variables used by this script
# The following variables are defined automatically by GitLab CI. Thus, you
# don't need to override them.
#
# CI_COMMIT_SHA Commit SHA, to use a unique directory name. e46f153dd47ce5f3ca8c56be3fb5d55039853655
# CI_DEFAULT_BRANCH Default branch. main
# CI_PROJECT_PATH Current project path. ranb2002/benjaminrancourt.ca
# CI_SERVER_HOST Hostname of the current GitLab instance. gitlab.com
# GITLAB_USER_EMAIL Email of the user used to commit the changes to the ranb2002@gitlab.com
# secondary repository.
# GITLAB_USER_NAME User name of the user used to commit the changes to Benjamin Rancourt
# the secondary repository.

.git:push:
  after_script:
    # Go to the new directory
    - cd "${CI_COMMIT_SHA}"

    # Add all generated files to Git
    - git add .

    - |-
      # Check if we have modifications to commit
      CHANGES=$(git status --porcelain | wc -l)

      if ["$CHANGES" -gt "0"]; then
        # Show the status of files that are about to be created, updated or deleted
        git status

        # Commit all changes
        git commit -m "${COMMIT_MESSAGE}"

        # Update the repository and make sure to skip the pipeline create for this commit
        git push origin "${CI_DEFAULT_BRANCH}" -o ci.skip
      fi
  before_script:
    # Clone the repository via HTTPS inside a new directory
    - git clone "https://${GITLAB_USERNAME}:${GITLAB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" "${CI_COMMIT_SHA}"

    # Set the displayed user with the commits that are about to be made
    - git config --global user.email "${GIT_USER_EMAIL:-$GITLAB_USER_EMAIL}"
    - git config --global user.name "${GIT_USER_NAME:-$GITLAB_USER_NAME}"
  image:
    entrypoint: ['']
    name: alpine/git:${GIT_VERSION}
  stage: deploy

Enter fullscreen mode Exit fullscreen mode
Common step to commit into a Git repository

If you are familiar with GitLab CI, you may have made two observations: there is no script keyword for this step and the after_script keyword starts by changing the current directory (cd "${CI_COMMIT_SHA}"). Why? πŸ™‹

The missing script keyword

First, the step was written to be used by multiple projects which may not have the same files to commit and push. So someone like me could extend the step and do something like below:

deploy:
  extends: .git:push
  script:
    # Move some generated files
    - mv built/*.jpg "${CI_COMMIT_SHA}"
Enter fullscreen mode Exit fullscreen mode

The ${CI_COMMIT_SHA} folder

Second, let's take a look at the ${CI_COMMIT_SHA} folder and its purpose. If you have looked carefully (or searched it into the current page), you may have seen that we are cloning the Git repository in this folder, as we cannot clone it into an already cloned directory.

I am not sure, but I think we need to reclone it as well, because the default cloning made by the runner is not correct to push to our repository.

This folder could have be named anything, but to be sure to be unique, I chose to take this variable. I am pretty sure that no project will have a directory named something like 73d571ffcbd5adbjdb0eegfe2a88bc70df7d9326. 🎲

Conclusion

So, that concludes on how to push new commits from a GitLab runner. I hope this post will be helpful for you and let me know if you improve my recipe! πŸ‘¨β€πŸ³

Stay safe! 😷

Discussion (0)

Forem Open with the Forem app