3 # Slack (slack.com) notification post-receive hook.
5 # Based on: https://github.com/joemiller/git-hooks Campfire notification post-receive hook. Author: Joe Miller
6 # (http://joemiller.me)
8 # Based on post-receive.irc by Mikael Fridh <frimik@gmail.com> https://gist.github.com/1821358
12 echo "Required config settings:"
13 echo " git config hooks.slack.webhook-url 'https://hooks.slack.com/services/...'"
14 echo " git config hooks.slack.channel 'general'"
15 echo " git config hooks.slack.show-only-last-commit 'true' #optional"
16 echo " git config hooks.slack.username 'git' #optional"
17 echo " git config hooks.slack.icon-url 'http://imgur/icon.png' #optional"
18 echo " git config hooks.slack.icon-emoji ':twisted_rightwards_arrows:' #optional"
19 echo " git config hooks.slack.repo-nice-name 'MyRepo' #optional"
20 echo " git config hooks.slack.repos-root '/path/to/repos' #optional"
21 echo " git config hooks.slack.changeset-url-pattern 'http://yourserver/%repo_path%/changeset/%rev_hash
23 echo " git config hooks.slack.compare-url-pattern 'http://yourserver/%repo_path%/changeset/%old_rev_ha
24 sh%..%new_rev_hash%' #optional"
27 function notify_slack() {
28 oldrev=$(git rev-parse $1)
29 newrev=$(git rev-parse $2)
36 if expr "$oldrev" : '0*$' >/dev/null
40 if expr "$newrev" : '0*$' >/dev/null
48 # --- Get the revision types
49 newrev_type=$(git cat-file -t $newrev 2> /dev/null)
50 oldrev_type=$(git cat-file -t "$oldrev" 2> /dev/null)
51 case "$change_type" in
54 rev_type="$newrev_type"
58 rev_type="$oldrev_type"
62 # The revision type tells us what type the commit is, combined with
63 # the location of the ref we can decide between
68 case "$refname","$rev_type" in
72 short_refname=${refname##refs/tags/}
76 refname_type="annotated tag"
77 short_refname=${refname##refs/tags/}
79 if [ -n "$announcerecipients" ]; then
80 recipients="$announcerecipients"
86 short_refname=${refname##refs/heads/}
88 refs/remotes/*,commit)
90 refname_type="tracking branch"
91 short_refname=${refname##refs/remotes/}
92 echo >&2 "*** Push-update of tracking branch, $refname"
93 echo >&2 "*** - no notification generated."
97 # Anything else (is there anything else?)
98 echo >&2 "*** Unknown type of update to $refname ($rev_type)"
99 echo >&2 "*** - no notification generated"
103 # plural suffix, default "", changed to "s" if commits > 1
106 # Repo name, either Gitolite or normal repo.
107 if [ -n "$GL_REPO" ]; then
108 # it's a gitolite repo
109 repodir=$(basename `pwd`)
112 repodir=$(basename `pwd`)
113 if [ "$repodir" == ".git" ]; then
114 repodir=`dirname $PWD`
115 repodir=`basename $repodir`
120 repoprefix=$(git config hooks.slack.repo-nice-name || git config hooks.irc.prefix || git config hooks.emailprefix || echo "$repo")
121 onlylast=`git config --get hooks.slack.show-only-last-commit`
122 onlylast=$onlylast && [ -n "$onlylast" ]
124 # Get the user information
125 # If $GL_USER is set we're running under gitolite.
126 if [ -n "$GL_USER" ]; then
132 case ${change_type} in
134 header="New ${refname_type} *${short_refname}* has been created in ${repoprefix}"
135 single_commit_suffix="commit"
138 header="$(tr '[:lower:]' '[:upper:]' <<< ${refname_type:0:1})${refname_type:1} *$short_refname* has been deleted from ${repoprefix}"
139 single_commit_suffix="commit"
142 num=$(git log --pretty=oneline ${1}..${2}|wc -l|tr -d ' ')
143 branch=${3/refs\/heads\//}
145 if [ ${num} -gt 1 ]; then
146 header="${num} new commits *pushed* to *${short_refname}* in ${repoprefix}"
147 single_commit_suffix="one"
150 header="A new commit has been *pushed* to *${short_refname}* in ${repoprefix}"
151 single_commit_suffix="one"
156 # most weird ... this should never happen
157 echo >&2 "*** Unknown type of update to $refname ($rev_type)"
158 echo >&2 "*** - notifications will probably screw up."
161 if $onlylast && [[ "${change_type}" != "delete" ]]; then
162 header="$header, showing last $single_commit_suffix:"
166 if [[ "${change_type}" != "delete" && "${refname_type}" == "branch" ]]; then
167 changeseturlpattern=`git config --get hooks.slack.changeset-url-pattern`
168 compareurlpattern=`git config --get hooks.slack.compare-url-pattern`
169 reporoot=`git config --get hooks.slack.repos-root`
172 if [ -n "$changeseturlpattern" -a -n "$reporoot" ]; then
173 if [[ $PWD == ${reporoot}* ]]; then
176 if [ "$base" == ".git" ]; then
177 repopath=`dirname $repopath`
179 idx=`echo $reporoot | wc -c | tr -d ' '`
180 repopath=`echo $repopath | cut -c$idx-`
181 urlformat=`echo $changeseturlpattern | sed "s|%repo_path%|$repopath|g" | sed "s/%rev_hash%/%H/g"`
183 if [ -n "$compareurlpattern" ]; then
184 comparelink=`echo $compareurlpattern | sed "s|%repo_path%|$repopath|g" | sed "s|%old_rev_hash%|$oldrev|g" | sed "s|%new_rev_hash%|$newrev|g"`
185 header=`echo $header | sed -e "s|\([a-zA-Z0-9]\{1,\} new commit[s]\{0,1\}\)|\<$comparelink\|\\1\>|"`
188 echo >&2 "$PWD is not in $reporoot. Not creating hyperlinks."
193 if [ -n "$urlformat" ]; then
194 formattedurl="<${urlformat}|%h> "
200 if [[ "${change_type}" == "update" ]]; then
208 # merge `git log` output with $header
215 # Process the log and escape double quotes; assuming for now that committer names don't have five semicolons in them
216 log_out=$( git log --pretty=format:"%cN;;;;;${formattedurl}%s" $countarg ${start}..${end} \
217 | sed -e 's/\\/\\\\/g' \
218 | sed -e 's/"/\\"/g' \
219 | sed -e 's/\(.*\);;;;;\(.*\)/{"title":"\1","value":"\2","short":false},/' )
223 attachments="[{ \"fallback\" : \"${header}\", \"color\" : \"good\", \"fields\" : [${fields}]}]"
226 if [ -n "${attachments}" ] && [[ "${attachments}" != "" ]]; then
227 msg=$(echo -e "\"text\":\"${header}\", \"attachments\" : $attachments")
229 msg=$(echo -e "\"text\":\"${header}\"")
232 # slack API uses \n substitution for newlines
233 # msg=$(echo "${msg}" | perl -p -e 's/\+/+/mg')
235 webhook_url=$(git config --get hooks.slack.webhook-url)
236 channel=$(git config --get hooks.slack.channel)
237 username=$(git config --get hooks.slack.username)
238 iconurl=$(git config --get hooks.slack.icon-url)
239 iconemoji=$(git config --get hooks.slack.icon-emoji)
241 if [ -z "$webhook_url" ] || [ -z "$channel" ]; then
242 echo "ERROR: config settings not found"
247 payload="{${msg}, \"channel\": \"#$channel\""
249 if [ -n "$username" ]; then
250 payload="$payload, \"username\": \"$username\""
253 if [ -n "$iconurl" ]; then
254 payload="$payload, \"icon_url\": \"$iconurl\""
255 elif [ -n "$iconemoji" ]; then
256 payload="$payload, \"icon_emoji\": \"$iconemoji\""
261 if [ -n "$DEBUG" ]; then
262 echo "POST $webhook_url"
263 echo "payload=$payload"
268 -d "payload=$payload" \
273 webhook_url=$(git config --get hooks.slack.webhook-url)
277 if [ -n "$webhook_url" ]; then