Advertisement
Guest User

git-slack-hook

a guest
Jan 22nd, 2018
422
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 9.49 KB | None | 0 0
  1. #!/bin/bash
  2. #
  3. # Slack (slack.com) notification post-receive hook.
  4. #
  5. # Based on: https://github.com/joemiller/git-hooks Campfire notification post-receive hook. Author: Joe Miller
  6. # (http://joemiller.me)
  7. #
  8. # Based on post-receive.irc by Mikael Fridh <frimik@gmail.com> https://gist.github.com/1821358
  9. #
  10. # Settings needed:
  11. #  git config hooks.slack.webhook-url "https://hooks.slack.com/services/..."
  12. #  git config hooks.slack.channel "general"
  13. #
  14. # - The Slack webhook URL can be found in:
  15. #   https://my.slack.com/services/new/incoming-webhook
  16. #
  17. function help() {
  18.   echo "Required config settings:"
  19.   echo " git config hooks.slack.webhook-url 'https://hooks.slack.com/services/...'"
  20.   echo " git config hooks.slack.channel 'general'"
  21.   echo " git config hooks.slack.show-only-last-commit true #optional"
  22.   echo " git config hooks.slack.show-full-commit true #optional"
  23.   echo " git config hooks.slack.username 'git' #optional"
  24.   echo " git config hooks.slack.icon-url 'http://imgur/icon.png' #optional"
  25.   echo " git config hooks.slack.icon-emoji ':twisted_rightwards_arrows:' #optional"
  26.   echo " git config hooks.slack.repo-nice-name 'MyRepo' #optional"
  27.   echo " git config hooks.slack.repos-root '/path/to/repos' #optional"
  28.   echo " git config hooks.slack.changeset-url-pattern 'http://yourserver/%repo_path%/changeset/%rev_hash%' #optional"
  29.   echo " git config hooks.slack.compare-url-pattern 'http://yourserver/%repo_path%/changeset/%old_rev_hash%..%new_rev_hash%' #
  30.  echo " git config hooks.slack.branch-regexp 'regexp'  #optional"
  31. }
  32.  
  33. function replace_variables() {
  34. <------>sed "s|%repo_path%|$repopath|g;s|%old_rev_hash%|$oldrev|g;s|%new_rev_hash%|$newrev|g;s|%rev_hash%|$newrev|g;s|%repo_pr
  35. }
  36.  
  37. function notify() {
  38.  oldrev=$(git rev-parse $1)
  39.  newrev=$(git rev-parse $2)
  40.  refname="$3"
  41.  
  42.  # --- Interpret
  43.  # 0000->1234 (create)
  44.  # 1234->2345 (update)
  45.  # 2345->0000 (delete)
  46.  if expr "$oldrev" : '0*$' >/dev/null
  47.  then
  48.    change_type="create"
  49.  else
  50.    if expr "$newrev" : '0*$' >/dev/null
  51.    then
  52.      change_type="delete"
  53.    else
  54.      change_type="update"
  55.    fi
  56.  fi
  57.  
  58.  # --- Get the revision types
  59.  newrev_type=$(git cat-file -t $newrev 2> /dev/null)
  60.  oldrev_type=$(git cat-file -t "$oldrev" 2> /dev/null)
  61.  case "$change_type" in
  62.    create|update)
  63.      rev="$newrev"
  64.      rev_type="$newrev_type"
  65.      ;;
  66.    delete)
  67.      rev="$oldrev"
  68.      rev_type="$oldrev_type"
  69.      ;;
  70.  esac
  71.  
  72.  # The revision type tells us what type the commit is, combined with
  73.  # the location of the ref we can decide between
  74.  #  - working branch
  75.  #  - tracking branch
  76.  #  - unannoted tag
  77.  #  - annotated tag
  78.  case "$refname","$rev_type" in
  79.    refs/tags/*,commit)
  80.      # un-annotated tag
  81.      refname_type="tag"
  82.      short_refname=${refname##refs/tags/}
  83.      ;;
  84.    refs/tags/*,tag)
  85.      # annotated tag
  86.      refname_type="annotated tag"
  87.      short_refname=${refname##refs/tags/}
  88.      # change recipients
  89.      if [ -n "$announcerecipients" ]; then
  90.        recipients="$announcerecipients"
  91.      fi
  92.      ;;
  93.    refs/heads/*,commit)
  94.      # branch
  95.      refname_type="branch"
  96.      short_refname=${refname##refs/heads/}
  97.      ;;
  98.    refs/remotes/*,commit)
  99.      # tracking branch
  100.      refname_type="tracking branch"
  101.      short_refname=${refname##refs/remotes/}
  102.      echo >&2 "*** Push-update of tracking branch, $refname"
  103.      echo >&2 "***  - no notification generated."
  104.      return 0
  105.      ;;
  106.    *)
  107.      # Anything else (is there anything else?)
  108.      echo >&2 "*** Unknown type of update to $refname ($rev_type)"
  109.      echo >&2 "***  - no notification generated"
  110.      return 0
  111.      ;;
  112.  esac
  113.  
  114.  branchregexp=$(git config --get hooks.slack.branch-regexp)
  115.  if [ -n "$branchregexp" ]; then
  116.    if [[ ! $short_refname =~ $branchregexp ]]; then
  117.      exit 0;
  118.    fi
  119.  fi
  120.  
  121.  #channels=$(git config hooks.irc.channel)
  122.  
  123.  # plural suffix, default "", changed to "s" if commits > 1
  124.  s=""
  125.  
  126.  # Repo name, either Gitolite or normal repo.
  127.  if [ -n "$GL_REPO" ]; then
  128.    # it's a gitolite repo
  129.    repodir=$(basename $(pwd))
  130.    repo=$GL_REPO
  131.  else
  132.    repodir=$(basename $(pwd))
  133.    if [ "$repodir" == ".git" ]; then
  134.      repodir=$(dirname $PWD)
  135.      repodir=$(basename $repodir)
  136.    fi
  137.    repo=${repodir%.git}
  138.  fi
  139.  
  140.  repoprefix=$(git config hooks.slack.repo-nice-name || git config hooks.irc.prefix || git config hooks.emailprefix || echo "$
  141.   onlylast=$(git config --get hooks.slack.show-only-last-commit)
  142.   onlylast=$onlylast && [ -n "$onlylast" ]
  143.   fullcommit=$(git config --get hooks.slack.show-full-commit)
  144.  
  145.   # Get the user information
  146.   # If $GL_USER is set we're running under gitolite.
  147.   if [ -n "$GL_USER" ]; then
  148.     user=$GL_USER
  149.   else
  150.     user=$USER
  151.   fi
  152.  
  153.   case ${change_type} in
  154.     "create")
  155.       header="New ${refname_type} *${short_refname}* has been created in ${repoprefix}"
  156.       single_commit_suffix="commit"
  157.       ;;
  158.     "delete")
  159.       header="$(tr '[:lower:]' '[:upper:]' <<< ${refname_type:0:1})${refname_type:1} *$short_refname* has been deleted from ${
  160.      single_commit_suffix="commit"
  161.      ;;
  162.    "update")
  163.      num=$(git log --pretty=oneline ${1}..${2}|wc -l|tr -d ' ')
  164.      branch=${3/refs\/heads\//}
  165.  
  166.      if [ ${num} -gt 1 ]; then
  167.        header="${num} new commits *pushed* to *${short_refname}* in ${repoprefix}"
  168.        single_commit_suffix="one"
  169.        s="s"
  170.      else
  171.        header="A new commit has been *pushed* to *${short_refname}* in ${repoprefix}"
  172.        single_commit_suffix="one"
  173.      fi
  174.  
  175.      ;;
  176.    *)
  177.      # most weird ... this should never happen
  178.      echo >&2 "*** Unknown type of update to $refname ($rev_type)"
  179.      echo >&2 "***  - notifications will probably screw up."
  180.      ;;
  181.  esac
  182.  headerNoAttachments=$header
  183.  if $onlylast && [[ "${change_type}" != "delete" ]]; then
  184.    header="$header, showing last $single_commit_suffix:"
  185.  fi
  186.  
  187.  
  188.  if [[ "${change_type}" != "delete" && "${refname_type}" == "branch" ]]; then
  189.    changeseturlpattern=$(git config --get hooks.slack.changeset-url-pattern)
  190.    compareurlpattern=$(git config --get hooks.slack.compare-url-pattern)
  191.    reporoot=$(git config --get hooks.slack.repos-root)
  192.  
  193.    urlformat=
  194.    if [ -n "$changeseturlpattern" -a -n "$reporoot" ]; then
  195.      if [[ $PWD == ${reporoot}* ]]; then
  196.        repopath=$PWD
  197.        base=$(basename $PWD)
  198.        if [ "$base" == ".git" ]; then
  199.          repopath=$(dirname $repopath)
  200.        fi
  201.        idx=$(echo $reporoot | wc -c | tr -d ' ')
  202.        repopath=$(echo $repopath | cut -c$idx-)
  203.        urlformat=$(echo $changeseturlpattern | replace_variables)
  204.  
  205.        if [ -n "$compareurlpattern" ]; then
  206.          comparelink=$(echo $compareurlpattern | replace_variables)
  207.          header=$(echo $header | sed -e "s|\([a-zA-Z0-9]\{1,\} new commit[s]\{0,1\}\)|\<$comparelink\|\\1\>|")
  208.         fi
  209.       else
  210.         echo >&2 "$PWD is not in $reporoot. Not creating hyperlinks."
  211.       fi
  212.     fi
  213.  
  214.     formattedurl=""
  215.     if [ -n "$urlformat" ]; then
  216.       formattedurl="<${urlformat}|%h> "
  217.     fi
  218.  
  219.  
  220.     nl="\\\\n"
  221.  
  222.     if [[ "${change_type}" == "update" ]]; then
  223.       start="${1}"
  224.     else
  225.       start="HEAD"
  226.     fi
  227.  
  228.     end="${2}"
  229.  
  230.  
  231.     # merge `git log` output with $header
  232.     if $onlylast; then
  233.       countarg="-n 1"
  234.     else
  235.       countarg=""
  236.     fi
  237.  
  238.     # show the full commit message
  239.     if [ "$fullcommit" == "true" ]; then
  240.       commitformat="%B"
  241.     else
  242.       commitformat="%s"
  243.     fi
  244.  
  245.     # Process the log and escape double quotes and backslashes; assuming commit names/messages don't have five of the followin
  246.     log_out=$( git log --pretty=format:"&&&&&%cN;;;;;${formattedurl}${commitformat}@@@@@" $countarg ${start}..${end} \
  247.         | perl -p -e 's/@@@@@\n+/@@@@@/mg' \
  248.         | sed -e 's/\\/\\\\/g' \
  249.         | sed -e 's/"/\\"/g' \
  250.         | sed -e 's/&&&&&\(.*\);;;;;/{ \"fallback\" : \"\", \"color\" : \"good\", \"fields\" : [{"title":"\1","value":"/g' \
  251.         | sed -e 's/@@@@@/","short":false},]},/g' \
  252.         | sed -e 's/,\]/]/' )
  253.  
  254.     attachments="[${log_out%?}]"
  255.  
  256.   fi
  257.  
  258.   if [ -n "${attachments}" ] && [[ "${attachments}" != "" ]]; then
  259.     msg=$(echo -e "\"text\":\"${header}\", \"attachments\" : $attachments")
  260.   else
  261.     msg=$(echo -e "\"text\":\"${headerNoAttachments}\"")
  262.   fi
  263.  
  264.   # slack API uses \n substitution for newlines
  265.   msg=$(echo -n "${msg}" | perl -p -e 's/\n/\\n/mg')
  266.  
  267.   webhook_url=$(git config --get hooks.slack.webhook-url)
  268.   channel=$(git config --get hooks.slack.channel)
  269.   username=$(git config --get hooks.slack.username)
  270.   iconurl=$(git config --get hooks.slack.icon-url)
  271.   iconemoji=$(git config --get hooks.slack.icon-emoji)
  272.  
  273.   if [ -z "$webhook_url" ]; then
  274.     echo "ERROR: config settings not found"
  275.     help
  276.     exit 1
  277.   fi
  278.  
  279.   payload="{${msg}"
  280.  
  281.   if [ -n "$channel" ]; then
  282.     payload="$payload, \"channel\": \"$channel\""
  283.   fi
  284.  
  285.   if [ -n "$username" ]; then
  286.     payload="$payload, \"username\": \"$username\""
  287.   fi
  288.  
  289.   if [ -n "$iconurl" ]; then
  290.     payload="$payload, \"icon_url\": \"$iconurl\""
  291.   elif [ -n "$iconemoji" ]; then
  292.     payload="$payload, \"icon_emoji\": \"$iconemoji\""
  293.   fi
  294.  
  295.   payload="$payload}"
  296.  
  297.   if [ -n "$DEBUG" ]; then
  298.     echo "POST $webhook_url"
  299.     echo "payload=$payload"
  300.     return
  301.   fi
  302.  
  303.   curl -s \
  304.       -d "payload=$payload" \
  305.       "$webhook_url" \
  306.       >/dev/null
  307.  
  308. }
  309.  
  310. # MAIN PROGRAM
  311. # Read all refs from stdin, notify slack for each
  312. while read line; do
  313.   set -- $line
  314.   notify $*
  315.   RET=$?
  316. done
  317.  
  318. exit $RET
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement