GitHub for Windows Pre-Commit Hook

前端 未结 4 965
你的背包
你的背包 2021-01-05 01:38

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

相关标签:
4条回答
  • 2021-01-05 02:19

    Adding an answer as the currently selected answer is no longer the case. I was able to write a pre-commit hook that works across GitHub Desktop for Windows, SourceTree for Windows, and Git Bash for Windows.

    I'm not sure if it's a hard requirement for windows commit hooks, but I included an exact reference to sh.exe like so:

    #!C:/Program\ Files/Git/usr/bin/sh.exe
    

    And it runs fine!

    0 讨论(0)
  • 2021-01-05 02:21

    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 <wojtha@gmail.com>
    # Author: Chuck "MANCHUCK" Reeves <chuck@manchuck.com>
    #
    ###############################################################################
    
    ### 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
    
    0 讨论(0)
  • 2021-01-05 02:23

    Sorry to be the bearer of bad news, but GitHub for Windows doesn't support pre-commit hooks, since it uses libgit2 to commit.

    0 讨论(0)
  • 2021-01-05 02:45

    You may look into using Visual Studio (or your builder) pre-build events, although there is a gotcha there too if full automation needed. Here is an example use. Now, that solution also requires git.exe on the path, but user does not need to interact with it. And it would be sweet if someone smarter than me can solve that backslash issue mentioned in the write-up.

    0 讨论(0)
提交回复
热议问题