Evaluate expressions in workflows and actions
Find information for expressions in GitHub Actions.
Literals
As part of an expression, you can useboolean
,null
,number
, orstring
data types.
Data type | Literal value |
---|---|
boolean | true orfalse |
null | null |
number | Any number format supported by JSON. |
string | You don't need to enclose strings in${{ and}} . However, if you do, you must use single quotes (' ) around the string. To use a literal single quote, escape the literal single quote using an additional single quote ('' ). Wrapping with double quotes (" ) will throw an error. |
Note that in conditionals, falsy values (false
,0
,-0
,""
,''
,null
) are coerced tofalse
and truthy (true
and other non-falsy values) are coerced totrue
.
Example of literals
env:myNull:${{null}}myBoolean:${{false}}myIntegerNumber:${{711}}myFloatNumber:${{-9.2}}myHexNumber:${{0xff}}myExponentialNumber:${{-2.99e-2}}myString:MonatheOctocatmyStringInBraces:${{'It''s open source!'}}
Operators
Operator | Description |
---|---|
( ) | Logical grouping |
[ ] | Index |
. | Property de-reference |
! | Not |
< | Less than |
<= | Less than or equal |
> | Greater than |
>= | Greater than or equal |
== | Equal |
!= | Not equal |
&& | And |
|| | Or |
Note
- GitHub ignores case when comparing strings.
steps.<step_id>.outputs.<output_name>
evaluates as a string. You need to use specific syntax to tell GitHub to evaluate an expression rather than treat it as a string. For more information, seeContexts reference.- For numerical comparison, the
fromJSON()
function can be used to convert a string to a number. For more information on thefromJSON()
function, seefromJSON.
GitHub performs loose equality comparisons.
If the types do not match, GitHub coerces the type to a number. GitHub casts data types to a number using these conversions:
Type Result Null 0
Boolean true
returns1
false
returns0
String Parsed from any legal JSON number format, otherwise NaN
.
Note: empty string returns0
.Array NaN
Object NaN
When
NaN
is one of the operands of any relational comparison (>
,<
,>=
,<=
), the result is alwaysfalse
. For more information, see theNaN Mozilla docs.GitHub ignores case when comparing strings.
Objects and arrays are only considered equal when they are the same instance.
GitHub provides a way to create conditional logic in expressions using binary logical operators (&&
and||
). This pattern can be used to achieve similar functionality to the ternary operator (?:
) found in many programming languages, while actually using only binary operators.
Functions
GitHub offers a set of built-in functions that you can use in expressions. Some functions cast values to a string to perform comparisons. GitHub casts data types to a string using these conversions:
Type | Result |
---|---|
Null | '' |
Boolean | 'true' or'false' |
Number | Decimal format, exponential for large numbers |
Array | Arrays are not converted to a string |
Object | Objects are not converted to a string |
contains
contains( search, item )
Returnstrue
ifsearch
containsitem
. Ifsearch
is an array, this function returnstrue
if theitem
is an element in the array. Ifsearch
is a string, this function returnstrue
if theitem
is a substring ofsearch
. This function is not case sensitive. Casts values to a string.
Example using a string
contains('Hello world', 'llo')
returnstrue
.
Example using an object filter
contains(github.event.issue.labels.*.name, 'bug')
returnstrue
if the issue related to the event has a label "bug".
For more information, seeObject filters.
Example matching an array of strings
Instead of writinggithub.event_name == "push" || github.event_name == "pull_request"
, you can usecontains()
withfromJSON()
to check if an array of strings contains anitem
.
For example,contains(fromJSON('["push", "pull_request"]'), github.event_name)
returnstrue
ifgithub.event_name
is "push" or "pull_request".
startsWith
startsWith( searchString, searchValue )
Returnstrue
whensearchString
starts withsearchValue
. This function is not case sensitive. Casts values to a string.
Example ofstartsWith
startsWith('Hello world', 'He')
returnstrue
.
endsWith
endsWith( searchString, searchValue )
Returnstrue
ifsearchString
ends withsearchValue
. This function is not case sensitive. Casts values to a string.
Example ofendsWith
endsWith('Hello world', 'ld')
returnstrue
.
format
format( string, replaceValue0, replaceValue1, ..., replaceValueN)
Replaces values in thestring
, with the variablereplaceValueN
. Variables in thestring
are specified using the{N}
syntax, whereN
is an integer. You must specify at least onereplaceValue
andstring
. There is no maximum for the number of variables (replaceValueN
) you can use. Escape curly braces using double braces.
Example offormat
format('Hello {0} {1} {2}','Mona','the','Octocat')
Returns 'Hello Mona the Octocat'.
Example escaping braces
format('{{Hello {0} {1} {2}!}}','Mona','the','Octocat')
Returns '{Hello Mona the Octocat!}'.
join
join( array, optionalSeparator )
The value forarray
can be an array or a string. All values inarray
are concatenated into a string. If you provideoptionalSeparator
, it is inserted between the concatenated values. Otherwise, the default separator,
is used. Casts values to a string.
Example ofjoin
join(github.event.issue.labels.*.name, ', ')
may return 'bug, help wanted'
toJSON
toJSON(value)
Returns a pretty-print JSON representation ofvalue
. You can use this function to debug the information provided in contexts.
Example oftoJSON
toJSON(job)
might return{ "status": "success" }
fromJSON
fromJSON(value)
Returns a JSON object or JSON data type forvalue
. You can use this function to provide a JSON object as an evaluated expression or to convert any data type that can be represented in JSON or JavaScript, such as strings, booleans, null values, arrays, and objects.
Example returning a JSON object
This workflow sets a JSON matrix in one job, and passes it to the next job using an output andfromJSON
.
name: buildon: pushjobs: job1: runs-on: ubuntu-latest outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: - id: set-matrix run: echo "matrix={\"include\":[{\"project\":\"foo\",\"config\":\"Debug\"},{\"project\":\"bar\",\"config\":\"Release\"}]}" >> $GITHUB_OUTPUT job2: needs: job1 runs-on: ubuntu-latest strategy: matrix: ${{ fromJSON(needs.job1.outputs.matrix) }} steps: - run: echo "Matrix - Project ${{ matrix.project }}, Config ${{ matrix.config }}"
name:buildon:pushjobs:job1:runs-on:ubuntu-latestoutputs:matrix:${{steps.set-matrix.outputs.matrix}}steps:-id:set-matrixrun:echo"matrix={\"include\":[{\"project\":\"foo\",\"config\":\"Debug\"},{\"project\":\"bar\",\"config\":\"Release\"}]}">>$GITHUB_OUTPUTjob2:needs:job1runs-on:ubuntu-lateststrategy:matrix:${{fromJSON(needs.job1.outputs.matrix)}}steps:-run:echo"Matrix - Project ${{ matrix.project }}, Config ${{ matrix.config }}"
Example returning a JSON data type
This workflow usesfromJSON
to convert environment variables from a string to a Boolean or integer.
name: printon: pushenv: continue: true time: 3jobs: job1: runs-on: ubuntu-latest steps: - continue-on-error: ${{ fromJSON(env.continue) }} timeout-minutes: ${{ fromJSON(env.time) }} run: echo ...
name:printon:pushenv:continue:truetime:3jobs:job1:runs-on:ubuntu-lateststeps:-continue-on-error:${{fromJSON(env.continue)}}timeout-minutes:${{fromJSON(env.time)}}run:echo...
The workflow uses thefromJSON()
function to convert the environment variablecontinue
from a string to a boolean, allowing it to determine whether to continue-on-error or not. Similarly, it converts thetime
environment variable from a string to an integer, setting the timeout for the job in minutes.
hashFiles
hashFiles(path)
Returns a single hash for the set of files that matches thepath
pattern. You can provide a singlepath
pattern or multiplepath
patterns separated by commas. Thepath
is relative to theGITHUB_WORKSPACE
directory and can only include files inside of theGITHUB_WORKSPACE
. This function calculates an individual SHA-256 hash for each matched file, and then uses those hashes to calculate a final SHA-256 hash for the set of files. If thepath
pattern does not match any files, this returns an empty string. For more information about SHA-256, seeSHA-2.
You can use pattern matching characters to match file names. Pattern matching forhashFiles
follows glob pattern matching and is case-insensitive on Windows. For more information about supported pattern matching characters, see thePatterns section in the@actions/glob
documentation.
Examples with a single pattern
Matches anypackage-lock.json
file in the repository.
hashFiles('**/package-lock.json')
Matches all.js
files in thesrc
directory at root level, but ignores any subdirectories ofsrc
.
hashFiles('/src/*.js')
Matches all.rb
files in thelib
directory at root level, including any subdirectories oflib
.
hashFiles('/lib/**/*.rb')
Examples with multiple patterns
Creates a hash for anypackage-lock.json
andGemfile.lock
files in the repository.
hashFiles('**/package-lock.json', '**/Gemfile.lock')
Creates a hash for all.rb
files in thelib
directory at root level, including any subdirectories oflib
, but excluding.rb
files in thefoo
subdirectory.
hashFiles('/lib/**/*.rb', '!/lib/foo/*.rb')
Status check functions
You can use the following status check functions as expressions inif
conditionals. A default status check ofsuccess()
is applied unless you include one of these functions. For more information aboutif
conditionals, seeWorkflow syntax for GitHub Actions andMetadata syntax reference.
success
Returnstrue
when all previous steps have succeeded.
Example ofsuccess
steps:...-name:Thejobhassucceededif:${{success()}}
always
Causes the step to always execute, and returnstrue
, even when canceled. Thealways
expression is best used at the step level or on tasks that you expect to run even when a job is canceled. For example, you can usealways
to send logs even when a job is canceled.
Warning
Avoid usingalways
for any task that could suffer from a critical failure, for example: getting sources, otherwise the workflow may hang until it times out. If you want to run a job or step regardless of its success or failure, use the recommended alternative:if: ${{ !cancelled() }}
Example ofalways
if:${{always()}}
cancelled
Returnstrue
if the workflow was canceled.
Example ofcancelled
if:${{cancelled()}}
failure
Returnstrue
when any previous step of a job fails. If you have a chain of dependent jobs,failure()
returnstrue
if any ancestor job fails.
Example offailure
steps:...-name:Thejobhasfailedif:${{failure()}}
failure with conditions
You can include extra conditions for a step to run after a failure, but you must still includefailure()
to override the default status check ofsuccess()
that is automatically applied toif
conditions that don't contain a status check function.
Example offailure
with conditions
steps:...-name:Failingstepid:demorun:exit1-name:Thedemostephasfailedif:${{failure()&&steps.demo.conclusion=='failure'}}
Object filters
You can use the*
syntax to apply a filter and select matching items in a collection.
For example, consider an array of objects namedfruits
.
[{"name":"apple","quantity":1},{"name":"orange","quantity":2},{"name":"pear","quantity":1}]
The filterfruits.*.name
returns the array[ "apple", "orange", "pear" ]
.
You may also use the*
syntax on an object. For example, suppose you have an object namedvegetables
.
{"scallions":{"colors":["green","white","red"],"ediblePortions":["roots","stalks"],},"beets":{"colors":["purple","red","gold","white","pink"],"ediblePortions":["roots","stems","leaves"],},"artichokes":{"colors":["green","purple","red","black"],"ediblePortions":["hearts","stems","leaves"],},}
The filtervegetables.*.ediblePortions
could evaluate to:
[["roots","stalks"],["hearts","stems","leaves"],["roots","stems","leaves"],]
Since objects don't preserve order, the order of the output cannot be guaranteed.