When I first started using GitHub Actions, environment variables felt confusing because examples often jumped straight into YAML code without explaining what was actually happening.
I kept seeing values appear from nowhere and had no idea why they were needed.
I’ll tell you that GitHub Actions environment variables are much simpler than they look.
They are just saved values that workflows reuse while running.Instead of typing the same information repeatedly, you store it once and use it wherever needed.
In this guide, I will explain what GitHub Actions environment variables are, where to create them, how to access them in YAML files, and when to replace variables with secrets.
Everything is broken into simple examples for beginners.
What are GitHub Actions Environment Variables?
GitHub Actions environment variables are named values stored within workflows that can be reused across jobs and steps.
Instead of hardcoding the same information repeatedly, you can store it once and reference it wherever needed in the workflow.
For example, you can define a variable like this:
env:
NAME: Ellison
Then use it inside a workflow step:
run: echo "Hello $NAME"
Output:
Hello Ellison
These variables help workflows stay cleaner and easier to manage because values are stored separately from commands.
| What Variables Help With | Why It Matters |
| Reusing values | Avoid repeating the same information |
| Easier updates | Change a value once instead of multiple places |
| Workflow management | Keep configuration organized |
| Environment control | Switch between testing and production settings |
I usually store values like app names, environment names, or URLs as variables because changing them later becomes much faster.
Where Can You Create GitHub Actions Environment Variables?

GitHub Actions environment variables can be created at different levels depending on where you want them to work. This is called the variable scope.
Choosing the correct scope helps avoid confusion and keeps workflows easier to manage.
There are three main places where you can create variables: the workflow level, the job level, and the step level.
Workflow Level Variables
Workflow-level variables work across the entire workflow file. Every job and step inside that workflow can access them unless you override the value later.
This scope works well for values that multiple jobs need, such as environment names, project names, or API URLs.
Example:
env:
APP_NAME: my-app
NODE_ENV: production
jobs:
build:
runs-on: ubuntu-latest
Since these variables are available throughout the workflow, they help reduce repeated configuration across jobs.
Job Level Variables
Job-level variables only work inside a specific job. Other jobs inside the same workflow cannot access them.
This scope is useful when one job requires different settings than another.
Example:
jobs:
build:
runs-on: ubuntu-latest
env:
JAVA_VERSION: 21
For example, if one job builds an application and another deploys it, both jobs may need different variables. Keeping them job-specific prevents unnecessary values from spreading across the workflow.
Step Level Variables
Step-level variables exist only inside a single step. Once that step finishes running, the variable is no longer available. These variables are useful for temporary values that only one command needs.
Example:
steps:
- name: Print Message
env:
MESSAGE: Hello World
run: echo $MESSAGE
Since these variables have the smallest scope, they help keep workflows cleaner by limiting values to only where they are required.
It is suggested to start with the smallest scope possible because it makes debugging easier as workflows grow.
How to Create GitHub Actions Environment Variables

GitHub allows you to create environment variables directly in your repository settings, so you do not have to put every value in YAML files.
Repository variables are useful when the same value needs to be reused across multiple workflows or updated without repeatedly editing workflow files.
You can create variables from:
Settings → Secrets And Variables → Actions → Variables
Follow these steps:
- Open your GitHub repository
- Click Settings
- Open Secrets and Variables from the left menu
- Select Actions
- Open the Variables tab
- Click New Repository Variable
- Add a variable name and value
- Save the variable
Example:
| Variable Name | Value |
| APP_NAME | my-project |
| API_URL | https://api.example.com |
| NODE_ENV | production |
After saving, you can access repository variables inside workflows:
env:
API_URL: ${{ vars.API_URL }}
Repository variables work well when several workflows need the same configuration values because updating the value once updates it everywhere it is used.
Repository variables are preferred when multiple workflows use the same values because changing the configuration in one place saves time later.
How to Access GitHub Actions Environment Variables in YAML

After creating variables, the next step is to use them in workflow files.
GitHub Actions supports different syntax styles depending on where the variable comes from and where you are trying to use it.
You may see syntax like:
${{ vars.API_URL }}
Or:
$NAME
These formats have different purposes:
| Syntax | When To Use It | Example |
$VARIABLE_NAME | Access variables inside commands or scripts | $NAME |
${{ env.NAME }} | Access workflow, job, or step variables | ${{ env.NODE_ENV }} |
${{ vars.NAME }} | Access repository variables from settings | ${{ vars.API_URL }} |
You may also hear the term contexts.
In simple terms, contexts help GitHub determine exactly where to look for a value. Instead of searching everywhere, contexts point GitHub to the correct location.
Here is a complete workflow example:
name: Demo Workflow
env:
APP_NAME: MyApp
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Print Values
run: echo "$APP_NAME using ${{ vars.API_URL }}"
This workflow uses both a workflow variable and a repository variable.
I usually keep repository values under vars and workflow values under env because it becomes easier to identify where the values come from.
GitHub Actions Environment Variables Vs. Secrets
Variables and secrets may look similar because both store values, but they serve different purposes. The biggest difference is visibility and security.
| Environment Variables | Secrets |
| Visible values | Hidden values |
| Good for configuration | Good for API keys |
| Can appear in logs | Hidden in logs |
| Used for normal settings | Used for sensitive data |
Use Environment Variables For:
- URLs
- Environment names
- Feature settings
- Project configuration values
Use Secrets For:
- Tokens
- Passwords
- API keys
- Authentication credentials
Example of using a secret:
${{ secrets.API_KEY }}
GitHub automatically masks secret values in workflow logs, which reduces the risk of exposing private information.
Bonus Tip: Avoid storing private keys in variables, as logs can sometimes reveal normal variable values during workflow runs.
Common Default GitHub Actions Environment Variables
GitHub automatically provides several built-in environment variables during workflow runs. These variables already exist, so you do not need to create them manually.
They help workflows understand details about the repository, commits, branches, and runner environment.
1. GITHUB_SHA
GITHUB_SHA stores the commit hash that triggered the workflow. This is useful when you want to track exactly which commit was built or deployed.
Example:
run: echo $GITHUB_SHA
Common use cases:
- Tracking deployments
- Build versioning
- Release logs
Since commit hashes are unique, this variable makes it easier to trace workflow activity back to a specific code change when debugging problems or reviewing deployment history.
2. GITHUB_REF
GITHUB_REF contains the branch or tag reference that triggered the workflow.
Example:
run: echo $GITHUB_REF
Possible output:
refs/heads/main
This variable is useful when workflows behave differently for branches or tags.
For example, you may want deployment workflows to run only on the main branch while testing workflows run on feature branches.
3. GITHUB_WORKSPACE
GITHUB_WORKSPACE points to the directory where your repository files are available during workflow execution.
Example:
run: echo $GITHUB_WORKSPACE
This helps when scripts need file paths or project locations.
Build tools, test scripts, and deployment commands often rely on this variable to find project files without hardcoding folder locations.
4. GITHUB_REPOSITORY
GITHUB_REPOSITORY stores repository information in the format:
owner/repository-name
Example:
run: echo $GITHUB_REPOSITORY
This variable is useful when workflows need repository names dynamically.
It can also help when creating logs, generating deployment reports, or building workflows that work across multiple repositories without manual changes.
Common Mistakes to Avoid

Small mistakes with variables can cause workflows to fail or behave differently than expected. These are some common problems beginners run into.
1. Mixing Variables And Secrets
Variables and secrets serve different purposes. Store normal configuration values in variables and sensitive values in secrets to avoid exposing private data.
Using variables for passwords or tokens increases the risk of accidentally showing sensitive values in logs or workflow outputs.
If the value should stay private, store it as a secret instead.
2. Using Wrong Variable Scope
A variable created at the step level cannot automatically work everywhere else. Always check whether the variable belongs at the workflow, job, or step level.
Scope problems often cause missing values or unexpected workflow failures. Choosing the correct scope early helps keep workflows easier to maintain as they grow.
3. Hardcoding Values Repeatedly
Writing the same URL, version number, or environment name multiple times makes updates harder. Store reusable values once and reference them instead.
Repeated values also increase the risk of inconsistencies because a single missed update can break part of the workflow while other sections still use older values.
4. Forgetting ${{ }} Syntax
Some situations require GitHub expressions instead of shell syntax. Missing ${{ }} Often causes workflows to fail because GitHub cannot resolve the value correctly.
This usually happens when switching between repository variables, environment variables, and secrets.
Double-check syntax whenever values appear empty during workflow runs.
5. Trying To Access Step Variables Outside Their Step
Step variables only exist during that specific step. Trying to reuse them later usually results in missing or empty values.
If multiple steps need the same value, move the variable to the job level or workflow level instead of redefining it repeatedly.
Check variable scope first whenever a workflow fails because scope issues are often easier to miss than syntax errors.
Wrapping Up
GitHub Actions environment variables are not just about storing values. They help keep workflows cleaner, reduce repeated configuration, and make updates easier as projects grow.
Once you understand where variables live, how to access them in YAML, and when to use secrets, workflows start feeling much more manageable.
One thing I noticed while learning GitHub Actions is that small workflow improvements save a surprising amount of time later.
Even moving a few repeated values into variables can make debugging and maintenance easier. Do not try to memorize every syntax immediately.
Focus on building small workflows, testing variables in different scopes, and gradually adding repository variables and secrets as your projects expand.
Your next workflow will probably use variables anyway, so this is a good time to start using them properly from day one.
Frequently Asked Questions
How do I Access Variables in YAML?
Use $VARIABLE_NAME or GitHub contexts like ${{ vars.NAME }}.
Are GitHub Actions Environment Variables Secure?
Normal variables are not meant for private values. Use secrets for sensitive data.
Can I Change Variables Without Editing YAML?
Yes. Repository variables can be updated from GitHub settings.


