Variables and secrets
Table of contents
- Types of configuration
- Environment variables
- Secrets
- Configuration variables
- Environments
- Practical exercises
1 - Types of configuration
Overview
Comparison
| Type | Masked | Scope | Usage |
|---|---|---|---|
env | ❌ | Workflow | Build configuration |
secrets | ✅ | Repo/Org/Env | API keys, tokens |
vars | ❌ | Repo/Org | URLs, flags |
🔝 Back to table of contents
2 - Environment variables
Definition in the workflow
# Niveau workflow
env:
CI: true
NODE_VERSION: '18'
jobs:
build:
# Niveau job
env:
BUILD_TYPE: production
runs-on: ubuntu-latest
steps:
# Niveau step
- name: Build
env:
DEBUG: '1'
run: |
echo "CI: $CI"
echo "NODE: $NODE_VERSION"
echo "TYPE: $BUILD_TYPE"
echo "DEBUG: $DEBUG"
Predefined variables
- run: |
# Informations GitHub
echo "Repository: $GITHUB_REPOSITORY"
echo "SHA: $GITHUB_SHA"
echo "Ref: $GITHUB_REF"
echo "Actor: $GITHUB_ACTOR"
echo "Workspace: $GITHUB_WORKSPACE"
# Runner
echo "OS: $RUNNER_OS"
echo "Arch: $RUNNER_ARCH"
echo "Temp: $RUNNER_TEMP"
Dynamic variables
steps:
- name: Set variables
run: |
echo "BUILD_DATE=$(date +%Y%m%d)" >> $GITHUB_ENV
echo "GIT_SHA_SHORT=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
- name: Use variables
run: |
echo "Date: $BUILD_DATE"
echo "SHA: $GIT_SHA_SHORT"
Step outputs
steps:
- name: Generate data
id: gen
run: echo "version=1.0.0" >> $GITHUB_OUTPUT
- name: Use output
run: echo "Version: ${{ steps.gen.outputs.version }}"
🔝 Back to table of contents
3 - Secrets
Create a secret
- Repository → Settings → Secrets and variables → Actions
- New repository secret
- Name and value
Usage
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy
env:
API_KEY: ${{ secrets.API_KEY }}
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
run: ./deploy.sh
- name: Login Docker
run: |
echo "${{ secrets.DOCKER_PASSWORD }}" | \
docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
GITHUB_TOKEN
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: Create Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release create v1.0.0
| Permission | Scope |
|---|---|
contents: read | Clone repo |
contents: write | Push, releases |
packages: write | GitHub Packages |
issues: write | Create issues |
Best practices
# ✅ Bon : Dans env, jamais dans run directement
- name: Deploy
env:
TOKEN: ${{ secrets.TOKEN }}
run: curl -H "Authorization: $TOKEN" ...
# ❌ Mauvais : Secret exposé dans les logs
- run: curl -H "Authorization: ${{ secrets.TOKEN }}" ...
Security
Secrets are masked in the logs, but avoid passing them as command arguments.
Organization secrets
# Accessible si partagé avec le repo
env:
ORG_API_KEY: ${{ secrets.ORG_API_KEY }}
🔝 Back to table of contents
4 - Configuration variables
Create a variable
- Repository → Settings → Secrets and variables → Actions
- Variables tab
- New repository variable
Usage
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Build
env:
APP_URL: ${{ vars.APP_URL }}
FEATURE_FLAG: ${{ vars.ENABLE_FEATURE }}
run: |
echo "URL: $APP_URL"
echo "Feature: $FEATURE_FLAG"
When to use vars vs secrets
| Data | Type | Example |
|---|---|---|
| API Key | secrets | sk_live_xxx |
| Password | secrets | myP@ssw0rd |
| Public URL | vars | https://api.example.com |
| Feature flag | vars | true |
| Version | vars | 1.0.0 |
🔝 Back to table of contents
5 - Environments
Create an environment
- Repository → Settings → Environments
- New environment (staging, production...)
- Configure the protections
Protection rules
| Protection | Description |
|---|---|
| Required reviewers | Manual approval |
| Wait timer | Delay before deployment |
| Deployment branches | Allowed branches |
Usage
jobs:
deploy-staging:
environment: staging
runs-on: ubuntu-latest
steps:
- name: Deploy
env:
URL: ${{ vars.DEPLOY_URL }} # Variable d'environment
KEY: ${{ secrets.DEPLOY_KEY }} # Secret d'environment
run: ./deploy.sh
deploy-production:
needs: deploy-staging
environment:
name: production
url: https://myapp.com
runs-on: ubuntu-latest
steps:
- run: ./deploy.sh
Complete workflow
name: Deploy
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: build
path: dist/
deploy-staging:
needs: build
environment: staging
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
name: build
- run: ./deploy.sh ${{ vars.STAGING_URL }}
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
deploy-production:
needs: deploy-staging
environment: production
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
name: build
- run: ./deploy.sh ${{ vars.PROD_URL }}
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
🔝 Back to table of contents
6 - Practical exercises
Exercise 1: Use secrets
Create a workflow that uses a secret for Docker login:
Solution
name: Docker Build
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Login to Docker Hub
env:
DOCKER_USER: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASS: ${{ secrets.DOCKER_PASSWORD }}
run: echo "$DOCKER_PASS" | docker login -u "$DOCKER_USER" --password-stdin
- run: docker build -t myapp .
Exercise 2: Dynamic variables
Create a variable with the date and the SHA:
Solution
name: Version Info
on: push
jobs:
version:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set version
run: |
echo "VERSION=$(date +%Y.%m.%d)-$(git rev-parse --short HEAD)" >> $GITHUB_ENV
- name: Show version
run: echo "Version: $VERSION"
Quiz
Q1. What is the difference between secrets and vars?
Answer
secrets are masked in the logs and for sensitive data. vars are visible and for non-sensitive configuration.
Q2. How do you access a secret?
Answer
${{ secrets.SECRET_NAME }}
🔝 Back to table of contents
Key takeaways
- secrets: sensitive data (masked)
- vars: non-sensitive configuration (visible)
$GITHUB_ENVfor dynamic variables$GITHUB_OUTPUTfor step outputs- GITHUB_TOKEN: auto-generated token
- Environments: staging, production with protections
- Never display secrets in the logs