🤖

TerraformコードのレビューをAIにさせてみた

2023/12/14に公開

こんにちは、マネーフォワード株式会社の tatsuo48です。
Terraformのコードレビューに最近流行りのOpenAIを導入してみました!

  • 導入方法
  • 使ってみての感想

について書きたいと思います。

導入方法

AIコードレビューというと以下のようなプロダクトがあります。
https://coderabbit.ai/

今回はこういったプロダクトは使わずに一旦簡単な技術検証として以下のようなGitHub Actionsを作成しました。
OPENAI_API_KEYOPENAI_ORG_IDにはそれぞれ以下から取得した値を入れておきます

https://platform.openai.com/api-keys
https://platform.openai.com/account/organization

name: Open AI PR reviewer

on:
  pull_request:
    #types: [opened, reopened]
    # If you add "synchronize", it will also work when the PR is updated, so the number of OpenAI API calls will increase. Please be careful with the billing.
    types: [opened, reopened, synchronize]

jobs:
  add-comment:
    runs-on: ubuntu-latest
    env:
      base_branch: master
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
      OPENAI_ORG_ID: ${{ secrets.OPENAI_ORG_ID }}
    steps:
      - name: Install jq
        run: sudo apt-get install -y jq

      - name: checkout
        uses: actions/checkout@v4
      - name: get review result and post comment
        shell: sh
        run: |
          git fetch origin master
          echo "diff result:"
          git diff remotes/origin/master -U100
          # get review result from Open AI
          echo -n '{
            "model": "gpt-4-1106-preview",
            "temperature": 1,
            "max_tokens": 4095,
            "top_p": 1,
            "frequency_penalty": 0,
            "presence_penalty": 0,
            "messages": 
              [
                {
                  "role": "system",
                  "content": "You are a helpful assistant. If you are unsure or uncertain of your answer, please answer that I don't know. When thinking about this content, think in English, and when outputting, answer in original language.\n\nYou are an engineer proficient in Terraform.\nPlease review with the best effort even if the code other than Terraform is provided.\n\nPassing the result of `git diff`.\nPlease review the changes in the Terraform code passed to you and point out the concern.\nYou don't need to comment anything other than the difference.\n\n- Summary of Changes\n- Will there be a recreate of Terraform resources?\n-Points to Note\n\nWhen pointing out an issue, please quote the relevant part of the code."
                },
                {
                  "role": "user",
                  "content": ' > payload.json
          echo $(git diff remotes/origin/master -U100) |jq -Rsa >> payload.json
          echo '}]}' >> payload.json
          echo "payload:"
          cat payload.json
          # send request and create comments file
          curl -s https://api.openai.com/v1/chat/completions \
            -H "Content-Type: application/json" \
            -H "OpenAI-Organization: ${OPENAI_ORG_ID}" \
            -H "Authorization: Bearer ${OPENAI_API_KEY}" \
            -d @payload.json | jq -r ".choices[].message.content" >> comments || exit 0
          # Add comment to PR using Github CLI
          echo "\nthis comment is created by OpenAI API." >> comments
          # Edit last commend or create new one
          if [[ "${{ github.event.action }}" == "opened" ]]; then
            gh pr comment -F ./comments ${{ github.event.pull_request.html_url }}
          else
            # PR is reopened or commiter push more commit. It is expected to already has old comment.
            # Try edit last comment or failback to create new comment
            gh pr comment --edit-last -F ./comments ${{ github.event.pull_request.html_url }} || 
              gh pr comment -F ./comments ${{ github.event.pull_request.html_url }}
          fi

使ってみての感想

実際のコメントはこんな感じです。
以下のようなRoute53のレコード変更のgit diffに対して

diff --git a/terraform.tf b/terraform.tf
index fb98e67..89c1a3d 100644
--- a/terraform.tf
+++ b/terraform.tf
@@ -1,7 +1,7 @@
 resource "aws_route53_record" "test" {
   zone_id = "Z2ZJ9XZJL0VW4H"
   name    = "test.example.com"
-  type    = "A"
+  type    = "CNAME"
   ttl     = "300"
-  records = ["${aws_eip.test.public_ip}"]
+  records = ["example.com"]
 }

以下のようなコメントがされます。

  • Summary of Changes:

    • The DNS record type has been changed from "A" to "CNAME" in the AWS Route 53 record resource.
    • The DNS record value has been changed from the AWS Elastic IP public IP address to the "example.com" domain.
  • Will there be a recreate of Terraform resources?

    • Yes, changing the type from "A" to "CNAME" will force a recreation of the Route 53 record because the type of a DNS record is an immutable field.
    • Changing the records field will also update the record, but this change does not require resource recreation; it's an update of the existing resource.
  • Points to Note:

    • When changing a record type from A to CNAME, ensure that the new value ("example.com") is a valid CNAME target.
    • DNS record changes can take time to propagate, and during the transition, there might be downtime or inconsistency in resolution.
    • It is important to verify that no services depend on the previous "A" record pointing to the AWS EIP, as this change would disrupt those services.

Relevant part of the code:

- type = "A"
+ type = "CNAME"
- records = ["${aws_eip.test.public_ip}"]
+ records = ["example.com"]

this comment is created by OpenAI API.

いかがでしょう?ぼちぼち良い感じのコメントなのではないでしょうか?

Yes, changing the type from "A" to "CNAME" will force a recreation of the Route 53 record because the type of a DNS record is an immutable field.

ここはちょっと怪しいですね、typeの変更ならリソースの再作成は行われなかったと思います。

まとめ

今回はTerraformのコードレビューをAIにやらせてみる方法とその感想をまとめてみました。
皆さんも是非使ってみてください〜

Discussion