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

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