Open5
GitHub Actions 小技
ピン留めされたアイテム
GitHub Actionsでちょっとしたアレを実現したい的なことを書き連ねる
三項演算子もどき
例: name:
などの出力を分岐したいとき
jobs:
job1:
name: ${{ fromJSON('["FALSE", "TRUE"]')[1 == 1] }}
解説
- GitHub Actions では配列やオブジェクトがリテラルで使えないので、JSON文字列から生成する
-
1 == 1
は真偽値だが、 GitHub Actions では1
になるので、配列にアクセスできる
変数にも使いたい
上の例だと環境変数を分岐したいときには使えないので...
jobs:
job1:
name: |
${{ env[fromJSON('[
"VERY_LONG_KEY_CASE_FALSE",
"VERY_LONG_KEY_CASE_TRUE"
]')[1 == 1]] }}
解説
- オブジェクトのプロパティはインデックス構文(
[0]
,[key]
など)と参照外し(.
アクセス)が使えるので、上の三項演算子もどきを使ってインデックス構文のキーを切り替える - 複数行はダメ元で試したものながら、問題なく動作したので記載
ステップを切り出す(Composite run steps actions)
ローカルかつプライベートリポジトリで切り出したいときの方法
(公開リポジトリならアクション用に別リポジトリを作ることが推奨されている)
マニュアル
.github/actions/composite-example/action.yml
公式のものを持ってきただけ
# via https://docs.github.com/en/actions/creating-actions/creating-a-composite-run-steps-action#creating-an-action-metadata-file
name: "Hello World"
description: "Greet someone"
inputs:
who-to-greet: # id of input
description: "Who to greet"
required: true
default: "World"
outputs:
random-number:
description: "Random number"
value: ${{ steps.random-number-generator.outputs.random-id }}
runs:
using: "composite"
steps:
- run: echo Hello ${{ inputs.who-to-greet }}.
shell: bash
- id: random-number-generator
run: echo "::set-output name=random-id::$(echo $RANDOM)"
shell: bash
# - run: ${{ github.action_path }}/goodbye.sh
# shell: bash
.github/workflows/composite-run.yml
name: "composite-example"
on:
workflow_dispatch:
jobs:
debug:
runs-on: "ubuntu-latest"
steps:
- uses: "actions/checkout@v2"
- name: "動く"
uses: "./.github/actions/composite-example"
- name: "動かない(Unable to resolve action `.github/actions@master`, repository not found)"
uses: ".github/actions/composite-example"
解説
-
uses:
はチェックアウトをした上で、./
をつけてパスを指定する。./
で始まっていないと、リポジトリを探しにいってしまい、 Not Found になる
matrix で実行する組み合わせを制御(妥協あり)
(matrix
を否定してそう...)
include
と exclude
だと人間の頭ではしんどい
.github/workflows/example.yml
name: "matrix_array"
on:
workflow_dispatch:
inputs:
target:
description: "sample input (1 | 2 | 3)"
required: true
default: ""
jobs:
debug_array:
runs-on: "ubuntu-latest"
strategy:
fail-fast: false
matrix:
entries:
- { key: 1, value: "value1" }
- { key: 2, value: "value2" }
- { key: 2, value: "value3" }
- { key: 3, value: "value4" }
- { key: 3, value: "value5" }
- { key: 3, value: "value6" }
name: ${{ fromJSON('["[Skipped] ", ""]')[matrix.entries.key == github.event.inputs.target] }}${{ matrix.entries.key }} => ${{ matrix.entries.value }}
env:
RUN: ${{ fromJSON('["", "1"]')[matrix.entries.key == github.event.inputs.target] }}
steps:
# env.RUN はこっちでも同じ. わかりやすい方で
# - if: "matrix.entries.key == github.event.inputs.target"
# name: "Set job as run"
# run: echo "RUN=1" >> $GITHUB_ENV
- if: "env.RUN"
run: "echo ${{ matrix.entries.value }}"
解説
-
matrix.entries
の配列を定義して、実行対象かどうかをmatrix.entries.key == github.event.inputs.target
で判定し、env.RUN
にセット -
env.RUN
の偽の値は空文字か未定義にする。false
や0
ではjobs.<job_id>.steps[*].if
で何故かtrue
になる。文字列で解釈されている? -
jobs.<job_id>.name
でmatrix
が使えるので割と自由が効く
妥協点
steps[*].if
で毎回 if: "env.RUN"
(もしくは if: "env.RUN && ..."
)と記述する必要がある。
ワークフローの解釈の順番の都合だと思っているが、 jobs.<job_id>.if
では matrix
が使えないので、ここで使えるとベスト
プライベートリポジトリのアクションを実行する
actions/checkout
を使ってプライベートリポジトリを取得してローカル実行する
name: "composite-private"
on:
workflow_dispatch:
jobs:
debug:
runs-on: "ubuntu-latest"
steps:
- uses: "actions/checkout@v2"
- uses: "actions/checkout@v2"
with:
repository: "mythrnr/actions-private-example"
token: "${{ secrets.SECRET_TOKEN }}"
path: "./.github/actions/private-example"
- uses: "./.github/actions/private-example"
解説
-
secrets.GITHUB_TOKEN
は別のリポジトリを取得できないのでsecrets.SECRET_TOKEN
を別途作成して使う