Reputation: 3859
I need to check each commit coming into GitLab and block any of them which have a certain file in. I used the documentation here
I have created a file named pre-receive
in the .git/custom_hooks
directory.
The file just has the contents:
#!/bin/sh
exit 1
Which, I believe, should reject any attempt to push code to the repo (?)
The file is owned by git and is executable:
ls -a
gives the response:
-rwxrwxrwx 1 git root 550 ...
The custom_hooks directory is also executable and owned by the git user.
But all commits go through without issue, the commit hook does not seem to activate in any way.
I do not see anything else in the documentation that I am supposed to do. Have I missed anything?
Upvotes: 7
Views: 13966
Reputation: 116
Place this script in the hooks directory of your gitlab server. Under hooks directory, create a new directory named - pre-receive.d and place the script file inside it.
#!/bin/bash
# Place this script in gitlab server directory -> <path_to_your_gitlab_server_root>/hooks/pre-receive.d
# Create directory,if it does not exists -> mkdir -p <path_to_your_gitlab_server_root>/hooks/pre-receive.d
# Get input data passed along pre-receive hook
read old_sha new_sha refname
# Default separator is ' ', change to ','
IFS=","
# Use env variable GL_USERNAME to get the matching details from users csv file
# This file can be easily generated from the database that you have configured for your gitlab instance.
# It contains records in following format - <username>,<user_email>,<user_name>
IFS=', ' read -r -a validuserarray <<< `grep -i "$GL_USERNAME," /tmp/gituser.csv `
valid_user_email=${validuserarray[1]}
valid_user_name=${validuserarray[2]}
# Get the last log user details from git log
IFS=', ' read -r -a incoming_committer_array <<< `git log -1 "$new_sha" --pretty=%ce,%cn | tr '[:upper:]' '[:lower:]'`
IFS=', ' read -r -a incoming_author_array <<< `git log -1 "$new_sha" --pretty=%ae,%an | tr '[:upper:]' '[:lower:]'`
# If no match found, fail the push
if [[ ${#validuserarray[@]} < 3 ]]; then
echo "GL-HOOK-ERR: You are not authorised to perform this action."
exit 1
fi
# Ensure no conflict markers are there
if git diff "$old_sha" "$new_sha" | grep -qE '^\+(<<<<<<<|>>>>>>>)'; then
echo "GL-HOOK-ERR: Code has conflict markers. Please resolve and retry."
exit 1
fi
# Validate author email ends with domain.com
if ! [[ "${incoming_author_array[0]}" =~ ^[A-Za-z0-9.]+[@]domain\.com$ ]]; then
echo "GL-HOOK-ERR: Author email address ${incoming_author_array[0]} is invalid."
exit 1
fi
# Validate committer email
if [ "${valid_user_email}" != "${incoming_committer_array[0]}" ]; then
echo "GL-HOOK-ERR: Committer email address ${incoming_committer_array[0]} is invalid."
exit 1
fi
# Validate committer name
if [ "${valid_user_name}" != "${incoming_committer_array[1]}" ]; then
echo "GL-HOOK-ERR: Committer name ${incoming_committer_array[1]} is invalid."
exit 1
fi
exit 0
For each push, gitlab will provide values - branch, old_sha, new_sha. In future, if you have any other use-case, simply put conditionals on these values.
Upvotes: 2
Reputation: 51870
One way to do that is to set a pre-commit hook on your local machine, and check for the presence of said file among the staged files :
# .git/hooks/pre-comit :
#!/bin/bash
forbidden=$(git diff --cached --diff-filter=ACMR -- forbidden/file)
if [ -n "$forbidden" ]; then
echo "*** rejecting commit, file '$forbidden' is present" >&2
exit 1
fi
One major benefit is : you (or other users) are informed right now that this file should not be committed, rather than later when the push is rejected.
Downsides are :
git commit -n
to skip pre-commit
and commit-msg
hooks)If you need to be 100% positive this file does not reach the central repo, one way to prevent this is indeed to set a pre-receive
hook, but this hook must be set on the server.
You tagged your question gitlab
, here is the documentation page to set such a hook :
https://docs.gitlab.com/ee/administration/server_hooks.html
You need to access your gitlab's install filesystem (e.g : ssh to gitlab's server with the admin account), and set the pre-receive
hook in the appropriate project(s).
Note that, since a user can push a whole branch (or even several branches) in one go, you should check the presence of said file in all new commits pushed to the server, not just the tip of each branch.
Upvotes: 2