Actio
Macros

static-if

Compile-time conditionals that keep or drop jobs, steps, and keys before any YAML is emitted.

static-if is a compile-time conditional. Its expression is evaluated by the transpiler, not by GitHub Actions. When it is false the guarded job, step, or map is removed from the generated workflow entirely; when it is true the static-if key is stripped and everything else is emitted verbatim.

Use static-if to shape the workflow at build time. Use the native if: for runtime conditions that depend on github.*, needs.*, steps.*, and other runtime contexts.

Form A — keep or drop a job or step

Place static-if directly on a job or step. A false expression deletes the whole map from the output.

With params.deploy false, the release job never appears:

.actio.yml
name: Deploy
on: [push]
params:
  deploy:
    type: boolean
    default: false
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: echo build
  release:
    static-if: params.deploy
    runs-on: ubuntu-latest
    steps:
      - run: ./release.sh
generated .yml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: echo build
.actio.yml
name: Deploy
on: [push]
params:
  deploy:
    type: boolean
    default: false
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: echo build
  release:
    static-if: params.deploy
    runs-on: ubuntu-latest
    steps:
      - run: ./release.sh
generated .yml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: echo build

Flip default: true and the job is emitted with the static-if key removed.

Form B — conditional merge

static-if(<expr>): is a merge key. When the expression is true, its mapping is merged into the parent map; when false, the whole block is dropped. This works on jobs, steps, and env: maps.

.actio.yml
name: Build
on: [push]
params:
  debug:
    type: boolean
    default: true
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/upload-artifact@v4
        with:
          name: dist
          static-if(params.debug):
            retention-days: "1"
generated .yml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/upload-artifact@v4
        with:
          name: dist
          retention-days: "1"
.actio.yml
name: Build
on: [push]
params:
  debug:
    type: boolean
    default: true
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/upload-artifact@v4
        with:
          name: dist
          static-if(params.debug):
            retention-days: "1"
generated .yml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/upload-artifact@v4
        with:
          name: dist
          retention-days: "1"

static-if vs if

  • static-if runs at compile time. False branches produce no YAML, so they cost nothing at runtime and never show up in the Actions UI.
  • if runs at runtime on GitHub's servers. The step or job is always present in the workflow; GitHub decides whether to run it.

They compose cleanly — a step can have both:

.actio.yml
- name: Publish preview
  static-if: params.deploy
  if: github.ref == 'refs/heads/main'
  run: ./publish-preview.sh

If params.deploy is false the step is dropped at compile time. If it is true the step is emitted with its if: intact for GitHub to evaluate at runtime.

Expression rules

  • Operates only on compile-time roots: params.*, for-each.*, and define.*.
  • Takes a bare expression — ${{ ... }} is runtime-only and rejected.
  • Must resolve to a boolean. Unknown references and non-boolean results are errors.
  • Referencing a runtime context (github, needs, steps, …) is an error; use if: for those.

On this page