Comparison of GitHub Actions with competitors
Deep dive into workflow syntax, triggers, and job configuration
Explore matrices, reusable workflows, and composite actions
•Runner Types and Execution Environments
•Persisting Build Outputs with Artifacts
•Controlling GitHub Permissions
•Authenticating to Third-Party Systems
•Matrix Strategies, Conditionals, and Concurrency Controls
Discover and integrate community actions from the GitHub Marketplace
Build custom JavaScript and Docker actions from scratch
•JavaScript and TypeScript Actions
Optimize logs, secrets, environments, and permissions for teams
•Developer Experience (Actions)
Harden workflows with security, reliability, and cost-saving techniques
•Maintainable Workflow Patterns
Apply course concepts by automating a real-world deployment pipeline
The
03-core-features--05-environment-variables.yaml
workflow clarifies how environment variables cascade:
env:
WORKFLOW_VAR: I_AM_WORKFLOW_SCOPED
jobs:
job-1:
runs-on: ubuntu-24.04
env:
JOB_VAR: I_AM_JOB_1_SCOPED
steps:
- name: Inspect scopes job 1 step 1
env:
STEP_VAR: I_AM_STEP_SCOPED
run: |
echo "WORKFLOW_VAR: $WORKFLOW_VAR" # visible
echo "JOB_VAR: $JOB_VAR" # visible
echo "STEP_VAR: $STEP_VAR" # visible only here
- name: Inspect scopes job 1 step 2
run: |
echo "WORKFLOW_VAR: $WORKFLOW_VAR" # visible
echo "JOB_VAR: $JOB_VAR" # visible
echo "STEP_VAR: ${STEP_VAR:-<UNSET>}" # not set here
job-2:
runs-on: ubuntu-24.04
steps:
- name: Inspect scopes job 2 step 2
run: |
echo "WORKFLOW_VAR: $WORKFLOW_VAR" # still visible
echo "JOB_VAR: ${FOO:-<UNSET>}" # not set here
echo "STEP_VAR: ${STEP_VAR:-<UNSET>}" # not set here
Remember:
${{ env.VAR_NAME }}
when you need to reference a variable from YAML configuration (for example inside an if:
condition).Sometimes you need to pass dynamic values forward such as build numbers, artifact paths, checksums, etc. GitHub Actions provides two special files for this:
KEY=value
lines to $GITHUB_ENV
to create environment variables that persist for the rest of the job.KEY=value
lines to $GITHUB_OUTPUT
inside a step that has an id
. You can then expose those as job outputs and consume
them from downstream jobs with the needs
context.03-core-features--06-passing-data.yaml
combines both techniques:
jobs:
producer:
runs-on: ubuntu-24.04
outputs:
foo: ${{ steps.generate-foo.outputs.foo }}
steps:
- name: Generate and export foo
id: generate-foo
run: |
foo=bar
# 1) Step output (for job output)
echo "foo=${foo}" >> "$GITHUB_OUTPUT"
# 2) Job-scoped environment variable
echo "FOO=${foo}" >> "$GITHUB_ENV"
- name: Inspect values inside producer
run: |
echo "foo (step output): ${{ steps.generate-foo.outputs.foo }}"
echo "FOO (set via GITHUB_ENV): $FOO"
consumer:
runs-on: ubuntu-24.04
needs: producer
steps:
- name: Inspect values inside consumer (note FOO is unset)
run: |
echo "Value from producer: ${{ needs.producer.outputs.foo }}"
echo "FOO in consumer: ${FOO:-<UNSET>}"
Notice how FOO
(set via $GITHUB_ENV
) disappears in the downstream job while the job output remains accessible.