在 GitHub Actions 中,如何将 terraform plan 的结果附加到 PR 上
你好,我是属于SRE部门的@ishii1648。
这篇文章是All About Group(株式会社オールアバウト) Advent Calendar 2022中的第19天的文章。
首先
我們目前正在 All About 進行 Terraform 的 CI 轉換。CI 的流程通常按以下順序進行相關操作:根據 PR 的創建和更新觸發相應的動作。
-
- 检测目标更改的目录
-
- 设置terraform
-
- 初始化terraform
-
- 计划terraform
-
- 验证terraform
- 将terraform计划结果附加到PR中
我觉得这是一个相当常见的结构,但有一个容易出错的地方,所以我希望能够分享解决方案和大家一起解决这个问题。
虽然这个内容相当专业,但如果对此感兴趣或有相同困扰的人能够从中获得帮助,那就非常幸运了。
关于绊倒点
如果使用terraform validate(使用conftest同样适用)的话,在terraform的设置中需要设置以下选项。
- name: Setup terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.x.x
terraform_wrapper: false
请注意 terraform_wrapper 选项,它的默认设置是 true,但是如果不将其设置为 false,验证操作将无法正常执行。
然而,如果设置为此,terraform将无法进行标准输出,从而使将计划结果附加到PR变得困难。
例如,在省略验证的CI构建中,可以使用以下代码将计划结果附加到PR上。
- name: Setup terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.2.0
- name: Terraform init & plan
id: plan
run: |
terraform init
terraform plan -no-color
working-directory: ${{ matrix.dir }}
continue-on-error: true
- name: Notify
if: steps.plan.outputs.exitcode == 2
uses: actions/github-script@v3.0.0
with:
github-token: ${{ secrets.github_token }}
script: |
const output = `## \`${{ matrix.dir }}\`
<details><summary>Show Plan</summary>
\`\`\`terraform\n${{ steps.plan.outputs.stdout }}\`\`\`
</details>`;
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
})
我正在接收并通知 terraform plan 的结果作为下一个作业的标准输出(steps.plan.outputs.stdout)。但是,如果我尝试添加验证过程,就无法再使用之前提到的标准输出,这让我感到困惑。
方法去除
有两种方式可以在提交请求(PR)附上结果的同时对其进行验证:
以下是其中一种方式的代码:
- name: Setup terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.2.0
terraform_wrapper: false
- name: Terraform init & plan
id: plan
run: |
terraform init
terraform plan -no-color -out=tfplan
working-directory: ${{ matrix.dir }}
continue-on-error: true
- name: Terraform show
id: show
run: |
terraform show -no-color tfplan > tfplan.txt
terraform show -no-color -json tfplan > tfplan.json
cat tfplan.txt
working-directory: ${{ matrix.dir }}
- name: Terraform validate
id: validate
run: |
cp ${GITHUB_WORKSPACE}/policies/constraints/* ${GITHUB_WORKSPACE}/policy-library/policies/constraints
gcloud beta terraform vet tfplan.json --policy-library=${GITHUB_WORKSPACE}/policy-library --format=json
- name: Notify
uses: actions/github-script@v3.0.0
with:
github-token: ${{ secrets.github_token }}
script: |
const output = `## \`${{ matrix.dir }}\`
<details><summary>Show Plan</summary>
\`\`\`terraform\n${{ steps.show.outputs.stdout }}\`\`\`
</details>`;
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
})
重点是在执行 terraform plan 时设置 out 选项。out 选项会将 plan 的执行结果以二进制文件形式保存。由于我们没有使用标准输出,因此即使禁用了 terraform_wrapper,这里的功能仍然有效。
保存为二进制格式的plan结果可以通过使用terraform show命令将其转化为文本,并将其内容作为通知处理。
最后
“那个怎么样了?” le?)
我认为这是非常具有专业性的内容,但如果要将Terraform进行持续集成,我认为在其中包含静态检查例如validate也是很普遍的。在我想出这种方法之前,我花费了一个多月的时间,所以如果有相同烦恼的人,我希望你们可以参考一下。
今天是All About Group(株式会社オールアバウト)Advent Calendar 2022的第19天。