githubActionsでハマった_条件分岐

に公開1

タイトルの通り。
githubActionsの条件分岐処理でハマってしまったので、今後の備忘として。

結論、文字列として評価されるケースとそうでないケースがあるので、そこ間違えないようにしようねという話です。
検証はact version 0.2.76にて行いました。

前提

envに設定したbool値は文字列として保持されるようです。

env:
  is_target: true

本題

githubActionsのifステートメントでの話
OKな条件分岐

# GitHub Actions式での比較
if: env.is_target == 'true'     # OK 文字列同士の比較
if: ${{ fromJSON(env.is_target) == true }} # OK fromJSONによってBool値になるためブール値 vs ブール値

次にNGな条件分岐

if: env.is_target               # NG 文字列比較になってしまうので、env.is_targetがfalseの場合にも次の処理に進んでしまう
if: ${{ env.is_target }}        # NG 文字列比較になってしまうので、env.is_targetがfalseの場合にも次の処理に進んでしまう
if: env.is_target == true       # NG 文字列 vs ブール値となりenv.is_targetがtrueの場合に次の処理が実行されない
if: ${{ fromJSON(env.is_target) == 'true'}} # NG fromJSONによってBool値になるため、↑と同様にenv.is_targetがtrueの場合に次の処理が実行されない

次にrun内で使うif文(これがいわゆるbashのif。runs-onでubuntuを指定)での話
OKな条件分岐

run: |
  # OK 文字列比較を明示
  if [[ "${{ env.is_target }}" == "true" ]]; then
  
  # OK 最もシンプル(コマンドとして実行)
  if ${{ env.is_target }}; then

NGな条件分岐

run: |
  # NG 今回のやらかし。env.is_target == 'true'がFALSEになり[[ false ]]は文字列の"FALSE"として解釈され、結果TRUEになって処理が進んでしまった。
  if [[ "${{ env.is_target == 'true' }}" ]]; then

  # NG 文字列として解釈され、常に次の処理が実行される
  if [[ false ]]; then

Discussion

teshigawarateshigawara

改めて見直してふと疑問に思ったのでメモ。
詳しい人教えてください。
以下、検証して正常に動作することを確認しているが、これって実行すると[[]]の中に展開されるのって普通のBool値になるから常にtrueになるんじゃないの?ということで混乱しております。

  if [[ "${{ env.is_target }}" == "true" ]]; then

claude君に聞いてみた(いい時代になった)

比較演算の場合

bash[[ "true" == "false" ]]
 ↓ これは「比較演算」として処理される
 左辺: "true" (文字列)
 演算子: ==
 右辺: "false" (文字列)
 結果: false(文字列比較の結果)

単独評価の場合

bash[[ false ]]
 ↓ これは「文字列存在チェック」として処理される
 対象: "false" (文字列)
 結果: true(空でない文字列なので)

bashの[[ ]]の構文解析

比較演算子がある場合

bash[[ LEFT_OPERAND OPERATOR RIGHT_OPERAND ]]
LEFT_OPERAND と RIGHT_OPERAND を比較
結果は比較結果(true/false)

比較演算子がない場合

bash[[ EXPRESSION ]]
EXPRESSION を値として評価
空でなければ true、空なら false