docs
docs copied to clipboard
Unclear when to use expression syntax with literals
Code of Conduct
- [X] I have read and agree to the GitHub Docs project's Code of Conduct
What article on docs.github.com is affected?
https://docs.github.com/en/actions/learn-github-actions/expressions#literals
What part(s) of the article would you like to see updated?
The following section talks about the literal data types used with expression syntax. The example that follows seems to indicate that when specifying anything that is not meant to be a string should be set using expression syntax.
However, if one attempts to do this in, for example, the inputs
section of a workflow, the validator shows an error that is quite the opposite:
On re-reading this part, I assume it is referring specifically to when setting environmental variables?
Additional information
No response
Thanks @schalkneethling, I'll get this triaged for review.
@schalkneethling
Experimenting with using templates for workflow_dispatch inputs, I found the following to be true:
- No matter what the input type, if I tried to use
default: ${{ true }}
, I got a workflow error: "A template expression is not allowed in this context" - In spite of this, I could use
default: ${{ 'true' }}
without getting a workflow error. However, doing this was never useful: a. Usingdefault: ${{ 'true' }}
when the input type was boolean resulted in the input checkbox not being checked, and the the default value was treated as false. b. Usingdefault: ${{ 'true' }}
when the input type was specified to be a string would literally display the default${{ 'true' }}
in the input text box. Actually trying to display this input value with a Bash statement such asecho "The string you entered is: ${{ github.event.inputs.my_string_input }}"
would cause the workflow to error out at that point in the workflow with the error "The string you entered is: ${{ 'true' }}: bad substitution". In fact, the question of setting defaults aside, any string input that looks like an expression template is likely to cause the workflow to crash: there doesn't seem to be any escaping of syntactically-significant input characters. - The declared type of an input seems only to affect how input entry is presented to the user: boolean types present as a check box, choice types present as a dropdown, and string types present as a text box. By the time you use
github.event.inputs.my_input
, that value has been cast or converted to a string, seemingly according to the rules outlined in the Learn GitHub Actions section on functions. For example, even if you give input variablemy_boolean
type "boolean" and check the resulting input box when you run the workflow,${{ github.event.inputs.my_boolean == 'true' }}
will evaluate to true, but${{ github.event.inputs.my_boolean == true }}
will evaluate to false.
I think the way inputs are treated in the context of workflow_call events is significantly different, but I'm still testing this out.
By the way, what validator did you use to get the above screen shot?
By the way, what validator did you use to get the above screen shot?
That was GitHub’s native in-browser workflow editor.
That was GitHub’s native in-browser workflow editor.
Thanks. For what it's worth, the validator gives me a slightly different error for the case you mention—namely, "type is set to boolean but default has invalid value". [UPDATE: Trying this again today, I get exactly the same error from the validator that you got.] If the type is set to string, however, the validator doesn't complain at all about a default of ${{ true }}
; but trying to run a workflow with this default immediately errors out with the message "A template expression is not allowed in this context", as I mentioned in point 1 above.
As for using template expressions for setting environment, it seems they can be used, but needn't be if one is merely setting an environment variable to a literal value. All of the following, for example, result in the expression ${{ env.true-string-* == 'true' }}
evaluating to true (and ${{ env.true-string-* == true }}
evaluating to false!), where * is a number 1 through 6.
env:
true-string-1: true
true-string-2: ${{ 'true' }}
true-string-3: 'true'
true-string-4: !!bool true
true-string-5: ${{ true }}
true-string-6: ${{ fromJSON(true) }}
[@schalkneethling: While the following comment might be of interest to you if you use called workflows, it is primarily motivated by the hope that @steveward or whoever from the GitHub team works on this issue will see fit to either uniformize the behavior of workflow_dispatch inputs and workflow_call inputs or rewrite or add to the documentation in order to make clear how they work very differently.]
As I hinted in my first comment, the way inputs are treated in the context of workflow_call events is significantly different from how they are treated in the context of a workflow_dispatch event. For example,
-
Using the expression syntax (${{ }}) to set a default for a workflow_call input is perfectly acceptable. ~Even the on-line validator agrees: if you change workflow_dispatch to workflow_call in the example above that flagged
default: ${{ true }}
as an error, you will see that error message disappear.~ [UPDATE: Trying this again today, I can no longer reproduce this behavior:default: ${{ true }}
gets flagged as an error by the online validator both in the context of workflow_dispatch inputs and workflow_call inputs. Nevertheless, in spite of the message from the online validator, specifying${{ true }}
in the context of aworkflow_call
input works perfectly fine when the called workflow is actually run! The behavior is exactly the same as ifdefault: true
were specified. (Again, this is not the case when${{ true }}
is used as a default forworkflow_dispatch
inputs!)By the way, I only noticed today that in the example in your original post (https://github.com/project-calavera/calavera-reusable-actions/blob/7ddf5e2fe2108c91da05a269c4e0f56b5e40f8b5/.github/workflows/publish-release.yml#L19), you are using inputs in the context of
workflow_call
, notworkflow_dispatch
as I had originally thought.]While there really isn't any good reason to use
${{ true }}
here instead of justtrue
, there may be use cases where using expression syntax might be of some value. For example, you could use an expression like${{ format('The event is {0}!', github.event_name) }}
to set the default value of aworkflow_call
input of type string. -
The context expression for workflow_call inputs is simpler:
inputs.my_input
is used rather thangithub.event.inputs.my_input
. -
A workflow_call input declared as boolean really is treated as a boolean value when used. For example, consider a workflow_dispatch input and a workflow_call input, both declared as boolean, both named
true_boolean_value
, and both set to or defaulted to true in a run of the workflow. Then (as I pointed out earlier),${{ github.event.inputs.true_boolean_value == 'true' }}
will evaluate to true, but{{ github.event.inputs.true_boolean_value == true }}
will evaluate to false. With the workflow_call input, we have the reverse:${{ inputs.true_boolean_value == 'true' }}
evaluates to false, but${{ inputs.true_boolean_value == true }}
evaluates to true.Note that if you have a caller workflow that has (workflow_dispatch) boolean input
true_boolean_value
, and you want to pass this through to a called workflow having a like-named boolean input, you have to first convert the workflow_dispatch value to a bona fide boolean, e. g.
call-reusable-workflow-boolean:
uses: ./.github/workflows/reusable.yaml
with:
true_boolean_value: ${{ github.event.inputs.true_boolean_value == 'true' }}
or
call-reusable-workflow-boolean:
uses: ./.github/workflows/reusable.yaml
with:
true_boolean_value: ${{ fromJSON(github.event.inputs.true_boolean_value) }}
Just doing
call-reusable-workflow-boolean:
uses: ./.github/workflows/reusable.yaml
with:
true_boolean_value: ${{ github.event.inputs.true_boolean_value }}
will result in a type error, because ${{ github.event.inputs.true_boolean_value }}
is seen as a string, and you can't pass a string for the value of a (workflow_call
) input declared to be a boolean.
Thanks for opening an issue! We've triaged this issue for technical review by a subject matter expert :eyes:
Thanks for opening this, @schalkneethling. I think inputs can only provided as strings, but you can set the type using type
, so
npm-publish:
description: Whether to publish the package to npm
default: true
required: false
type: boolean
is valid for specifiying an input that is a boolean (using strings in YAML)
but forcing an expression to be a boolean is not valid YAML for GitHub Actions, e.g. this wouldn't be valid:
npm-publish:
description: Whether to publish the package to npm
default: ${{ true}}
required: false
type: boolean
On re-reading this part, I assume it is referring specifically to when setting environmental variables?
I think you're right, but will get an SME to confirm
Thanks for opening this, @schalkneethling. I think inputs can only provided as strings, but you can set the type using
type
, sonpm-publish: description: Whether to publish the package to npm default: true required: false type: boolean
is valid for specifiying an input that is a boolean (using strings in YAML)
but forcing an expression to be a boolean is not valid YAML for GitHub Actions, e.g. this wouldn't be valid:
npm-publish: description: Whether to publish the package to npm default: ${{ true}} required: false type: boolean
On re-reading this part, I assume it is referring specifically to when setting environmental variables?
I think you're right, but will get an SME to confirm
@lucascosti As I point out in my comment above, using
npm-publish:
description: Whether to publish the package to npm
default: ${{ true}}
required: false
type: boolean
works perfectly well in the context of on.workflow_call.inputs
, even though the on-line validator may flag it as a type error. (And as I also point out, it doesn't work in the context of on.workflow_dispatch.inputs
.)
And to address the original subject of this issue, as far as I can tell, it is never necessary to use expression syntax with literals. For example, in the article https://docs.github.com/en/actions/learn-github-actions/expressions#literals referenced by the original poster, as far as I can tell, for the non-string examples of environment variable settings,
env:
myNull: null
myBoolean: false
myIntegerNumber: 711
myFloatNumber: -9.2
myHexNumber: 0xff
myExponentialNumber: -2.99-e2
could just as well have been used as what is given there. (There may be some subtle difference, however, between (for example) myHexNumber: 0xff
and myHexNumber: ${{ 0xff }}
: In the first case, it is the YAML parser that interprets 0xff
as the number 255. In the second case, the YAML parser sees ${{ 0xff }}
as a string, and it is only when the ${{ }}
expression is interpreted that the value is found to be a number.
This is a gentle bump for the docs team that this issue is waiting for technical review.
This is a gentle bump for the docs team that this issue is waiting for technical review.
So, some of this is sort of described in https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#providing-inputs
So, some of this is sort of described in https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#providing-inputs
Thanks. This is very useful information. It appears that this note was added about June 9 or so, and references to github.event.inputs.*
in the surrounding text were changed to simply inputs.*
at about that time as well. I don't know what the workflow is for releasing changes to the documentation, so I don't know when this first appeared in the public-facing documentation. I also don't know if this was merely a clarification to the documentation or whether it reflects an actual change to the workings of GitHub Actions.
They unified github.event.inputs and inputs around then.
This is probably the announcement: https://github.blog/changelog/2022-06-10-github-actions-inputs-unified-across-manual-and-reusable-workflows/
This is a gentle bump for the docs team that this issue is waiting for technical review.
This is a gentle bump for the docs team that this issue is waiting for technical review.
This is a gentle bump for the docs team that this issue is waiting for technical review.
This is a gentle bump for the docs team that this issue is waiting for technical review.
Thank you for your patience as we are working through our backlog 💛
This is a gentle bump for the docs team that this issue is waiting for technical review.
This is a gentle bump for the docs team that this issue is waiting for technical review.
This is a gentle bump for the docs team that this issue is waiting for technical review.
This is a gentle bump for the docs team that this issue is waiting for technical review.
This is a gentle bump for the docs team that this issue is waiting for technical review.
This is a gentle bump for the docs team that this issue is waiting for technical review.
This is a gentle bump for the docs team that this issue is waiting for technical review.
This is a gentle bump for the docs team that this issue is waiting for technical review.
This is a gentle bump for the docs team that this issue is waiting for technical review.
👋 Hey all! Thanks to everyone for the open conversation and the support you all have extended to each other. I wanted to check in and see if the changes noted in the comment here covered this issue enough to close it out? If not, I'm happy to dig a bit further. Thanks again for being so great to each other! 💖
I don't think it did.
Some of the problems appear to be a disagreement between a validator and everyone else's expectations (including humans and the docs and the engine). It looks like the validator may have improved since?
That said, using https://github.com/mechanical-ink/calavera-reusable-actions/blob/7ddf5e2fe2108c91da05a269c4e0f56b5e40f8b5/.github/workflows/publish-release.yml (linked from the original description) in a new workflow file editor in a repository, I see:
Invalid type found: one of
string
,number
,boolean
were expected butinteger
was found
I have no idea how number
and integer
differ. But the error message is incredibly confusing.
There are two founds
and an expected
and I can't possibly parse what it's trying to say.
https://github.com/actions/setup-node/blob/869f4dd0c7f320ae834c2724d92a364de3893c24/action.yml#L8-L9
@jsoref Thanks for confirming and provided this additional information. I'll keep this up on the review board and surface it to some of our teams. 👍