ランナー (runs-on) を動的に指定する方法 [GitHub Actions]
概要
ランナー (runs-on
) を動的に指定する方法をいくつか紹介します。
GitHub ホストランナーの障害時はセルフホストランナーで走らせたり、CI の優先度を調整したりできます。
方法1: workflow_dispatch.inputs で指定
workflow_dispatch
の inputs
でランナーを指定します。
runs-on: ${{ github.event.inputs.runner }}
# or
runs-on: ${{ fromJSON(github.event.inputs.runner) }}
実例
GitHub ホストランナーは頻繁に障害が起きます。
障害対策の 1 つとして障害時だけセルフホストランナーを建てて使うことができます。
name: Deploy
on:
workflow_dispatch:
inputs:
runner:
description: Select runner
required: true
default: ubuntu-20.04
type: choice
options:
- ubuntu-20.04
- self-hosted
jobs:
deploy:
runs-on: ${{ github.event.inputs.runner }}
timeout-minutes: 5
steps:
- run: cat $GITHUB_EVENT_PATH
ラベルを複数指定することもできます。
options
は文字列しか受け付けないのと fromJSON()
関数を使用するので完全な JSON を指定する必要があります。
name: Deploy
on:
workflow_dispatch:
inputs:
runner:
description: Select runner
required: true
default: '"ubuntu-20.04"'
type: choice
options:
- '"ubuntu-20.04"'
- '[ "ubuntu-22.04" ]'
- '[ "self-hosted", "Linux" ]'
jobs:
deploy:
runs-on: ${{ fromJSON(github.event.inputs.runner) }}
timeout-minutes: 5
steps:
- run: cat $GITHUB_EVENT_PATH
方法2: イベントのペイロードで切り替え
イベントのペイロードやコンテキストの内容によって切り替えます。
runs-on: ${{ github.event.sender.login == 'my-bot' && 'low-priority' || 'self-hosted' }}
実例
セルフホストランナーで優先度の低い CI は指定のランナーで走らせます。
固定台数で運用している場合に BOT がトリガーした CI でランナーが埋まるのを防ぎたいなど。
追加のラベルなしのランナーと low-priority
ラベルの付いたランナーがあるものとします。
name: Test
on:
pull_request:
jobs:
test:
runs-on: >-
${{
github.event.sender.type == 'Bot'
&& fromJSON('[ "self-hosted", "low-priority" ]')
|| fromJSON('[ "self-hosted" ]')
}}
timeout-minutes: 5
steps:
- run: cat $GITHUB_EVENT_PATH
改行 (>-
) についてはこちらにまとめてあります。
YAML の仕様なので if
以外でも使えます。
方法3: ジョブを分ける
Ubuntu と Windows で動かす場合など steps
の内容が異なる場合はジョブから分けてしまった方が良いです。
jobs:
ubuntu:
if: contains(github.event.pull_request.labels.*.name, 'Windows') == false
runs-on: ubuntu-20.04
timeout-minutes: 5
steps:
- run: cat $GITHUB_EVENT_PATH
windows:
if: contains(github.event.pull_request.labels.*.name, 'Windows') == true
runs-on: windows-2022
timeout-minutes: 5
steps:
- run: cat $Env:GITHUB_EVENT_PATH
ジョブを分けた上で Reusable workflow や カスタムアクション を使ってジョブの中身を共通化することもできます。
余談
runs-on
を動的に指定するのは見かけたことがなかったのでこの記事を書いていたのですが、情報の確認のためにドキュメントを眺めていたら最近(今週?)追加されたサンプルページに似たようなコードが記載されていました😹
ドキュメントが充実していっているのはいいことですね。
JSON を配列にしつつ bool を暗黙的に int へキャストして配列のインデックスとして扱っているのでしょうか。
緩い比較を活用しているのだと思いますが分かりにくいのでおすすめはしません。
runs-on: ${{ fromJSON('["ubuntu-latest", "self-hosted"]')[github.repository == 'github/docs-internal'] }}
こちらの方が可読性が高いです。
runs-on: ${{ github.repository == 'github/docs-internal' && 'self-hosted' || 'ubuntu-latest' }}
Discussion