この記事は、ただの集団 Advent Calendar 2018の17日目の記事です。
昨日は、takatorixさん(タカトリックス )の社内の検索技術勉強会ふりかえりでした。
きっかけ
我々のエンジニアチームでは、チーム全体の定量的な目標を決めています。
そこで、日次で数値の確認が必須だということになり、目標進捗可視化プロジェクトをしました。
エンジニア個人の評価が難しいという話はよく聞きますが、エンジニアチームとしての評価は数値化出来て、追って(改善して)ゆくのはとても大事なことだと思ったので、今回の題材に選びました
はじめに
-
この記事に含まれる事
- エンジニアチームの定量的な目標を運用していく方法
-
この記事に含まれない事
- エンジニアチームの目標の決め方
- 運用した結果(最近始めたため。効果測定は今後の記事で書くかもしれません。)
前提
チーム構成
- エンジニアチーム: 4チーム(内、1チームはインフラ担当)
- 1チーム: 4-7名
開発の進め方
- スクラム(※ほぼ全員がCSD研修受験済み)
用意するもの
- github
- 我々のサービスはマイクロサービスのため、リポジトリは大量です。
- Google Spreadsheet
- Google App Script(GAS)
チーム目標(一部)
- デプロイ頻度
- 1チームあたり、何回リリースしているか
- 集計方法: 直近の4スプリントの平均
- ただし、チーム数が変動しても割合に影響ないような集計方法
- 集計対象
- mergeされている、masterへのPullRequest
- 変更失敗率
- 「Bugfix リリース / 全リリース」の割合
- いわゆる、Hotfixの割合
- 集計方法: 直近の4スプリントの平均
- 集計対象
- mergeされていてbugラベルが付与されている、masterへのPullRequest
実際にやった事
大きく分けると
- データ抽出
- 集計
- ダッシュボード作成
- 自動化
の4つです。詳しく説明していきます。
1. データ抽出
こちらはGASから、githubのREST APIを叩く形で実現しました。
事前準備
-
MomentをGASで使えるように設定
- 日付の計算には、jsのライブラリのMomentを利用しています。(GASでMomentを使うやり方は各所で紹介されているので今回は省略します。:Bow:)
-
ログ出力用のspread sheetのシートを用意
-
ダッシュボード用のspread sheetのシートを用意
- シート名は
Dashboard
- シート名は
こちらほぼ実際のGASのコード。
必要な部分は、NOTEで説明を入れています。
function extractRowData() {
const prList = []
var githubAccessToken = PropertiesService.getScriptProperties().getProperty('GITHUB_ACCESS_TOKEN'); //NOTE: GASの環境変数に設定しておく
const options = {"headers" : {"Authorization": "token " + githubAccessToken }}
const repoNames = Array(
"リポジトリ1",
"リポジトリ2",
"リポジトリ3"
)
var lineNumber = 2 // NOTE: 生データとしてspreadSheetに吐きだす為の行番号。1行目はヘッダーなので、2行目から始める。
for(var repo = 0; repo < repoNames.length; repo++) {
var repoName = repoNames[repo]
var prResponse = UrlFetchApp.fetch('https://api.github.com/repos/オーガニゼーション名/' + repoName + '/pulls?state=closed&base=master', options) // NOTE: closeされている、かつmasterに対するPullRequestを取得
var prJsonData = JSON.parse(prResponse.getContentText())
var prs = prJsonData.map(function(d){
return {
prNum:d.number,
prMergedAt: Moment.moment(d.merged_at),
state: d.state,
labels: d.labels
}
}) // NOTE: 集計に必要な情報だけ抽出する。
for (var i = 0; i < prs.length; i++) {
var pullRequest = prs[i]
var commitResponse = UrlFetchApp.fetch('https://api.github.com/repos/オーガニゼーション名/' + repoName + '/pulls/' + pullRequest.prNum + '/commits', options)
var commitJsonData = JSON.parse(commitResponse.getContentText())
var author = commitJsonData.map(function(d){
return d.commit.committer.name
})
const countStart = Moment.moment("2019-08-01")
if(pullRequest.prMergedAt.year() !== 70 && pullRequest.prMergedAt.isAfter(countStart)) { // NOTE: closeされたprはmergeAtが1970年になるから除外する。もっと良い除外方法が絶対にある。
// NOTE: ここから下は、spread sheetに書き出す部分
// NOTE: 👇 merge日
writeSpreadSheet('A', lineNumber, pullRequest.prMergedAt.format("YYYY-MM-DD"), "rowData")
// NOTE: 👇 mergeした人
writeSpreadSheet('B', lineNumber, author, "rowData")
// NOTE: 👇 リポジトリ名
writeSpreadSheet('C', lineNumber, repoName, "rowData")
// NOTE: 👇 PullRequestURL(REST APIのresponseにPRのURLが含まれてないので、仕方なく文字列演算)
writeSpreadSheet('D', lineNumber, "https://github.com/オーガニゼーション名/" + repoName + "/pull/" + pullRequest.prNum, "rowData")
// NOTE: 👇 Option[ラベル]
writeSpreadSheet('E', lineNumber, pullRequest.labels, "rowData")
lineNumber++
}
}
}
// NOTE: :point_down: ダッシュボードの作成用に集計日を出力
writeSpreadSheet('A', 1, Moment.moment().format("YYYY-MM-DD"), "Dashboard")
}
//NOTE: スプレットシートに書き出す為の関数
function writeSpreadSheet(column, line, prInfo, sheetName) {
var sheet = SpreadsheetApp.getActive().getSheetByName(sheetName);
sheet.getRange(column + line).setValue(prInfo);
}
2. 集計
ここからは、エクセル芸人です。
spreadSheetのrowDataというシートには、データ抽出段階で抽出されたデータがあります。
このデータを元に、バンバン集計していきます。
事前準備
デプロイ頻度
変更失敗率
3. ダッシュボード作成
事前準備
- ログ出力用のspread sheetのシートを用意
- シート名は
Dashboad
- シート名は
- グラフと、その日の速報値を置けばOK
4. 自動化
データ抽出用の関数を自動で実行するように設定します。
GASを利用しているので、簡単にtriggerが設定できます
今回は、1日1回実行するように設定しました。
まとめ
指標を置くのはとても大事。
効果検証して、改善していくのもっと大事。
この指標をもって、改善していくのが楽しみ