Skip to main content

Variables and secrets


Table of contents

  1. Types of configuration
  2. Environment variables
  3. Secrets
  4. Configuration variables
  5. Environments
  6. Practical exercises


1 - Types of configuration

Overview

Comparison

TypeMaskedScopeUsage
envWorkflowBuild configuration
secretsRepo/Org/EnvAPI keys, tokens
varsRepo/OrgURLs, 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

  1. Repository → Settings → Secrets and variables → Actions
  2. New repository secret
  3. 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
PermissionScope
contents: readClone repo
contents: writePush, releases
packages: writeGitHub Packages
issues: writeCreate 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

  1. Repository → Settings → Secrets and variables → Actions
  2. Variables tab
  3. 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

DataTypeExample
API Keysecretssk_live_xxx
PasswordsecretsmyP@ssw0rd
Public URLvarshttps://api.example.com
Feature flagvarstrue
Versionvars1.0.0

🔝 Back to table of contents



5 - Environments

Create an environment

  1. Repository → Settings → Environments
  2. New environment (staging, production...)
  3. Configure the protections

Protection rules

ProtectionDescription
Required reviewersManual approval
Wait timerDelay before deployment
Deployment branchesAllowed 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_ENV for dynamic variables
  • $GITHUB_OUTPUT for step outputs
  • GITHUB_TOKEN: auto-generated token
  • Environments: staging, production with protections
  • Never display secrets in the logs

🔝 Back to table of contents


← Previous chapter | Next chapter: Cache and artifacts →