Wantedlyで推薦基盤の整備をしている一條(GitHub: @rerost, Twitter: @hazumirr)です。趣味は小さいツールを作って自分の仕事の効率を上げることです。
今回は1年半くらい前に趣味で作成し社内でも運用しているrerost/issue-creatorというissueを自動生成するツールについて説明したいと思います。
問題意識
Wantedly社内では社員全員がGitHubのissue上で非同期コミュニケーションを行なっています。
その中でもミーティングではアジェンダの共有であったり、議事録やNext Actionを残しておく場として活用している場合があります。
このミーティングは単発的なものもありますが多くが定期的に行われるものです。issueはミーティングごとに作成されるため、場合にもよりますが毎週行われるミーティングではissueも毎週作る必要があります。
この作業は人手で行われており、非常に面倒なものです。記憶を頼りに書くと次のようなフローになります。
- 前のissueから内容をコピペする
- 日付・前のissueへのリンクを書き直す
- issueを作成する
- それぞれのミーティング用のラベルがあるのでそれを指定する
という流れです。
これを行うのは忘れやすく、また非常に面倒です。
おそらく同様のツールはあるとは思いますが、探したところフィットするものが見つけられなったのと、小さいツールなためメンテ可能と判断し、自分で作ることにしました。
解決策
二度と定期的なissueを人の手で作りたくなかったので次の機能を持つツールを作ることにしました。
- issue用のテンプレートを用意し、それを使いissueを作成する(例: issue-creator create <template issueへのURL>)
- 上の機能を定期的に実行するためのマニフェストファイルを吐く(例: issue-creator schedule render '<CronTabでの時刻>' <template issueへのURL>)
template issueは次のようなものになります https://github.com/rerost/issue-creator/issues/1 。
例: テンプレートissueのタイトル
[{{.CurrentTime.Format "01/02/2006"}}-{{AddDateAndFormat "01/02/2006" 7 }}] Sample
例: テンプレートissueの本文
issue-creator
Create new issue from this issue
```
issue-creator create https://github.com/rerost/issue-creator/issues/1
```
Create new issue from this issue by every monday
```
issue-creator schedule render '0 0 * * 1' https://github.com/rerost/issue-creator/issues/1
```
last issue: {{.LastIssue.URL}}
「2」については利用者側が次のようなテンプレートを用意すると、それに従いマニフェストファイルなどを吐き出すようになっています。
例ではkubernetesのCronJob用のマニフェストを吐くようにしています。
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: {{ .Name | replace "_" "-" | lower}}
namespace: <定期実行するnamespace>
labels:
name: {{ .Name | replace "_" "-" | lower}}
app: {{ .Name | replace "_" "-" | lower}}
role: job
spec:
schedule: "{{ .Schedule }}"
jobTemplate:
metadata:
name: {{ .Name | replace "_" "-" | lower}}
labels:
name: {{ .Name | replace "_" "-" | lower}}
app: {{ .Name | replace "_" "-" | lower}}
role: job
spec:
backoffLimit: 0
template:
metadata:
name: {{ .Name | replace "_" "-" | lower}}
labels:
name: {{ .Name | replace "_" "-" | lower}}
app: {{ .Name | replace "_" "-" | lower}}
role: job
spec:
restartPolicy: Never
containers:
- name: job
image: <issue-creatorがインストールされているイメージ>
imagePullPolicy: Always
command: [{{- range $index, $var := .Commands}}{{- if ne $index 0}}, {{- end}}"{{$var}}"{{- end}}]
デザイン的な話
基本的にこのフローを自動化するための問題点はいくつかありました。
- 自動生成するために必要な値が多い(例: issueを作成するレポジトリ、 ミーティング用のラベル、テンプレート)
- どこまで社内の事情を入れるべきかkubernetesのCronJobを使うのは適切か。またCronJobを使うのであれば社内のCronJobのベストプラクティスをどこまで入れるべきか
自動生成するために必要な値が多い
これだと設定が面倒になり、更にtemplate fileもどこかいておく必要があります。
これは避けたかったので、GitHub上にTemplate用のIssueを作成することで解決されるようにしています(これは自分のアイディアではなく、@Altech さんのアイディア)。自動生成するために必要な値が多い
これについては、issue-creatorに伝える必要のある情報がかなり増えるのが問題でした。例えばこれらを愚直にissue-creatorの引数にすると次のようになります。
例: issue-creator <repo> <label> <template file path>
どこまで社内の事情を入れるべきか
あまり社内の事情をツール上に入れてしまうと、他社で使おうとした際に使えなくなり非常に困るのでできるだけ社内の事情は入れたくなかったです。
そこであくまで、社内の事情はテンプレートに閉じるようにし、それを差し込めるようにしておくに留めることにしました。
これにより、テンプレートはどこかに行ってしまいましたが
のように、GitHub Actions上でもissueが自動作成できるようにしています。
まとめ
ツールとしてはシンプルなものになっていますが、実際これにより人手でissueを定期的に作成している人はエンジニアの中ではほとんど見かけなくなりました。
また、このツールは元々エンジニア向けのツールとして作成していましたが、最近社内のビジネスチームでも導入され、徐々に広まっていっています。
こういった小さい問題やもっと大きなサービスの問題を解決したい人はぜひ話を聞きに来てください。