# Expressions and Contexts — GitHub Actions

Source: https://www.skillbyai.com/en/github-actions/m-expr

> ${{ }} everywhere.

## github, env, vars, secrets, matrix, needs, steps

Expressions inside `${{ }}` read **contexts**: `github` (event, ref, sha, actor), `env`, `vars` (configuration variables), `secrets`, `matrix`, `needs`, `steps`, `runner`, `inputs`. Operators and functions include `==`, `&&`, `contains()`, `startsWith()`, `format()`, `toJSON()`, `hashFiles()` and status functions such as `success()` and `failure()`. Expressions are evaluated before the shell sees the script, which is why inserting untrusted values directly into `run:` is dangerous (see the security section). actionlint knows the shape of many contexts and catches misspelled properties.

## Useful expressions

Not linted or run here; check the GitHub Actions documentation for current syntax.

```yaml
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
if: ${{ contains(github.event.pull_request.labels.*.name, 'deploy') }}
key: deps-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
name: Test on ${{ matrix.os }} / Node ${{ matrix.node }}
if: ${{ failure() && github.ref == 'refs/heads/main' }}   # alert only for main
```

## Use vars for non-secret configuration

Repository and environment variables (vars context) keep settings like regions or URLs out of workflow files without treating them as secrets.

**Quiz:** When are ${{ }} expressions in a run: script evaluated?

- [ ] Only on Windows
- [ ] By the shell at runtime
- [ ] Never
- [x] Before the shell runs the script, by GitHub Actions

*Answer:* Before the shell runs the script, by GitHub Actions. Substitution happens first.
