Blog
- Details
Git hooks are shell scripts that run automatically before or after Git executes an important command like Commit or Push. They can be used to enforce conventions around git actions, such as branch names and commit messages.
Git hooks reside in .git/hooks. To enable a hook, just remove the .sample extension
Git Hook | Git Command | Description |
applypatch-msg.sample | git am | When a patch message is changed |
commit-msg.sample | git commit | To set the message of a commit action |
fsmonitor-watchman.sample | launch watchman | To integrate watchman |
post-update.sample | git push | By updating all data after the push |
pre-applypatch.sample | git am | Before applying a patch |
pre-commit.sample | git commit | Before committing |
prepare-commit-msg.sample | git commit | When a commit message is set |
pre-push.sample | git push | Before making a push |
pre-rebase.sample | git rebase | Before making a pass or merge |
pre-receive.sample | git push | When we push and get the data from the remote repository |
update.sample | git push | By updating the remote data in a push |
Reference: https://www.hostinger.com/tutorials/how-to-use-git-hooks/
> git config core.hooksPath ./.githooks
Note: IntelliJIDE does not support custom hook locations, nor prepare-commit-msg
Branch Names
Having a common naming convention for branches can make it easier to determine what a branch is being used for.
Something like
ticket#-ShortDesc
is more useful than
as you can at least track back the branch back to the originating ticket
The git hook pre-commit can be used to enforce branch names
File pre-commit:
#!/usr/bin/env bash
local_branch="$(git rev-parse --abbrev-ref HEAD)"
#valid_branch_regex="^(feature|bugfix|improvement|library|prerelease|release|hotfix)\/[a-z0-9._-]+$"
valid_branch_regex="^#?[0-9]{6,10}-[a-zA-Z]+$"
error()
{
echo "GIT PRE-COMMIT HOOK ERROR:"
echo "$1"
echo ""
echo "Your commit will be rejected."
echo "You should rename your branch to a valid name and try again."
exit 1
}
if [[ ! $local_branch =~ $valid_branch_regex ]]
then
error "Branch names must match: $valid_branch_regex."
fi
exit 0
Commit Messages
As git tends to intermingle commits from different branches based on time, you can also enforce comments to contain ticket numbers too.
Something like
ticket# added audit log
as you can at least track back the commit back to the originating ticket
In general, you should try to make multiple commits grouped by concept, and commit every day or two.
The git hooks prepare-commit-msg and commit-msg
can be used to enforce ticket numbers in commits
File prepare-commit-msg:
#!/usr/bin/env bash
# commit message file
commit_msg_file="$1"
# condition the commit is invoked; none (git commit), message (git commit -m <msg>), template, merge, squash, or commit
# commit_source=$2
# commit hash
# sha1=$3
local_branch="$(git rev-parse --abbrev-ref HEAD)"
get_ticket_nbr="^#?([0-9]{6,10}).*"
valid_ticket_nbr="^[0-9]{6,10}$"
error()
echo "GIT PREPARE-COMMIT HOOK ERROR:"
echo "$1"
echo ""
}
# check if commit message already has the ticket # prepended
# if not, try to prepend
commit_msg=$(cat "$commit_msg_file")
if [[ ! $commit_msg =~ $get_ticket_nbr ]]
then
if [[ $local_branch =~ $get_ticket_nbr ]]
then
ticket="${BASH_REMATCH[1]}"
if [[ $ticket =~ $valid_ticket_nbr ]]
then
echo "#${ticket} " > "$commit_msg_file"
echo "$commit_msg" >> "$commit_msg_file"
fi
fi
fi
exit 0
File commit-msg:
#!/usr/bin/env bash
# commit message file
commit_msg_file="$1"
valid_comment_prefix="^#?[0-9]{6,10} .+"
error()
cp "$commit_msg_file" "_gitmsg.saved.txt"
echo "GIT COMMIT-MSG HOOK ERROR:"
echo "$1"
echo ""
echo "Original checkin message has been stored in '_gitmsg.saved.txt'"
echo "Your commit will be rejected."
echo "You should update your commit and try again."
exit 1
}
commit_msg=$(cat "$commit_msg_file")
if [[ ! $commit_msg =~ $valid_comment_prefix ]]
then
error "Comment must match: $valid_comment_prefix"
fi
exit 0
You should now have some ideas on how to enforce some consistency in your git actions.
- Details
A simple way to add CORs headers to legacy apps:
But first, some definitions of what CORs and CORs preflight requests are:
"Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any other origins (domain, scheme, or port) than its own from which a browser should permit loading of resources. CORS also relies on a mechanism by which browsers make a “preflight” request to the server hosting the cross-origin resource, in order to check that the server will permit the actual request. In that preflight, the browser sends headers that indicate the HTTP method and headers that will be used in the actual request."
Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
"CORS does not protect your server. CORS attempts to protect your users by telling browsers what the restrictions should be on sharing responses with other domains. Normally this kind of sharing is utterly forbidden, so CORS is a way to poke a hole in the browser's normal security policy. These holes should be as small as possible, so always check the HTTP_ORIGIN against some kind of internal list."
Reference: https://stackoverflow.com/questions/8719276/cross-origin-request-headerscors-with-php-headers
CORs preflight request:
"A CORS preflight request is a CORS request that checks to see if the CORS protocol is understood and a server is aware using specific methods and headers."
Reference: https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request
"The Access-Control-Allow-Headers response header is used in response to a preflight request which includes the Access-Control-Request-Headers to indicate which HTTP headers can be used during the actual request."
Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers
Note, developer tools will not show CORs preflight requests.
Now to the code:
function addCORSHeaders()
{
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
// cors preflight check; doesn't care about content, just headers and status
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS');
header('Access-Control-Allow-Headers: X-Requested-With, Content-Type, Accept, Origin, Authorization');
// cache of cors preflight check; max varies by browser; some only 10min, some 24hr
header('Access-Control-Max-Age: 86400');
header('Content-Length: 0');
header('Content-Type: text/plain');
// HTTP/1.1 or HTTP/1.0 or HTTPS/2.0 or etc
header($_SERVER['SERVER_PROTOCOL'] . ' 200 OK');
exit();
}
// if can, allow just your domain.com or allow just subdomains *.domains.com
// but if have multiple shared apps/domains, * allow from anywhere
header('Access-Control-Allow-Origin: *');
}
Add a function/method call to addCORSHeaders() to your middleware, or before your output.
Note, If your app has authentication, don't forget to allow OPTIONS as unauthenticated, like your login page.
You can check the network response to see the added headers in browsers developer tools.
But as developer tools do not show CORs preflight requests, you may have to log access or trace using xdebug.
- Details
"Xdebug is an extension for PHP, and provides a range of features to improve the PHP development experience. Step Debugging A way to step through your code in your IDE or editor while the script is executing."
Source: https://xdebug.org/
Install following the instructions from https://xdebug.org/docs/install
php.ini settings that worked for me:
zend_extension=xdebug-2.9.4-7.2-vc15-x86_64
[xdebug]
xdebug.remote_enable = 1
xdebug.remote_autostart = 0
xdebug.remote_host = 127.0.0.1
xdebug.remote_port = 9072
xdebug.idekey = "PHPSTORM"
xdebug.profiler_enable = 0
Enabling PHP xdebug is fairly simple, just add arguments to your PHP call
> php -d -dxdebug.remote_enable=1 -dxdebug.remote_autostart=1 -dxdebug.idekey=PHPSTORM your/script.php
The option -d can set/override php.ini values
-d foo[=bar] Define INI entry foo with value 'bar'
Reference: https://www.php.net/manual/en/features.commandline.options.php
If you are using cmder, which bundles the conemu console
you can add the alias to your users_aliases.cmd
C:\Portable\cmder\config\user_aliases.cmd
xphp7=C:/laragon/bin/php/php-7.2.28-Win32-VC15-x64/php -d -dxdebug.remote_enable=1 -dxdebug.remote_autostart=1 -dxdebug.idekey=PHPSTORM $*
php7=C:/laragon/bin/php/php-7.2.28-Win32-VC15-x64/php $*
And use as
> xphp7 slimapp/cli.php arg1 arg2=test
Reference: Slim PHP CLI
- Details
To change the bash prompt on your AWS EC2 instance from the default of
[ec2-user@ip-10-1-1-1 ~]$
to
ec2-user@ec2-name /data/cool-app (development=)
└─►
read and apply the following bash_profile update:
Note, By default, AWS EC2 does not set /etc/hosts, so use a fixed string in your bash prompt,
or follow the AWS documentation:
https://aws.amazon.com/premiumsupport/knowledge-center/linux-static-hostname/
Create a temp file with the contents:
> echo '
# change me vars
ec2_name="ec2namechangeme"
# use vim
export EDITOR=vim
alias vi="vim"
# allow tab auto complete w/ sudo
if [[ "$HOME" == "/home/ec2-user" ]]; then
complete -cf sudo
fi
# git status
git_status="n"
# existing git file in most distros
git_prompt=/usr/share/git-core/contrib/completion/git-prompt.sh
if [[ -f $git_prompt ]]; then
source $git_prompt
export GIT_PS1_SHOWDIRTYSTATE=true # + staged, * unstaged
export GIT_PS1_SHOWUNTRACKEDFILES=true # % untracked files
export GIT_PS1_SHOWUPSTREAM="auto" # < behind, > ahead, <> diverged, = no difference
export GIT_PS1_SHOWSTASHSTATE=true # $ something is stashed
git_status="y"
fi
unset git_prompt
# export PS1="[\u@\h \W]\$" # default
PS1="\u@${ec2_name} "
PS1+="\[\033[01;34m\]\${PWD#\$HOME/}\[\033[00m\]"
if [ $git_status = "y" ]; then
PS1+=" \[\033[0;32m\]\$(__git_ps1 '\''(%s)'\'')\[\033[00m\]"
fi
PS1+="\n\[\033[0;32m\]└─►\[\033[00m\] "
export PS1
PATH=$PATH:$HOME/bin:/usr/bin:/usr/local/bin
export PATH
unset USERNAME
alias git-log="git log --pretty=oneline"
alias git-preview-files="git fetch; git diff --name-only HEAD..@{u}"
alias git-preview-diff="git fetch; git diff HEAD..@{u}"
' > temp_bash_profile.sh
Note, '\'' = '
Update ec2_name="ec2name" to the name of your ec2 ie super-cool-service
> vim temp_bash_profile.sh
Append to existing bash profile
# using sed
> sed -i '/# User specific environment and startup programs/ r temp_bash_profile.sh' ~/.bash_profile
# or edit and add to the end
> vim ~/.bash_profile
Test and see results
> source ~/.bash_profile
ec2-user@ec2-name /data/cool-app (development=)
└─►