Appearance
GitHub Actions环境变量
环境变量在GitHub Actions中扮演着重要角色,它们用于在工作流、作业和步骤之间传递数据,配置运行环境,以及管理敏感信息。本文档将详细介绍环境变量的使用方法和最佳实践。
环境变量基础
环境变量的作用域
GitHub Actions中环境变量有三个作用域级别:
- 工作流级别(Workflow level):对整个工作流有效
- 作业级别(Job level):仅对特定作业有效
- 步骤级别(Step level):仅对特定步骤有效
yaml
# 工作流级别的环境变量
env:
NODE_VERSION: '18.x'
BUILD_PATH: './dist'
CI: true
jobs:
build:
runs-on: ubuntu-latest
# 作业级别的环境变量
env:
NODE_ENV: production
DEBUG: false
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: npm ci
# 步骤级别的环境变量
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Build application
run: |
echo "Node version: $NODE_VERSION"
echo "Build path: $BUILD_PATH"
echo "CI: $CI"
echo "Node environment: $NODE_ENV"
echo "Debug: $DEBUG"
env:
BUILD_NUMBER: ${{ github.run_number }}
预定义环境变量
GitHub Actions提供了许多预定义的环境变量:
yaml
jobs:
debug-env:
runs-on: ubuntu-latest
steps:
- name: Print predefined environment variables
run: |
echo "GITHUB_WORKFLOW: $GITHUB_WORKFLOW"
echo "GITHUB_RUN_ID: $GITHUB_RUN_ID"
echo "GITHUB_RUN_NUMBER: $GITHUB_RUN_NUMBER"
echo "GITHUB_ACTION: $GITHUB_ACTION"
echo "GITHUB_ACTIONS: $GITHUB_ACTIONS"
echo "GITHUB_ACTOR: $GITHUB_ACTOR"
echo "GITHUB_REPOSITORY: $GITHUB_REPOSITORY"
echo "GITHUB_EVENT_NAME: $GITHUB_EVENT_NAME"
echo "GITHUB_SHA: $GITHUB_SHA"
echo "GITHUB_REF: $GITHUB_REF"
echo "GITHUB_REF_NAME: $GITHUB_REF_NAME"
echo "GITHUB_WORKSPACE: $GITHUB_WORKSPACE"
echo "GITHUB_EVENT_PATH: $GITHUB_EVENT_PATH"
echo "RUNNER_OS: $RUNNER_OS"
echo "RUNNER_TEMP: $RUNNER_TEMP"
echo "RUNNER_TOOL_CACHE: $RUNNER_TOOL_CACHE"
自定义环境变量
基本用法
yaml
env:
APP_NAME: 'my-application'
APP_VERSION: '1.0.0'
NODE_VERSION: '18.17.0'
PORT: 3000
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Use environment variables
run: |
echo "Building $APP_NAME version $APP_VERSION"
echo "Using Node.js $NODE_VERSION"
echo "Server will run on port $PORT"
使用表达式设置环境变量
yaml
jobs:
dynamic-env:
runs-on: ubuntu-latest
steps:
- name: Set environment variables using expressions
run: |
echo "Repository: $REPO_NAME"
echo "Branch: $BRANCH_NAME"
echo "Is main branch: $IS_MAIN_BRANCH"
env:
REPO_NAME: ${{ github.repository }}
BRANCH_NAME: ${{ github.ref_name }}
IS_MAIN_BRANCH: ${{ github.ref == 'refs/heads/main' }}
COMMIT_AUTHOR: ${{ github.event.head_commit.author.name }}
RUN_AT: ${{ github.event.repository.updated_at }}
条件环境变量
yaml
jobs:
conditional-env:
runs-on: ubuntu-latest
steps:
- name: Set conditional environment variables
run: |
echo "Environment: $ENVIRONMENT"
echo "Database URL: $DATABASE_URL"
env:
ENVIRONMENT: ${{ github.ref == 'refs/heads/main' && 'production' || 'development' }}
DATABASE_URL: ${{ github.ref == 'refs/heads/main' && secrets.PROD_DB_URL || secrets.DEV_DB_URL }}
密钥管理(Secrets)
使用密钥
yaml
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy with secrets
run: |
# 使用密钥进行部署
echo "Deploying with token..."
# deployment command using $DEPLOY_TOKEN
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
API_KEY: ${{ secrets.API_KEY }}
DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
密钥的安全使用
yaml
jobs:
secure-deployment:
runs-on: ubuntu-latest
steps:
- name: Secure deployment
run: |
# 密钥不会在日志中显示
curl -X POST \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"message": "Deployment successful"}' \
$API_URL
env:
API_TOKEN: ${{ secrets.API_TOKEN }}
API_URL: ${{ secrets.API_URL }}
环境变量的继承和覆盖
作用域覆盖规则
yaml
env:
GLOBAL_VAR: 'global'
SHARED_VAR: 'workflow-level'
jobs:
job1:
runs-on: ubuntu-latest
env:
JOB_VAR: 'job1'
SHARED_VAR: 'job1-level' # 覆盖工作流级别的变量
steps:
- name: Check variable inheritance in job1
run: |
echo "GLOBAL_VAR: $GLOBAL_VAR" # 输出: global
echo "SHARED_VAR: $SHARED_VAR" # 输出: job1-level
echo "JOB_VAR: $JOB_VAR" # 输出: job1
- name: Step with local override
run: |
echo "SHARED_VAR: $SHARED_VAR" # 输出: job1-level
echo "STEP_VAR: $STEP_VAR" # 输出: step-level
env:
SHARED_VAR: 'step-level' # 覆盖作业级别的变量
STEP_VAR: 'step-level'
job2:
runs-on: ubuntu-latest
env:
JOB_VAR: 'job2'
SHARED_VAR: 'job2-level' # 覆盖工作流级别的变量
steps:
- name: Check variable inheritance in job2
run: |
echo "GLOBAL_VAR: $GLOBAL_VAR" # 输出: global
echo "SHARED_VAR: $SHARED_VAR" # 输出: job2-level
echo "JOB_VAR: $JOB_VAR" # 输出: job2
动态环境变量
在步骤中设置环境变量
yaml
jobs:
dynamic-env:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set environment variables dynamically
run: |
# 设置环境变量到GITHUB_ENV文件
echo "BUILD_NUMBER=$(date +%s)" >> $GITHUB_ENV
echo "BUILD_TAG=v1.0.$(date +%s)" >> $GITHUB_ENV
echo "COMMIT_MESSAGE=$(git log -1 --pretty=format:%s)" >> $GITHUB_ENV
echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV
- name: Use dynamically set environment variables
run: |
echo "Build number: $BUILD_NUMBER"
echo "Build tag: $BUILD_TAG"
echo "Commit message: $COMMIT_MESSAGE"
echo "Short SHA: $SHORT_SHA"
使用输出设置环境变量
yaml
jobs:
set-env-from-output:
runs-on: ubuntu-latest
steps:
- name: Calculate values
id: calculator
run: |
RESULT=$(echo "2 + 2" | bc)
echo "result=$RESULT" >> $GITHUB_OUTPUT
echo "timestamp=$(date -u +%Y%m%d_%H%M%S)" >> $GITHUB_OUTPUT
- name: Set calculated values as environment variables
run: |
echo "CALC_RESULT=${{ steps.calculator.outputs.result }}" >> $GITHUB_ENV
echo "BUILD_TIME=${{ steps.calculator.outputs.timestamp }}" >> $GITHUB_ENV
- name: Use calculated environment variables
run: |
echo "Calculated result: $CALC_RESULT"
echo "Build time: $BUILD_TIME"
复杂环境变量配置
嵌套对象和数组
yaml
jobs:
complex-env:
runs-on: ubuntu-latest
steps:
- name: Work with complex environment variables
run: |
echo "Environment: $ENV_CONFIG"
# 解析JSON格式的环境变量
echo $ENV_CONFIG | jq .
env:
ENV_CONFIG: ${{ toJSON(vars) }}
vars: |
{
"database": {
"host": "${{ secrets.DB_HOST }}",
"port": 5432,
"name": "myapp"
},
"features": ["auth", "logging", "metrics"],
"timeout": 30
}
多环境配置
yaml
env:
# 全局配置
APP_NAME: 'my-app'
NODE_VERSION: '18'
jobs:
development:
runs-on: ubuntu-latest
env:
ENVIRONMENT: 'development'
API_URL: 'https://dev-api.example.com'
LOG_LEVEL: 'debug'
DATABASE_URL: ${{ secrets.DEV_DATABASE_URL }}
steps:
- name: Deploy to development
run: |
echo "Environment: $ENVIRONMENT"
echo "API URL: $API_URL"
echo "Log level: $LOG_LEVEL"
staging:
runs-on: ubuntu-latest
env:
ENVIRONMENT: 'staging'
API_URL: 'https://staging-api.example.com'
LOG_LEVEL: 'info'
DATABASE_URL: ${{ secrets.STAGING_DATABASE_URL }}
steps:
- name: Deploy to staging
run: |
echo "Environment: $ENVIRONMENT"
echo "API URL: $API_URL"
echo "Log level: $LOG_LEVEL"
production:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
env:
ENVIRONMENT: 'production'
API_URL: 'https://api.example.com'
LOG_LEVEL: 'warn'
DATABASE_URL: ${{ secrets.PROD_DATABASE_URL }}
steps:
- name: Deploy to production
run: |
echo "Environment: $ENVIRONMENT"
echo "API URL: $API_URL"
echo "Log level: $LOG_LEVEL"
环境变量验证
验证必需的环境变量
yaml
jobs:
validate-env:
runs-on: ubuntu-latest
steps:
- name: Validate required environment variables
run: |
: "${APP_NAME:?APP_NAME is required}"
: "${DATABASE_URL:?DATABASE_URL is required}"
: "${API_TOKEN:?API_TOKEN is required}"
echo "All required environment variables are set"
echo "App: $APP_NAME"
echo "Database: $DATABASE_URL"
env:
APP_NAME: ${{ vars.APP_NAME }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
API_TOKEN: ${{ secrets.API_TOKEN }}
条件验证
yaml
jobs:
conditional-validation:
runs-on: ubuntu-latest
steps:
- name: Conditional validation
run: |
if [ "$IS_PRODUCTION" = "true" ]; then
echo "Validating production environment..."
: "${PROD_DATABASE_URL:?PROD_DATABASE_URL is required for production}"
: "${PROD_API_KEY:?PROD_API_KEY is required for production}"
else
echo "Validating development environment..."
: "${DEV_DATABASE_URL:?DEV_DATABASE_URL is required for development}"
fi
env:
IS_PRODUCTION: ${{ github.ref == 'refs/heads/main' }}
PROD_DATABASE_URL: ${{ secrets.PROD_DATABASE_URL }}
PROD_API_KEY: ${{ secrets.PROD_API_KEY }}
DEV_DATABASE_URL: ${{ secrets.DEV_DATABASE_URL }}
环境变量最佳实践
1. 使用变量(Variables)而非密钥存储非敏感配置
yaml
# 在GitHub仓库设置中配置变量
# 不要将非敏感配置信息存储在密钥中
env:
APP_VERSION: ${{ vars.APP_VERSION }} # 使用变量
LOG_LEVEL: ${{ vars.LOG_LEVEL }} # 使用变量
API_URL: ${{ vars.API_URL }} # 使用变量
SECRET_KEY: ${{ secrets.SECRET_KEY }} # 使用密钥(敏感信息)
2. 环境变量命名规范
yaml
env:
# 使用大写字母和下划线
APP_NAME: 'my-application'
DATABASE_URL: ${{ secrets.DATABASE_URL }}
API_VERSION: 'v1'
# 避免使用小写或驼峰命名
# appName: 'my-application' # 不推荐
# databaseUrl: '...' # 不推荐
3. 敏感信息处理
yaml
jobs:
secure-operation:
runs-on: ubuntu-latest
steps:
- name: Secure operation
run: |
# 不要在日志中直接输出敏感信息
echo "Processing with secure token..." # 好的做法
# echo "Token: $TOKEN" # 避免这样做
# 在脚本中使用环境变量
./secure-script.sh --token="$TOKEN"
env:
TOKEN: ${{ secrets.SECURE_TOKEN }}
4. 环境变量的分层配置
yaml
# 工作流级别:全局配置
env:
APP_NAME: 'my-app'
NODE_VERSION: '18'
jobs:
build:
runs-on: ubuntu-latest
# 作业级别:环境特定配置
env:
NODE_ENV: 'production'
BUILD_TARGET: 'dist'
steps:
- name: Build step
run: |
echo "Building $APP_NAME for $NODE_ENV"
# 步骤级别:临时配置
env:
TEMP_VAR: 'temporary-value'
实际应用示例
构建环境配置
yaml
name: Build and Test
on: [push, pull_request]
env:
NODE_VERSION: '18'
BUILD_PATH: './dist'
TEST_REPORT_PATH: './test-reports'
jobs:
build:
runs-on: ubuntu-latest
env:
NODE_ENV: 'development'
BUILD_MODE: 'production'
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build application
run: npm run build
env:
NODE_ENV: ${{ env.NODE_ENV }}
BUILD_PATH: ${{ env.BUILD_PATH }}
- name: Run tests
run: npm run test:ci
env:
TEST_REPORT_PATH: ${{ env.TEST_REPORT_PATH }}
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-${{ github.sha }}
path: ${{ env.BUILD_PATH }}
部署环境配置
yaml
name: Deploy
on:
push:
branches: [main]
env:
APP_NAME: 'my-application'
DEPLOY_PATH: '/var/www/app'
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
env:
NODE_ENV: 'production'
DEPLOY_USER: 'deploy'
steps:
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: build-${{ github.sha }}
path: ${{ env.DEPLOY_PATH }}
- name: Deploy application
run: |
echo "Deploying ${{ env.APP_NAME }} to production"
echo "Deploy path: ${{ env.DEPLOY_PATH }}"
echo "Environment: ${{ env.NODE_ENV }}"
# 部署逻辑
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
通过合理使用环境变量,可以构建灵活、安全、可维护的GitHub Actions工作流,有效管理配置信息和敏感数据。