GitHub Enterprise 3.6.2中如何关联Terraform Plan与Apply工作流?
解决GitHub Actions中Terraform Plan与Apply的衔接问题
方案一:分两个工作流,通过GitHub Artifacts传递Plan文件
这是最直接可行的方案,利用GitHub Artifacts在PR触发的Plan工作流和合并触发的Apply工作流之间传递Plan输出文件。
1. PR触发的Plan工作流(.github/workflows/terraform-plan.yml)
name: Terraform Plan on: pull_request: paths: - '**.tf' - '**.tfvars' - 'terraform.lock.hcl' jobs: plan: runs-on: ubuntu-latest permissions: contents: read pull-requests: write actions: write steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Terraform uses: hashicorp/setup-terraform@v3 with: terraform_version: 1.5.0 # 匹配你的Terraform版本 - name: Terraform Init run: terraform init -backend-config=backend.tfvars # 根据实际配置调整 - name: Terraform Lint run: tflint --config .tflint.hcl # 需提前安装tflint,或使用官方action - name: Generate Terraform Plan run: | terraform plan -out=tfplan.binary terraform show -json tfplan.binary > tfplan.json - name: Upload Plan Artifacts uses: actions/upload-artifact@v4 with: name: tfplan-pr-${{ github.event.number }} path: | tfplan.binary tfplan.json retention-days: 30 # 按需调整保留时间 - name: Add Plan Summary to PR uses: actions/github-script@v6 with: script: | const fs = require('fs'); const plan = JSON.parse(fs.readFileSync('tfplan.json', 'utf8')); const changes = plan.resource_changes.map(rc => `${rc.type}.${rc.name}: ${rc.change.actions.join(', ')}`); github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: `### Terraform Plan Summary\n\`\`\`\n${changes.join('\n')}\n\`\`\`` });
2. 合并触发的Apply工作流(.github/workflows/terraform-apply.yml)
name: Terraform Apply on: pull_request_target: types: [closed] paths: - '**.tf' - '**.tfvars' - 'terraform.lock.hcl' jobs: apply: runs-on: ubuntu-latest permissions: contents: read actions: read if: github.event.pull_request.merged == true steps: - name: Get PR Number id: get-pr run: echo "pr_number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT - name: Download Plan Artifacts uses: actions/download-artifact@v4 with: name: tfplan-pr-${{ steps.get-pr.outputs.pr_number }} path: ./plan - name: Checkout Merged Code uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.merge_commit_sha }} - name: Setup Terraform uses: hashicorp/setup-terraform@v3 with: terraform_version: 1.5.0 - name: Terraform Init run: terraform init -backend-config=backend.tfvars - name: Verify Plan Consistency run: | # 可选:验证当前代码与Plan时的代码一致,防止中间变更 terraform plan -out=current_plan.binary if diff ./plan/tfplan.binary current_plan.binary; then echo "代码与Plan版本一致,继续执行Apply" else echo "警告:当前代码与Plan时的代码存在差异,请确认后再执行" # 若需严格校验,可在此处添加exit 1终止工作流 fi - name: Terraform Apply run: terraform apply ./plan/tfplan.binary env: TF_IN_AUTOMATION: "true"
关键细节说明
- Artifact命名包含PR号,确保合并时能精准匹配对应的Plan文件
- 使用
pull_request_target触发合并事件,避免私有仓库的权限访问问题 - 可选的一致性检查步骤,防止PR合并后到Apply前有其他代码变更
- 配置必要的工作流权限,确保能读写PR评论、操作Artifacts
方案二:利用GitHub Environments实现审批(需手动触发)
如果坚持要在同一工作流中完成,可借助GitHub Environments的手动审批功能,但无法自动等待PR合并,只能在Plan后暂停等待人工触发Apply(适合需要额外审核的场景)。
示例工作流:
name: Terraform Plan & Apply on: pull_request: paths: - '**.tf' jobs: plan: runs-on: ubuntu-latest permissions: contents: read actions: write steps: # 同方案一的Plan步骤,省略... - name: Upload Plan Artifact uses: actions/upload-artifact@v4 with: name: tfplan path: tfplan.binary apply: needs: plan runs-on: ubuntu-latest environment: production # 提前在仓库设置该环境并开启审批 if: github.event.pull_request.merged == true permissions: contents: read actions: read steps: - name: Download Plan Artifact uses: actions/download-artifact@v4 with: name: tfplan # 同方案一的Apply步骤,省略...
注意事项
- 工作流最长执行时间为72小时,若PR审核超过这个时间,工作流会直接失败
- 需手动在GitHub Environments中批准
apply任务,无法完全自动触发,因此更适合需要额外人工确认的场景
总结
推荐使用方案一,它完美适配"PR创建自动Plan,合并自动Apply"的需求,避免了工作流长时间挂起的问题,同时通过Artifacts保证了Plan文件的可靠传递。
内容的提问来源于stack exchange,提问作者Chris Batchelor
相关产品推荐
相关产品推荐

