Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/bash
- #
- # Slack (slack.com) notification post-receive hook.
- #
- # Based on: https://github.com/joemiller/git-hooks Campfire notification post-receive hook. Author: Joe Miller
- # (http://joemiller.me)
- #
- # Based on post-receive.irc by Mikael Fridh <frimik@gmail.com> https://gist.github.com/1821358
- #
- # Settings needed:
- # git config hooks.slack.webhook-url "https://hooks.slack.com/services/..."
- # git config hooks.slack.channel "general"
- #
- # - The Slack webhook URL can be found in:
- # https://my.slack.com/services/new/incoming-webhook
- #
- function help() {
- echo "Required config settings:"
- echo " git config hooks.slack.webhook-url 'https://hooks.slack.com/services/...'"
- echo " git config hooks.slack.channel 'general'"
- echo " git config hooks.slack.show-only-last-commit true #optional"
- echo " git config hooks.slack.show-full-commit true #optional"
- echo " git config hooks.slack.username 'git' #optional"
- echo " git config hooks.slack.icon-url 'http://imgur/icon.png' #optional"
- echo " git config hooks.slack.icon-emoji ':twisted_rightwards_arrows:' #optional"
- echo " git config hooks.slack.repo-nice-name 'MyRepo' #optional"
- echo " git config hooks.slack.repos-root '/path/to/repos' #optional"
- echo " git config hooks.slack.changeset-url-pattern 'http://yourserver/%repo_path%/changeset/%rev_hash%' #optional"
- echo " git config hooks.slack.compare-url-pattern 'http://yourserver/%repo_path%/changeset/%old_rev_hash%..%new_rev_hash%' #
- echo " git config hooks.slack.branch-regexp 'regexp' #optional"
- }
- function replace_variables() {
- <------>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
- }
- function notify() {
- oldrev=$(git rev-parse $1)
- newrev=$(git rev-parse $2)
- refname="$3"
- # --- Interpret
- # 0000->1234 (create)
- # 1234->2345 (update)
- # 2345->0000 (delete)
- if expr "$oldrev" : '0*$' >/dev/null
- then
- change_type="create"
- else
- if expr "$newrev" : '0*$' >/dev/null
- then
- change_type="delete"
- else
- change_type="update"
- fi
- fi
- # --- Get the revision types
- newrev_type=$(git cat-file -t $newrev 2> /dev/null)
- oldrev_type=$(git cat-file -t "$oldrev" 2> /dev/null)
- case "$change_type" in
- create|update)
- rev="$newrev"
- rev_type="$newrev_type"
- ;;
- delete)
- rev="$oldrev"
- rev_type="$oldrev_type"
- ;;
- esac
- # The revision type tells us what type the commit is, combined with
- # the location of the ref we can decide between
- # - working branch
- # - tracking branch
- # - unannoted tag
- # - annotated tag
- case "$refname","$rev_type" in
- refs/tags/*,commit)
- # un-annotated tag
- refname_type="tag"
- short_refname=${refname##refs/tags/}
- ;;
- refs/tags/*,tag)
- # annotated tag
- refname_type="annotated tag"
- short_refname=${refname##refs/tags/}
- # change recipients
- if [ -n "$announcerecipients" ]; then
- recipients="$announcerecipients"
- fi
- ;;
- refs/heads/*,commit)
- # branch
- refname_type="branch"
- short_refname=${refname##refs/heads/}
- ;;
- refs/remotes/*,commit)
- # tracking branch
- refname_type="tracking branch"
- short_refname=${refname##refs/remotes/}
- echo >&2 "*** Push-update of tracking branch, $refname"
- echo >&2 "*** - no notification generated."
- return 0
- ;;
- *)
- # Anything else (is there anything else?)
- echo >&2 "*** Unknown type of update to $refname ($rev_type)"
- echo >&2 "*** - no notification generated"
- return 0
- ;;
- esac
- branchregexp=$(git config --get hooks.slack.branch-regexp)
- if [ -n "$branchregexp" ]; then
- if [[ ! $short_refname =~ $branchregexp ]]; then
- exit 0;
- fi
- fi
- #channels=$(git config hooks.irc.channel)
- # plural suffix, default "", changed to "s" if commits > 1
- s=""
- # Repo name, either Gitolite or normal repo.
- if [ -n "$GL_REPO" ]; then
- # it's a gitolite repo
- repodir=$(basename $(pwd))
- repo=$GL_REPO
- else
- repodir=$(basename $(pwd))
- if [ "$repodir" == ".git" ]; then
- repodir=$(dirname $PWD)
- repodir=$(basename $repodir)
- fi
- repo=${repodir%.git}
- fi
- repoprefix=$(git config hooks.slack.repo-nice-name || git config hooks.irc.prefix || git config hooks.emailprefix || echo "$
- onlylast=$(git config --get hooks.slack.show-only-last-commit)
- onlylast=$onlylast && [ -n "$onlylast" ]
- fullcommit=$(git config --get hooks.slack.show-full-commit)
- # Get the user information
- # If $GL_USER is set we're running under gitolite.
- if [ -n "$GL_USER" ]; then
- user=$GL_USER
- else
- user=$USER
- fi
- case ${change_type} in
- "create")
- header="New ${refname_type} *${short_refname}* has been created in ${repoprefix}"
- single_commit_suffix="commit"
- ;;
- "delete")
- header="$(tr '[:lower:]' '[:upper:]' <<< ${refname_type:0:1})${refname_type:1} *$short_refname* has been deleted from ${
- single_commit_suffix="commit"
- ;;
- "update")
- num=$(git log --pretty=oneline ${1}..${2}|wc -l|tr -d ' ')
- branch=${3/refs\/heads\//}
- if [ ${num} -gt 1 ]; then
- header="${num} new commits *pushed* to *${short_refname}* in ${repoprefix}"
- single_commit_suffix="one"
- s="s"
- else
- header="A new commit has been *pushed* to *${short_refname}* in ${repoprefix}"
- single_commit_suffix="one"
- fi
- ;;
- *)
- # most weird ... this should never happen
- echo >&2 "*** Unknown type of update to $refname ($rev_type)"
- echo >&2 "*** - notifications will probably screw up."
- ;;
- esac
- headerNoAttachments=$header
- if $onlylast && [[ "${change_type}" != "delete" ]]; then
- header="$header, showing last $single_commit_suffix:"
- fi
- if [[ "${change_type}" != "delete" && "${refname_type}" == "branch" ]]; then
- changeseturlpattern=$(git config --get hooks.slack.changeset-url-pattern)
- compareurlpattern=$(git config --get hooks.slack.compare-url-pattern)
- reporoot=$(git config --get hooks.slack.repos-root)
- urlformat=
- if [ -n "$changeseturlpattern" -a -n "$reporoot" ]; then
- if [[ $PWD == ${reporoot}* ]]; then
- repopath=$PWD
- base=$(basename $PWD)
- if [ "$base" == ".git" ]; then
- repopath=$(dirname $repopath)
- fi
- idx=$(echo $reporoot | wc -c | tr -d ' ')
- repopath=$(echo $repopath | cut -c$idx-)
- urlformat=$(echo $changeseturlpattern | replace_variables)
- if [ -n "$compareurlpattern" ]; then
- comparelink=$(echo $compareurlpattern | replace_variables)
- header=$(echo $header | sed -e "s|\([a-zA-Z0-9]\{1,\} new commit[s]\{0,1\}\)|\<$comparelink\|\\1\>|")
- fi
- else
- echo >&2 "$PWD is not in $reporoot. Not creating hyperlinks."
- fi
- fi
- formattedurl=""
- if [ -n "$urlformat" ]; then
- formattedurl="<${urlformat}|%h> "
- fi
- nl="\\\\n"
- if [[ "${change_type}" == "update" ]]; then
- start="${1}"
- else
- start="HEAD"
- fi
- end="${2}"
- # merge `git log` output with $header
- if $onlylast; then
- countarg="-n 1"
- else
- countarg=""
- fi
- # show the full commit message
- if [ "$fullcommit" == "true" ]; then
- commitformat="%B"
- else
- commitformat="%s"
- fi
- # Process the log and escape double quotes and backslashes; assuming commit names/messages don't have five of the followin
- log_out=$( git log --pretty=format:"&&&&&%cN;;;;;${formattedurl}${commitformat}@@@@@" $countarg ${start}..${end} \
- | perl -p -e 's/@@@@@\n+/@@@@@/mg' \
- | sed -e 's/\\/\\\\/g' \
- | sed -e 's/"/\\"/g' \
- | sed -e 's/&&&&&\(.*\);;;;;/{ \"fallback\" : \"\", \"color\" : \"good\", \"fields\" : [{"title":"\1","value":"/g' \
- | sed -e 's/@@@@@/","short":false},]},/g' \
- | sed -e 's/,\]/]/' )
- attachments="[${log_out%?}]"
- fi
- if [ -n "${attachments}" ] && [[ "${attachments}" != "" ]]; then
- msg=$(echo -e "\"text\":\"${header}\", \"attachments\" : $attachments")
- else
- msg=$(echo -e "\"text\":\"${headerNoAttachments}\"")
- fi
- # slack API uses \n substitution for newlines
- msg=$(echo -n "${msg}" | perl -p -e 's/\n/\\n/mg')
- webhook_url=$(git config --get hooks.slack.webhook-url)
- channel=$(git config --get hooks.slack.channel)
- username=$(git config --get hooks.slack.username)
- iconurl=$(git config --get hooks.slack.icon-url)
- iconemoji=$(git config --get hooks.slack.icon-emoji)
- if [ -z "$webhook_url" ]; then
- echo "ERROR: config settings not found"
- help
- exit 1
- fi
- payload="{${msg}"
- if [ -n "$channel" ]; then
- payload="$payload, \"channel\": \"$channel\""
- fi
- if [ -n "$username" ]; then
- payload="$payload, \"username\": \"$username\""
- fi
- if [ -n "$iconurl" ]; then
- payload="$payload, \"icon_url\": \"$iconurl\""
- elif [ -n "$iconemoji" ]; then
- payload="$payload, \"icon_emoji\": \"$iconemoji\""
- fi
- payload="$payload}"
- if [ -n "$DEBUG" ]; then
- echo "POST $webhook_url"
- echo "payload=$payload"
- return
- fi
- curl -s \
- -d "payload=$payload" \
- "$webhook_url" \
- >/dev/null
- }
- # MAIN PROGRAM
- # Read all refs from stdin, notify slack for each
- while read line; do
- set -- $line
- notify $*
- RET=$?
- done
- exit $RET
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement