こんにちは!
プログラム2課の竹下です。
2023年も残り僅かになり、今年の出来事を振り返ることも多くなりました。
みなさんは今年どんなコードを書きましたか?
過去のコードを振り返りたい時は、バージョン管理ツールが役立ちますね。
そんな便利なバージョン管理ツールの一つである、SVNでのコミットをSlackに通知する方法を紹介します。
Slackに通知するメリット
・コミットがリアルタイムで分かる
→ SVNでlogを見る手間が無く、ローカル環境が最新の状態かを確認できます。
・Slack上でコミットに対してのやり取りを行いやすい
→ Slackに通知されたメッセージを使うことで不具合修正等のやり取りを円滑に行いやすくなりました。
・多量のファイル更新が分かる
→ 時間がかかる更新が意図しないタイミングで発生しないため、作業が止まることが無くなりました。
Slackに通知する方法
コミットをSlackに通知するには、SlackBotの作成とコミットしたタイミングで情報の取得が必要になります。
※今回はSubversionクライアントとしてTortoiseSVNを使用しています。
SlackBotの作成
SlackAPIよりSlackBotを新規作成します。
次に、通知メッセージを送りたいチャンネルに追加と権限を設定します。
※必要権限は 「app_mentions:read」「channels:history」「incoming-webhook」です。
最後に、WebhookURLを取得しておきます。
コミットのタイミングを取得
まず、SVNのサーバー上にあるhooksフォルダ内にpost-commit.cmdを作成します。
※ファイル名をpost-commitにするとコミットが正常に完了したタイミングで実行されます。
作成したpost-commit.cmdでは、次に作成するPowerShellを実行します。
このpost-commit.cmdに渡される引数は[リポジトリパス]、[リビジョン番号]、[トランザクション名]です。
powershell -ExecutionPolicy RemoteSigned -File %1\hooks\PostCommit.ps1 -repo %1 -rev %2
コミット情報の取得
今回は、PowerShellでsvnlookを用いてコミット情報を取得していきます。
svnlookは、SVNのリポジトリの状態を調べるコマンドラインツールです。
この中では、コミット情報からユーザー、日付、メッセージ、変更ファイル数を取得してSlackBotにメッセージを渡します。
※注意点として、Slackに渡す文字列はUTF8変換する必要があります。
# 引数を変数に代入
Param([string]$repo, [int]$rev)
# コミットしたユーザーの取得
$author = svnlook author $repo -r $rev
# コミットした日付取得
$date = svnlook date $repo -r $rev
# ログメッセージの取得
$log = svnlook log $repo -r $rev
#改行
$log = $log -split "`r`n"
$log = $log -join "`n"
# 変更のあったファイル
$changed = svnlook changed $repo -r $rev
$changed = $changed -split "`r`n"
$faileNum = $changed.Length
#メッセージ作成
$mainText = "<!subteam^グループID|グループ名>`nコミットが行われました。`n``````★コミット情報`n・日時:${date}`n・名前:${author}`n・リビジョン:${rev}`n・変更ファイル数:${faileNum}`n★コミットメッセージ`n${log}``````"
$text = "`{`"text`": `"${mainText}`"`}"
# UTF8変換
$Byte = [System.Text.Encoding]::UTF8.GetBytes($text)
# Slackに通知
Invoke-RestMethod -Uri "Slack側で作成したWebhookのURL" -Method Post -Body $Byte
これでコミットをSlackにリアルタイムで通知することが出来ました!
運用中に発生した問題
Slackに通知を出来るようにして運用している際に、発生した問題点と解決方法を紹介します。
問題1:コミット者にsvnlookの環境が無いと動作しない
解決方法: サーバー上にsvnlook環境を置きコード内でパスを通すように
svnlookを使用してコミット情報の取得しましたが、コミット者が環境パスを通していないと動作しませんでした。
そのため、サーバー上にsvnlookのexeフォルダを置き、コード内でパスを通すようにしました。
# svnlookを使用できるようにパスを通す
$CurrentDir = Split-Path $MyInvocation.MyCommand.Path
$CurrentDir = $CurrentDir + "exeフォルダまでのパス"
$ENV:Path="${CurrentDir};"+$ENV:Path
問題2:コミットメッセージに「\」が入っているとエラーが出る
解決方法:「\」に対してエスケープ対処
SlackBotのメッセージは、json形式で渡すため書式的にエラーがあると動作しませんでした。
そのため、jsonで意味を成す文字にエスケープ対処しました。
# ログメッセージの取得
$log = svnlook log $repo -r $rev
# 特殊文字の置き換え
# バックスラッシュを最初に置き換える必要がある
$log = $log -replace "\\","`\`\"
# ダブルコーテーション
$log = $log -replace "`"","`\`""
#改行
$log = $log -split "`r`n"
$log = $log -join "`n"
最終的にPowerShellのコードは下記のようになりました。
メンションは頻繁に飛んでしまうため、基本は飛ばさなくてもいいかもしれないですね。
# 引数を変数に代入
Param([string]$repo, [int]$rev)
# svnlookを使用できるようにパスを通す
$CurrentDir = Split-Path $MyInvocation.MyCommand.Path
$CurrentDir = $CurrentDir + "exeフォルダまでのパス"
$ENV:Path="${CurrentDir};"+$ENV:Path
# コミットしたユーザーの取得
$author = svnlook author $repo -r $rev
# コミットした日付取得
$date = svnlook date $repo -r $rev
# ログメッセージの取得
$log = svnlook log $repo -r $rev
# 特殊文字の置き換え
# バックスラッシュを最初に置き換える必要がある
$log = $log -replace "\\","`\`\"
# ダブルコーテーション
$log = $log -replace "`"","`\`""
#改行
$log = $log -split "`r`n"
$log = $log -join "`n"
# 変更のあったファイル
$changed = svnlook changed $repo -r $rev
$changed = $changed -split "`r`n"
$faileNum = $changed.Length
#メッセージ作成
$mainText = "<!subteam^グループID|グループ名>`nコミットが行われました。`n``````★コミット情報`n・日時:${date}`n・名前:${author}`n・リビジョン:${rev}`n・変更ファイル数:${faileNum}`n★コミットメッセージ`n${log}``````"
$text = "`{`"text`": `"${mainText}`"`}"
# UTF8変換
$Byte = [System.Text.Encoding]::UTF8.GetBytes($text)
# Slackに通知
Invoke-RestMethod -Uri "Slack側で作成したWebhookのURL" -Method Post -Body $Byte
最後に
今回は、SVNのコミットをSlackに通知する方法を紹介させていただきました。
Slackに通知することで小さな手間を省けたり、コミュニケーションのやり取りを円滑に行えて便利なので、是非使ってみてください。
参考サイト
・SlackとSubVersionの連携(Windows)
・TortoiseSVNで「svnは内部コマンドまたは外部コマンド~」エラーが出る時の対処方法
【免責事項】
本サイトでの情報を利用することによる損害等に対し、
株式会社ロジカルビートは一切の責任を負いません。