Environment variables and secrets #741
|
What's the difference between env, secrets, and vars contexts in a workflow? Can a step access a secret from another job directly? |
Replies: 1 comment
|
| Context | What it holds | Scope | Where defined |
|---|---|---|---|
| env | Plain-text variables you set inline | Per-step, per-job, per-workflow, or per-environment | env: key in YAML, or $GITHUB_ENV |
| secrets | Encrypted values (passwords, tokens, API keys) | Repository, environment, or organization | GitHub UI, CLI, or REST API |
| vars | Plain-text configuration variables (no encryption) | Repository, environment, or organization | GitHub UI, CLI, or REST API |
Key distinctions:
envis ephemeral — defined in the workflow file itself or set during a run. It's visible in logs (unless you explicitly mask it). Use it for step-to-step data or temporary configuration.secretsare encrypted at rest, never displayed in logs, and scrubbed from any output. Use them for sensitive data. They are not available to forked PRs by default (unless explicitly configured).varswas introduced later to fill the gap betweenenvandsecrets— reusable configuration values that aren't sensitive but you don't want hardcoded across workflow files (e.g., default region, app name, deployment URL). They are plain text, visible to anyone who can read the repo.
Access syntax:
${{ env.MY_VAR }}${{ secrets.MY_SECRET }}${{ vars.MY_CONFIG }}
Can a step access a secret from another job directly?
No — not without explicitly passing it. Secrets are scoped to the job that requests them. Jobs run on separate runners, so they don't share memory. To use a secret from a previous job, you must:
- Output it from the first job using workflow commands (though this is strongly discouraged for secrets — it may leak them into logs).
- Pass it as a job output — but outputs are visible in the API and logs.
- Re-declare the secret in each job that needs it.
The standard approach is to just reference the secret by name in each job:
jobs: build: runs-on: ubuntu-latest steps: - run: echo "${{ secrets.DEPLOY_KEY }}"
deploy:
needs: build
runs-on: ubuntu-latest
steps:
# This is a separate job — secret must be requested again
- run: echo "${{ secrets.DEPLOY_KEY }}"
Exception — environment secrets: If a secret is scoped to a GitHub Environment (e.g., production), you can reference it from any job that declares that environment:
deploy:
environment: production
steps:
- run: echo "${{ secrets.DEPLOY_KEY }}"
But you still re-declare it per job. There's no cross-job secret inheritance without explicit wiring.
envvssecretsvsvarsin GitHub ActionsKey distinctions:
envis ephemeral — defined in the workflow file itself or set during a run…