Gitlab挂钩强制开发人员在其提交消息中使用JIRA问题

时间:2018-11-25 07:04:04

标签: bash gitlab hook

我想使用Linux Bash脚本针对以下内容仅对一个存储库实现Gitlab自定义钩子:

  1. 我要强制开发人员在其提交消息中提及其发行状态(例如:已修复,正在进行中)的JIRA发行号,如果提交消息中没有发行号,则应自动拒绝该推送。
  2. 如果提交消息的JIRA问题ID具有状态,则应允许开发人员推送更改。

我对应该选择的最佳Gitlab钩子和如何在提交消息中使用JIRA问题感到困惑。

1 个答案:

答案 0 :(得分:1)

碰巧,我有一个脚本可以做到这一点。我的人员还检查是否符合其他一些提交样式问题,但您可以根据需要对其进行自定义。

#!/bin/bash
#
# pre-receive hook for Commit Check
#
# Adapted from
#  http://blog.hgomez.net/2015/03/02/Gitlab-custom-hooks-Bash-Way.html

REGEX='^(\(([A-Z]+-[0-9]+|maint|docs)\) [A-Z]|Version [0-9]+).*[^\.]$'

check_single_commit()
{
  FIRST_LINE=$(echo "$COMMIT_MESSAGE" | sed -n 1p)
  SECOND_LINE=$(echo "$COMMIT_MESSAGE" | sed -n 2p)

  # Warn if line 1 > 50 chars
  WIDTH=$(echo $FIRST_LINE | wc -c)
  [ $WIDTH -gt 50 ] && [ $WIDTH -le 70 ] && printf "Warning: first line of commit exceeds 50 characters\n\n"

  # Fail if there is no Jira, docs or maint ref.
  echo $FIRST_LINE | egrep -q "$REGEX"
  COMMIT_CHECK_STATUS=$?
  if [ $COMMIT_CHECK_STATUS -gt 0 ]; then
    echo "Fail: No Jira ref found in commit message"
    echo "Expected: $REGEX"
    echo "Actual:"
    echo "$COMMIT_MESSAGE" |sed -e 's/^/  /'
    echo ""
  fi

  # Fail if second line is not blank.
  if [ ! -z "$SECOND_LINE" ] && [ $COMMIT_CHECK_STATUS -eq 0 ]; then
    [ -z "$SECOND_LINE" ] ; COMMIT_CHECK_STATUS=$?
    echo "Second line of commit is not blank, but is '$SECOND_LINE'"
    echo ""
  fi

  # Fail if line 1 > 70 chars
  if [ $WIDTH -gt 70 ] && [ $COMMIT_CHECK_STATUS -eq 0 ]; then
    [ $WIDTH -le 70 ] ; COMMIT_CHECK_STATUS=$?
    echo "Fail: first line of commit exceeds 70 characters, please use the commit body"
    echo ""
  fi
}

check_all_commits()
{
  REVISIONS=$(git rev-list master..$NEW_VALUE)
  IFS='\n' read -ra LIST_OF_REVISIONS <<< "$REVISIONS"

  for rid in "${!LIST_OF_REVISIONS[@]}"; do
    REVISION=${LIST_OF_REVISIONS[rid]}
    COMMIT_MESSAGE=$(git cat-file commit $REVISION | sed '1,/^$/d')
    check_single_commit

    if [ $COMMIT_CHECK_STATUS -ne 0 ]; then
      echo "Commit validation failed for commit $REVISION" >&2
      echo ""
      echo "Please read: https://chris.beams.io/posts/git-commit/"
      echo ""
      exit 1
    fi
  done
}

# Get custom commit message format

# After a push occurs and before any refs are updated on the remote repository,
# the git-receive-pack process invokes the pre-receive hook script with the
# standard input of one line per ref to be updated:
#
# <old-value> SP <new-value> SP <ref-name> LF
#
# This string represents these arguments:
#
# <old-value> Old object name stored in the ref. When you create a new ref,
# this equals 40 zeroes.
# <new-value> New object name to be stored in the ref. When you delete a ref,
# this equals 40 zeroes.
# <ref-name>  The full name of the ref.

while read OLD_VALUE NEW_VALUE REFNAME ; do
  [ $NEW_VALUE == 0000000000000000000000000000000000000000 ] && exit 0
  check_all_commits
done

exit 0

# vim:set ft=sh