Checkpoint Lab — Environment Variables, Configuration Variables, Outputs, and Data Passing
The checkpoint combines the chapter into one controlled experiment.
You will build a two-job pipeline with three producer steps, use
workflow env, an optional repository
vars value, GITHUB_ENV, and
GITHUB_OUTPUT, then deliberately misuse the same-job
environment channel as a cross-job transport. The first run must
fail for the predicted reason. You will preserve it, repair only the
interface, and prove the second run succeeds without changing
unrelated execution state.
Learning objectives
- Design and execute a three-step/two-job data pipeline with explicit value origin, scope, and transport predictions.
-
Prove workflow/job/step environment precedence and same-job
GITHUB_ENVbehavior from logs. - Demonstrate a deliberate cross-job misuse and diagnose it without changing runner, permissions, or trigger.
-
Repair the workflow with
GITHUB_OUTPUT→ job output →needswhile preserving the failed run. - Produce an evidence packet that distinguishes configuration, environment state, outputs, and file/artifact candidates.
1. Checkpoint charter and safety boundary
| Item | Checkpoint contract |
|---|---|
| Repository | Learner-owned disposable repository only. |
| Workflow | .github/workflows/ch05-checkpoint.yml |
| Trigger | Manual workflow_dispatch. |
| Runner | ubuntu-24.04. |
| Permissions | {}. |
| Credentials / external systems | None. |
| Optional configuration variable |
LAB_TRACK=repo-track; workflow has a safe
fallback.
|
| Expected first outcome |
Consumer job fails because same-job
GITHUB_ENV is misused across jobs.
|
| Expected repaired outcome | Consumer succeeds through explicit job output. |
2. Write predictions before creating the defect
-
Workflow-level
APP_NAMEwill be visible in producer steps. -
Producer Step 1 writes
STAGE=assembled; Step 1 itself will not see the new value, but Steps 2/3 will. -
Step 2 creates
release_labelthroughGITHUB_OUTPUT. - Step 3 confirms both same-job environment and step output.
-
In broken revision A, consumer will not receive
CROSS_JOB_HINTwritten to producerGITHUB_ENV. -
In repaired revision B, consumer receives the mapped
release_labelthroughneeds.produce.outputs.release_label.
Also predict that the two jobs receive independent runner workspaces. A green producer does not imply the consumer has the producer's environment.
3. Revision A — deliberately broken transport
name: Chapter 05 checkpoint
on:
workflow_dispatch:
inputs:
suffix:
description: 'Synthetic release suffix'
type: string
required: true
default: 'checkpoint'
permissions: {}
env:
APP_NAME: chapter05-lab
TRACK: ${{ vars.LAB_TRACK || 'fallback-track' }}
jobs:
produce:
runs-on: ubuntu-24.04
steps:
- name: Step 1 - establish same-job environment
run: |
echo 'STAGE=assembled' >> "$GITHUB_ENV"
printf 'writer-sees-stage=%q\n' "${STAGE-}"
- name: Step 2 - compute explicit step output
id: meta
env:
SUFFIX: ${{ inputs.suffix }}
run: |
printf 'stage=%s track=%s\n' "$STAGE" "$TRACK"
printf 'release_label=%s-%s\n' "$APP_NAME" "$SUFFIX" >> "$GITHUB_OUTPUT"
- name: Step 3 - verify same-job data and create bad handoff
env:
LABEL: ${{ steps.meta.outputs.release_label }}
run: |
printf 'producer_label=%s stage=%s\n' "$LABEL" "$STAGE"
echo "CROSS_JOB_HINT=$LABEL" >> "$GITHUB_ENV"
printf 'run=%s attempt=%s sha=%s\n' "$GITHUB_RUN_ID" "$GITHUB_RUN_ATTEMPT" "$GITHUB_SHA"
consume:
needs: produce
runs-on: ubuntu-24.04
steps:
- name: Prove the misuse
run: |
printf 'consumer_hint=%q\n' "${CROSS_JOB_HINT-}"
test -n "${CROSS_JOB_HINT-}"
4. Execute Revision A and preserve first-failure evidence
Dispatch with suffix=checkpoint. Record:
- Workflow/source SHA and run ID/attempt.
-
Optional effective
TRACKvalue (non-sensitive only). -
Step 1 log proving the writer step does not see newly written
STAGE. -
Step 2/3 logs proving later same-job steps do see
STAGE=assembled. - Step 3 log proving the step output created the expected release label.
- Producer job conclusion = success.
-
Consumer log showing empty
CROSS_JOB_HINTand consumer conclusion = failure.
Do not edit the workflow until this packet is saved. The failed consumer is evidence, not noise.
5. Diagnose the causal layer
Event creation succeeded; YAML parsed; both jobs entered the graph; the producer runner executed successfully; permissions were irrelevant; no external action failed. The missing value appears only at the job boundary. That isolates the defect to data transport.
The producer already has the correct small value in
steps.meta.outputs.release_label. The smallest repair
is therefore to expose that value at the job interface and consume
it through needs.
6. Revision B — replace ambient handoff with explicit job output
Change only the producer/consumer interface:
jobs:
produce:
runs-on: ubuntu-24.04
outputs:
release_label: ${{ steps.meta.outputs.release_label }}
steps:
# Keep the same three producer steps.
# Remove CROSS_JOB_HINT as a supposed handoff.
consume:
needs: produce
runs-on: ubuntu-24.04
steps:
- name: Consume explicit handoff
env:
LABEL: ${{ needs.produce.outputs.release_label }}
run: |
printf 'consumer_label=%s\n' "$LABEL"
test "$LABEL" = 'chapter05-lab-checkpoint'
Keep the same trigger, suffix, runner label, permissions, optional repository variable, and synthetic values so the interface change is the only material difference.
7. Execute Revision B and compare causally
Record the new workflow SHA, run ID/attempt, producer/consumer conclusions, and output value. Verify the consumer succeeds. The difference between A and B should be explainable without invoking runner drift, token changes, or external service behavior.
| Evidence | Revision A | Revision B |
|---|---|---|
Producer same-job STAGE |
Works | Works |
| Step output release label | Produced | Produced |
| Cross-job mechanism | Incorrect GITHUB_ENV assumption |
Mapped job output |
| Consumer value | Empty | Expected label |
| Consumer conclusion | Failure | Success |
8. Classify one file-shaped value
Add a thought experiment: producer generates
evidence/report.json containing 5 MB of test evidence.
Do not add its contents to the job output. Record that the correct
production transport is an artifact/file mechanism, optionally
paired with a small digest/path identifier output.
This checkpoint does not need an external artifact action to prove the design boundary; later chapters cover artifact mechanics in depth.
9. Required evidence packet
- Both workflow revisions with hashes.
- Prediction list completed before execution.
- Run IDs/attempts for A and B.
- Event name, source SHA, workflow SHA, runner OS/arch.
-
Value ledger for
APP_NAME,TRACK,STAGE,release_label, and the hypothetical report file. - Producer Step 1/2/3 conclusions and bounded logs.
- Consumer failure evidence from Revision A.
- Exact job-output mapping and consumer success evidence from Revision B.
- Assumptions/limitations: no secrets, artifacts uploaded, packages, deployments, self-hosted runners, or cloud resources.
10. Verification checklist
- Exactly two jobs; producer has the three required progressive steps.
permissions: {}remains unchanged.- All values are synthetic/non-sensitive.
GITHUB_ENVis used only as same-job state.GITHUB_OUTPUTcreates the named step output.-
Revision B maps the output at job scope and consumes it through
needs. - Broken run remains preserved before repair.
- No whole-context dump or credential logging exists.
- 5 MB report is classified as artifact/file data, not an output.
11. Cleanup / rollback
- Keep both runs until checkpoint review is complete.
- Leave Revision B as the repaired state or revert the entire disposable branch after review.
-
Remove
LAB_TRACKif it was created only for the lab. - Delete only learner-owned disposable repository resources after evidence retention needs are met.
- No cloud, registry, environment, package, self-hosted runner, or credential cleanup is required.
12. What Chapter 05 adds to the production operating model
Chapter 05 adds the value-transport contract: every important value has a documented origin, sensitivity class, effective scope, precedence/owner, lifetime, transport mechanism, consumer, size/format expectation, and evidence trail. Same-job environment state stays same-job; cross-job control data uses explicit outputs; file-shaped evidence uses file/artifact transport; secrets remain outside ordinary configuration.
Chapter 06 can now focus on GITHUB_TOKEN, permissions,
least privilege, and API access without conflating authorization
with ordinary configuration/dataflow.
Knowledge check
Why must Revision A fail even though the producer job succeeds?
The producer writes the handoff only to its own
GITHUB_ENV; the consumer is a different job and
receives no such environment value.
What is the smallest causal repair?
Map steps.meta.outputs.release_label to
produce.outputs.release_label and read it through
needs.produce.outputs.release_label.
Why keep runner, permissions, trigger, and inputs unchanged between A and B?
To isolate the transport-interface change and make the comparison causal.
Where should a 5 MB report go?
Into file/artifact transport, optionally with a small digest/path identifier as an output.
What does Chapter 05 add before token/permission work begins?
An explicit value-transport contract separating configuration, same-job environment state, cross-job outputs, files/artifacts, and sensitive data.
Official references and version notes
-
Variables
— current distinction between workflow
env, configuration variables, default variables, and secrets. - Variables reference — current default variables, naming rules, precedence, configuration-variable limits, and context guidance.
- Store information in variables — current examples for workflow/job/step environment variables, configuration variables, contexts, and cross-step/job data flow.
-
Workflow commands for GitHub Actions
— current environment files including
GITHUB_ENV,GITHUB_OUTPUT, multiline syntax, and restrictions. -
Passing information between jobs
— current job-output mapping and
needs.<job>.outputsconsumption. -
Workflow syntax for GitHub Actions
— current
env, job outputs,needs, output size limits, and workflow syntax. - Store and share data with workflow artifacts — current artifact model for files that must outlive a step/job filesystem or are inappropriate for small outputs.
-
GitHub Actions changelog: set-output update
— why new workflow code should use environment files rather than
the deprecated stdout
set-outputcommand.
Version-sensitive variable/output behavior was rechecked against
current primary GitHub documentation on
2026-09-09. Executable labs use a disposable
repository, ubuntu-24.04, built-in Bash steps only,
and explicit permissions: {}; no external action,
secret, package, deployment, self-hosted runner, or cloud account
is required. At verification time, workflow/job/step
env uses the most specific scope; default
GITHUB_*/RUNNER_* environment variables
cannot be overwritten; the step that writes
GITHUB_ENV does not see the new value but later steps
in the same job do; GITHUB_ENV cannot set
NODE_OPTIONS; GITHUB_OUTPUT is the
current step-output channel; multiline environment/output values
use delimiter syntax whose delimiter must not occur on a line by
itself; and arbitrary data is safer as a file rather than
delimiter-encoded text. Configuration variables are non-secret,
have organization/repository/environment scopes, and are subject
to current limits including 48 KB per variable, 500 repository
variables, 1,000 organization variables, 100 environment
variables, and a 256 KB combined repository+organization payload
per workflow run. Job outputs are limited to 1 MB per job and 50
MB total per workflow run (size approximated using UTF-16), so
large/binary evidence belongs in files/artifacts rather than
outputs. GitHub Actions is continuously delivered, so regenerate
only after rechecking these limits and commands. The checkpoint
intentionally uses no external action so the transport boundary is
isolated from action runtime/version behavior.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.