2022/10/11 この記事で紹介している set-output
は廃止(deprecated
)されることが決定し、近々使えなくなることがアナウンスされました。
本来、set-output
は「アクション毎の環境変数」を保持し、どのアクションが設定したのか明確にするためのものでした。しかし、ユーザーが知らない間にアクション間で意図しない値をやりとりされる可能性もあったことから、GITHUB_OUTPUT
に変数定義を追記する形に統一するそうです。
- name: Save state
run: echo "::save-state name={name}::{value}"
- name: Set output
run: echo "::set-output name={name}::{value}"
- name: Save state
run: echo "{name}={value}" >> $GITHUB_STATE
- name: Set output
run: echo "{name}={value}" >> $GITHUB_OUTPUT
run
内でグローバル変数をセットして他の run
で使いまわしたい。
GitHub Actions の Workflow で、
env
ではなく、異なるrun
ステップ間で変数を共有したい。
name: Sample Workflow
on:
pull_request:
jobs:
sample_job:
runs-on: ubuntu-latest
steps:
- name: Step1
run: |
FOO='bar'
echo "The FOO is ${FOO}"
: # 結果: The FOO is bar
- name: Step2
run: |
echo "The FOO is ${FOO}"
: # 結果: The FOO is
: # $FOO は引き継がれない
TL; DR (今北産業)
-
別ステップへの変数渡しには大きく 2 種類がある。
- ワークフロー全体の「環境変数」経由:
-
GITHUB_ENV
に変数を追加セット(追記)する
-
- 各々のステップの「公開変数」経由:
-
::set-output
でセットされた変数
-
- ワークフロー全体の「環境変数」経由:
-
ワークフロー全体の「環境変数」渡しの場合:
-
GITHUB_ENV
に追記する。- Set:
run: echo "<name>=<value>" >> $GITHUB_ENV
- Get:
${{ env.<name> }}
- Set:
- 一番楽。
- 後日、汎用化する可能性が「ない」場合に使う。他と変数名がバッティング(重複)する可能性があるため。
アクション化やコピペピピックな使い方など、汎用的に利用する可能性がある場合は、env
への書き込みは推奨されない。どのアクションで設定された値か、ユーザがトレースしにくくなるため。その場合、env
値は参照のみに限定して、次項の「ステップのグローバル変数」を使う。
- 後日、汎用化する可能性が「ない」場合に使う。他と変数名がバッティング(重複)する可能性があるため。
-
-
各々のステップの「公開変数」渡しの場合:
- 一番安全(変数名がバッティングしないため再利用性が高い)
-
run
で::set-output
を使う。- ステップ内で
id
を宣言する。(ステップ ID の設定) - 同ステップの
run
内で「::set-output
」と「変数」をecho
して値を設定する。 - 他のステップで
id
を参照すると同じ値が使える。
- ステップ内で
idの構文id: <ステップ ID>
set-outputの構文(パラメーター)::set-output name=<変数名>::<値>
呼び出し時の構文${{ steps.[設定した時点のステップID].outputs.[設定した変数名] }}
設定例(変数MY_VALUEに"fuga"がセットされる。ステップIDは"hoge")- name: Step1 id: hoge run: echo '::set-output name=MY_VALUE::fuga'
呼び出し例(ステップID"hoge"の変数MY_VALUEを取得。ステップのnameが違うことに注目)- name: Step2 # $value1 には 'fuga' が入る run: value1=${{ steps.hoge.outputs.MY_VALUE }}
使用例... - name: Step1 Set FOO run: | hoge='bar' echo "::set-output name=FOO::${hoge}" id: step-foo - name: Step2 Get FOO # 結果: The FOO is bar run: echo 'The FOO is' ${{ steps.step-foo.outputs.FOO }} ...
TS; DR (RUN
の変数を理解するまでのコマケーこと)
Workflow の run
ステップで定義された変数は、たとえ export
しても続く他の run
ステップでは使えません。Docker の RUN
ディレクティブ(指示子)と似た動きをします。
確かに、env
を使えば環境変数として定義できます。つまり、どの run
ステップでも使える変数を設定できます。
name: Sample Workflow
on:
pull_request:
env:
HOGE_FUGA: Piyo
jobs:
sample_job:
runs-on: ubuntu-latest
env:
FOO_BAR: Buzz
steps:
- name: Step1
run: |
echo "The HOGE is ${{ env.HOGE_FUGA }}"
: # Output: The HOGE is Piyo
- name: Step2
run: |
echo "The FOO is ${{ env.FOO_BAR }}"
: # Output: The FOO is Buzz
しかし、このパターンで env
文を使う場合、あらかじめわかっている値しか代入できません。例えば「ステップの中で日付をセットしたい」といったことができません。
実は、この env
文は、環境変数の GITHUB_ENV
に追記する役割があります。
GITHUB_ENV
は「シェル配列」となっており、1 行 1 変数定義で構成されています。
そのため、以下の様に変数定義を改行付きで GITHUB_ENV
に(>>
で)追加すると、各ステップで取得した情報をセットして利用できます。
name: Sample Workflow
on:
pull_request:
jobs:
sample_job:
runs-on: ubuntu-latest
steps:
- name: Step1
run: |
echo "HOGE_FUGA=Piyo" >> $GITHUB_ENV
: # 改行付き echo であることに注目
- name: Step2
run: |
echo "The HOGE is ${{ env.HOGE_FUGA }}"
: # Output: The HOGE is Piyo
- 参考文献:
- コメント
- Setting an environment variable | Actions | Docs @ GitHub
通常は、これが一番楽な設定です。
しかし、どのステップでも書き換えることができるため、逆に言えば「どのステップで追加・編集・削除されたか」も不透明になります。
そのワークフローを見れば一目瞭然なのですが、ワークフローを同じリポジトリ内の別のワークフローで再利用する場合や、アクションとして公開する場合に、追跡するのが大変になります。
「特定のステップで作成された変数が使いたい」と調べたところ、下記のように公式ドキュメントに記載がありました。
You can use the
set-output
command in your workflow to set the same value:sample.yaml- name: Set selected color run: echo '::set-output name=SELECTED_COLOR::green' id: random-color-generator - name: Get color run: echo 'The selected color is' ${steps.random-color-generator.outputs.SELECTED_COLOR}
( Using workflow commands to access toolkit functions | Workflow commands for GitHub Actions @ GitHub Docs より)
【筆者訳】
run
ステップ内でset-output
コマンドを使うと、同じ値を他のステップでも使えるようになります。sample.yaml- name: Set Foo run: | hoge='bar' echo "::set-output name=FOO::${hoge}" id: step-foo - name: Get Foo # 結果: The FOO is bar run: echo 'The FOO is' ${{ steps.step-foo.outputs.FOO }}
※ 筆者注) 上記の訳の YAML はわかりやすいように変更、および原文の YAML の typo を修正しています。
実は、この原文には typo があるようで ${steps.random....COLOR}
では動かず、 ${{ steps.random....COLOR }}
と二重の ${{ ... }}
(カギ括弧)で囲う必要があります。
GitHub Actions で実行した日付を取得する
echo
+ ::set-output key=value::
の仕組みを応用すると日付も取得できます。イメージ作成やビルドなどには便利ではないでしょうか。
- name: Get current date (YYMMDD)
id: date
run: echo "::set-output name=today::$(date +'%Y%m%d')"
...
- name: Build and push Docker image
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: |
keinos/helloworld:latest
build-args: |
TAG_BUILD=Build: ${{ steps.date.outputs.today }})
参考文献
- Support global environment variables のコメント | GitHub Actions @ GitHub Community
- Workflow commands for GitHub Actions @ GitHub Docs