PJ内で何名かランダムに選びたいとき用のアクションが欲しくなったので作った。
Shell Scriptレベルなのでローカルでも動かせるが、みんなが使えるようにGitHub Actionsのyamlで書いた。
ユースケース:
- 司会を選ぶ
- レビュワーを選ぶ
- ランダム1 on 1
目次
つくったもの概要
作ったyamlが以下。
チーム名と選択数をInputとして指定することができる。
流れとしては、
- 対象メンバの件数取得
- shufコマンドを使って、ランダムに指定選択数分のindex値を取得
- 対象メンバリスト内からランダムindex値のデータを取得
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| name: Random sampling
on: workflow_dispatch: inputs: team: description: 'target team name: ALFA or BRAVO' required: true default: 'all' number: description: 'select number' required: true default: '1'
jobs: build: runs-on: ubuntu-latest
steps: - uses: actions/checkout@v2 - name: All if: ${{ github.event.inputs.team == 'all' }} env: NUMBER: ${{github.event.inputs.number}} run: | max=$(($(yq e '.member | length' list.yaml)-1)) target=$(seq 0 $max | shuf -n ${NUMBER}) target_comma=$(echo $target| sed "s/ /,/g") yq e ".member[${target_comma}]" list.yaml
- name: team if: ${{ github.event.inputs.team != 'all' }} env: TEAM_NAME: ${{github.event.inputs.team}} NUMBER: ${{github.event.inputs.number}} run: | max=$(($(yq e ".member[].team | select(.==\"""${TEAM_NAME}""\")" list.yaml | wc -l)-1)) target=$(seq 0 $max | shuf -n ${NUMBER}) target_comma=$(echo $target| sed "s/ /,/g") yq e . list.yaml -j | jq ".member[] | select(.team==\"""${TEAM_NAME}""\")" | jq -s ".[${target_comma}]"
|
前提としてカレントディレクトリに以下のような、list.yaml
ファイルが存在する想定。
各チームメンバの名前と所属チームを記載したリスト。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| member: - name: 太郎 team: ALFA - name: 次郎 team: ALFA - name: 三郎 team: ALFA - name: 四郎 team: ALFA - name: 花子 team: BRAVO - name: 菊子 team: BRAVO - name: 白子 team: BRAVO
|
詳細
対象メンバの件数取得
普通に全件取得なら件数はyq
コマンドでlength
指定すれば容易に取れる。
(欲しいのはindexの最大値なのでマイナス1している)
1
| max=$(($(yq e '.member | length' list.yaml)-1))
|
teamで絞る場合は、valueの値でselectすればOK
配列に戻して、lengthで取るのが面倒だったので、wcで行数としてカウントした。
1
| max=$(($(yq e ".member[].team | select(.==\"""${TEAM_NAME}""\")" list.yaml | wc -l)-1))
|
shufコマンドを使って、ランダムに指定選択数分のindexを取得
ランダム選択はshuf
コマンドを使う
-n
オプションで先頭から指定個数分取得できる。
1
| target=$(seq 0 $max | shuf -n ${NUMBER})
|
ちなみに、macの場合はgshuf
になる
インストールはbrew install coreutils
でOK
1 2 3 4 5 6 7 8 9 10 11
| $ seq 0 5 | gshuf 0 3 5 4 1 2 $ seq 0 5 | gshuf -n 3 1 0 2
|
対象メンバリスト内からランダムindex値のデータを取得
取得したindex値が複数の場合、スペース区切りで変数に入っているので、カンマ区切りにしておく。
1
| target_comma=$(echo $target| sed "s/ /,/g")
|
これはjqとかyqで、配列から複数index値指定で取得するときはカンマ区切りで指定するためこの変換を挟む。
全件取得ならyqでそのままindex値をカンマ区切り指定で取得すればOK
1
| yq e ".member[${target_comma}]" list.yaml
|
team名で絞るなら、select条件を挟む必要がある。ただしそれをすると配列情報が失われて、index値で取得できなくなる。
1 2 3 4 5 6 7 8 9
| $ yq e '.member[] | select(.team=="ALFA")' list.yaml name: 太郎 team: ALFA name: 次郎 team: ALFA name: 三郎 team: ALFA name: 四郎 team: ALFA
|
なので、一旦jsonにしてからjq
でフィルタ & 配列に戻した上で取得する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| $ yq e . list.yaml -j | jq '.member[] | select(.team=="ALFA")' { "name": "太郎", "team": "ALFA" } { "name": "次郎", "team": "ALFA" } { "name": "三郎", "team": "ALFA" } { "name": "四郎", "team": "ALFA" }
|
jq
の-s
オプションで配列にすることができる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| $ yq e . list.yaml -j | jq '.member[] | select(.team=="ALFA")' | jq -s [ { "name": "太郎", "team": "ALFA" }, { "name": "次郎", "team": "ALFA" }, { "name": "三郎", "team": "ALFA" }, { "name": "四郎", "team": "ALFA" } ]
|
参考
おわりに
GUI上で結果を見ることはできるが、最後に通知とかを入れれば完璧。
list.yamlは、GitHubのTeamから情報とってきて対象リストを用意する感じでもいい気がする。