Commit git hook to repo - bash

I have a problem with configuration tslint and pre-commit hook.
The point is that i created tsconfig file which work's well. And added bash script which not allow me to commit if tslint return any bugs. Problme is that i need commit this hook file for other people in my team. This should automatly replace pre-commit hook from .git folder. I just found a bash script which check my hooks in 'hooks' folder and replace them in .git folder. How can I commit this and make this 'automatically' for my team?

"Committing a hook" is not possible for security reasons. If you could, then someone just cloning your repo and running basic operations could get arbitrary code executed on their machines.
Two common ways to deal with this are:
Document what people have to do to get the hook operational in their repository.
Automate what people have to do to get it. For example, in a project using a Makefile, I have this in the Makefile and people can just run make setup-pre-push-hook to get the hook to run "make check" whenever they push:
setup-pre-push-hook: setup-pre-push-hook-file
grep -q 'make check' .git/hooks/pre-push || \
printf '\n%s\n\n' 'make check' >> .git/hooks/pre-push
setup-pre-push-hook-file:
test -f .git/hooks/pre-push || echo '#!/bin/sh' >.git/hooks/pre-push
test -x .git/hooks/pre-push || chmod +x .git/hooks/pre-push

Related

Why all the script in my git hooks (pre-commit, post-commit, pre-receive, pre-push etc) do not run?

Why all the script in my git hooks (pre-commit, post-commit, pre-receive, pre-push etc) do not run?
Note:
this question is not a duplicate;
I have try the answer to each of the other questions but none of them work.
I did chmod +x, added the path to hook. rename script, neither of them solve my issue.
Inside my git
branches config description HEAD hooks info objects refs
Inside hooks:
applypatch-msg.sample fsmonitor-watchman.sample post-update.sample pre-commit prepare-commit-msg.sample pre-rebase.sample update.sample
commit-msg post-merge.sh pre-applypatch.sample pre-commit.sample pre-push pre-receive
I run them manually and they are all working fine.:
$ bash pre-commit
You are about to commit to master
Do you really want to do this? [y/n] y
pre-commit script
#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".
echo "You are about to commit" $(git diff --cached --name-only --diff-filter=ACM)
echo "to" $(git branch --show-current)
while : ; do
read -p "Do you really want to do this? [y/n] " RESPONSE < /dev/tty
case "${RESPONSE}" in
[Yy]* ) exit 0; break;;
[Nn]* ) exit 1;;
esac
done
But when i git commit and git push to the repository none of the scripts work.
$git commit -m "Test hooks"
[master] Test hooks 1 file
changed, 1 insertion(+)
My git version is 2.39.1
I created the repository on a VM with Ubuntu 18.04.6 LTS installed
Here was the procedure fro creating the repo.
mkdir project1.git
cd project1.git
git init --bare
After the creation i clone the repo to my local computer (windows).
Clone the git repository
git clone git#{ip}:/home/git/git_repositories/project1.git/
But I want use the scripts in project1.git/hooks to make this work.
A pre-commit hook for instance would not work in a bare repository (which has no working tree).
It would work only in your cloned repository, on Windows, where you can create a myClonedRepo/.git/hook/pre-commit script (no extension, no .sh), which will be run before each commit.
From the comments:
all users could create/clone their repositories from a shared Git template repository. The article "Creating a Custom Git Template" gives an illustration of that approach, but means that:
every user must access the same shared folder
they need to activate the init.templateDir config setting in their global Git configuration
any check which must be enforced for all the team members, especially for a distributed team, is best managed by server-side hooks instead.

Execute Bash Script After Git Post-Receive Hook executes

I have a bash script on my test server that will export my wordpress db, rsync the db to the prod server, and git push all of my files to prod sever.
Within the prod server's git repo I have a git post-receive hook correctly configured.
#!/bin/bash
#Receive Git Push from Test
git --work-tree=/home/username/public_html --git-dir=/home/username/public_html/git/production-site.git checkout -f
Within the working tree directory (WordPress directory) on the prod server I also have a bash script that will import the newly uploaded db. /home/username/public_html/db-import-script.sh
#!/bin/bash
#bunch of commands
...
...
...
Question:
How can I automatically execute the db import script immediately following a git push?
troubleshooting:
inside of post-receive, I have tried using an absolute paths to execute the script, no luck
#!/bin/bash
#Receive Git Push from Test
git --work-tree=/home/username/public_html --git-dir=/home/username/public_html/git/production-site.git checkout -f
#execute script with absolute path
/home/username/public_html/db-import-script.sh
db-import-script.sh does not execute. NOTE: this script must remain located in the Wordpress directory b/c it uses wp-cli commands for various actions.
any tips?
I use e.g. gitea and on server one has to simply copy a script in post-receive.d/ folder. The post-receive hook (see below and you may use it as a template) will scan this folder and execute scripts in it.
#!/usr/bin/env bash
# AUTO GENERATED BY GITEA, DO NOT MODIFY
data=$(cat)
exitcodes=""
hookname=$(basename $0)
GIT_DIR=${GIT_DIR:-$(dirname $0)/..}
for hook in ${GIT_DIR}/hooks/${hookname}.d/*; do
test -x "${hook}" && test -f "${hook}" || continue
echo "${data}" | "${hook}"
exitcodes="${exitcodes} $?"
done
for i in ${exitcodes}; do
[ ${i} -eq 0 ] || exit ${i}
done
kiss rule... (keep it simple stupid)
rather than spending days trying to learn sysdig well enough to trace a process that I have never previously heard of and it subprocesses. (no offence intended Charles, just need to actually get tasks done. Your bash debug-log snippet highly useful)
and rather than creating some git / gitea hybrid (no offence #m19v, I did try your solution, but didn't work)
knowing that production server db-import.sh worked properly and that my test server git push / db upload push.sh worked properly.
My final solution was to leave the production server's post-receive properly configured and to.... remotely execute my db-import.sh script via ssh directly within the directory in which it needs to be executed.
In a nutshell, I added this to the end of push.sh script on my test server:
#Remotely execute db import
ssh -p22 -i /home/username/.ssh/id_rsa username#1233.456.789.12 'cd public_html && bash' << EOF
./db-import.sh
EOF
Bang problem solved...

Prevent git from overwriting file owner upon git pull

I've seen a handful of similar questions on here, but none of the solutions given seem to be working... wondering if they're outdated, or this case is somehow different...so I wanted to open up a new thread to talk about it.
I've run into a frustrating problem where, every time I perform and git pull, it changes the owner to the pull-er's user. What happens then is that the site shows the following error:
Warning: file_get_contents(/var/www/html/wp-content/themes/<my-theme>/resources/views/<changed-file>): failed to open stream: Permission denied in /var/www/html/wp-includes/class-wp-theme.php on line 1207
which can only be fixed by running chown www-data on the changed file.
This will become an issue when more people begin to work on the site, or when important files are change (default template/header/footer..), and the site goes blank until chown is run.
Site details
Laravel, wordpress, ubuntu 18, armor hosting
Git repo stored in custom theme
I've tried a few solutions, but none seem to work, (perhaps because they're implemented incorrectly..)
Solutions I've tried
1: set filemode to false - I set filemode to false, locally and globally, on my local machine and the server in question. I've tried changing the case to "fileMode" too.
2: implement post-update hook - I added a post update hook to automatically update the file permissions/ownership. Here's the script (note that the git repo is in the custom theme):
#!/bin/sh
# default owner user
OWNER="www-data:www-data"
# changed file permission
PERMISSION="664"
# web repository directory
REPO_DIR="/var/www/html/wp-content/themes/quorum-theme"
# remote repository
REMOTE_REPO="origin"
# public branch of the remote repository
REMOTE_REPO_BRANCH="master"
cd $REPO_DIR || exit
unset GIT_DIR
files="$(git diff-tree -r --name-only --no-commit-id HEAD#{1} HEAD)"
git merge FETCH_HEAD
for file in $files
do
sudo chown $OWNER $file
sudo chmod $PERMISSION $file
done
exec git-update-server-info
Let me know if there is anything else worth trying, or if you notice an issue with my code...
All the best,
Jill
You are pretty close to the correct solution.
You need to enable the following hooks:
post-merge, called after a successful git pull
post-checkout, called after a successful git checkout
If you are sure to only use git pull, the post-merge hook is enough.
Enabling both hooks guarantee you the hook is always called at not extra cost.
The content of the hook should be like:
#!/bin/sh
# default owner user
OWNER="www-data:www-data"
# web repository directory
REPO_DIR="/var/www/html/wp-content/themes/quorum-theme"
echo
echo "---"
echo "--- Resetting ownership to ${OWNER} on ${REPO_DIR}"
sudo chown -R $OWNER $REPO_DIR
echo "--- Done"
echo "---"
The script will reset the ownership to OWNER of all files and directory inside REPO_DIR.
I have copied the values from your post, eventually change it to your needs.
To enable the hook you should:
create a file named post-merge with the script above
move it inside the directory .git/hook/ of your repo
give it the executable permission with chmod +x post-merge
Repeat eventually these steps for the post-checkout hook, that needs to be equal to the post-merge hook.
Pay attention to perform a sudo git pull if your user is not root. All the files and directories in the target directory are owned by www-data, you need to perform the git pull command with a superuser privilege or the command will fail.
From the looks of your question, it looks like you are using git pull to deploy in production.
git is not a deployment tool. If you want to deploy your code, I would invite you to write a deployment script.
The first version of your script could be :
# deploy.sh
# cd to the appropriate directory :
cd /var/www/mysite
# change to the correct user before pulling :
sudo -u www-data git pull
An updated version would be to stop depending on git pull.
Ideally : you want to be able to identify the versions of your code that can be deployed to productions, and not depend on the fact that "git pull will work without triggering merge conflicts".
Here is the outline of a generic workflow you can follow :
When you want to deploy to production :
produce some artifact that packs your code from an identified commit : for php code this can be a simple .tar.gz
# set a clearly identifiable tag on target commit
git tag v-x.y.z
# create a tar.gz archive that stores the files :
# look at 'git help archive'
git archive -o ../myapp-x.y.z.tgz v-x.y.z
push that artifact your production server
scp myapp-x.y.z.tgz production-server:
run your deployment script, without calling git anymore :
# deploy.sh :
# usage : ./deploy.sh myapp-x.y.z.tgz
archive="$1"
# extract the archive to a fresh folder :
mkdir /var/www/mysite.new
tar -C /var/www/mysite.new -xzf "$archive"
chown -R www-data: /var/www/mysite.new
# replace old folder with new folder :
mv /var/www/mysite /var/www/mysite.old
mv /var/www/mysite.new /var/www/mysite
Some extra actions you will generally want to manage around your deployment :
backup your database before deploying
hanlde config parameters (copy your production config file ? setup the environment ? ...)
apply migration actions
restart apache or nginx
...
You probably want to version that deploy.sh script along with your project.
My approach works for me.
First, add a file named post-merge to /path/to/your_project/.git/hooks/
cd /path/to/your_project/.git/hooks/
touch post-merge
Then, change it's ownership to same as <your_project> folder(this is the same as nginx and php-fpm runner), in my case, I use www:www
sudo chown www:www post-merge
Then change it's file mode to 775(then it can be executed)
sudo chmod 775 post-merge
Then put the snippet below to post-merge. To understand the snippet, see here(actually that's me).
#!/bin/sh
# default owner user
OWNER="www:www"
# changed file permission
PERMISSION="664"
# web repository directory
REPO_DIR="/www/wwwroot/your_project/"
# remote repository
REMOTE_REPO="origin"
# public branch of the remote repository
REMOTE_REPO_BRANCH="master"
cd $REPO_DIR || exit
unset GIT_DIR
files="$(git diff-tree -r --name-only --no-commit-id HEAD#{1} HEAD)"
for file in $files
do
sudo chown $OWNER $file
sudo chmod $PERMISSION $file
done
exec git-update-server-info
Everything is done, now, go back to your_project folder
cd /path/to/your_project/
run git pull under your_project folder, remember you must run as root or sudo(I remember sudo)
sudo git pull
Now check the new file that pulled from remote repository, see if its ownership has been changed to www:www(if it was as expected, the ownership of the new pulled file should be changed to www:www).
This approach is much better than sudo chown -R www:www /www/wwwroot/your_project/, because it only change the new file's ownership, not all of then! Say I just pulled 2 new file, if you change the whole folder's ownership, it's costs more time and server resources(cpu usage, memory usage...), that's totally unnecessary.

Git hook on Ubuntu broken

I recently got a git hook from someone that aims to add the issue number, which is in a specific location of the branch name, to the beginning of all commits. The goal is to take the #number from feature/#number-issue. Here is some info:
➜ .githooks pwd
/home/luctia/.githooks
➜ .githooks git config --global --list
user.name=luctia
user.email=myemail
core.hookspath=/home/luctia/.githooks
➜ .githooks cat commit-msg
#!/bin/sh
WI=$(git status --branch | grep -iPo "(feature|bug)\/#\d+" | head -1)
WI=$(echo "($WI)" | grep -Po "\d+")
if [[ ! -z "$WI" ]]; then
WI="#$WI"
CM=$(cat "$1")
if [[ ! $CM == *"$WI "* ]]; then
echo "$WI $CM" > "$1"
fi
fi
This doesn't seem to work, though. The script is executable for every user, so that's not the issue. I have tried switching from sh to bash, and with that edit I've executed the script on a file in a repo, which added the number to the beginning of the file, so I know it works. I'm not sure if git hooks can execute bash files, but it doesn't make a difference whether I use sh or bash, though I would like to know if it can run bash scripts.
I'm using Webstorm for my IDE right now, and it doesn't work in there, and it also doesn't work on CLI git. I have no idea how to proceed.
Edit: I am pretty sure the script is not executed. When I add data > /tmp/hook to the script, no file appears. I do have to change from sh to bash though.
The problem was that I was trying to make this work on a pre-existing project, with an existing .git directory. I thought changing the config with the --global flag would just work, but apparently the config inside the .git directory of the project did not change, and the old hookspath was still there. When I changed it, the script started working.

How to run a script on every commit

I want to run a script locally whenever someone in RepoA, makes a commit on a branch
currentBranch=$(git rev-parse --abbrev-ref HEAD)
if [[ $currentBranch = *"my-"* ]]; then
echo "contains my"
else
echo "Hold on there! you need to rename your branch before you commit!
"
fi
I have this running so far which works, whenever I run npm run test:script it runs > "test:script": "./branchname.sh"
however, I have some issues. one how can I run this every time someone commits?
I have tried putting it in my package.json
"pre-commit": [
"lint",
"test:script"
],
but it doesn't run on every commit
also, how can I get the commit itself to abort if the script fails, i.e. jump into the else block
You can take advantage of git hooks. There is a bunch of files you can find in your .git/hooks folder whitin your project folder.
Here the full documentation: https://git-scm.com/book/gr/v2/Customizing-Git-Git-Hooks
Note that you need to give exec permissions to hook files.
Hooks can be basically bash files, so you can abort the commit exiting with a value != 0.
Here an example: https://github.com/xyzale/my-stuff/blob/master/git/hooks/pre-commit
In order to share the hooks with your collaborators you can add a hooks/ folder to your repository and either symlinking it to .git/hooks or editing the git config about the hooks location through the command
git config core.hooksPath hooks

Resources