-
Notifications
You must be signed in to change notification settings - Fork 191
Description
A few have encountered this issue in the past too: https://github.com/orgs/community/discussions/25641
These end up being equivalent, which is unexpected behaviour at first glance.
if: |
${{ false }}
if: format('{0}\n', false)
It seems that when ${{ }}
is encountered in if:
, the value is treated as a string to interpolate, which is then used for the truthy check directly. No trimming, no recursive evaluation.
That means this is also a string:
if: true && ${{ false }}
# equiv: format('true && {0}', false)
Spaces also trigger this behaviour:
if: ' ${{ false }}'
# same as
if: format(' {0}', false)
As an experiment, these were also tried, to force the string 'false':
if: ${{ 'fa' }}${{ 'lse' }}
if: format('{0}{1}', 'fa', 'lse')
if: format('{0}', false)
if: ${{ false }}${{ '' }}
Which is not converted to the boolean false
, but is instead tested as the string 'false'
; again being truthy in the final evaluation.
While it'd be great to fully unravel expressions, I think there's a shortcut that can be taken:
If there is anything before or after the first ${{ }}
, it's a string that will always be truthy
Edgecase
Technically, placing ''
and null
next to each other will collapse to ''
, so is falsy.
But in reality, you should be using join(a.*.c, '')
or chaining ||
.
if: ${{ '' }}${{ null }}${{ null }}${{ '' }}${{ '' }}
# equiv: format('{0}{1}{2}{3}{4}', '', null, null, '', '')
# equiv: ''
- reference workflow where much of this was tested: https://github.com/antdking/actions-scratch-pad/actions/runs/4089246585/jobs/7051744589