我想你正在运行社区版的 gitlab。
然后,只有服务器管理员可以通过将所需脚本复制到受影响的存储库来配置挂钩脚本。
gitlab 本身已经将$GIT_DIR/hooks 目录用于自己的脚本。幸运的是,他们将控制权转发给 gitlab 特定的 $GIT_DIR/custom_hooks 目录中的任何钩子脚本。另见this question about how to run multiple hooks with the same type on gitlab。
脚本本身可能如下所示:
#!/bin/bash
#
# Hook script to export current state of repo to a release area
#
# Always hardcode release area - if configured in the repo this might incur data loss
# or security issues
echo "Git hook: $0 running"
. $(dirname $0)/functions
git=git
release_root=/gitlab/release
# The above release directory must be accessible from the gitlab server
# and any client machines that want to access the exports. Please configure.
if [ $(git rev-parse --is-bare-repository) = true ]; then
group_name=$(basename $(dirname "$PWD"))
repo_name=$(basename "$PWD")
else
cd $(git rev-parse --show-toplevel)
group_name=$(basename $(readlink -nf "$PWD"/../..))
repo_name=$(basename $(readlink -nf "$PWD"/..))
fi
function do_release {
ref=$1
branch=$2
# Decide on name for release
release_date=$(git show -s --format=format:%ci $ref -- | cut -d' ' -f1-2 | tr -d -- -: | tr ' ' -)
if [[ ! "$release_date" =~ [0-9]{8}-[0-9]{6} ]]; then
echo "Could not determine release date for ref '$ref': '$release_date'"
exit 1
fi
dest_root="$release_root/$group_name/$repo_name"
dated_dir="dated/$release_date"
export_dir="$dest_root/$dated_dir"
# Protect against multiple releases in the same second
if [[ -e "$export_dir" ]]; then
export_dir="$export_dir-02"
dated_dir="$dated_dir-02"
while [[ -e "$export_dir" ]]; do
export_dir=$(echo $export_dir | perl -pe 'chomp; print ++$_')
dated_dir=$(echo $dated_dir | perl -pe 'chomp; print ++$_')
done
fi
# Create release area
if ! mkdir -pv "$export_dir"; then
echo 'Failed to create export directory: ' "$export_dir"
exit 1
fi
# Release
if ! git archive $branch | tar -x -C "$export_dir"; then
echo 'Failed to export!'
exit 1
fi
chmod a-w -R "$export_dir" # Not even me should change this dir after release
echo "Exported $branch to $export_dir"
( cd "$dest_root" && rm -f latest && ln -s "$dated_dir" latest )
echo "Adjusted $dest_root/latest pointer"
}
process_ref() {
oldrev=$(git rev-parse $1)
newrev=$(git rev-parse $2)
refname="$3"
set_change_type
set_rev_types
set_describe_tags
echo " Ref: $refname","$rev_type"
case "$refname","$rev_type" in
refs/heads/*,commit)
# branch
refname_type="branch"
function="branch"
short_refname=${refname##refs/heads/}
if [[ $short_refname == release ]]; then
echo " Push accepted. Releasing export for $group_name/$repo_name $short_refname"
do_release "$refname" "$short_refname"
else
echo " Push accepted. No releases done for $group_name/$repo_name $short_refname"
fi
;;
refs/tags/*,tag)
# annotated tag
refname_type="annotated tag"
function="atag"
short_refname=${refname##refs/tags/}
;;
esac
}
while read REF; do process_ref $REF; done
exit 0
脚本是基于this post-receive.send_email script 启动的,该this post-receive.send_email script 已在 SO 上多次引用。
在脚本中硬编码的变量中配置发布区域,或者例如添加一种机制来读取 repo 中的配置文件。也许你想让用户控制这个区域。取决于您的安全情况。
发布区域必须可供 git@gitlab 用户访问,当然还有任何期望导出的客户。
要导出的分支在脚本中是硬编码的。
发布区域将如下填充:
$release_root/$group_name/$repo_name/dated/$release_date
加上一个符号链接latest 指向最新的$release_date。这个想法是,这可以扩展,以便以后也能够导出标签。如果您希望导出不同的分支,也应将$branch 作为路径组件包含在内。
gitlab 服务器的访问控制没有传递到目录结构。目前我手动执行此操作,这就是为什么我不使用此挂钩自动填充所有新存储库的原因。我宁愿手动配置,然后相应地调整 $release_root/$groupname 路径上的 unix 组权限(和/或 ACL)。这需要每个组只执行一次并且有效,因为不允许其他人在我的 gitlab 实例上创建新组。这与默认值有很大不同。
我们还能为您做什么? ;-)