Conditional operator or function for expression syntax · Issue #409 · actions/runner · GitHub
Skip to content

Conditional operator or function for expression syntax #409

Closed

Description

@StephenCleary

Describe the enhancement

I'd like some kind of conditional operation added to expression syntax. This can be an actual ternary operator (? :) or a built-in function (e.g., if(<condition>, <true-value>, <false-value>)).

Additional information

There is a workaround: using shell scripts to evaluate the condition, setting step outputs, and having other steps reference those outputs. But it would be much cleaner to have some kind of ternary / if/then/else / conditional branching built in to the expression syntax.

Activity

  1. changed the title [-]Conditional operator or function[/-] [+]Conditional operator or function for expression syntax[/+] on Apr 6, 2020
  2. added
    Actions FeatureFeature requires both runner, pipelines service and launch changes
    and removed
    enhancementNew feature or request
    on Jun 8, 2020
  3. ylemkimon commented on Aug 16, 2020

    @ylemkimon

    Another alternative syntax could be:

    ${{ if(condition) }} evaluateIfTrue ${{ else }} evaluateIfFalse ${{ endif }}
    

    like CircleCI.

  4. ylemkimon commented on Nov 15, 2020

    @ylemkimon

    It seems, although not identical, <condition> && <true-value> || <false-value> works in most cases.

  5. molszanski commented on Dec 30, 2020

    @molszanski

    Syntax: ${{ x && 'ifTrue' || 'ifFalse' }}

    fake ternary example

        steps:
          - name: stuff
            env:
              PR_NUMBER_OR_MASTER: ${{ github.event.number == 0 && 'master' ||  format('pr-{0}', github.event.number)  }}

    on condition is that your first <true-value> must be true for this to work

  6. added a commit that references this issue on Jun 17, 2021
  7. TWiStErRob commented on Jul 17, 2021

    @TWiStErRob
  8. LaPeste commented on Aug 26, 2021

    @LaPeste

    The fact that in a year no one said a word about this, means that the team isn't interested in following up on this one?

  9. 34 remaining items

  10. salilsub commented on Jan 30, 2026

    @salilsub

    Hi everyone, we just announced our new case function which is adds conditionals for expressions.

  11. lpulley commented on Jan 30, 2026

    @lpulley

    BTW it seems that this example from the case docs is not valid YAML:

    env:
      MY_ENV_VAR: ${{ case(
        github.ref == 'refs/heads/main', 'production',
        github.ref == 'refs/heads/staging', 'staging',
        startsWith(github.ref, 'refs/heads/feature/'), 'development',
        'unknown'
      ) }}

    The ) }} is not indented, so is not considered part of the MY_ENV_VAR value. Maybe this, with double quotes?

    env:
      MY_ENV_VAR: "${{ case(
        github.ref == 'refs/heads/main', 'production',
        github.ref == 'refs/heads/staging', 'staging',
        startsWith(github.ref, 'refs/heads/feature/'), 'development',
        'unknown'
      ) }}"
  12. lpulley commented on Jan 30, 2026

    @lpulley

    Also, I'm seeing errors like this when using non-boolean values as predicates in case:

    The workflow is not valid. Error when evaluating 'run-name'. .github/workflows/my-workflow.yml (Line: 2, Col: 11): Error from function 'case': case predicate must evaluate to a boolean value
    

    but the expressions docs say:

    Note that in conditionals, falsy values (false, 0, -0, "", '', null) are coerced to false and truthy (true and other non-falsy values) are coerced to true.

    Is there a reason that case doesn't coerce non-falsy values to true?

  13. AllanGuigou commented on Jan 30, 2026

    @AllanGuigou
    Contributor

    @lpulley we've fixed the invalid YAML in the docs,

    env:
      MY_ENV_VAR: |-
        ${{ case(
          github.ref == 'refs/heads/main', 'production',
          github.ref == 'refs/heads/staging', 'staging',
          startsWith(github.ref, 'refs/heads/feature/'), 'development',
          'unknown'
        ) }}
    

    Thanks for calling that out!

    As for the boolean values, we intentionally require predicates to be booleans to avoid common failure scenarios that unintentionally or incorrectly rely on falsy coercions. I'll take a look to see how we can improve the docs in regards to that as well.

  14. lpulley commented on Jan 30, 2026

    @lpulley

    I see. I know an input (inputs context in workflows & actions) with no default value is falsy if it is not provided; is it equal to the empty string? In other words: instead of case(inputs.maybe-this-input-was-provided, 'thing A', 'thing B'), I should do case(inputs.maybe-this-input-was-provided != '', 'thing A', 'thing B')?

  15. ericsciple commented on Mar 10, 2026

    @ericsciple
    Collaborator

    @lpulley 👍 the empty string check should work since empty string is also falsy

  16. ericsciple commented on Mar 10, 2026

    @ericsciple
    Collaborator

    Closing this issue since the case function is released:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions