最近、梅ちゃんが「レビューが必要なチケット」を教えてくれるようになった
こんにちは、株式会社POLでソフトウェアエンジニアをしているmotikomaです。好きなキャンプ場は石川県志賀町にある大島キャンプ場です。
みなさんのチームにはマスコットキャラクターはいますか?
うちのチームには「梅ちゃん」という猫がいます。昔は姿がなく概念として存在していただけだったのですが、徐々に鳴き声を獲得し、最近は電脳空間上に実体を得ました。
ちなみに実体名は「ハンニバル」です。そう、カルタゴの将軍ですね。
さて、今回はJIRAのレビューが必要なチケットを梅ちゃん(あだ名)が教えてくれるようになったという話をしたいと思います。
レビュー状況を分かりやすくしたい
うちのチームでは朝会でJIRAの「アクティブなスプリント」を見ながら、スプリントゴールを達成できそうかどうかを確認しています。その際にレビューが必要なチケットをチェックします。
朝会後には「ワイワイレビュー会」という時間を入れており、Gatherに集まって相談しながらレビューを進めています。今まではSlackにレビュースレッドを立てて、そこに各自が作成したGithubのプルリクのURLを返信し、レビューしたかどうかをアイコンで可視化していました。
これはこれで趣があるのですが、プルリクのリンクを貼るのが手動で手間だったんですよね。そこで、梅ちゃんにやってもらうことにしたというのが今回の話です。
なお、JIRAチケットにGithubのプルリクが紐づいているので、今回はJIRAチケットのリンクを投稿してもらうようにしました。JIRAチケットに受け入れ条件を書いているので、そこを起点にしてレビューしたかったので。
※他にもっと効率的な方法がありそうですが思いついたら改善する予定で
Boltを使ってSlackアプリを作成
Boltを使ってSlackアプリを作ってみることにしました。作成の際にはBolt 入門ガイドやTypeScript製のサンプルアプリが参考になりました。
JIRA API経由でレビューステータス中のチケット一覧を取得します。公式記事はこちらです。下記の記事も参考にさせていただきました!
https://www.ricksoft.jp/blog/archives/8182/
// app.ts
import { App } from "@slack/bolt";
import { postJiraReviewIssueLinks } from "./command";
const app = new App({
token: process.env.SLACK_BOT_TOKEN,
signingSecret: process.env.SLACK_SIGNING_SECRET
});
const main = async () => {
// Start your app
await app.start(Number(process.env.PORT) || 3000);
console.log('⚡️ Bolt app is running!');
};
main();
postJiraReviewIssueLinks(app);
// command.ts
import { App } from "@slack/bolt"
export const postJiraReviewIssueLinks = (app: App) => {
app.command(`/reviews`, async ({ command, ack, context, say }) => {
await ack();
// issue番号一覧を取得
const issueKeys = await getIssueKeys(getToken());
// issue数を取得
const numberOfIssues = Math.floor(issueKeys.length);
// メッセージを投稿
if (numberOfIssues >= 10) {
say(":fire::fire: 大変!レビューが必要なチケットが制限数10を超えているよ! :firefighter::fire_engine:");
}
await say("レビューが必要なチケットだよ");
for (let i = 0; i < issueKeys.length; i++) {
const issuekey = issueKeys[i];
const url = "https://hogehoge/browse/".concat(issuekey);
await say(url);
}
await say("終わり!お疲れ様!");
});
}
const getToken = (): string => {
const id = process.env.EMAIL;
const api_token = process.env.JIRA_API_TOKEN;
const encodedToken = Buffer.from(id + ":" + api_token).toString("base64");
return encodedToken;
}
const getIssueKeys = async (token: string) => {
const BASE_URL = 'https://hogehoge/rest/api/2/';
// JIRAから担当者別のレビューステータスのチケットを取得するJQLをUTF-8でエンコード
const JQL = "search?jql=hogehoge";
const ISSUES_URL = BASE_URL + JQL;
const options = {
uri: ISSUES_URL,
headers: {
"Content-Type": 'application/json',
"Authorization": 'Basic ' + token
},
method: 'GET',
json: true
};
const request = require('request-promise');
const keys = await request(options).then((response: any) => {
return response["issues"].map( (issue: { key: string; }) => { return issue.key; });
}).catch((err: any) => {
console.log(err);
})
return keys;
}
梅ちゃんが「レビューが必要なチケット」を教えてくれるようになった
「猫って餃子を食べると大変なことになるんじゃね…?」と一瞬思ったのですが、概念としての猫なら大丈夫かなと思い直しました。餃子猫というキャラ特性を得た瞬間ですね。
また、レビューが必要なチケットが制限数を超えているかどうかもチェックしていて、超えている時は教えてくれます。
チームにいろんな問いかけをしてくれるようになった
うちのチームでは週次でふりかえりを実施しているのですが、優勝したことや楽しかったことや悲しかったことや学んだことについて雑談しています。この前は最近遊んでいるゲームの話で盛り上がりました。
で、「いい感じなことは再現したいし、いい感じじゃないことはうまくいくようにしたいよね」ということで、ふりかえりで出た話をもとに梅ちゃんに適当に問いを呟いてもらうことにしました。とりあえず、現状はこんな感じですが少しずつ変わっていくと思います。
力こそパワー!!!
そういえば、詳細設計レビューしてもらった?
チケット完了前にPdMと受け入れ条件確認した?
APIの統合テスト書いた?
あー、それチケット化しますか
そのサブタスク1日以内に終わりそう? 終わらなさそうなら分けてもいいかも?
ちょっと休憩しよ?
そのチケット、ペアプロの方が手戻り減りそう?
速さこそスピード!!!
デザインチェック依頼する前にセルフチェックした?
お腹が減ったにゃあ
チケット完了前にスマホで確認した?
そのリリース明日でもいいんじゃない?余裕持ってSTG確認しよ?
影響範囲が大きいチケットは単独でリリースしよ?
コミット前に差分を確認した?不要な記述含まれてない?
うちのチームではモブプロやペアプロを結構やってる方だと思うのですが、そういった同期的な取り組みであれば複数観点によるツッコミが入るんで、
対応が丁寧になってミスは減る感覚があります。
が、常にやってるわけではないので、一人の時とか対応が雑になったり、ミスったりするんですよね汗
なので、梅ちゃんが非同期で問いを投げかけてくれると、「あー、そういえばそうね。じゃあ、やろうか」という流れに繋がる機会が何度かありました。もちろん、うまくいかないこともあるんですけどね。また、その場でトリガーにならなくても、徐々に根付いていくというのもあるかなと思います(気がついた時にチケット作成するとか)
ちなみに非同期でbotがチームの言葉を話すという体験はRSGT2020でkyon_mmさんが発表されていた「チームの再定義 -進化論とアジャイル」を参考にしました。感謝!
まとめ
最初は概念だった梅ちゃんが徐々に実体を得て、チームの業務をサポートしてくれるようになったよという話でした。今後はGithubのAPIとか使って、さらに色々サポートできるようになってもらいたいと考えています。
この記事が気に入ったらサポートをしてみませんか?