<p>This is because <code>${{ }}</code> <a href="https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables#using-the-env-context-to-access-environment-variable-values" rel="nofollow noreferrer">creates a GitHub context</a>. And from the notes in the documentation</p>
<blockquote>
<p>Contexts are usually denoted using the dollar sign and curly braces, as ${{ context.property }}. In an if conditional, the ${{ and }} are optional, <strong>but if you use them they must enclose the entire comparison statement, as shown above.</strong></p>
</blockquote>
<p>So the right answer here is not to use Contexts...</p>
<pre class="lang-yaml prettyprint-override"><code>foo:
  runs-on: ubuntu-latest
  env:
    mytrue: 1
  steps:
    - name: Conditional Test
      if: env.mytrue == 0
      run: |
        exit 1;
</code></pre>
<h2>Explanation</h2>
<p>What you're seeing is because otherwise under the hood the Context executes in a <code>.format()</code></p>
<pre><code>format('{0} == 0', env.mytrue))
</code></pre>
<p>Which evaluates to a string..</p>
<pre><code>##[debug]....Evaluating String:
##[debug]....=&gt; '{0} == 0'
</code></pre>
<p>The string '1 == 0' is true in Bash..</p>
<pre><code>bash -c 'if [ &quot;1 == 0&quot; ]; then echo TRUE; fi;'
</code></pre>
<p>And the implementation depends on that string being reduced to &quot;0&quot; or &quot;1&quot;. If you instead use <code>${{env.mytrue == 0}}</code> it will evaluate as such.</p>
<pre><code>##[debug]Evaluating condition for step: 'Conditional Test'
##[debug]Evaluating: (success() &amp;&amp; (env.mytrue == 0))
##[debug]Evaluating And:
##[debug]..Evaluating success:
##[debug]..=&gt; true
##[debug]..Evaluating Equal:
##[debug]....Evaluating Index:
##[debug]......Evaluating env:
##[debug]......=&gt; Object
##[debug]......Evaluating String:
##[debug]......=&gt; 'mytrue'
##[debug]....=&gt; '1'
##[debug]....Evaluating Number:
##[debug]....=&gt; 0
##[debug]..=&gt; false
##[debug]=&gt; false
##[debug]Expanded: (true &amp;&amp; ('1' == 0))
##[debug]Result: false
</code></pre>
<p>You'll see now there is no format, and you have this</p>
<pre><code>##[debug]..Evaluating success:
##[debug]..=&gt; true
##[debug]..Evaluating Equal:
</code></pre>

CC BY-SA 4.0
2024-12-03T18:55:39.053Z
2024-12-03T18:55:39.053Z
Evan Carroll
<p>I have the following job ...</p>
<pre class="lang-yaml prettyprint-override"><code>foo:
  runs-on: ubuntu-latest
  env:
    mytrue: 1
  steps:
    - name: Conditional Test
      if: ${{env.mytrue}} == 0
      run: |
        exit 1;
</code></pre>
<p><a href="https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/troubleshooting-workflows/enabling-debug-logging" rel="nofollow noreferrer">When I have DEBUG logging on</a>, I can even see this evaluated as false..</p>
<pre><code>##[debug]Evaluating condition for step: 'Conditional Test'
##[debug]Evaluating: (success() &amp;&amp; format('{0} == 0', env.mytrue))
##[debug]Evaluating And:
##[debug]..Evaluating success:
##[debug]..=&gt; true
##[debug]..Evaluating format:
##[debug]....Evaluating String:
##[debug]....=&gt; '{0} == 0'
##[debug]....Evaluating Index:
##[debug]......Evaluating env:
##[debug]......=&gt; Object
##[debug]......Evaluating String:
##[debug]......=&gt; 'mytrue'
##[debug]....=&gt; '1'
##[debug]..=&gt; '1 == 0'
##[debug]=&gt; '1 == 0'
##[debug]Expanded: (true &amp;&amp; '1 == 0')
##[debug]Result: '1 == 0'
##[debug]Starting: Conditional Test
##[debug]Loading inputs
##[debug]Loading env
Run exit 1;
</code></pre>
<p>However, why if the condition is evaluating to false is the <code>run</code>,</p>
<pre><code>##[debug]..=&gt; '1 == 0'
##[debug]=&gt; '1 == 0'
##[debug]Expanded: (true &amp;&amp; '1 == 0')
##[debug]Result: '1 == 0'
</code></pre>
<p>Why is the run block executing?</p>

<github-actions>
My if statement `${{env.mytrue}} == 0` doesn't seem to work in GitHub Actions conditional
Evan Carroll
# My if statement `${{env.mytrue}} == 0` doesn't seem to work in GitHub Actions conditional

(Asked by: username_0 on 2024-12-03)

I have the following job ...
foo:
  runs-on: ubuntu-latest
  env:
    mytrue: 1
  steps:
    - name: Conditional Test
      if: ${{env.mytrue}} == 0
      run: |
        exit 1;

When I have DEBUG logging on, I can even see this evaluated as false..
##[debug]Evaluating condition for step: 'Conditional Test'
##[debug]Evaluating: (success() && format('{0} == 0', env.mytrue))
##[debug]Evaluating And:
##[debug]..Evaluating success:
##[debug]..=> true
##[debug]..Evaluating format:
##[debug]....Evaluating String:
##[debug]....=> '{0} == 0'
##[debug]....Evaluating Index:
##[debug]......Evaluating env:
##[debug]......=> Object
##[debug]......Evaluating String:
##[debug]......=> 'mytrue'
##[debug]....=> '1'
##[debug]..=> '1 == 0'
##[debug]=> '1 == 0'
##[debug]Expanded: (true && '1 == 0')
##[debug]Result: '1 == 0'
##[debug]Starting: Conditional Test
##[debug]Loading inputs
##[debug]Loading env
Run exit 1;

However, why if the condition is evaluating to false is the run,
##[debug]..=> '1 == 0'
##[debug]=> '1 == 0'
##[debug]Expanded: (true && '1 == 0')
##[debug]Result: '1 == 0'

Why is the run block executing?

**Tags:** github-actions


---

## 1 answers

### Answer by username_0 on 2024-12-03. Score: 0 | Accepted answer

This is because ${{ }} creates a GitHub context. And from the notes in the documentation

Contexts are usually denoted using the dollar sign and curly braces, as ${{ context.property }}. In an if conditional, the ${{ and }} are optional, but if you use them they must enclose the entire comparison statement, as shown above.

So the right answer here is not to use Contexts...
foo:
  runs-on: ubuntu-latest
  env:
    mytrue: 1
  steps:
    - name: Conditional Test
      if: env.mytrue == 0
      run: |
        exit 1;

Explanation
What you're seeing is because otherwise under the hood the Context executes in a .format()
format('{0} == 0', env.mytrue))

Which evaluates to a string..
##[debug]....Evaluating String:
##[debug]....=> '{0} == 0'

The string '1 == 0' is true in Bash..
bash -c 'if [ "1 == 0" ]; then echo TRUE; fi;'

And the implementation depends on that string being reduced to "0" or "1". If you instead use ${{env.mytrue == 0}} it will evaluate as such.
##[debug]Evaluating condition for step: 'Conditional Test'
##[debug]Evaluating: (success() && (env.mytrue == 0))
##[debug]Evaluating And:
##[debug]..Evaluating success:
##[debug]..=> true
##[debug]..Evaluating Equal:
##[debug]....Evaluating Index:
##[debug]......Evaluating env:
##[debug]......=> Object
##[debug]......Evaluating String:
##[debug]......=> 'mytrue'
##[debug]....=> '1'
##[debug]....Evaluating Number:
##[debug]....=> 0
##[debug]..=> false
##[debug]=> false
##[debug]Expanded: (true && ('1' == 0))
##[debug]Result: false

You'll see now there is no format, and you have this
##[debug]..Evaluating success:
##[debug]..=> true
##[debug]..Evaluating Equal:


---

