self-host →

GitHub Actions Environment Variables

The environment variables GitHub Actions defines for every run, how to use them in your workflows, and how to set custom variables of your own.

Environment variables are crucial for passing data between steps and jobs in GitHub Actions workflows. Let’s dive into how to use them effectively.

Default Environment Variables#

GitHub Actions provides a set of default environment variables available in every workflow run. Some key ones include:

  • GITHUB_REPOSITORY: The owner and repository name, e.g. octocat/Hello-World
  • GITHUB_SHA: The commit SHA that triggered the workflow
  • GITHUB_REF: The fully-formed ref that triggered the workflow, e.g. refs/heads/main or refs/tags/v1.0.0
  • GITHUB_WORKSPACE: The default working directory on the runner, where your repository is checked out

For a full list, check out the official docs.

Setting Environment Variables#

Job-level Variables#

Set variables for all steps in a job using the env key:

jobs:
example-job:
runs-on: ubuntu-latest
env:
MY_VAR: value1
ANOTHER_VAR: value2
steps:
- name: Use job-level vars
run: echo $MY_VAR $ANOTHER_VAR

Step-level Variables#

Set variables for a specific step:

jobs:
example-job:
runs-on: ubuntu-latest
steps:
- name: Step with custom env
env:
STEP_VAR: step_value
run: echo $STEP_VAR

Adding custom environment variables from a step#

To set variables that persist across the subsequent steps of the same job, append them to the GITHUB_ENV file. Note that values written to GITHUB_ENV do not carry over to other jobs — to pass data between jobs, use job outputs instead (shown in the example below, and covered in depth in Passing data between steps and jobs).

jobs:
example-job:
runs-on: ubuntu-latest
steps:
- name: Set custom var
run: echo "CUSTOM_VAR=dynamic_value" >> $GITHUB_ENV
- name: Use custom var
run: echo $CUSTOM_VAR

Practical Example: Dynamic Configuration#

Here’s a workflow that demonstrates various env var techniques:

name: Dynamic Config
on: [push]
jobs:
configure:
runs-on: ubuntu-latest
outputs:
env_name: ${{ steps.set-env.outputs.env_name }}
steps:
- name: Set environment name
id: set-env
run: |
if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
echo "ENV_NAME=production" >> $GITHUB_ENV
echo "env_name=production" >> $GITHUB_OUTPUT
else
echo "ENV_NAME=staging" >> $GITHUB_ENV
echo "env_name=staging" >> $GITHUB_OUTPUT
fi
- name: Display env from previous step
run: |
echo "ENV_NAME from previous step: $ENV_NAME"
deploy:
needs: configure
runs-on: ubuntu-latest
env:
DEPLOY_ENV: ${{ needs.configure.outputs.env_name }}
steps:
- name: Deploy to environment
run: |
echo "Deploying to $DEPLOY_ENV"

This workflow:

  1. Sets an environment name based on the branch, writing it both to $GITHUB_ENV (for later steps in the same job) and to $GITHUB_OUTPUT (for other jobs)
  2. Passes the env name to the deploy job via a job output (needs.configure.outputs.env_name), since $GITHUB_ENV values do not cross job boundaries
  3. Consumes that output as a job-level env variable in deploy