【Github】Github Actions ~ runs-onを動的変更することを考える ~

■ はじめに

Self-hosted runner が各環境(e.g. dev/stage/prod)にあり
動的に変更したいってことを考える。

なお、以下のサイトが参考になった。

https://zenn.dev/snowcait/articles/56fad93b7dc95e

目次

【1】案1:ファイルを分けて管理する
 1)デメリット
【2】案2:workflow_dispatch.inputs で指定
 1)デメリット
 2)サンプル
【3】案3:条件分岐(真or偽)で切り替える
 1)デメリット
 2)サンプル
 3)補足:3通り以上になった場合
【4】案4:Reusable Workflows を利用する
 1)デメリット
 2)サンプル

【1】案1:ファイルを分けて管理する

* 例えば「dev.workflow.yml」「prod.workflow.yml」って
 感じで分ける

1)デメリット

[1] ファイルが増える
[2] 同じ処理を別々のファイルに書くためメンテナンス性が下がる

【2】案2:workflow_dispatch.inputs で指定

構文

runs-on: ${{ github.event.inputs.runner }}
# or
runs-on: ${{ fromJSON(github.event.inputs.runner) }}

1)デメリット

* 手動でデプロイする運用ならいいが、
 それ以外(自動化)は不可

2)サンプル

name: DemoWorkflow1

on:
  workflow_dispatch:
    inputs:
      env:
        description: 'Enviroment'
        required: true
        default: 'dev'
        type: choice
        options:
        - dev
        - stage
        - prod
      demoInputValue:
        description: 'Sample input'
        required: true
        type: string
jobs:
  job1:
    runs-on: ubuntu-latest
    env:
      ENV: ${{ inputs.env }}
      DEMO_INPUT_VALUE: ${{ inputs.demoInputValue }}
    steps:
      - run: |
          echo "ENV: $ENV"
          echo "DEMO_INPUT_VALUE: $DEMO_INPUT_VALUE"

【3】案3:条件分岐(真or偽)で切り替える

https://stackoverflow.com/questions/73241812/how-to-dynamically-assign-the-runs-on-value-in-the-github-actions

構文

    runs-on: >-
      ${{
        【条件】
          && 【条件が真の場合】
          || 【条件が偽の場合】
      }}

1)デメリット

* 条件が増えると可読性が下がる

2)サンプル

例1:ブランチで切換

name: demo for multiple runners

on:
  push:
    branches:
      - dev
      - prod

jobs:
  demo-job1:
    # if affected branch is 'demo' then runs on 'ubuntu-latest' else self-hosted...
    runs-on: >-
      ${{
        github.ref_name == 'dev'
          && fromJSON('[ "ubuntu-latest", "development" ]')
          || fromJSON('["self-hosted", "production" ]')
      }}
    steps:
      - name: Demo sample
        run: echo "Hello, world!!"

3)補足:3通り以上になった場合

* ネストも可能っぽい
 => ただ、可読性が悪くなる

構文

    runs-on: >-
      ${{
        【条件1】
          && 【条件1が真の場合】
          || (【条件2】 && 【条件1が偽で、条件2が真の場合】 || 【それ以外】)
      }}

例1:3通り

name: StartA

on:
  push:

jobs:
  test:
    runs-on: >-
      ${{
        github.ref_name == 'prod'
          && fromJSON('[ "ubuntu-latest" ]')
          || (github.ref_name == 'stage' && fromJSON('["ubuntu-24.04" ]')
          || fromJSON('["ubuntu-20.04" ]'))
      }}
    steps:
      - name: test
        run: echo "Hi!!"

【4】案4:Reusable Workflows を利用する

Reusable Workflows の引数に設定する runs-on の値を
当たすようにする方法。(まずは、以下のサンプルをみた方がいいかも)
 => Reusable Workflowsについては、以下の関連記事を参照のこと

Github Actions ~ workflow_run / workflow_call ~
https://dk521123.hatenablog.com/entry/2024/02/14/232546

1)デメリット

* はじめに、Reusable Workflows に渡す引数を決めるために
 runs-onを固定しなくてはならない

2)サンプル

.github/workflows/start.yml

name: StartDemo

on:
  push:

jobs:
  init:
    # ★デメリット:まずは固定する必要がある
    runs-on: "ubuntu-latest"
    steps:
      # ★ここで値を決める
      - name: set for dev
        if: github.ref_name == 'develop'
        run: |
          value="ubuntu-24.04"
          echo "GITHUB_RUNS_ON=${value}" >> $GITHUB_ENV
      - name: set for stage
        if: github.ref_name == 'stage'
        run: |
          value="ubuntu-22.04"
          echo "GITHUB_RUNS_ON=${value}" >> $GITHUB_ENV
      - name: set for prod
        if: github.ref_name == 'prod'
        run: |
          value="ubuntu-latest"
          echo "GITHUB_RUNS_ON=${value}" >> $GITHUB_ENV
      # ★ここで、最終的な値を outputs に設定する
      - name: set value
        id: set-value
        run: |
          echo "ref_name = ${{ github.ref_name }}"
          echo "GITHUB_RUNS_ON = ${{ env.GITHUB_RUNS_ON }}"
          echo "github_runs_on=${{ env.GITHUB_RUNS_ON }}" >> $GITHUB_OUTPUT
    outputs:
      github_runs_on: ${{ steps.set-value.outputs.github_runs_on }}
  call_demo_workflow:
    needs: init
    uses: ./.github/workflows/reusable.yml
    with:
      # ★ここで、runs-onの値を渡す
      runs_on: ${{ needs.init.outputs.github_runs_on }}

.github/workflows/reusable.yml

name: reusable

on:
  workflow_call:
    inputs:
      # ★引数としてもらってくる
      runs_on:
        description: runs on
        default: ubuntu-latest
        type: string

jobs:
  greeting:
    # ★引数でもらってきた値をそのまま設定する
    runs-on: ${{ inputs.runs_on }}
    steps:
      - id: message
        run: |
          echo "Hello world..."

関連記事

Github ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2019/07/18/234652
Github Actions ~ 基礎知識編 ~
https://dk521123.hatenablog.com/entry/2021/11/04/142835
Github Actions ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2022/06/16/151443
Github Actions ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2023/12/22/195715
Github Actions ~ workflow_run / workflow_call ~
https://dk521123.hatenablog.com/entry/2024/02/14/232546
Github Actions ~ if ~
https://dk521123.hatenablog.com/entry/2024/03/11/000000
Github Actions ~ Self-hosted runners / 入門編 ~
https://dk521123.hatenablog.com/entry/2023/12/18/204119
Github Actions ~ Self-hosted runners / あれこれ編 ~
https://dk521123.hatenablog.com/entry/2024/02/07/002736
Amazon S3AWS CLI
https://dk521123.hatenablog.com/entry/2017/04/01/235355