Skip to content
On this page

GitHub Actions环境变量

环境变量在GitHub Actions中扮演着重要角色,它们用于在工作流、作业和步骤之间传递数据,配置运行环境,以及管理敏感信息。本文档将详细介绍环境变量的使用方法和最佳实践。

环境变量基础

环境变量的作用域

GitHub Actions中环境变量有三个作用域级别:

  1. 工作流级别(Workflow level):对整个工作流有效
  2. 作业级别(Job level):仅对特定作业有效
  3. 步骤级别(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工作流,有效管理配置信息和敏感数据。