$shibayu36->blog;

クラスター株式会社のソフトウェアエンジニアです。エンジニアリングや読書などについて書いています。

TypeScriptプロジェクトのテストとlintをGitHub Actionsで実行する

お試しでTypeScriptプロジェクトのテストやlintをGithub Actionsで実行してみた。

lintの設定

https://github.com/shibayu36/typescript-cli-project/pull/1

push時にはeslintが走り、PullRequestにはreviewdogがコメントしてくれる構成にした。この設定だけで勝手にcommit statusもいい感じに更新してくれるし、reviewdogがlintのエラーのところにコメントを付けてくれるので便利。

f:id:shiba_yu36:20200825093431p:plain f:id:shiba_yu36:20200825093336p:plain

テストの設定

https://github.com/shibayu36/typescript-cli-project/pull/2

strategy.matrixを使い、nodeのv12とv14の両方でテストをする設定を書いてみた。テストの結果はGithub Actionsのコンソールで確認できる。

f:id:shiba_yu36:20200825093714p:plain

感想

  • すぐに設定できて、最低限やりたいことは出来てよかった
  • 一方でテストレポートの出力のベストプラクティスがいまいち分からないなどの問題もあった。テストに関してはTravis CIなど他のツールを使ったほうが良いかもしれない
  • Github Releasesなど、GitHubの機能との連携をしたいジョブを実行するときは使いやすそう

PullRequestからチーム開発の生産性・健全性を測るCLIツールを書いてみた

最近、開発チームの生産性や健全性をどのように計測したら良いかについて興味を持っている。その中で「LeanとDevOpsの科学」の中に書いてあるようなデプロイの頻度・変更のリードタイム・MTTR・変更失敗率の4指標や、開発チームの生産性・健全性を客観的に知るためにリポジトリ履歴から機械的に可視化するツールを作った - Qiitaに興味を持った。

一方、それらの指標を考えてみた時、以下のような点について悩んでいた。

  • マイクロサービスなどで複数レポジトリとなり、さらにデプロイ手法がそれぞれ違う状況の場合、変更のリードタイム = コミット〜本番稼働までの時間を計測するのがなかなか難しい
  • コミットという単位だとかなり小さく、個々人のばらつきも大きすぎるように感じるので、もう少し良い単位はないのだろうか

このような悩みから、PullRequestの単位で集計することで、生産性や健全性をもう少し測りやすくなるのではないかと考え、集計ツールを作ってみた。

https://github.com/shibayu36/merged-pr-stat

やりたいこと

  • 特定期間にマージされたPullRequestの統計情報を集計したい
  • 複数レポジトリ横断で、かつ色んな絞り込み条件をかけて、PullRequestを集計したい
    • マイクロサービス対応や、botを取り除く・プロジェクトチームで切り分けるなど柔軟に集計したい
    • 集計のやり方を工夫すれば、ユーザーの価値に直結するPullRequestだけ集計できる状態にもしておきたい

統計情報としては、次のものを計測した。5 metrics Engineering Managers can extract from Pull Requests – SourceLevel50 shades of Lead Time. Measuring each part of the development process – SourceLevelも参考にした。

  • PullRequest数
    • チーム全体の、PullRequest数/day/developer を生産性や健全性の参考にしてみたい (d/d/d を意識)
    • 巨大PullRequestが悪という考え方に基づいてPullRequestを分割した場合、この指標が上がるのも良いと考えた
  • PullRequestのリードタイム = PullRequestの初コミット日時〜マージ日時
    • 変更のリードタイムは「コミット〜本番稼働」を計測しているが、それよりももう少し計測しやすさに重きをおいた
  • PullRequestのTime to Merge = PullRequest作成〜マージまでの時間
    • レビュー時間の参考値に使えそうなので計測してみた

ツールの使い方

インストール

npmでインストールできる。

npm install -g shibayu36/merged-pr-stat

集計の仕方

例えばvscodeとTypeScriptの2レポジトリで7月中にマージされたPullRequestを集計したいと思ったら次のコマンドを打つ。するとPullRequest数や、リードタイムの平均・中央値、Time to Mergeの平均・中央値を取得できる。

$ GITHUB_TOKEN=... merged-pr-stat --start=2020-07-01T00:00:00 --end=2020-07-30T23:59:59 --query="repo:microsoft/vscode repo:microsoft/TypeScript"
{
  "count": 258,
  "authorCount": 77,
  "additionsAverage": 107.89147286821705,
  "additionsMedian": 19,
  "deletionsAverage": 41.97286821705426,
  "deletionsMedian": 3,
  "leadTimeSecondsAverage": 578271,
  "leadTimeSecondsMedian": 58163,
  "timeToMergeSecondsAverage": 735697,
  "timeToMergeSecondsMedian": 82453
}

--queryオプションには Issue およびプルリクエストを検索する - GitHub Docs のクエリがすべて利用できる。そのため、例えば label:feature のようにラベルで絞り込んだり、 -author:app/dependabot でdependabotだけを取り除いたり、authorを並べてチームの特定プロジェクトに所属している人だけに絞り込むことも可能だ。

特定期間をn日ごとに集計する

上記コマンドだと、直近1年分を1週間ごとで集計したいとなった時にやりづらい。そこでそのようなことをするためのサンプルスクリプトも用意した。

例えばrepo:microsoft/vscodeとrepo:microsoft/TypeScript で、2020-01-01から1週間単位で集計したいなら次のコマンドを打つ。出力された内容をスプレッドシートに貼り付けるとグラフを作れる。

$ git clone https://github.com/shibayu36/merged-pr-stat.git
$ cd merged-pr-stat
$ npm install
$ export GITHUB_TOKEN=...; npx ts-node examples/make-stat-on-interval-days-basis.ts --start=2020-01-01T00:00:00 --end=2020-07-30T23:59:59 --interval-days=7 --query="repo:microsoft/vscode repo:microsoft/TypeScript"
startDate,endDate,count,authorCount,additionsAverage,additionsMedian,deletionsAverage,deletionsMedian,leadTimeSecondsAverage,leadTimeSecondsMedian,timeToMergeSecondsAverage,timeToMergeSecondsMedian
2020-01-01 00:00:00,2020-01-07 23:59:59,34,21,438.4117647058824,47.5,93.3529411764706,3.5,2411248,258766,2083335,235491
2020-01-08 00:00:00,2020-01-14 23:59:59,52,33,2142.5,74,1700.3076923076924,10,2264733,313925,2210338,246444
...

PR数の推移。黄色は1ヶ月の移動平均。開発チームの人数と営業日数が分からないのでPR/d/dは計測できないが、単純にPR数が安定していてすごい。 f:id:shiba_yu36:20200823134023p:plain

リードタイム(hour)の中央値の推移。first commitから1日ちょっとくらいでマージされている。 f:id:shiba_yu36:20200823134846p:plain

PullRequestの生ログを取得する

もしPullRequestの生ログを使い、spreadsheetなどで別に集計したいとなったら、logコマンドを使うと良い。JSONCSVで出力できる。

$ GITHUB_TOKEN=... merged-pr-stat log --start=2020-07-01T00:00:00 --end=2020-07-07T23:59:59 --query="repo:microsoft/vscode" --format csv
title,author,url,createdAt,mergedAt,additions,deletions,authoredDate,leadTimeSeconds,timeToMergeSeconds
Encoding euckr does not exist anymore (fix #101847),bpasero,https://github.com/microsoft/vscode/pull/101853,2020-07-07T12:09:03Z,2020-07-07T12:25:10Z,36,25,2020-07-07T12:03:23Z,1307,967
Fixes quick find symbol finder shows 'no matching results' after backspace,jeanp413,https://github.com/microsoft/vscode/pull/101844,2020-07-07T09:31:01Z,2020-07-07T11:20:42Z,11,7,2020-07-07T09:27:08Z,6814,6581
[Settings Editor] Add extra bottom padding for lists in settings,9at8,https://github.com/microsoft/vscode/pull/101812,2020-07-06T17:16:20Z,2020-07-06T18:45:35Z,4,2,2020-07-03T20:19:08Z,253587,5355
...

まとめ

今回はPullRequestからチーム開発の生産性・健全性を測るCLIツールを紹介してみた。今回取れる指標の推移をトラッキングすることで、開発チームに問題が起こっているかを、直感ではなくデータとして把握できるようになると良いなと思っている。

参考

現代のソフトウェア開発を学ぶために「正しいものを正しくつくる」を読んだ

最近はいかにエンジニアリングの立場でプロダクトを成長させられるかについて考えている。そこで、現代のソフトウェア開発やアジャイルについて学ぶため、同僚にオススメされた「正しいものを正しくつくる」を読んだ。

なぜ現代ソフトウェア開発は難しいのかから始まり、現代ソフトウェア開発の不確実性へ対処するためにアジャイルを利用するという流れになっていて非常にわかりやすかった。また「正しいものをつくる」ことと「正しくつくる」ことをうまく切り分けて説明してくれたので、自分の中で論点を整理しやすかった。

「正しくつくる」部分に関しては、これまで自分も注力してきたところであったので、かなり経験知を言語化できた。一方「正しいものをつくる」部分に関しては、まだ経験が足りず、漠然としか理解できなかったのは残念だ。ただ今後プロダクトオーナーとコミュニケーションをする上で、この漠然とした知識も役立ってくれるだろう。

この本の中で自分が印象に残ったところは以下の部分(数字はkindleのlocation番号)。

  • プロダクトづくりの全体像の図 79, 3592
    • 感想) MVP特定までの価値探索(正しいものを探す)、特定後のアジャイル開発(正しくつくる)が非常に分かりやすく、何回もこの図に立ち返りたい
  • 問題やリスクのしっぽを掴むためのファイブフィンガー 1060
    • 感想) スプリント中にやりきれそうかどうかをこれまでは自己主張してほしいと言っていたがうまくいかないことも多かった。しかしファイブフィンガーはその課題に対処できそう
  • スクラムマスターはスプリントレトロスペクティブがより良くなろうと前向きになれる場としてデザインする。プロセスやツールという観点で最適化しようとしても、個々人の活動の質が上向かなければプロダクトづくりは良くならない 1146
  • 品質について、国際規格では、6つの定義がある 1659
    • 機能性 = 目的を満たすために必要な機能の実装度合い
    • 信頼性 = 正常に動作し続ける度合い
    • 使用性 = わかりやすさ、使いやすさの度合い
    • 効率性 = 目的達成のために必要な時間や資源の度合い
    • 保守性 = メンテナンスにかかる労力の度合い
    • 移植性 = 別の環境に移行してそのまま動作する度合い
    • 感想) 品質ってなんだろう?と悩んでいたので勉強になった!品質を落とすというのは曖昧で難しいけれど、この6つの中でどれは落とせるかを考えるなら出来そう。
  • スプリント強度を高める戦術
    • 背骨駆動開発 2231
      • プロダクトの中心となる機能群を先に作り切る
      • 小規模精鋭でそのプロダクトの様々な指針となるように作る
      • 感想) この段階では少数精鋭にしようという指針が良い
    • 状況をクリーンに保つ5つの条件 = 1.受け入れ条件を定義している、2.ベロシティを計測し安定させている、3. 受け入れテストを実施している、4.ふりかえりを実施しカイゼンし続けている、5.実運用相当のデータが揃っている
      • 感想) スプリントがうまくいくためのやり方は経験で分かっていたけど、完全に言語化されて腹落ちできてありがたい
  • チームをうまく動かすために、小さくとも成果を認め、それを積み上げることから始めると良い。そうすることでチーム内の信頼感を醸成し、思考や行動、結果が徐々に変わっていく。最初の方ではスプリントでどれだけできなかったことが多くても、1つでも完了にできたプロダクトバックログアイテムがあればそれに注目する 2196
    • 感想) スプリントレビューでお通夜みたいな雰囲気になるのあるあるなので大切
  • 仮説キャンバス 3675
    • 感想) プロダクトのMVP検証の取り掛かりとして、リーンキャンバスより、もっと必要なものが追加されていそう。市場規模とかがあるのも良い
  • プロダクトバックログの詳細化への段階は3段階 4408
    • 第一段階. 機能仮説の段階。予算確保のための必要コストの概算見立てをする。過去の経験から各機能仮説ごとに大雑把に見立てたり、過去と相対的にどの程度になるかで見立てる
    • 第二段階. MVPを特定する段階。ユーザーストーリー形式で整える
    • 第三段階. ユーザーストーリーから開発チームメンバーで再度規模の見立てを行う。プラニングポーカーなど。規模を算出するためだけでなく、チームメンバーのプロダクトに対する理解を深めたりリスクの検出も行う
    • 感想) 段階を分けると、開発前にざっくりと見積もりをする目的と、開発中にプラニングポーカーなどでより詳細に見積もりし直す目的が分かる。

「エンジニアリングの立場でプロダクトを成長させられるか」という観点でもっと勉強をしていきたいので、次は「LeanとDevOpsの科学」を読んでいきたい。

読書メモ

### 第1章 なぜプロダクトづくりがうまくいかないのか
* この本のテーマ 19
    * アジャイルに作ることで直面する不確実性への適応。アジャイルに作るとは、作ることを通じて学びを得る活動
    * プロダクトとして「何を作るべきか」をどのようにして見定めるのか
    * 以上の問題を乗り越えた先
* プロダクトづくりの全体像の図 79, 3592 ※
    * MVP特定までの価値探索(正しいものを探す)、特定後のアジャイル開発(正しくつくる)が非常に分かりやすい図
* 今のプロダクト開発は、「どうあるべきか本当のところ誰にもわからないが、なんとかして形に仕立てていく」開発 212
    * 非常に不確実性の高いプロダクト作り
* プロダクト自体と、それを作る人達についての多様性が、プロダクトづくりの不確実性に大きく影響を与えている 247
    * プロダクトづくりの不確実性 = プロダクトの領域による多様性(SoR/SoE) x 作り手の多様性(役割・経験・働き方) 398
    * 多様な役割による相互理解の溝など。役割という境界をはさみすぎてしまう 349
* 「要件」という言葉には、人によって要求/要件/仕様といった別のものを指していることがある 407
    * 要求 = こうしたい、こうありたいという希望
    * 要件 = こうしたいという要求を実現するための条件
    * 仕様 = 要件を満たすための詳細な条件

### 第2章 プロダクトをアジャイルにつくる
* スクラムの経験主義を支えるコンセプトである透明性、検査、適応を推し進めるために、スクラムでは5つの価値基準を持つことを提案している。確約、勇気、集中、公開、尊敬 867
    * ミッションの達成にそれぞれが努めると約束する
    * 問題を見逃さずにチームとして向き合う勇気を持つこと
    * スプリントの活動に全員で集中すること
    * 自身が抱えている課題をオープンにし、お互いを尊敬する気持ちを持つこと
* スクラムチームを表現する言葉は「自己組織化」と「職能横断」 878
    * 自己組織化 = ミッション実現に向かうための選択を自分たちで決定し、行動できる度合い
    * 職能横断 = チームの外側に頼らず仕事を成し遂げられる編成
* スクラムチームのプロダクトオーナーとは、プロダクトの価値を高めることに責任を持つ 894
    * プロダクトバックログを利用して、プロダクトとして何を作るべきか明確にすることに最も責任を持つ
* 問題やリスクのしっぽを掴むためのファイブフィンガー 1060 ※
    * 5本の指を使って自分の意見を表明するプラクティス
    * 例) 5本なら自信を持ってスプリント中にやりきれる、1本なら既にやりきれる気がしていないと決めて、一斉に挙げる
        * 揃った結果を眺めてチームで話し合う
        * 全員が4~5本になったら大体大丈夫そう、1~2本ならプラニングを見直すとか
        * 本数にばらつきがあるときも注意
* スプリントレビューではプロダクトのお披露目を主目的に置いた儀式にしてはならない。あくまで成果をレビューし、次に何をするべきかを検討し、必要に応じて舵取りの調整を行う 1114
* スプリントレビューのアウトプットとは、レビューを経て変更が加えられたプロダクトバックログといえる 1133
* スクラムマスターはスプリントレトロスペクティブがより良くなろうと前向きになれる場としてデザインする 1146 ※
    * プロセスやツールという観点で最適化しようとしても、個々人の活動の質が上向かなければプロダクトづくりは良くならない
* ゴールデンサークル: 人に何か行動を促してもらうためには、まず目的(Why)を伝えることから初めて、次にその目的を実現する手段(How)、さらに具体的な行動や製品(What)を伝えるという流れのフレームワーク 1258
* アジャイルに作る = 少しずつ反復的に開発を進めることであり、そのプロダクトを必要とする人から必要なフィードバックを得ながら調整し続けられるプロダクトづくり 1313
* 早く形にすると、プロセスを一通しできるので、作るものやチームについての問題に早く気付ける 1330

### 不確実性への適応 - 正しく作る
* 「早く少しだけ形にする」だけでは適応できない問題がある。「暗黙的な期待を放置したままでは合意形成にならない」「不確実性への対処から得られる学びが新たな不確実性を生む」 1642
* 品質について、国際規格では、6つの定義がある 1659 ※
    * 機能性 = 目的を満たすために必要な機能の実装度合い
    * 信頼性 = 正常に動作し続ける度合い
    * 使用性 = わかりやすさ、使いやすさの度合い
    * 効率性 = 目的達成のために必要な時間や資源の度合い
    * 保守性 = メンテナンスにかかる労力の度合い
    * 移植性 = 別の環境に移行してそのまま動作する度合い
* 人の期待をマネージしながら不確実性に基づく学びに適応する術の全体像 1752 ※
    * ミッションは、期待をマネジメントする。インセプションデッキなど
        * なぜやるのかを定義し、チームが自律的に動けるように
    * 余白の戦略、余白で持って不確実性を受け止める
        * 調整の余白 = 広さでコミットし深さで調整する
            * 広さとはプロダクト要求の範囲、深さとは実現する機能の度合いのこと 1883
            * 松竹梅でどこまでやるかオプションを付けると変更を受け入れられる弾力性のあるプロダクトバックログになる 1939
        * 期間の余白 = プロジェクトに期間バッファを設ける
            * バッファはタスク単位でなくプロジェクトでまとめて取る。シビアに見積もり、割合でバッファを取る 2077
        * 受け入れの余白 = アイスボックスを設ける
            * 新しいタスクが出たが、相対的には優先度が低いので凍結しておくコーナー。余白が残っていたら話題に載せる 2114
    * 全体への共通理解を統べる作戦 = プロダクトづくりの状況をチームの共通理解とする活動
    * スプリント強度を高める戦術
        * 背骨駆動開発 2231
            * プロダクトの中心となる機能群を先に作り切る
            * 小規模精鋭でそのプロダクトの様々な指針となるように作る
        * 状況をクリーンに保つ5つの条件 = 1.受け入れ条件を定義している、2.ベロシティを計測し安定させている、3. 受け入れテストを実施している、4.ふりかえりを実施しカイゼンし続けている、5.実運用相当のデータが揃っている
* スプリントが残念な結果に終わってしまう要因のひとつに必要なコミュニケーションの不足がある 2150
    * 必要な情報が揃っていない、情報がチーム内で伝達されていない、逆にチームメンバーが必要な情報の獲得に動いていない、お互いの気づきや意志の表明が足りないなど
* 全体としては余白でもって不確実性を受け止めながら、目の前のスプリントは確実に遂行できるように仕切るという考え方をする 2181
* チームをうまく動かすために、小さくとも成果を認め、それを積み上げることから始めると良い。そうすることでチーム内の信頼感を醸成し、思考や行動、結果が徐々に変わっていく 2196 ※
    * 成功循環モデル
    * 小さく結果を積み上げ、それを徐々に大きくしていくイメージ
    * 最初の方ではスプリントでどれだけできなかったことが多くても、1津でも完了にできたプロダクトバックログアイテムがあればそれに注目する

### 第4章 アジャイル開発は2度失敗する
* プロダクトオーナーはプロダクトバックログの内容や並び順によって、プロダクトとして何を作るべきか、優先すべきかを表現する人物 2742
* プロダクトオーナーはなぜこのプロダクトを作るのかを決める 2742
    * ビジョンづくり = プロダクトを通じて世の中にどのような変化をもたらすか
    * ミッションづくり = これができなければ自分たちの存在意義が問われる使命
    * コンセプトづくり = 誰のどんな問題をどうやって解決するかをシンプルにまとめたもの 2797
* プロダクトオーナーは「プロダクトの世界観を実現するために何を備えるのか」という問いに応え続ける 2842
    * 要求は何か、インターフェースはどうあるべきか、ビジネスモデルはどうあるべきか
* プロダクトオーナーはプロダクトを形にしていくために必要な運用スキルと知識が求められる 2893
    * プロダクトがどうあるべきかの牽引のため -> 受け入れテストの実施とテスト結果の活用、ユーザーテストによるフィードバック取得と継続的な計測
    * チームとの協働のために -> プロダクトバックログの管理方法、コミュニケーション設計
    * プロジェクトを遂行するために -> プロジェクトマネジメント
    * 開発メンバーとの意思疎通のために -> ソフトウェア開発の基本的な知識
* アウトカム( = 実際の成果)に繋げるために、越境する 3127
    * 開発チームのミッションを「正しく作ること」、プロダクトオーナーのミッションを「正しいものを探すこと」と分断させず、ミッションは共通で「プロダクトを通じて実現したいことを形にする」とする
    * お互いが越境し、チームとして効果的に動いていくためには、行動指針や意思決定のための共通の「基準 = プロダクトとして何が正しいのか」が必要 3143

### 第5章 仮説検証型アジャイル開発
* 仮説には、想定ユーザーの課題に関するもの(課題仮説)と、どのソリューションが有効なのかというソリューション仮説のカテゴライズがある 3627
* 仮説キャンバス 3675 ※
    * プロダクトのMVP検証の取り掛かりとして、リーンキャンバスより、もっと必要なものが追加されていそう
* 検証キャンバス = 仮説を踏まえて何をどのように検証するのかプランをまとめられる 4154

### 第6章 ともに作る
* プロダクトバックログの詳細化への段階は3段階 4408 ※
    * 第一段階. 機能仮説の段階。予算確保のための必要コストの概算見立てをする。過去の経験から各機能仮説ごとに大雑把に見立てたり、過去と相対的にどの程度になるかで見立てる
    * 第二段階. MVPを特定する段階。ユーザーストリー形式で整える
    * 第三段階. ユーザーストーリーから開発チームメンバーで再度規模の見立てを行う。プラニングポーカーなど。規模を算出するためだけでなく、チームメンバーのプロダクトに対する理解を深めたりリスクの検出も行う
* 越境のためのコマンド 4756
    * 上上下下左右左右過去未来
    * 一段高く -> もっと高く -> 細部へ -> もっと細部へ -> 自分よりの関係者をひとまわり広く捉える -> 相手側の関係者 -> もっと自分よりを広く -> もっと相手側を広く -> 過去から捉える -> 時間軸を思いっきり伸ばす
* 「越境」という価値観で、目的のためなら手段を選ばないチームとなることで、不確実性に適応できる 4789 ※
    * 「自分たちは正しいものを正しくつくっているか?」と問い続け、方向も変えられるように 4910