Github ActionsにてPythonスクリプトの定期実行を運用しているのですが、運用していると「直前のステップの成否によって条件分岐させたうえ、成功した場合は値を次ステップへ受け渡したい」などといった処理をさせたい場面が出てきました。
本記事では、GitHub Actionsで次ステップ以降へ値を受け渡す方法と、Pythonスクリプトでその値をエクスポート・受け取る方法について解説します。
目次:
GitHub Actionsで次ステップ以降へ値を受け渡す方法2つ
GitHub Actionsのデフォルト環境変数には様々なものがありますが、他ステップで値を参照したいときに利用できる環境変数として、次の2つがあります。
- GITHUB_OUTPUT環境変数
- GITHUB_ENV環境変数
また、他ステップへ値を渡す環境変数ではないものの、APIキーなどを安全に格納する方法として利用する場面の多いSecrets環境変数について GitHub ActionsのSecrets変数でjsonファイルを利用する方法 (base64活用) の記事で紹介しています。
GITHUB_OUTPUT環境変数を利用したステップ間のデータ共有(原則)
原則として、ステップ間へのデータ共有にはGITHUB_OUTPUT環境変数を利用します。
yamlへの記法は以下のとおり。
steps:
# 環境変数へ値をセットするステップ
- name: export the value to env
id: export-step # 後で本stepsコンテキストから参照するため、idの設定が必要
# GITHUB_OUTPUT環境変数へ値をエクスポート
run: echo "output_value_number=12345678" >> "${GITHUB_OUTPUT}"
# GITHUB_OUTPUT環境変数から値を受け取るステップ
- name: print the value
# ステップ内の環境変数としてセット
env: # steps.ステップID.outputs.変数名
OUTPUT_VALUE: $ {{ steps.export-step.outputs.output_value_number }}
run: echo "{$OUTPUT_VALUE}"
GITHUB_ENV環境変数は異なる複数のステップで同じ値を参照する場合に効果的
もう一つ、GITHUB_ENV環境変数を利用する方法があります。
echo "{environment_variable_name}={value}" >> "$GITHUB_ENV"
Workflow commands for GitHub Actions - GitHub Docs: Setting an environment variable
以降続くすべてのステップから、通常どおり環境変数が参照可能となります。
GITHUB_ENV環境変数は前述のGITHUB_OUTPUT環境変数とは異なり、呼び出し側(受け取り側)ステップでステップIDの指定は不要です。
そのため、異なる複数のステップで同じ値を参照する場合は効果的。事実上のグローバル変数といえます。
しかし反面、ステップ間の依存関係が分かりづらくなり、バグの温床となりやすいというデメリットがあります。
また、GitHub Actions の「GITHUB_ENV」は、環境変数を設定したstepでは参照不可 という細かな制約もあるようです。
基本的にはGITHUB_OUTPUT環境変数を利用する方法が良いでしょう。
値をGITHUB_OUTPUT環境変数として書き出すPythonスクリプト
プログラムで実行した何らかの値をGITHUB_OUTPUT環境変数としてエクスポートするPythonスクリプトは以下のとおりです。
例: 実行した時刻をtimestamp変数としてGITHUB_OUTPUT環境変数へセット
以下では実行した時刻をtimestamp変数として、GITHUB_OUTPUT環境変数へ渡しています。
import datetime
from zoneinfo import ZoneInfo
import os
def generate_var(date: datetime.datetime, zone: ZoneInfo) -> str:
value = date.astimezone(zone).strftime("%Y-%m-%d_%H-%M")
# timestamp環境変数として、GITHUB_OUTPUTへセット: fh = File Handle
with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
print(f"timestamp={value}", file=fh)
return value
if __name__ == "__main__":
generate_var(datetime.datetime.now(), ZoneInfo("Asia/Tokyo"))
参考: How to pass output from a GitHub Action step that is in python? · community · Discussion #133693
受け取りステップで実行するPythonスクリプト
受け取り側ステップにおいてもPythonから値を参照、出力するようなスクリプトを書きました。
import os
print(os.environ['PYTHON_TIMESTAMP'])
set-outputは廃止
以前には下記のようなset-output記法を行う必要があったのですが、現在は廃止となりエラーまたは警告が出るようになったようです。
# Print special GitHub Actions syntax to set output
print(f"::set-output name=timestamp::{value}")
- GitHub Actions: Deprecating save-state and set-output commands - GitHub Changelog
- Github Actionsのset-outputは廃止されるってよ #GitHubActions - Qiita
ワークフローのyamlファイル全体
以上のPythonファイルを実行するワークフローとなるyamlファイル全体は以下のとおりです。
記述の際には GitHub Actionsのyamlファイルに必須で書くべき3項目 を反映させています。
name: Pass variable via github_output
on:
push:
workflow_dispatch:
defaults:
run:
shell: bash
jobs:
pass_var:
runs-on: ubuntu-latest
timeout-minutes: 3
steps:
- name: fetch repository
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: "pip"
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
# スクリプト内でGITHUB_OUTPUT環境変数をセットするステップ
- name: Run generate_timestamp.py
id: generate_var
run: |
python generate_timestamp.py
# GITHUB_OUTPUT環境変数を参照してステップ内環境変数とし、スクリプトから参照するステップ
- name: Set output as a variable and Run get_var.py
env:
PYTHON_TIMESTAMP: ${{ steps.generate_var.outputs.timestamp }}
run: python get_variable.py
実際の例: 直前のステップの成否によって条件分岐→成功した場合は値を次ステップへ受け渡し
最後に、実際のワークフローサンプルとして下記パターンのymlファイルを示します。
- Pythonスクリプトを実行。最後に生成した値をGITHUB_OUTPUT環境変数へ渡す
- 失敗したら失敗用のスクリプトを実行
- 成功したら成功用のスクリプトを実行
実際には、上記の2, 3はAPIを介して実行結果に応じた内容でメールを送信(Resendを利用)するスクリプトとしています。
成功・失敗の判定には、手前の処理(直前に実施されたステップ)の成否によって分岐が可能なステータスチェック関数を利用しています。
name: Schedule Execution with Condition
on:
schedule:
- cron: "0 0 1 * *"
workflow_dispatch:
defaults:
run:
shell: bash
jobs:
execute-with-condition:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Fetch Repository
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
# スクリプト内で値をresult=12345678としてGITHUB_OUTPUT環境変数へ渡すステップ
- name: Execute python script
id: execute_app
run: python app.py
# 手前のexecute_appステップが失敗した場合
- name: Execute script if failed
if: ${{ failure() }}
run: python script_failed.py
# execute_appステップが成功した場合
- name: Execute script if success
if: ${{ success() }}
env:
RESULT: ${{ steps.execute_app.outputs.result }}
run: python script_success.py
以上です。
この記事の気になる箇所を読み返す:
Category: インフラ・サーバー
Tags: Python