We have a development team that is using a 50/50 split of GitHub for windows and Bash shell for their Git management.
We have implemented a pre-commit hook (designed to run unit tests and fail the commit when tests fail). As a simplified version I have attached a cut down version below which demos our issue.
#!/bin/sh
exit 1
If we attempt a commit from the bash shell, the commit as expected fails. However if we perform the same commit from the GitHub for windows application it is successfully committed to the local repo.
So Does anyone know how we can get the same functionality from GitHub application? Unfortunately we can't move the users off the application, and its now an obvious hole.
Thanks for your help.
However, Git on Windows is able to recognize the shebang first line. Therefore, we add a shebang line in a Git hook script on Windows just as we do on Linux. Below are two Git commit-msg hooks that run on Linux and Windows respectively. If you are using Git for Windows, the bash script also works on Windows.
Open a terminal window by using option + T in GitKraken Client. Once the terminal windows is open, change directory to . git/hooks . Then use the command chmod +x pre-commit to make the pre-commit file executable.
The pre-commit hook is run first, before you even type in a commit message. It's used to inspect the snapshot that's about to be committed, to see if you've forgotten something, to make sure tests run, or to examine whatever you need to inspect in the code.
Sorry to be the bearer of bad news, but GitHub for Windows doesn't support pre-commit hooks, since it uses libgit2 to commit.
Using Git shell you can have commit hooks. I got some commit hooks working with PowerShell. I found a powerShell script that did lint that I expanded to run phpunit and phpcs (paths are hard coded so you will need to adjust):
pre Commit File:
#!/bin/sh
echo
exec powershell.exe -ExecutionPolicy RemoteSigned -File '.\.git\hooks\pre-commit-hook.ps1'
exit
pre-commit.ps1 file:
###############################################################################
#
# PHP Syntax Check for Git pre-commit hook for Windows PowerShell
#
# Author: Vojtech Kusy <[email protected]>
# Author: Chuck "MANCHUCK" Reeves <[email protected]>
#
###############################################################################
### INSTRUCTIONS ###
# Place the code to file "pre-commit" (no extension) and add it to the one of
# the following locations:
# 1) Repository hooks folder - C:\Path\To\Repository\.git\hooks
# 2) User profile template - C:\Users\<USER>\.git\templates\hooks
# 3) Global shared templates - C:\Program Files (x86)\Git\share\git-core\templates\hooks
#
# The hooks from user profile or from shared templates are copied from there
# each time you create or clone new repository.
### SETTINGS ###
# Path to the php.exe
$php_exe = "C:\php\php.exe";
# Path to the phpcs
$php_cs = "C:\Includes\PEAR\phpcs.bat";
# Path to the phpunit
$php_unit = "C:\Includes\PEAR\phpunit.bat";
# Path to the phpunit bootstrap file
$bootstrap = "tests\bootstrap.php";
# Flag, if set to 1 require test file to exist, set to 0 to disable
$requireTest = 1;
# Extensions of the PHP files
$php_ext = "php|phtml"
# Flag, if set to 1 git will unstage all files with errors, set to 0 to disable
$unstage_on_error = 0;
### FUNCTIONS ###
function php_syntax_check {
param([string]$php_bin, [string]$extensions, [int]$reset)
$err_counter = 0;
write-host "Pre-commit PHP syntax check:" -foregroundcolor "white" -backgroundcolor "black"
git diff-index --name-only --cached HEAD -- | foreach {
if ($_ -match ".*\.($extensions)$") {
$file = $matches[0];
$errors = & $php_bin -l $file
$testFileExists = (Test-Path $file -PathType Leaf)
write-host $file ": " -foregroundcolor "gray" -backgroundcolor "black" -NoNewline
if ($testFileExists) {
if ($errors -match "No syntax errors detected in $file") {
write-host "OK!" -foregroundcolor "green" -backgroundcolor "black"
}
else {
write-host "ERROR! " $errors -foregroundcolor "red" -backgroundcolor "black"
if ($reset) {
git reset -q HEAD $file
write-host "Unstaging ..." -foregroundcolor "magenta" -backgroundcolor "black"
}
$err_counter++
}
} else {
write-host "OK! (file deleted)" -foregroundcolor "green" -backgroundcolor "black"
}
}
}
if ($err_counter -gt 0) {
write-host "Some File(s) have syntax errors. Please fix then commit" -foregroundcolor "red" -backgroundcolor "black"
exit 1
}
}
function php_cs_check {
param([string]$php_cs, [string]$extensions, [int]$reset)
$err_counter = 0;
write-host "Pre-commit PHP codesniffer check:" -foregroundcolor "white" -backgroundcolor "black"
git diff-index --name-only --cached HEAD -- | foreach {
if ($_ -match ".*\.($extensions)$") {
$file = $matches[0];
write-host $file ": " -foregroundcolor "gray" -backgroundcolor "black" -NoNewline
if ($file -match "tests\/") {
write-host "PASSED! (test file)" -foregroundcolor "green" -backgroundcolor "black"
} else {
$errors = & $php_cs --standard=Zend $file
if ($LastExitCode) {
write-host "FAILED! (contains errors)" -foregroundcolor "red" -backgroundcolor "black"
if ($reset) {
git reset -q HEAD $file
write-host "Unstaging ..." -foregroundcolor "magenta" -backgroundcolor "black"
}
$err_counter++
} else {
write-host "PASSED!" -foregroundcolor "green" -backgroundcolor "black"
}
}
}
}
if ($err_counter -gt 0) {
write-host "Some File(s) are not following proper codeing standards. Please fix then commit" -foregroundcolor "red" -backgroundcolor "black"
exit 1
}
}
function php_unit_check {
param([string]$php_unit, [string]$bootstrap, [string]$extensions, [int]$reset, [int]$requireTest)
$err_counter = 0;
write-host "Pre-commit PHP unit check:" -foregroundcolor "white" -backgroundcolor "black"
git diff-index --name-only --cached HEAD -- | foreach {
if ($_ -match ".*\.($extensions)$") {
$file = $matches[0];
write-host $file ": " -foregroundcolor "gray" -backgroundcolor "black" -NoNewline
if ($file -match "tests\/") {
write-host "SKIPPED! (test file)" -foregroundcolor "green" -backgroundcolor "black"
} elseif ($file -match ".*Bootstrap.php") {
write-host "SKIPPED! (bootstrap file)" -foregroundcolor "green" -backgroundcolor "black"
} elseif ($file -match "([application|library\\NDX].*)(.($extensions))$") {
$testFile = 'tests/' + $matches[1] + "Test.php";
$testFileExists = (Test-Path $testFile -PathType Leaf)
if ($testFileExists) {
$errors = & $php_unit --bootstrap $bootstrap $testFile
if ($LastExitCode) {
write-host "FAILED! (" $testFile ")" -foregroundcolor "red" -backgroundcolor "black"
if ($reset) {
git reset -q HEAD $file
write-host "Unstaging ..." -foregroundcolor "magenta" -backgroundcolor "black"
}
$err_counter++
} else {
write-host "PASSED!" -foregroundcolor "green" -backgroundcolor "black"
}
} elseif($requireTest) {
write-host "FAILED! Test file Not found: (" $testFile ")" -foregroundcolor "red" -backgroundcolor "black"
if ($reset) {
git reset -q HEAD $file
write-host "Unstaging ..." -foregroundcolor "magenta" -backgroundcolor "black"
}
$err_counter++
} else {
write-host "PASSED! (Test file not found and not required)" -foregroundcolor "darkGreen" -backgroundcolor "black"
}
} else {
write-host "IGNORED!" -foregroundcolor "darkGreen" -backgroundcolor "black"
}
}
}
if ($err_counter -gt 0) {
write-host "Some File(s) failed unit testing. Please fix then commit" -foregroundcolor "red" -backgroundcolor "black"
exit 1
}
}
### MAIN ###
php_syntax_check $php_exe "php|phtml" $unstage_on_error
write-host
php_cs_check $php_cs "php" $unstage_on_error
write-host
php_unit_check $php_unit $bootstrap "php" $unstage_on_error $requireTest
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With