Handling Environment Variables in GitHub Actions Pipelines
Master environment variables in GitHub Actions to decouple config from your code. Learn to define workflow-level variables and map secrets securely.

Previously in this course, we covered managing secrets, which allows you to store sensitive data like API keys without exposing them in your repository. In this lesson, we build on that foundation by learning how to inject non-sensitive configuration data into your workflow using environment variables.
When you hardcode values like database URLs, feature flags, or API base paths into your workflow YAML, you create "brittle" pipelines. If those values change, you have to edit your code. Using environment variables allows you to change behavior without touching the logic, mirroring how you might manage configuration in your local application development, such as using .env files.
Understanding Environment Variables in CI/CD
Environment variables are key-value pairs available to the processes running in your CI/CD runner. They provide a standardized way to pass configuration to your scripts, whether those scripts are shell commands or application tests.
In GitHub Actions, you can define these variables at three different levels:
- Workflow level: Available to all jobs in the workflow.
- Job level: Available only to all steps within a specific job.
- Step level: Available only to the specific step where they are defined.
This hierarchy follows the principle of least privilege—only define the variable at the scope where it is actually needed.
Worked Example: Injecting Configuration
Let’s update our project’s pipeline to use an environment variable for an API endpoint. Instead of hardcoding the URL in our test script, we will define it in the YAML and access it through the shell.
YAMLname: Configuration Example on: [push] env: # Workflow-level environment variable API_ENDPOINT: "https://api.myapp.com/v1" jobs: test: runs-on: ubuntu-latest steps: - name: Print Config env: # Step-level mapping of a secret to an env var API_KEY: ${{ secrets.MY_API_KEY }} run: | echo "Connecting to $API_ENDPOINT" # We use the env var in our shell command ./run-tests.sh --key $API_KEY
In this example, $API_ENDPOINT is available to every step in the workflow because it is declared at the top level. $API_KEY, however, is scoped strictly to the "Print Config" step. This is a secure practice: by mapping secrets to step-level variables, you ensure they aren't accidentally logged or accessed by other steps that don't require them.
Hands-on Exercise
- Open your current workflow file in
.github/workflows/. - Define an environment variable at the job level called
APP_ENVand set it tostaging. - Add a step that uses the
runkeyword to print the value ofAPP_ENVusingecho "Running in $APP_ENV mode". - Commit your changes and verify the output in the GitHub Actions "Run" logs.
Common Pitfalls
- Case Sensitivity: On Linux runners (like
ubuntu-latest), environment variables are case-sensitive.$api_endpointis not the same as$API_ENDPOINT. - Over-scoping: Avoid defining everything at the workflow level. If only one job needs a specific configuration, define it at the job level to keep your configuration clean and debuggable.
- Logging Secrets: While GitHub Actions automatically masks secrets in the logs, if you manually print an environment variable that contains a secret (e.g.,
echo $SECRET_KEY), GitHub might not be able to mask it effectively. Never echo secrets to the terminal. - Variable Expansion: Remember that environment variables are expanded by the shell. If you are using Windows runners, the syntax differs (e.g.,
%VAR%vs$VAR), though GitHub Actions handles most of this abstraction for you.
Frequently Asked Questions
Q: Should I put all my configuration in environment variables? A: Use them for operational settings (like API URLs or log levels). For application-specific configuration that is highly complex, consider a dedicated config file managed via your code.
Q: Can I override a workflow-level variable in a specific job? A: Yes. If you define a variable with the same name at the job level, it will override the workflow-level value for that specific job.
Q: How do I handle environment variables when building container images?
A: You need to use ARG or ENV instructions in your Dockerfile. We will explore how to pass these variables from your CI pipeline into your Docker build process in upcoming lessons.
Recap
We’ve successfully moved away from hardcoding values. By defining environment variables at the workflow, job, or step level, you’ve increased the portability of your pipeline. You also learned to securely map secrets to variables, keeping your credentials safe while keeping your workflows dynamic.
Up next: Introduction to Linting — we will start enforcing code quality automatically.
Work with me

CI/CD Pipeline & Docker Containerization
Ship with confidence: automated CI/CD pipelines and Docker setups so every push is tested and deployed — no more manual, error-prone releases.

VPS Server Setup, Deployment & Hardening
Get your app live on a fast, secure server — properly configured, hardened, and deployment-ready. No more wrestling with the command line.

