Skip to content

Instantly share code, notes, and snippets.

@helloworld-du
Last active June 14, 2019 08:56
Show Gist options
  • Save helloworld-du/dbff246f1714f75fd4e0 to your computer and use it in GitHub Desktop.
Save helloworld-du/dbff246f1714f75fd4e0 to your computer and use it in GitHub Desktop.
git hook(pre commit)

pre-commit hook

by [email protected] 原始地址: pre-commit hook

功能简述

1、在提交代码(git commit)到git库时,本钩子被触发。
2、调用phpcbf和phpcs,来做代码检查并尝试自动修复代码样式。
3、将修复后的代码提交到git库中。

安装步骤

假设目录结构:

YOUR_PROJECT_ROOT/
  |—— pre-commit
  |——ruleset.xml
  |—— vendor/
        |——bin/
            |——phpcs
            |——phpcbf

1、安装依赖PHP_CodeSniffer,定义代码样式,本例中使用FunPlus-Coding-Standards
2、配置钩子,参考如下配置。
3、git中注册钩子。

cd YOUR_PROJECT_ROOT/.git/hook/
ln -s ../../pre-commit .

钩子的配置参考

环境相关

define('PROJECT_ROOT', YOUR_PROJECT_ROOT); //项目的路径
define('PHP_CS_CHECK_CMD', PROJECT_ROOT.'/vendor/bin/phpcs'); //执行检查的命令
define('PHP_CS_RULESET', PROJECT_ROOT.'ruleset.xml');         //检查和修复使用的rule set,可以为""
define('PHP_CS_FIX_CMD', PROJECT_ROOT.'/vendor/bin/phpcbf');  //修复的命令

流程相关

define('AUTO_FIX_CS', TRUE);    //是否自动修复文件
define('CI_WHEN_ERROR', TRUE);  //修复后,依然有问题,是否依然提交
define('SHOW_DETAIL', TRUE);    //是否显示详细
define('SHOW_NOTICE', TRUE);    //是否给出notice

参考

1. git钩子

参考 Git Hook 或自行Google

2.代码检查

本钩子使用PHP_CodeSniffer做代码检查,需要提前配置好PHP_CodeSniffer和PHP_CodeSniffer所需的rule set。

#!/usr/bin/env php
<?php
/**
* ci时自动检查并尝试修复代码格式
* @author dushengchen <[email protected]>
* @link https://gist.github.com/helloworld-du/dbff246f1714f75fd4e0
*/
define('PROJECT_ROOT', dirname(__DIR__)); //项目的路径
define('PHP_CS_CHECK_CMD', PROJECT_ROOT.'/vendor/bin/phpcs'); //执行检查的命令
define('PHP_CS_RULESET', PROJECT_ROOT.'/git_hook/fp-ruleset.xml'); //检查和修复使用的rule set,为空时使用默认的
define('AUTO_FIX_CS', TRUE); //是否自动修复文件
define('PHP_CS_FIX_CMD', PROJECT_ROOT.'/vendor/bin/phpcbf'); //修复的命令
define('CI_WHEN_ERROR', TRUE); //修复后,依然有问题,是否依然提交
define('SHOW_DETAIL', TRUE); //是否显示详细
define('SHOW_NOTICE', TRUE); //是否给出notice
$lDiffFile = gitDiffFile(PROJECT_ROOT);
//过滤掉非php文件,
$lChangeFile = array_filter(
$lDiffFile, function ($sFileName) {
return file_exists(PROJECT_ROOT.'/'.$sFileName) && filterByFileExt($sFileName);
}
);
if(!$lChangeFile) {
displayAndSleep('No php file in change list.');
exit(0);
}
//如果自动修复,就直接先调用phpcbf,再phpcs,看看修复完还有哪些遗留问题,
//如果不自动修复,就只做phpcs
if (!AUTO_FIX_CS) {
displayTitle('PHP code style check:');
$lFailPass = doCsCheck($lChangeFile, SHOW_DETAIL);
if (!$lFailPass) {
exit(0);
}
exit(1);
}
displayTitle('Begin check and Try to fix:');
foreach($lChangeFile as $lFilePath) {
echo 'Scanning: ', $lFilePath;
$sRealPath = PROJECT_ROOT.'/'.$lFilePath;
$ret = fixPhpFile($sRealPath);
echo "...DONE\n";
}
echo "\n";
$lFailPass = doCsCheck($lChangeFile, SHOW_DETAIL);
if (!SHOW_DETAIL) {
displayNotice("Wanna see DETAIL, Please open FLAG: SHOW_DETAIL\n");
} else {
displayNotice("Wanna ignore DETAIL? Close FLAG: SHOW_DETAIL\n");
}
$sfileList = implode(' ', $lDiffFile);
displayTitle('ADD to git');
echo "Files:\nADD: ",implode("\nADD: ", $lDiffFile),"\n";
system('git add --all '.$sfileList);
//自动提交
if (!$lFailPass || CI_WHEN_ERROR) {
displayTitle('Commit to git');
echo "Files:\nCI: ",implode("\nCI: ", $lDiffFile),"\n";
$lFailPass && displayNotice("Stop CI? Please open FLAG: SHOW_DETAIL\n");
exit(0);
}
exit(1);
function displayTitle($str) {
static $iNum = 0;
$iNum++;
displayAndSleep("${iNum}. ${str}", 'green');
}
function displayAndSleep($str, $color = 'white') {
$ret = colorEcho("\n\n\t\t".$str."\n", $color);
sleep(1);
return $ret;
}
function displayNotice($str) {
if (!SHOW_NOTICE) {
return TRUE;
}
return colorEcho("Notice: ".$str, 'yellow');
}
function doCsCheck($lFileList, $bShowDetail = FALSE) {
$lFailPass = [];
foreach($lFileList as $lFilePath) {
if (!$bShowDetail) {
echo 'Cheaking: ', $lFilePath;
}
$sRealPath = PROJECT_ROOT.'/'.$lFilePath;
$retVal = phpCsSniffer($sRealPath, $bShowDetail);
if ($retVal) {
$lFailPass[] = $lFilePath;
}
if (!$bShowDetail) {
echo $retVal ? "...NO\n" : "...YES\n";
}
}
displayAndSleep("Check summary: error(".count($lFailPass). "/".count($lFileList).")", 'violet');
return $lFailPass;
}
function fixPhpFile($sPath, $bShowDetail = FALSE) {
$sCmd = PHP_CS_FIX_CMD.
(PHP_CS_RULESET ? ' --standard='.PHP_CS_RULESET.' ' : ' ')
.$sPath;
if ($bShowDetail) {
system($sCmd, $retVal);
} else {
exec($sCmd, $lOutput, $retVal);
}
return $retVal;
}
function phpCsSniffer($sPath, $bShowDetail = FALSE) {
$sCmd = PHP_CS_CHECK_CMD.
(PHP_CS_RULESET ? ' --standard='.PHP_CS_RULESET.' ' : ' ')
.$sPath;
if ($bShowDetail) {
system($sCmd, $retVal);
} else {
exec($sCmd, $lOutput, $retVal);
}
return $retVal;
}
function gitDiffFile($sPath) {
exec('git diff --cached --name-only '.$sPath, $lOutput, $retVal);
return $lOutput ?: [];
}
function filterByFileExt($sFileName, $sExt = '.php') {
$x = preg_match('/(.*)('.$sExt.')$/', $sFileName);
return $x;
}
function colorEcho($sContent, $color = 'white') {
static $lColor = [
'black' => '30',
'red' => '31',
'green' => '32',
'yellow' => '33',
'blue' => '34',
'violet' => '35',
'cyan' => '36',
'white' => '37',
];
$color = isset($lColor[$color]) ? $lColor[$color] : 37;
$sCmd = "echo \"\033[".$color."m".$sContent." \033[0m\"";
passthru($sCmd);
return TRUE;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment