Atlassian
bamboo
BotFramework

Bambooのビルド結果をSkypeに通知する

More than 1 year has passed since last update.

これはAtlassian User Group Tokyo Advent Calendar 2016の10日目の記事です。

最近ようやくBambooを触る機会があり、JenkinsでやっていたようにChatへビルド実行結果を共有したい!という思いが強く、調べてみました。


  • HipChatの場合:アトラシアン製品ですので、標準で連携してます。

  • Slackの場合:世界的に使われている製品ですので、Add-on探せばいっぱいありました。

  • Chatworkの場合:日本の製品ですので、見当たらず

  • Skypeの場合:世界的なはずなのに出てこないww #BotFrameworkが新しいからですかねorz

本記事ではSkypeを対象にしてますが、Chatworkでも同じような考え方だと思いますので参考にしていただければと思います


1. × Jobの一番最後にShellScriptで組み込む

まずやってみたのがこれです。Jenkins使ってた時代もこんな感じでやっていたなぁという記憶をもとにトライしました。

ただし、BambooのビルドJobの中から環境変数などで簡単にビルドの状態は取得できないことが判明( ノД`)(参考:Bamboo variables

そこで以下を参考にスクリプトの中でBambooのRestAPIを叩いてビルド結果を取得するという構成にしました。

https://gist.github.com/remmelt/9640659

ちゃんとコメントまで読めばよかったのですが、Jobの中に組み込んだスクリプトからlatest.jsonを読み取っても前回のビルド結果が取得されるだけで思ったものはできていないです。とはいえ、参考までにコードは載せておきます。


コード

使ったサーバにjqが入っていなかったという理由で、シェル芸がいくつか出てきてますw

社内サーバだとそういう人もいるかなと思い最後までがんばりましたが、途中何度か心折れそうになりました。

jqがある環境の人はぜひjq使いましょう!

#!/bin/sh

set -ex

curl -X GET -sS\
-u "${bamboo.rest.api.id}:${bamboo.rest.api.password}" \
-H "Content-Type: application/json" \
https://YOUR_BAMBOO_SERVER/bamboo/rest/api/latest/result/${bamboo_buildKey}/latest.json?buildstate > build.json

buildStatus=$(cat build.json | awk '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}' | grep -o '\"buildState\":\".*\"' | sed s/\"//g | cut -d ':' -f2)
testResult=$(cat build.json | awk '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}' | grep -o '\"buildTestSummary\":\".*\"' | sed s/\"//g | cut -c18- | sed -e 's/<[^>]*>//g')
reason=$(cat build.json | awk '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}' | grep -o '\"reasonSummary\":\".*\"' | sed s/\"//g | cut -c15- | sed -e 's/<[^>]*>//g')

message="------------------------------\n Build is ${buildStatus}!!\n------------------------------\n${reason}\n${planName} : ${testResult}\n"

# 失敗例なので、Skype投稿部分は省略

rm -f build.json


環境設定

${bamboo.XXX} となっている箇所はBambooのVariablesで設定を行う箇所です。

bamboo部分は自動的に補完されますので、XXX部分を定義する形となります。passwordとついているものはマスクされ、ログにも出ないので安心して使えます。


2. × 別Stageに通知用Jobを組み込む

これもダメ。一瞬うまくいったと思いましたが、前のStageがこけた場合に通知用Jobが実行されないという致命的な問題がありましたorz


3. ○ 同一Stageに通知用Jobを組み込み、ビルドJobが完了するまでポーリングする

同一StageだとJobは並列に実行されます。通知用Jobはすぐに実行開始されますが、ビルドJobが実行中だと一定間隔後にリトライを行うことでビルド結果が確認できるまで待つような構成になっています。現在はこれで動かしています。


通知用JOBのコード

1の処理にビルド中ならリトライするという処理を組み込んだだけです。無限ループはあまりよくないかと思い、10分でタイムアウトするようにしています。ビルドJOBは「JOB1」というキーになっている前提のコード例です。

Skype投稿用のID/PWなどは私の過去の投稿を参考にしてください

 → MicrosoftBotFrameworkのRestAPIを使ったTimerBotの「Botアカウントの作成」部分

set -ex

buildjson="build_${bamboo_planKey}_${bamboo_buildNumber}.json"
authjson="auth_${bamboo_planKey}_${bamboo_buildNumber}.json"

RETRY_COUNT=30
SLEEP_TIME=20s

for i in `seq 1 $RETRY_COUNT`
do
curl -X GET -sS\
-u "${bamboo.rest.api.id}:${bamboo.rest.api.password}" \
-H "Content-Type: application/json" \
https://YOUR_BAMBOO_SERVER/bamboo/rest/api/latest/result/${bamboo_planKey}-JOB1/${bamboo_buildNumber}.json?buildstate > "${buildjson}"

buildStatus=$(cat "${buildjson}" | awk '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}' | grep -o '\"buildState\":\".*\"' | sed s/\"//g | cut -d ':' -f2)
testResult=$(cat "${buildjson}" | awk '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}' | grep -o '\"buildTestSummary\":\".*\"' | sed s/\"//g | cut -c18- | sed -e 's/<[^>]*>//g')
reason=$(cat "${buildjson}" | awk '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}' | grep -o '\"reasonSummary\":\".*\"' | sed s/\"//g | cut -c15- | sed -e 's/<[^>]*>//g')

if [ "$buildStatus" != "Unknown" ]; then
break
else
echo "retry #$i .."
sleep "${SLEEP_TIME}"
fi
done

cat "${buildjson}" | awk '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}'

message="------------------------------\n build is ${buildStatus}!!\n------------------------------\n${reason}\n${bamboo_planRepository_branch} #${bamboo_buildNumber} : ${testResult}\n"

curl -X POST -sS\
-H "Content-Type: application/x-www-form-urlencoded" \
-d grant_type=client_credentials \
-d client_id=${bamboo.skype.bot.id} \
-d client_secret=${bamboo.skype.bot.password} \
-d scope=https%3A%2F%2Fgraph.microsoft.com%2F.default \
https://login.microsoftonline.com/common/oauth2/v2.0/token > "${authjson}"

token=$(cat "${authjson}" | grep -o '\"access_token\":\".*\"' | sed s/\"//g | cut -d ':' -f2)

curl -X POST -sS\
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${token}" \
-d "{ 'type' : 'message/text', 'text' : '${message}' }" \
https://api.skype.net/v3/conversations/${bamboo.skype.chatroom}/activities/

rm -f "${buildjson}"
rm -f "${authjson}"


注意点:ビルド実行エージェント

Bambooのビルドはエージェントに対して1つずつ実行されるようです。このようなJob構成にするには2つのエージェントが必要で、なおかつ同一サーバのキューに入ることがないことを保証しなければいけません。

そのため、Job設定の画面で「Requirements」を指定し、実行するサーバを排他にしておくとよいと思います。


結果

成功するとこんな通知が届くことになるかと思います

------------------------------

build is Successful!!
------------------------------
Code changes detected
develop #10 : 100 passed


4. RSSを監視して通知する

Bambooの外の話になってしまいましたが、実はこれが一番簡単です。ただ、3でできてしまったので見送っています。


5. Add-onを開発し、NotificationにSkypeを追加する

これが本来の形ですね。長期的にはやりたいですが、まだ手を出してません。

明日は@yutwatanさんです!