Study guide
3.2 Contexts, Expressions & Functions
GitHub Actions Certification GH-200
Track your progress as you read
Finished sections get a check mark.
1 Chapter 1: Introduction & Exam Overview
1.1 Exam Structure, Format & Scoring 1.2 GitHub Actions Architecture & Core Mental Model 1.3 Hands-On Preparation & Exam Day Strategy
2 Chapter 2: Workflow Triggers & Event Architecture
2.1 Webhook & Code Events: push, pull_request, and pull_request_target 2.2 Scheduled & Manual Triggers: schedule, workflow_dispatch, and repository_dispatch 2.3 Release, Issue, and Dynamic Lifecycle Events 2.4 Branch, Tag, and Path Filtering Patterns
3 Chapter 3: Jobs, Matrix Strategies & Execution Control
3.1 Job Anatomy, Step Execution & Job Dependencies (needs) 3.2 Contexts, Expressions & Functions 3.3 Environment Variables & Workflow Commands 3.4 Matrix Strategies & Multi-Platform Builds 3.5 YAML Anchors, Aliases & Merge Keys
4 Chapter 4: Reusable Workflows & Troubleshooting
4.1 Authoring & Calling Reusable Workflows (workflow_call) 4.2 Comparing Reusable Workflows, Composite Actions & Starter Workflows 4.3 Troubleshooting Workflow Runs & Debug Logging 4.4 Concurrency Controls & Status Check Functions
5 Chapter 5: Authoring Custom Actions
5.1 Action Architecture & action.yml Specification 5.2 Authoring Composite Actions 5.3 Building JavaScript Actions 5.4 Building Docker Container Actions
6 Chapter 6: Action Distribution, Marketplace & Advanced Action Types
6.1 Action Versioning, Semantic Releases & Tagging 6.2 Publishing Actions to GitHub Marketplace 6.3 Service Containers & Network Topology 6.4 actions/github-script & Workflow Tooling
7 Chapter 7: Runner Infrastructure & Self-Hosted Runners
7.1 GitHub-Hosted Runners & Larger Runners 7.2 Self-Hosted Runner Setup, Architecture & Communication 7.3 Self-Hosted Runner Security & Ephemeral Runners 7.4 Runner Groups, Labels & Organization Routing
8 Chapter 8: Enterprise Governance, Policies & Environments
8.1 Enterprise & Organization Action Policies 8.2 Environments, Protection Rules & Deployment Approvals 8.3 Repository Rulesets, Required Status Checks & Governance 8.4 Usage Limits, Billing Multipliers & Usage Metrics
9 Chapter 9: Secrets, Permissions & OIDC Cloud Authentication
9.1 Encrypted Secrets Architecture & Scopes 9.2 GITHUB_TOKEN & Least Privilege Configuration 9.3 OpenID Connect (OIDC) & Workload Identity Federation 9.4 Script Injection Prevention & Secure Workflow Patterns
10 Chapter 10: Supply Chain Hardening & Performance Optimization
10.1 Supply Chain Hardening: SHA Pinning, Dependabot & Artifact Attestations 10.2 Caching Dependencies with `actions/cache` 10.3 Artifacts Management & Job Handoff 10.4 Workflow Performance, Cost Optimization & Architecture Review
3.2 Contexts, Expressions & Functions
Key Takeaways Explain This Topic AI
GitHub Actions contexts are structured JSON objects providing access to workflow metadata, runner environments, repository variables, secrets, and execution results.
Expressions are evaluated at workflow runtime using ${{ <expression> }}; inside if: conditionals, the ${{ }} wrapper syntax is optional.
Built-in string and array functions (contains(), startsWith(), endsWith(), format(), join()) allow dynamic string manipulation and pattern matching directly in YAML.
Data transformation functions toJSON() and fromJSON() enable object serialization, log inspection, and dynamic parsing of JSON arrays for matrix generation.
The hashFiles() function calculates a single SHA-256 hash across one or more file glob patterns, providing deterministic cache keys and fingerprint verification.
Last updated: August 2026
Contexts, Expressions & Functions
GitHub Actions workflows are not static scripts; they are dynamic, programmable automation pipelines. Through contexts , expressions , and built-in functions , you can interrogate runtime metadata, evaluate boolean logic, manipulate strings and JSON payloads, and dynamically control step and job execution.
1. GitHub Actions Contexts Architecture
A context is a structured collection of variables and metadata exposed as a JSON object during workflow execution. Contexts provide information about the triggering webhook event, the repository, the runner environment, secrets, configuration variables, and upstream job/step outputs. +-----------------------------------------------------------------------------+
- | GITHUB ACTIONS CONTEXT MODEL |
- | |
- | [ Workflow Execution Engine ] |
- | | |
- | +---> github : Event payload, ref, actor, repository, SHA |
- | +---> env : Workflow / Job / Step environment variables |
- | +---> vars : Non-sensitive configuration variables |
- | +---> secrets : Encrypted repository / org / env secrets |
- | +---> steps : Step execution status and outputs |
- | +---> runner : OS, architecture, temp path, tool cache |
- | +---> needs : Upstream job outputs and status results |
- | +---> matrix : Current matrix permutation properties |
- | +---> strategy : Matrix fail-fast and max-parallel settings |
- | +---> inputs : Workflow dispatch / reusable workflow inputs |
- +-----------------------------------------------------------------------------+
- Comprehensive Context Reference Table
Context Description & Scope Key Properties & Common Exam Usage
github Metadata about the workflow run and triggering event. Available everywhere. github.sha , github.ref , github.ref_name , github.event_name , github.event.* , github.actor , github.repository , github.run_id , github.run_number , github.token .
env Environment variables defined at workflow, job, or step level. ${{ env.TARGET_ENV }} , ${{ env.APP_PORT }} . Note: Not available in runs-on or workflow-level on: .
vars Non-sensitive configuration variables configured in repository/org settings. ${{ vars.DOCKER_REGISTRY }} , ${{ vars.NODE_VERSION }} , ${{ vars.ENABLE_FEATURE_X }} .
secrets Encrypted secrets configured in repo/org/environment settings. Masked in logs. ${{ secrets.PROD_API_KEY }} , ${{ secrets.GITHUB_TOKEN }} , ${{ secrets.AWS_ROLE_ARN }} .
steps Information about steps executed within the current job. steps.<step_id>.outputs.<name> , steps.<step_id>.conclusion , steps.<step_id>.outcome .
runner Information about the physical/virtual runner executing the job. runner.os ( Linux , Windows , macOS ), runner.arch ( X64 , ARM64 ), runner.temp , runner.tool_cache .
needs Outputs and execution status of upstream jobs defined in needs: . needs.<job_id>.outputs.<output_name> , needs.<job_id>.result ( success , failure , cancelled , skipped ).
matrix Properties of the active matrix permutation. Available only in matrix jobs. matrix.os , matrix.node-version , matrix.custom_property .
strategy Information about the matrix execution strategy. strategy.fail-fast , strategy.max-parallel , strategy.job-index , strategy.job-total .
job Information about the currently running job. job.status ( success , failure , cancelled ).
inputs Inputs passed via workflow_dispatch , workflow_call , or composite action. inputs.environment , inputs.deploy_tag , inputs.dry_run .
Warning
Context Availability Rules on the Exam: Not all contexts are available at all locations in a YAML file:
secrets and vars cannot be accessed in the concurrency: or on: trigger blocks.
env defined at the job level cannot be accessed in the job's runs-on: block (use matrix or literal values instead).
steps context is only accessible within the steps: array of that specific job.
2. Expression Syntax & Evaluation Rules
Expressions are written using the format ${{ <expression> }} . They can contain literal values, context references, mathematical operators, logical operators, and built-in functions. steps:
- name: Conditional Execution Example
- if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
- run: ./deploy.sh
- The if: Condition Special Syntax Rule
In an if: key at the job or step level, the ${{ }} wrapper is optional unless you are concatenating an expression with literal strings: # Both of these are 100% valid and identical in behavior:
if: github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'do-not-merge')
if: ${{ github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'do-not-merge') }}
Literal Data Types in Expressions:
- Boolean: true , false (case-insensitive in expression engine)
- Null: null
- Number: 42 , 3.14159 , -10 , 0xFF
String: Single quotes must be used for literal strings: 'production' , 'ubuntu-latest' . Double quotes inside ${{ 'string' }} cause syntax errors. To escape a literal single quote inside a string, use two single quotes: 'It''s a release build' .
3. Built-In Functions Catalog
GitHub Actions provides a rich suite of built-in functions for string matching, formatting, array inspection, JSON handling, and file fingerprinting.
String & Array Manipulation Functions
contains(search, item) Returns true if search contains item . If search is an array, it checks for item presence. If search is a string, it checks for substring occurrence. Comparison is case-insensitive . # Checks if branch name contains 'feature/'
- if: contains(github.ref, 'feature/')
- # Checks if PR has 'security' label
- if: contains(github.event.pull_request.labels.*.name, 'security')
startsWith(searchString, searchValue) & endsWith(searchString, searchValue) Checks if a string starts or ends with a given substring (case-insensitive). if: startsWith(github.ref, 'refs/tags/v')
if: endsWith(github.actor, '-bot')
format(string, val1, val2, ...) Replaces {0} , {1} , etc., in the template string with supplied arguments. run: echo "${{ format('Deploying {0} to {1} cluster', github.sha, vars.CLUSTER_NAME) }}"
join(array, optional_separator) Concatenates array elements into a single string. If separator is omitted, commas are used. # If matrix.targets = ['x86_64', 'arm64'], join yields 'x86_64;arm64'
- run: ./build --targets "${{ join(matrix.targets, ';') }}"
- Data Transformation Functions: toJSON & fromJSON
toJSON(value) Converts any context, object, or array into a pretty-printed JSON string. Invaluable for debugging and inspecting webhook payloads. - name: Dump GitHub Context for Debugging
run: echo '${{ toJSON(github) }}'
fromJSON(str) Parses a JSON string into a structured data type (object or array), or converts JSON literals ( 'true' , '42' ) into boolean/numeric primitives. # Accessing properties from a JSON string output
- name: Parse Metadata
- run: echo "Deployed to: ${{ fromJSON(needs.setup.outputs.config_json).region }}"
- Integrity & Caching Function: hashFiles()
hashFiles(path1, path2, ...) accepts one or more comma-separated file paths or glob patterns and returns a single SHA-256 hash of the matched files' contents. If no files match or the path does not exist, it returns an empty string "" . - name: Cache Node Modules
uses: actions/cache@v4
with:
- path: ~/.npm
- key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}
- restore-keys: |
- ${{ runner.os }}-node-
- 4. Operator Precedence & Evaluation Truth Table
GitHub Actions evaluates expressions using standard operator precedence (highest to lowest):
- () (Grouping)
- ! (Logical NOT)
- < , <= , > , >= (Relational operators)
- == , != (Equality operators)
- && (Logical AND)
- || (Logical OR)
- Expression Evaluation & Truthiness Rules
Expression Evaluation Result Explanation
null == '' false null is distinct from an empty string.
'hello' == 'HELLO' true String equality comparisons in expressions are strictly case-insensitive .
!null true null coerces to falsy; NOT null evaluates to true .
!'' true Empty string '' coerces to falsy; NOT '' evaluates to true .
!'false' false Critical Exam Trap: Non-empty string 'false' is truthy ! Use boolean false or fromJSON('false') .
contains('Hello World', 'world') true Substring searching is case-insensitive.
hashFiles('non-existent/**') '' (empty string) Unmatched file globs return an empty string.
5. End-to-End Practical YAML Workflow name: Advanced Context & Expression Pipeline
on:
pull_request:
types: [opened, synchronize, labeled]
push:
branches: [main]
jobs:
evaluate-environment:
runs-on: ubuntu-latest
outputs:
- is_release: ${{ steps.check-release.outputs.is_release }}
- target_env: ${{ steps.check-release.outputs.target_env }}
steps:
- name: Inspect Runner Context
- run: |
- echo "Operating System: ${{ runner.os }}"
- echo "Architecture: ${{ runner.arch }}"
- echo "Temp Directory: ${{ runner.temp }}"
- name: Determine Deployment Target
- id: check-release
- run: |
- if [[ "${{ github.ref }}" == "refs/heads/main" && "${{ github.event_name }}" == "push" ]]; then
- echo "is_release=true" >> "$GITHUB_OUTPUT"
- echo "target_env=production" >> "$GITHUB_OUTPUT"
- else
- echo "is_release=false" >> "$GITHUB_OUTPUT"
- echo "target_env=preview" >> "$GITHUB_OUTPUT"
- fi
conditional-step-demo:
- needs: evaluate-environment
- runs-on: ${{ fromJSON('["ubuntu-latest", "ubuntu-24.04"]')[0] }}
steps:
- name: Production Only Step
- # Demonstrates unquoted if expression with boolean coercion
- if: needs.evaluate-environment.outputs.is_release == 'true' && github.actor != 'dependabot[bot]'
- run: echo "Executing authorized production release triggered by ${{ github.actor }}"
- name: Formatting Notification Message
- run: |
MSG="${{ format('Run {0} for commit {1} targeting {2}', github.run_number, github.sha, needs.evaluate-environment.outputs.target_env) }}"