Mastering GitHub Actions: Working with Environment Variables

In any CI/CD pipeline, hardcoding values like database URLs, API versions, or build environments is a bad practice. Environment variables allow you to store and reuse configuration data dynamically. In GitHub Actions, understanding how to define, access, and scope these variables is essential for creating flexible and maintainable workflows.

What are Environment Variables?

Environment variables are key-value pairs used to pass configuration information into your scripts and commands. In GitHub Actions, they can be used to store everything from the name of a Java JAR file to the specific deployment region for a cloud provider.

Understanding Variable Scopes

GitHub Actions allows you to define variables at three different levels. The level at which you define a variable determines its "scope" or where it can be accessed.

Workflow Level (Global)
│
├── Job Level (Available only to specific job)
│   │
│   └── Step Level (Available only to specific step)
    
  • Workflow Level: Defined at the root of the YAML file. Accessible by all jobs and steps in the workflow.
  • Job Level: Defined within a specific job. Accessible only by the steps within that job.
  • Step Level: Defined within a specific step. Accessible only by that specific step.

Defining and Using Variables

You define variables using the env keyword. To access them, you can use the env context in expressions or access them directly as environment variables in shell scripts.

Example: Java Build Configuration

In this example, we define a global variable for the Java version and a job-specific variable for the Maven build profile.

name: Java CI with Env Vars
on: [push]

env:
  JAVA_VERSION: '17' # Workflow level

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      BUILD_PROFILE: 'production' # Job level
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up JDK
        uses: actions/setup-java@v3
        with:
          java-version: ${{ env.JAVA_VERSION }}

      - name: Build with Maven
        run: mvn clean package -P${{ env.BUILD_PROFILE }}
        env:
          MAVEN_OPTS: "-Xmx2g" # Step level
    

Default Environment Variables

GitHub provides several built-in environment variables that are automatically available in every runner. These are useful for getting metadata about the repository or the current run.

  • GITHUB_REPOSITORY: The owner and repository name (e.g., "octocat/Hello-World").
  • GITHUB_SHA: The commit SHA that triggered the workflow.
  • GITHUB_REF: The branch or tag ref that triggered the workflow.
  • GITHUB_RUN_ID: A unique number for each workflow run.

Real-World Use Cases

1. Versioning: Using a variable to manage the version number of your application across multiple build and deployment steps.

2. Dynamic Naming: Naming build artifacts based on the current branch name or commit hash using GITHUB_REF or GITHUB_SHA.

3. Feature Toggles: Enabling or disabling specific tests or build steps based on a custom variable defined at the start of the workflow.

Common Mistakes to Avoid

  • Case Sensitivity: Environment variables are case-sensitive. MY_VAR is not the same as my_var.
  • Context Syntax: Forgetting to use the ${{ env.VAR_NAME }} syntax when using variables inside a with or if statement.
  • Shadowing: Defining a variable at the step level with the same name as a workflow-level variable will "shadow" (overwrite) the global one for that specific step.
  • Confusing Variables with Secrets: Never store passwords, API keys, or tokens in env blocks. Use GitHub Secrets for sensitive data.

Interview Notes: Environment Variables

  • Question: How do you pass a variable from one step to another?
  • Answer: You can use the GITHUB_OUTPUT file to set an output in one step and reference it in another using the steps context.
  • Question: What is the precedence of environment variables in GitHub Actions?
  • Answer: The most specific scope wins. A step-level variable overrides a job-level variable, which in turn overrides a workflow-level variable.
  • Question: Can you use environment variables in the on: trigger section?
  • Answer: No, environment variables are only available after the workflow run has started and the runner is initialized.

Summary

Environment variables are the backbone of dynamic GitHub Actions workflows. By mastering the workflow, job, and step scopes, you can create highly reusable CI/CD pipelines. Remember to use default variables for repository metadata and always reserve the env block for non-sensitive configuration, keeping your secrets secure in the dedicated Secrets store.

Next Topic: securing-sensitive-data-with-secrets