🐙

GitHub Actions でラベルを扱う

2023/11/20に公開

ラベルの取得

- id: labels
  shell: bash
  env:
    GH_REPO: ${{ github.repository }}
    GH_TOKEN: ${{ github.token }}
    PR_NUMBER: ${{ github.event.number }}
  run: |
    json=$(gh pr view "$PR_NUMBER" --json labels | jq -c '.labels|map(.name)')
    echo "json=$json" >> "$GITHUB_OUTPUT"
  • 構造化されたデータの方が後続で扱いやすく、また Actions の ${{ }} 式で利用しやすかったりするので、JSON 形式でアウトプットしている
    • 後続では ${{ steps.labels.outputs.json }} のようにアクセスする
  • GitHub CLI を利用しなくても ${{ fromJSON(github.event.pull_request.labels.*.name) }} で同様の JSON は取得可能、だが、プルリクを作成して job が実行されるまでの間にラベルをつけたり、job を再実行したりした際に最新のラベルが取得できないので、上記のように GitHub CLI を用いて都度、最新のラベルを取得するようにしている
    • pull-requests: read permission が必要

ちなみに Windows runner の場合、デフォルトは bash ではないので、shell: bash はいちおう書いておいた方が無難。

利用例:プルリクに指定のラベルが含まれるかの判定

- if: contains(fromJSON(steps.labels.outputs.json), 'help wanted')
  shell: bash
  run: |
    # do something..

利用例:ラベル名で何かの処理

- shell: bash
  env:
    LABELS: ${{ steps.labels.outputs.json }}
  run: |
    for i in $(seq 0 $(($(echo "$LABELS" | jq length) - 1)))
    do
      label=$(echo "$LABELS" | jq -r .[$i])
      # do something..
      echo "$label"
    done

シェルではなく JavaScript で扱う場合は次の通り。

- uses: actions/github-script@v6
  env:
    LABELS: ${{ steps.labels.outputs.json }}
  with:
    script: |
      const { LABELS } = process.env;
      const labels = JSON.parse(LABELS);
      labels.forEach(label => {
        // do something..
        console.log(label);
      });

ラベルの付与

条件はなんでもよいのだが、例えばプルリクに *.js ファイルが含まれる場合に frontend ラベルを付与するとした場合の例。

- uses: yumemi-inc/changed-files@v1
  id: changed
  with:
    patterns: '**/*.js'
- if: steps.changed.outputs.exists == 'true'
  shell: bash
  env:
    GH_REPO: ${{ github.repository }}
    GH_TOKEN: ${{ github.token }}
    PR_NUMBER: ${{ github.event.number }}
  run: |
    gh pr edit "$PR_NUMBER" --add-label 'frontend'
  • こちらも GitHub CLI を利用
    • pull-requests: writerepository-projects: read permission が必要

ラベルの削除にも対応する場合は次の通り。

- uses: yumemi-inc/changed-files@v1
  id: changed
  with:
    patterns: '**/*.js'
- env:
    GH_REPO: ${{ github.repository }}
    GH_TOKEN: ${{ github.token }}
    PR_NUMBER: ${{ github.event.number }}
    OPTION: ${{ steps.changed.outputs.exists == 'true' && '--add-label' || '--remove-label' }}
  run: |
    gh pr edit "$PR_NUMBER" "$OPTION" 'frontend'

Discussion