Search code examples
gitlabgitlab-ci-runnergit-post-receive

GitLab global post-receive server hook for all repositories not executed after CI job completion


Context

After setting up a GitLab server, GitLab runner CI, and creating a test-repository that completes a CI-job successfully, I was experiencing some difficulties in ensuring a post-receive script is completed after the CI is finished successfully on the test repository commit.

MWE

The MWE does the complete deployment, and uploads a repository to the GitLab server and runs the CI on the repository. However, it is not yet generalised well, hence it has (at least) the following requirements: System: Ubuntu 20.04, Architecture:AMD64.

git clone [email protected]:Deployment-Oneliners/Self-host-GitLab-Server-and-Runner-CI.git
cd Self-host-GitLab-Server-and-Runner-CI
git checkout post-receive
rm -r test/libs/*
chmod +x install-bats-libs.sh
./install-bats-libs.sh
./install_gitlab.sh -s -r
./test.sh
./test/libs/bats/bin/bats test/test_post_receive.bats

One would expect the post-receive job to create a file on /home/<your ubuntu username>/Desktop/helloworld.txt. (Which it does not, I assume because the post-receive script is not ran.)

To uninstall the MWE completely, one can run: ./uninstall_gitlab.sh -y -h -r.

Issue

  1. The documentation says
  • For an installation from source is usually /home/git/gitlab-shell/hooks.
  • For Omnibus GitLab installs is usually /opt/gitlab/embedded/service/gitlab-shell/hooks.

However, for the used deployment script, this is /home/name/gitlab/data/gitlab-shell instead. Hence, I assumed that /home/name/gitlab/data/gitlab-shell/hooks is the default hooks directory.

I tested this hypothesis by creating a post-receive/post-receive directory and script, ensured they were owned by the gitlab-runner user, and runnable, and making a new commit such that the CI would complete again. The post-receive script was not executed by GitLab.

Next, I logged into the docker and found the actual gitlab-shell folder using:

sudo docker ps -a
docker exec -t -i 0f17db17c212 /bin/bash
cd /opt/gitlab/embedded/service/gitlab-shell/
mkdir hooks
cd hooks
mkdir post-receive.d
cd post-receive.d
echo '#!/bin/bash' | tee post-receive
echo 'touch server_example_output.txt' | tee -a tee post-receive
chmod +x post-receive

and verified the post-receive script creates a file called: example_output.txt in the same folder as the script (since I can't reach out to the linux user from inside the docker). I did not know how to make the post-receive owned by gitlab-runner as the chown command did not work because it says the gitlab-runner user is not found. I assume this is because the root acount inside the docker is actually the gitlab-runner account. The content of the post-receive script inside the docker is:

#!/bin/bash
touch server_example_output.txt

and it was manually verified using: ./post-receive which created the example_output.txt file. However, running the CI on a new commit did not result in the creation of that output file.

Additionally, I tried to create a post-receive script inside the docker for a particular repository . This was successful and I learned that the script is ran from the root of the directory, so if you write touch output.txt the file will not be created in /hooks/output.txt, but in the hashed <long hash code>.git/ directory.

Question

How can I ensure the GitLab post-receive script is executed after a repository commit is performed in the GitLab server? (Is there some gui/button in the GitLab server that allows one to test whether the post-receive script is found by GitLab and executable)?


Solution

  • The issue was that I was twofold:

    1. I created the post-receive script inside the linux user, instead of inside the docker.
    2. I was looking for the output of the post-receive script in the wrong location. I assumed that it would produce an output in the same directory as the script is located. But the post-receive script is called from the root of the .git directy, hence that is where the output is created.

    Initially I tried to overcome the issue of 2 by using an absolute path, but issue 1 implied that the absolute path that I had chosen did not actually exist inside the Docker container. Therefore, no output was created, (and I was looking in the wrong place for that output on the Linux device, instead of in the Docker container).

    The manual solution I found was: First get the Docker container id with: sudo docker ps -a, which returned ... ca3ba74eb832 .... Then open the docker inside the terminal with:

    sudo docker exec -t -i ca3ba74eb832 /bin/bash
    cd /opt/gitlab/embedded/service/gitlab-shell/
    mkdir hooks
    cd hooks
    mkdir post-receive.d
    cd post-receive.d
    nano post-receive
    

    then enter:

    #!/bin/bash
    touch touch general_server_output.txt
    

    and save the post-receive file. Then make it runnable with:

    chmod +x post-receive
    

    It was not required to make the post-receive owned by the gitlab-runner user, because the root user inside the Docker container is actually that user, so it was already owned by the gitlab-runner (even though inside the Docker container that user is called root).