第60节 高级的 Githook 设计
❤️💕💕记录sealos开源项目的学习过程。k8s,docker和云原生的学习。Myblog:http://nsddd.top
[TOC]
社区不规范怎么办
作为 OpenIM 社区首席运营官,对整个社区的 communtiy 以及 GitHub 配置仓库 进行了全面的配置。并且对整个 OpenIM 的 Makefile
和 CICD
流,以及整个 OpenIM 使用的日志包 、错误码、协同流、贡献者文档以及 社区文档 进行架构和设计。
在这个时候总会有一些问题,即使你觉得自己的 贡献者文档 写的很牛逼了,很全面了,但是依旧很少有人愿意花心思去按照你写的规范去学习。这对我打造顶级的开源社区是一个非常大的阻碍,于是就有了今天的这个文档,我会将它记录在 GitHub Gists 上,提供拉取和使用的说明、链接,并且定期的维护它。
首先,我提供克隆的链接:
git clone https://gist.github.com/cubxxw/126b72104ac0b0ca484c9db09c3e5694
如何设计
首先是针对基础的功能,那就是我们熟知的 commit
信息和 push
信息。
- 我们可以对
commit
信息的格式进行设置 - 我们可以对
push
的大小进行设置 - 我们提供了
actions
的功能 - 我们提供了
Makefile
标记和清除Hook
的能力
我之前在学习 git 的时候写了一篇很全的笔记,并且分享在 GitHub 上面,在这个 🤖 链接 上可以学习到 git 很多高级用法。
这篇文章讲解了 git 有哪些规范,寻找合适的 CICD 流:
统一格式:
统一格式:git commit -m 'type(scope): 描述(#issue)'
我们在提交的时候带上邮箱信息
-s
来签证,这是一个很好的习惯。git commit -s -m "..."
git commit
艺术:<类型>[可选 范围]: <描述> [可选 正文] [可选 脚注]
git commit
提交类型可以是如下:
feat
:新功能(feature)fix
:修补bugdocs
:文档(documentation)style
: 格式(不影响代码运行的变动)refactor
:重构(即不是新增功能,也不是修改bug的代码变动)test
:增加测试chore
:构建过程或辅助工具的变动perf
:性能优化revert
:回滚build
:构建ci
:持续集成
⚠️ 使用这个 Git hook 应该注意什么?
- 这个
git hook
会在你不小心上传大文件的时候,阻止你,并且警告你,这是不可逆转的 - 这个
git hook
会在你没有办法控制提交格式的时候,让你很痛苦。
如何使用
你可以选择两种方式来使用 Git hook:
- 直接作为
.git/hooks
文件夹中的pre-commit
钩子。 - 使用 Husky 更新您的
package.json
:
Husky 使得 git hook 变的更加容易和方便:
"husky": {
"hooks": {
"pre-commit": "sh ./some-path/pre-commit-prevent-large-files.sh"
}
}
这个钩子我是为 OpenIM 社区项目设计的,但是转念一想,反正都做成很方便和高端的 Github Gist 了,为何不用 Gist 的特性来对 Git Hook 做一个记录和保存,后期提供维护和下载,也提供了一个交流平台,这是非常 perfect 的。
所以我第一步,利用了 GitHub Gist 提供了一个下载的通道,这样以后有别的项目也可以直接一键使用脚本来拉取到本地。
不仅仅如此,我针对提交设计了一个脚本,我们使用脚本可以一键并且规范的 push 到远程仓库。
curl -L https://gist.githubusercontent.com/cubxxw/126b72104ac0b0ca484c9db09c3e5694/raw/gitsync.sh |sh
默认限制为每个文件最大5MB。如果你觉得你的提交是一个特例,你可以使用以下命令覆盖这个限制:
GIT_FILE_SIZE_LIMIT=50000000 git commit -m "test: this commit is allowed file sizes up to 50MB"
# OR
git commit --no-verify
我不关心任何特定的文件,只是限制整个提交本身,这至少应该使开发人员的事情两次之前,他们可能会作出决定 git commit --no-verify
可复用脚本一键安装:
curl -L https://gist.github.com/cubxxw/126b72104ac0b0ca484c9db09c3e5694/raw/install.sh |bash
Contents
Note 点击右上角
Raw
进入脚本文件
可复用的安装脚本
#!/bin/sh
set -e
echo "Starting install script..."
SET_GIT_TEMPLATE_DIR=false
EXISTING_TEMPLATE=$(git config --global init.templateDir || echo "")
if [ -z "$EXISTING_TEMPLATE" ]; then
echo "Creating a new global git template dir at ~/.git_template"
mkdir ~/.git_template
EXISTING_TEMPLATE="$(cd ~; pwd -P)/.git_template"
SET_GIT_TEMPLATE_DIR=true
else
EXISTING_TEMPLATE="$(eval cd $(dirname "$EXISTING_TEMPLATE"); pwd -P)/$(basename "$EXISTING_TEMPLATE")"
echo "Using existing git template dir: $EXISTING_TEMPLATE"
fi
HOOKS_DIR="$EXISTING_TEMPLATE/hooks"
PRECOMMIT_HOOK="$HOOKS_DIR/pre-commit"
echo "Creating hooks dir if it doesn't already exist: $HOOKS_DIR"
mkdir -p "$HOOKS_DIR"
if [ -f "$PRECOMMIT_HOOK" ]; then
echo "Cannot install hook as it's already defined: '$PRECOMMIT_HOOK'" >&2
exit 1
fi
echo "Downloading the hook to $PRECOMMIT_HOOK"
curl -L https://gist.github.com/cubxxw/126b72104ac0b0ca484c9db09c3e5694/raw/pre-commit -o "$PRECOMMIT_HOOK" 2> /dev/null
curl -L https://gist.github.com/cubxxw/126b72104ac0b0ca484c9db09c3e5694/raw/commit-msg -o "$PRECOMMIT_HOOK" 2> /dev/null
curl -L https://gist.github.com/cubxxw/126b72104ac0b0ca484c9db09c3e5694/raw/pre-push -o "$PRECOMMIT_HOOK" 2> /dev/null
echo "Making it executable"
chmod +x "$PRECOMMIT_HOOK"
if [ "$SET_GIT_TEMPLATE_DIR" = true ]; then
echo "Defining ~/.git_template as the global git template dir"
git config --global init.templateDir '~/.git_template'
fi
echo -e "\nDone! Any future git repo created in this user profile will contain the hook\n"
##################################################
GIT_PATH=$(git rev-parse --show-toplevel)
echo "===> Copying hooks to $GIT_PATH/.git/hooks/"
mv ~/.git_template/hooks/* $GIT_PATH/.git/hooks/
git commit 设置
pre-commit 文件:
#!/usr/bin/env bash
# Copyright © 2023 OpenIMSDK.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# ==============================================================================
# This is a pre-commit hook that ensures attempts to commit files that are
# are larger than $limit to your _local_ repo fail, with a helpful error message.
# You can override the default limit of 2MB by supplying the environment variable:
# GIT_FILE_SIZE_LIMIT=50000000 git commit -m "test: this commit is allowed file sizes up to 50MB"
#
# ==============================================================================
YELLOW="\e[93m"
GREEN="\e[32m"
RED="\e[31m"
ENDCOLOR="\e[0m"
printMessage() {
printf "${YELLOW}OpenIM : $1${ENDCOLOR}\n"
}
printSuccess() {
printf "${GREEN}OpenIM : $1${ENDCOLOR}\n"
}
printError() {
printf "${RED}OpenIM : $1${ENDCOLOR}\n"
}
printMessage "Running local OpenIM pre-commit hook."
# flutter format .
# https://gist.github.com/cubxxw/126b72104ac0b0ca484c9db09c3e5694
# TODO! GIT_FILE_SIZE_LIMIT=50000000 git commit -m "test: this commit is allowed file sizes up to 50MB"
# Maximum file size limit in bytes
limit=${GIT_FILE_SIZE_LIMIT:-2000000} # Default 2MB
limitInMB=$(( $limit / 1000000 ))
function file_too_large(){
filename=$0
filesize=$(( $1 / 2**20 ))
cat <<HEREDOC
File $filename is $filesize MB, which is larger than github's maximum
file size (2 MB). We will not be able to push this file to GitHub.
Commit aborted
HEREDOC
git status
}
# Move to the repo root so git files paths make sense
repo_root=$( git rev-parse --show-toplevel )
cd $repo_root
empty_tree=$( git hash-object -t tree /dev/null )
if git rev-parse --verify HEAD > /dev/null 2>&1
then
against=HEAD
else
against="$empty_tree"
fi
# Set split so that for loop below can handle spaces in file names by splitting on line breaks
IFS='
'
shouldFail=false
for file in $( git diff-index --cached --name-only $against ); do
file_size=$(([ ! -f $file ] && echo 0) || (ls -la $file | awk '{ print $5 }'))
if [ "$file_size" -gt "$limit" ]; then
printError "File $file is $(( $file_size / 10**6 )) MB, which is larger than our configured limit of $limitInMB MB"
shouldFail=true
fi
done
if $shouldFail
then
printMessage "If you really need to commit this file, you can override the size limit by setting the GIT_FILE_SIZE_LIMIT environment variable, e.g. GIT_FILE_SIZE_LIMIT=42000000 for 42MB. Or, commit with the --no-verify switch to skip the check entirely."
printError "Commit aborted"
exit 1;
fi
commit-msg
#!/usr/bin/env bash
# Copyright © 2023 OpenIMSDK.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# ==============================================================================
#
# Store this file as .git/hooks/commit-msg in your repository in order to
# enforce checking for proper commit message format before actual commits.
# You may need to make the script executable by 'chmod +x .git/hooks/commit-msg'.
# commit-msg use go-gitlint tool, install go-gitlint via `go get github.com/llorllale/go-gitlint/cmd/go-gitlint`
# go-gitlint --msg-file="$1"
# An example hook script to check the commit log message.
# Called by "git commit" with one argument, the name of the file
# that has the commit message. The hook should exit with non-zero
# status after issuing an appropriate message if it wants to stop the
# commit. The hook is allowed to edit the commit message file.
YELLOW="\e[93m"
GREEN="\e[32m"
RED="\e[31m"
ENDCOLOR="\e[0m"
printMessage() {
printf "${YELLOW}OpenIM : $1${ENDCOLOR}\n"
}
printSuccess() {
printf "${GREEN}OpenIM : $1${ENDCOLOR}\n"
}
printError() {
printf "${RED}OpenIM : $1${ENDCOLOR}\n"
}
printMessage "Running the OpenIM commit-msg hook."
# This example catches duplicate Signed-off-by lines.
test "" = "$(grep '^Signed-off-by: ' "$1" |
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
echo >&2 Duplicate Signed-off-by lines.
exit 1
}
./tools/go-gitlint \
--msg-file=$1 \
--subject-regex="^(build|chore|ci|docs|feat|feature|fix|perf|refactor|revert|style|test)(.*)?:\s?.*" \
--subject-maxlen=150 \
--subject-minlen=10 \
--body-regex=".*" \
--max-parents=1
if [ $? -ne 0 ]
then
printError "Please fix your commit message to match OpenIM coding standards"
printError "https://gist.github.com/cubxxw/126b72104ac0b0ca484c9db09c3e5694"
exit 1
fi
push
#!/usr/bin/env bash
YELLOW="\e[93m"
GREEN="\e[32m"
RED="\e[31m"
ENDCOLOR="\e[0m"
printMessage() {
printf "${YELLOW}OpenIM : $1${ENDCOLOR}\n"
}
printSuccess() {
printf "${GREEN}OpenIM : $1${ENDCOLOR}\n"
}
printError() {
printf "${RED}OpenIM : $1${ENDCOLOR}\n"
}
printMessage "Running local OpenIM pre-push hook."
if [[ `git status --porcelain` ]]; then
printError "This script needs to run against committed code only. Please commit or stash you changes."
exit 1
fi
#
#printMessage "Running the Flutter analyzer"
#flutter analyze
#
#if [ $? -ne 0 ]; then
# printError "Flutter analyzer error"
# exit 1
#fi
#
#printMessage "Finished running the Flutter analyzer"
actions
git-warning.yml
文件:
# This workflow will check for large files being added in PRs
# and label the PR if one is found that exceeds the configured limit.
#
# For more information, see: https://github.com/marketplace/actions/lfs-warning
name: Large file size warning
on:
pull_request:
# Ignore some files to avoid consuming Actions minutes unnecessarily
# for file types we're fairly confident we'll never need to worry about
paths-ignore:
- '**.config'
- '**.cs'
- '**.cshtml'
- '**.cs'
- '**.csproj'
- '**.cmd'
- '**.dockerignore'
- '**.gitignore'
- '**.graphql'
- '**.jsx?'
- '**.md'
- '**.props'
- '**.ps1'
- '**.scss'
- '**.sh'
- '**.sln'
- '**.tsx?'
- '**.yml'
- '**/appsettings.*.json'
- '**/Dockerfile'
jobs:
run-check:
runs-on: ubuntu-latest
steps:
- uses: actionsdesk/lfs-warning@v2.0
with:
#token: ${{ secrets.GITHUB_TOKEN }} # Optional
filesizelimit: '5242880' # 5MB
嵌入到 Makefile 后,整个逻辑就更简单了:
# Copy githook scripts when execute makefile
COPY_GITHOOK:=$(shell cp -f script/githooks/* .git/hooks/; chmod +x .git/hooks/*)
END 链接
✴️版权声明 © :本书所有内容遵循CC-BY-SA 3.0协议(署名-相同方式共享)©