Skip to content

Instantly share code, notes, and snippets.

@kimihito
Forked from seriwb/circleci-coverage-slack.sh
Last active July 8, 2017 07:52
Show Gist options
  • Save kimihito/d3317d25f4b11e2bfbfeca94c24d045f to your computer and use it in GitHub Desktop.
Save kimihito/d3317d25f4b11e2bfbfeca94c24d045f to your computer and use it in GitHub Desktop.
カバレッジをSlack通知するスクリプト
###
# Post coverage rate to Slack
#
# Usage: bash circleci-coverage-slack.sh [simplecov|cobertura|jacoco]
#
# Required environment variables:
#
# - CIRCLE_TOKEN: project-specific readonly API token (need to access build artifacts for others)
# - SLACK_ENDPOINT: Slack endpoint url
# - COVERAGE_FILE: coverage filename (default: .last_run.json)
# - MAX_BUILD_HISTORY: max history num to fetch old rate (default: 5)
#
GITHUB_URL="github.com"
CIRCLECI_URL="circleci.com"
function calcCoberturaRate() {
local rate=$(ruby -r "rexml/document" -e '
node = REXML::XPath.first(REXML::Document.new(STDIN.read), "coverage")
puts "%.2f" % (node.attributes["line-rate"].to_f * 100)
')
[ "$rate" == "100.00" ] && rate=100
echo $rate
}
function calcJacocoRate() {
local rate=$(ruby -r "rexml/document" -e '
node = REXML::XPath.first(REXML::Document.new(STDIN.read), "report/counter[@type=\"LINE\"]")
missed = node.attributes["missed"].to_f
covered = node.attributes["covered"].to_f
puts "%.2f" % (covered / (covered + missed) * 100)
')
[ "$rate" == "100.00" ] && rate=100
echo $rate
}
function calcSimplecovRate() {
local rate=$(ruby -r "json" -e '
json_data = JSON.parse(STDIN.read)
covered = json_data["result"]["covered_percent"].to_f
puts "%.2f" % covered
')
[ "$rate" == "100.00" ] && rate=100
echo $rate
}
function calcRate() {
case "$coverage_type" in
"cobertura" )
calcCoberturaRate
;;
"jacoco" )
calcJacocoRate
;;
"simplecov" )
calcSimplecovRate
;;
esac
}
coverage_type=${1:-simplecov}
coverage=$(find $CIRCLE_ARTIFACTS -type f | grep ${COVERAGE_FILE:-.last_run.json})
url_base="https://${CIRCLECI_URL}/api/v1/project/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}"
## calculate rates
rate_new=$(cat $coverage | calcRate)
rate_old=0
for build_num in $(echo $CIRCLE_PREVIOUS_BUILD_NUM; seq $(expr $CIRCLE_BUILD_NUM - 1) -1 1 | head -n ${MAX_BUILD_HISTORY:-5}); do
echo "fetching coverage info for build:${build_num} ..."
artifacts="${url_base}/${build_num}/artifacts"
[ -n "$CIRCLE_TOKEN" ] && artifacts="${artifacts}?circle-token=${CIRCLE_TOKEN}"
coverage=$(curl -s -H 'Accept: application/json' $artifacts | jq -r '.[].url' | grep ${COVERAGE_FILE:-.last_run.json})
[ -n "$coverage" ] && break
done
if [ -n "$coverage" ]; then
[ -n "$CIRCLE_TOKEN" ] && coverage="${coverage}?circle-token=${CIRCLE_TOKEN}"
rate_old=$(curl -s $coverage | calcRate)
fi
## construct messages
author=$(git log --format='%an <%ae>' -1 | sed 's/\\/\\\\/g;s/\"/\\"/g')
log=$(git log --format=%s -1 | sed 's/\\/\\\\/g;s/\"/\\"/g')
mode=$(ruby -e 'puts (ARGV[0].to_f <=> ARGV[1].to_f) + 1' -- $rate_new $rate_old)
mes=("DECREASED" "NOT CHANGED" "INCREASED")
color=("danger" "#a0a0a0" "good")
report=""
if [ $coverage_type = "simplecov" ]; then
report=" - <https://${CIRCLECI_URL}/gh/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/${CIRCLE_BUILD_NUM}/artifacts/0$CIRCLE_ARTIFACTS/coverage/index.html|report>"
fi
cat > .slack_payload <<_EOT_
{
"attachments": [
{
"fallback": "Coverage ${mes[$mode]} (${rate_new}%)",
"text": "*${mes[$mode]}* (${rate_old}% -> ${rate_new}%)",
"pretext": "Coverage report: <https://${CIRCLECI_URL}/gh/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}|${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}> - <https://${CIRCLECI_URL}/gh/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/${CIRCLE_BUILD_NUM}|#${CIRCLE_BUILD_NUM}>${report}",
"color": "${color[$mode]}",
"mrkdwn_in": ["pretext", "text", "fields"],
"fields": [
{
"value": "Commit: <https://${GITHUB_URL}/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/commit/${CIRCLE_SHA1}|${CIRCLE_SHA1}>",
"short": false
},
{
"value": "Author: ${author}",
"short": false
},
{
"value": "${log}",
"short": false
}
]
}
]
}
_EOT_
## post to slack
curl -s --data-urlencode payload@.slack_payload ${SLACK_ENDPOINT}
rm .slack_payload
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment