You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于GitHub Actions+Terraform Cloud+Azure的多目录部署问题求解

解决方案一:多目录Terraform部署标准最优方案

针对多目录(app1、app2等)的基础设施部署场景,推荐结合GitHub Actions矩阵策略+路径触发+Terraform Workspace隔离的方案,既符合最佳实践,又能高效实现目录级别的独立部署。

核心思路

  1. 路径触发:仅当指定目录或工作流文件变更时触发部署流程,避免不必要的运行。
  2. 矩阵策略:复用工作流步骤,对每个目标目录单独执行Terraform操作。
  3. 状态隔离:每个目录对应一个Terraform Cloud Workspace,确保基础设施状态互不干扰。

完整工作流示例

name: Terraform Multi-Directory Deployment
on:
  push:
    paths:
      - 'app1/**'
      - 'app2/**'
      - '.github/workflows/terraform.yml'
  pull_request:
    paths:
      - 'app1/**'
      - 'app2/**'
      - '.github/workflows/terraform.yml'

jobs:
  terraform-deploy:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        target_dir: ['app1', 'app2'] # 新增目录只需添加新条目

    steps:
      - name: 检出代码
        uses: actions/checkout@v4

      - name: 筛选变更目录
        id: filter
        run: |
          # 根据事件类型获取变更目录
          if [ "${{ github.event_name }}" = "push" ]; then
            CHANGED=$(git diff --name-only HEAD^ HEAD | cut -d'/' -f1 | sort -u)
          else
            CHANGED=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} | cut -d'/' -f1 | sort -u)
          fi
          # 判断当前矩阵目录是否在变更列表中
          if echo "$CHANGED" | grep -q "${{ matrix.target_dir }}"; then
            echo "deploy=true" >> $GITHUB_OUTPUT
          else
            echo "deploy=false" >> $GITHUB_OUTPUT
          fi

      - name: 配置Terraform环境
        if: steps.filter.outputs.deploy == 'true'
        uses: hashicorp/setup-terraform@v3
        with:
          cli_config_credentials_token: ${{ secrets.TF_CLOUD_TOKEN }}

      - name: Terraform初始化
        if: steps.filter.outputs.deploy == 'true'
        working-directory: ${{ matrix.target_dir }}
        run: terraform init -reconfigure

      - name: Terraform Plan
        if: steps.filter.outputs.deploy == 'true'
        working-directory: ${{ matrix.target_dir }}
        run: terraform plan -out=tfplan
        env:
          ARM_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
          ARM_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
          ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
          ARM_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}

      - name: Terraform Apply
        if: steps.filter.outputs.deploy == 'true' && github.event_name == 'push'
        working-directory: ${{ matrix.target_dir }}
        run: terraform apply tfplan
        env:
          ARM_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
          ARM_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
          ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
          ARM_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}

方案优势

  • 扩展性强:新增目录只需在matrix.target_dir中添加条目。
  • 资源高效:仅变更目录会执行部署操作,节省CI/CD资源。
  • 状态安全:每个目录的Terraform状态独立存储,避免互相影响。

解决方案二:修复现有脚本在GitHub Actions中的运行问题

你遇到的HEAD^报错,本质是GitHub Actions默认采用浅克隆(仅拉取最新1次提交),导致找不到HEAD^的历史提交;同时PR场景下HEAD^的引用逻辑也不适用。以下是具体修复步骤:

1. 修改代码检出步骤,获取完整提交历史

在工作流的checkout步骤中添加fetch-depth: 0参数,拉取完整仓库历史:

- name: 检出代码
  uses: actions/checkout@v4
  with:
    fetch-depth: 0 # 获取所有提交历史,支持HEAD^等引用

2. 优化变更目录检测脚本,兼容不同事件类型

修改脚本,区分push和pull_request事件,使用正确的提交对比范围:

#!/bin/bash

# 根据事件类型确定提交对比范围
if [ "${{ github.event_name }}" = "push" ]; then
  # Push事件:对比当前提交与上一次提交
  DIFF_REF="HEAD^ HEAD"
elif [ "${{ github.event_name }}" = "pull_request" ]; then
  # PR事件:对比PR基准分支与当前分支的提交
  DIFF_REF="${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }}"
else
  echo "不支持的事件类型"
  exit 1
fi

# 获取变更的包含main.tf的目录
CHANGED_DIRS=$(git diff --name-only $DIFF_REF | xargs dirname | grep -E '^(app1|app2)' | sort -u)

# 遍历目录执行Terraform Plan
for dir in $CHANGED_DIRS; do
  echo "=== 处理目录: $dir ==="
  cd "$dir" || continue
  terraform init -reconfigure
  terraform plan
  cd ..
done

修复原理

  • fetch-depth: 0解决了浅克隆导致的历史提交缺失问题,让HEAD^在push场景下可用。
  • PR场景下改用基准分支SHA与当前分支SHA对比,避免HEAD^引用错误。

内容的提问来源于stack exchange,提问作者Fuat Ulugay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 00:35:19