Introduction
A documentation project for the Actions Universe including running them locally
Common Mistakes
Multi Line Expressions in if
Wrong
if: |
${{
success()
&& needs.test.result == 'success'
}}
this ends up like "${{ format('{0}\n', success() && needs.test.result == 'success') }}"
and is equivalent to "always()"
Correct
if: |-
${{
success()
&& needs.test.result == 'success'
}}
if: |
success()
&& needs.test.result == 'success'
if: |-
success()
&& needs.test.result == 'success'
Multi Line Expressions with non string type
Wrong
matrix: |
${{
fromjson('{
"Hello": ["World"]
}')
}}
this ends up like "${{ format('{0}\n', fromjson('{\n "Hello": ["World"]\n }')) }}"
and is equivalent to "Object\n"
Correct
matrix: |-
${{
fromjson('{
"Hello": ["World"]
}')
}}
Jobs are skipped even if dependent jobs succeed
By default all job if conditons not using any function of success()
, always()
, cancelled()
or failure()
, are rewritten as success() && (<old-condition>)
Wrong
if: "true"
needs:
- dependency1
- dependency2
this will be rewritten to
if: "success() && true"
needs:
- dependency1
- dependency2
and is skipped once any transitive dependency has been skipped, failed or the workflow has been cancelled.
Correct
parameters of success not supported in act
if: "success('dependency1', 'dependency2`) && true"
needs:
- dependency1
- dependency2
Otherwise use the far more verbose syntax
if: "!cancelled() && needs.dependency1.result == 'success' && needs.dependency2.result == 'success' && true"
needs:
- dependency1
- dependency2
Do not use always()
, if you don't want to risk not beeing able to cancel the job while force cancel api might be a solution outside of a GitHub Actions Outage.
Passing parameter as boolean in Reusable Workflows
Wrong for push
on:
push:
workflow_dispatch:
inputs:
BOOLEAN:
type: boolean
jobs:
test:
uses: ./.github/workflows/workflow.yml
with:
BOOLEAN: ${{ inputs.BOOLEAN }}
Correct
on:
push:
workflow_dispatch:
inputs:
BOOLEAN:
type: boolean
jobs:
test:
uses: ./.github/workflows/workflow.yml
with:
BOOLEAN: ${{ inputs.BOOLEAN || false }}
Passing string as number in Reusable Workflows
Wrong
on:
push:
workflow_dispatch:
inputs:
NUMBER: {}
jobs:
test:
uses: ./.github/workflows/workflow.yml
with:
NUMBER: ${{ inputs.NUMBER }}
Wrong for push
on:
push:
workflow_dispatch:
inputs:
NUMBER: {}
jobs:
test:
uses: ./.github/workflows/workflow.yml
with:
NUMBER: ${{ fromJson(inputs.NUMBER) }}
Correct
on:
push:
workflow_dispatch:
inputs:
NUMBER: {}
jobs:
test:
uses: ./.github/workflows/workflow.yml
with:
NUMBER: ${{ fromJson(inputs.NUMBER || '0') }}
on:
push:
workflow_dispatch:
inputs:
NUMBER: {}
jobs:
test:
uses: ./.github/workflows/workflow.yml
with:
NUMBER: ${{ inputs.NUMBER && fromJson(inputs.NUMBER) || 0 }}
Accessing index by actions context in if
Wrong
if: steps[${{ steps.token.outputs.y }}].outputs.test == 'ok'
This ends up as ${{ success() && format('steps[{0}].outputs.test == ''ok''', steps.token.outputs.y) }}
and is similar to ${{ success() }}
or ${{ success() && 'Non Empty String' }}
.
Correct
if: steps[steps.token.outputs.y].outputs.test == 'ok'
Comparing Reusable Workflow booleans
Wrong
on:
workflow_call:
inputs:
b:
type: boolean # This is important for this to not work
jobs:
test:
if: ${{ inputs.b == 'true' }}
Correct
on:
workflow_call:
inputs:
b:
type: boolean
jobs:
test:
if: ${{ inputs.b == true }}
on:
workflow_call:
inputs:
b:
type: boolean
jobs:
test:
if: ${{ inputs.b }}
on:
workflow_call:
inputs:
b:
type: boolean
jobs:
test:
if: ${{ format('{0}', inputs.b) == 'true' }}
Types in composite actions don't exist
All inputs are strings, for whatever reason this type field is not producing an error and is allowed as additional property
Wrong
inputs:
B:
type: boolean # No such field defined in spec
default: false
runs:
using: composite
steps:
- run: echo test
if: inputs.B
inputs:
B:
type: boolean # No such field defined in spec
default: false
runs:
using: composite
steps:
- run: echo test
if: inputs.B == true
Correct
inputs:
B:
default: false
runs:
using: composite
steps:
- run: echo test
if: inputs.B == 'true'
Currently there are two tools available for running Actions locally
- act a completely independent actions implementation
- Runner.Client sends job requests to the official actions/runner
VSCode Extensions
Download it from https://github.com/nektos/act
.actrc file
This file is read line by line and split by the first space.
example
-P ubuntu-latest=ubuntu:latest
The right parameter can include spaces, those are preserved.
Do not quote the right hand side.
Do not assume this is shell syntax.
In act you can use ${ENV_NAME}
to insert env values. (Not supported in Runner.Client)
Do not put inline subshell commands into this file.
Use vars.yml file
Append the following into your .actrc
.
--var-file vars.yml
Use secrets.yml file
Append the following into your .actrc
.
--secret-file secrets.yml
now create secrets.yml
MY_SECRET: |
My Multi
Line Value
Download it from https://github.com/christopherhx/runner.server
Supports .actrc
as well, ignores unsupported arguments.
Download it from https://github.com/ChristopherHX/runner.server/tree/main/src/runner-server-vscode
Download it from https://github.com/SanjulaGanepola/github-local-actions