CircleCI実践入門本でつまずいたところ
目的
Terraformでつまずいた部分をまとめておきます。
CircleCI実践入門本でつまずいた部分をまとめておきます。
初めてのスクラップなのでまだまだ手探りですが、使いながら学んでいこうと思います。
State Lockingを導入しようとしたら Requested resource not foundエラーで躓いた
概要
躓いたのは上記の本の8.6 Terraformで内容としては、CircleCIでTerraformを実行させてAWSのEC2インスタンスを作成させるという内容です。git push
されましたらTerraformの実行結果はSlackなど別に出力させる場合に使われるtfnotifyをインストールして、masterブランチならterraform apply
、それ以外ならterraform plan
を実行させるconfig.yml
が記述されています。
技術書の中身を吟味しながら自分のGithubにforkして環境変数部分は変更した上で、git push
してCircleCIを実行させてのですが、以下のようなエラーが発生しました。
#!/bin/sh -eo pipefail
terraform apply -auto-approve | tee "$TFNOTIFY_LOG"
Acquiring state lock. This may take a few moments...
Error: Error locking state: Error acquiring the state lock: 2 errors occurred:
* ResourceNotFoundException: Requested resource not found
* ResourceNotFoundException: Requested resource not found
Terraform acquires a state lock to protect the state from being written
by multiple users at the same time. Please resolve the issue above and try
again. For most commands, you can disable locking with the "-lock=false"
flag, but this is not recommended.
Exited with code exit status 1
CircleCI received exit code 1
Requested resource not foundと出ており、何かしらのリソースが見つからないというエラーが出ています。
一度ローカルマシン上でTerraformを実行して動きを確認しましたが、同じエラーが出てくる結果となりました。
原因が分からず、Stack Overflowに質問してみることにしました。
解決
回答があり内容を見ますと、State Locking導入のS3のバックエンド宣言が原因っぽい書き込みがありました。
書籍では事前にS3の作成を済ました前提で記載されていますが、State Lockingを利用できるようにするにはS3とDynamoDBを事前に作成してからS3バックエンドの宣言をmain.tf
に記述する必要があるようです。
なのでまずはmain.tf
の中身を以下のようにしてgit push
します。
# Specify the provider and access details
provider "aws" {
region = "ap-northeast-1"
profile = "default"
}
resource "aws_dynamodb_table" "dynamodb-terraform-state-lock" {
name = "terraform-state-lock-dynamo"
hash_key = "LockID"
read_capacity = 20
write_capacity = 20
attribute {
name = "LockID"
type = "S"
}
tags = {
Name = "DynamoDB State Lock Table"
}
}
CIが問題なく最後まで処理が完了し、DynamoDBの作成が確認できましたら、S3のバックエンド宣言とEC2インスタンスの作成をmain.tf
に記述していきます。
# Specify the provider and access details
provider "aws" {
region = "ap-northeast-1"
profile = "default"
}
terraform {
backend "s3" {
key = "terraform.tfstate"
bucket = "circleci-book-terraform-sample-yuta"
region = "ap-northeast-1"
dynamodb_table = "terraform-state-lock-dynamo"
}
}
# 一度作成したらコメントアウトしておく
#resource "aws_dynamodb_table" "dynamodb-terraform-state-lock" {
# name = "terraform-state-lock-dynamo"
# hash_key = "LockID"
# read_capacity = 20
# write_capacity = 20
#
# attribute {
# name = "LockID"
# type = "S"
# }
#
# tags = {
# Name = "DynamoDB State Lock Table"
# }
#}
resource "aws_instance" "web" {
instance_type = "t3.small"
# Amazon Linux2
ami = "ami-0992fc94ca0f1415a"
count = 1
tags = {
Name = "EC2 instance terraform"
}
}
この時DynamoDB記述箇所をコメントアウトしていないとエラーが出ますので、コメントアウトしておきます。
#!/bin/sh -eo pipefail
terraform apply -auto-approve | tee "$TFNOTIFY_LOG"
Acquiring state lock. This may take a few moments...
aws_instance.web[1]: Creating...
aws_instance.web[0]: Creating...
aws_dynamodb_table.dynamodb-terraform-state-lock: Creating...
aws_instance.web[1]: Still creating... [10s elapsed]
aws_instance.web[0]: Still creating... [10s elapsed]
aws_instance.web[0]: Creation complete after 18s [id=i-01041160d4458b7e7]
aws_instance.web[1]: Creation complete after 18s [id=i-0cf7c55a431f7ac3b]
Error: error creating DynamoDB Table: ResourceInUseException: Table already exists: terraform-state-lock-dynamo
Releasing state lock. This may take a few moments...
Exited with code exit status 1
CircleCI received exit code 1
こちらをmaster以外のブランチでgit push
し、GithubのプルリクにTerraformの出力結果を表示させてmasterブランチにmergeさせます。
mainブランチでCIが実行されますとterraform apply
が動き、EC2インスタンスが作成されSlackにも実行結果が通知されることが確認できました。
reviewdogでGitHubにプルリクを送れない問題
11章のさまざまなタスクの自動化で11.6のドキュメントの校正に関する部分で分からないところがありました。
textlintとreviewdogを使って、GitHubレポジトリで管理しているドキュメントの校正を自動で行うようにCIを構築するという内容です。
textlintはJSで記述されたOSSであり、テキストファイルの検査を行うことができ、プラグインを活用することで英語、日本語、中国語などのドキュメントの校正を行うことが出来ます。
textlintで検知した実行結果をGitHubにプルリクしてくれるものがreviewdogと呼ばれるGoで記述されたOSSです。(アイコン可愛い)
以下のように、.config.yml
にtextlintとreviewdogの処理を実行させるようにして、README.MDの記載に問題があればプルリクを出せるようにしてあります。
- run:
name: "textlintをインストールする"
command: npm install --save-dev textlint textlint-rule-no-mix-dearu-desumasu
- run:
name: "依存モジュールをインストールする"
command: npm install
- run:
name: "reviewdogをインストールする"
command: |
curl -sfL https://raw.githubusercontent.com/reviewdog/reviewdog/master/install.sh| sh -s
- run: # (d1)
name: "textlintをREADME.mdに対して実行する"
command: npx textlint -f checkstyle README.md >> .textlint.log
- run: # (d2)
name: "reviewdogを実行する"
when: on_fail
command: |
cat .textlint.log | ./bin/reviewdog -f=checkstyle -name="textlint" -reporter="github-pr-review"
workflows:
version: 2
proofreading:
jobs:
- proofreading_job
# textlint-reviewdog-sample
[![CircleCI](https://circleci.com/gh/circleci-book/textlint-reviewdog-sample.svg?style=svg)](https://circleci.com/gh/circleci-book/textlint-reviewdog-sample)
[CircleCI実践入門](https://gihyo.jp/book/2020/978-4-297-11411-4)の11章「ドキュメントの校正」におけるサンプルコードです。
この文は敬体である。この文は常体だ。
参考
- https://github.com/azu/textlint-reviewdog-example
またreviewdogがプルリクのコメントを書き込むためにGitHubトークンが必要なので、事前にCircleCI側の環境変数REVIEWDOG_GITHUB_API_TOKEN
を設定しています。
もう一つ事前に必要な設定で、Only build pull requests
をオンにします。
この状態でgit push
をしてCircleCIを回しましたが、reviewdogがプルリクを作れないというメッセージが出ました。
#!/bin/bash -eo pipefail
cat .textlint.log | ./bin/reviewdog -f=checkstyle -name="textlint" -reporter="github-pr-review"
reviewdog: this is not PullRequest build.
CircleCI received exit code 0
現在StackOverflowで問い合わせており、解決出来たら更新する予定です。
(FB 書きにくいので、ここに書きます。)
参考資料として二点です。
Circle CI の環境変数書き方
その参考資料とソースコードを基に、
下記を reviewdog の前のステップに加えます。
- run:
name: Update PATH and Define Environment Variable at Runtime
command: |
echo 'export CIRCLE_PROJECT_REPONAME =reviewdog' >> $BASH_ENV
echo 'export CIRCLE_PROJECT_USERNAME=hogehoge' >> $BASH_ENV
echo "export CIRCLE_SHA1 =$CIRCLE_SHA1" >> $BASH_ENV
source $BASH_ENV
(CIRCLE_PROJECT_REPONAME は CI_REPO_NAME にしても問題ないはずです。他も同義)
余裕があれば、上のステップの前に、これらのキーの中身が空かどうか見ておきたいですねw
なぜなら、作り上、定義しなくて済む方法はあるように見えます。
何かしらの理由で、いずれかが欠落したかもしれません。
- run:
name: confirm current Environment Variable at Runtime
command: |
echo $CIRCLE_PROJECT_REPONAME
echo $CIRCLE_PROJECT_USERNAME
echo $CIRCLE_SHA1
もともとこれらの環境変数には値がデフォルトで入っていますね。
Using build environment variables:
BASH_ENV=/tmp/.bash_env-603518182415f763cb771860-0-build
CI=true
CIRCLECI=true
CIRCLE_BRANCH=master
CIRCLE_BUILD_NUM=31
CIRCLE_BUILD_URL=https://circleci.com/gh/Yuhta28/textlint-reviewdog-sample/31
CIRCLE_COMPARE_URL=
CIRCLE_JOB=proofreading_job
CIRCLE_NODE_INDEX=0
CIRCLE_NODE_TOTAL=1
CIRCLE_PREVIOUS_BUILD_NUM=30
CIRCLE_PROJECT_REPONAME=textlint-reviewdog-sample
CIRCLE_PROJECT_USERNAME=Yuhta28
CIRCLE_REPOSITORY_URL=git@github.com:Yuhta28/textlint-reviewdog-sample.git
CIRCLE_SHA1=63f014f671388d293ba4ad1cc5db3952570bc5a6
CIRCLE_SHELL_ENV=/tmp/.bash_env-603518182415f763cb771860-0-build
CIRCLE_STAGE=proofreading_job
CIRCLE_USERNAME=Yuhta28
CIRCLE_WORKFLOW_ID=5ebabc47-fde0-46c2-8065-74446ac44b4d
CIRCLE_WORKFLOW_JOB_ID=aad4b5b3-95aa-4281-9075-c0bf027ba31e
CIRCLE_WORKFLOW_UPSTREAM_JOB_IDS=
CIRCLE_WORKFLOW_WORKSPACE_ID=5ebabc47-fde0-46c2-8065-74446ac44b4d
CIRCLE_WORKING_DIRECTORY=~/project
Using environment variables from project settings and/or contexts:
CIRCLE_JOB=**REDACTED**
GITHUB_USER=**REDACTED**
NPM_TOKEN=**REDACTED**
REVIEWDOG_GITHUB_API_TOKEN=**REDACTED**
The redacted variables listed above will be masked in run step output.
SHA1にセットしようとしたらエラーが出たので、これだけ除外してやりましたが、結果変わらずでしたね(;_;)
#!/bin/bash -eo pipefail
echo 'export CIRCLE_PROJECT_REPONAME=reviewdog' >> $BASH_ENV
echo 'export CIRCLE_PROJECT_USERNAME=hogehoge' >> $BASH_ENV
echo "export CIRCLE_SHA1 =$CIRCLE_SHA1" >> $BASH_ENV
source $BASH_ENV
/tmp/.bash_env-603517ae3a1256421d7c4ec6-0-build: line 3: export: `=7653c8a1ebd1392ffd27f271ca5dd02294a2def3': not a valid identifier
Exited with code exit status 1
CircleCI received exit code 1
あ、先ほど、ユータさんが作った issue で作者から返信が来ました。
確かに、CIRCLE_PR_NUMBER も必要で、ユータさんが今回出したリストにありませんでしたね。
echo
で確認したらemptyでした。
ここにPR番号をセットする必要がありそうですが、どうやってセットすればいいのか(汗)
聞いてみようと思います。
CI それぞれの問題はissueより、CIの問題で探した方が早いかもしれません。
circleci 2.0 なら、CIRCLE_PULL_REQUEST が使えるみたいです。
-guess
オプションをつけるとPRのIDを推測してくれるっぽいのですが、わかったところで次に続かないところで足踏みしてます。
#!/bin/bash -eo pipefail
cat .textlint.log | ./bin/reviewdog -f=checkstyle -name="textlint" -reporter="github-pr-review" -guess
reviewdog: PullRequest not found, query: type:pr state:open repo:*******/textlint-reviewdog-sample head:master 9f86c65c0f24f62c7dcab6f83eef7ef8993d2008
reviewdog: this is not PullRequest build.
CircleCI received exit code 0
あー悲しみ😰
まぁ、エンジニアライフあるあるですねw
CIRCLE_PULL_REQUEST は echo で取れそうでしょうか?
残念ながら空みたいでecho打っても何も表示されないですね😿
最終的には学んだ事を応用してこのzennをローカルエディターで書いてGitHubリポジトリに管理して、文章校正を自動で行うようにしたかったですが、textlintだけ入れてみようと思います。
一回ここまできたら、PR 番号の直書きしてみてはいかがでしょうか?
本当に reviewdog は PR みに行ってくれるかの検証です。
またこれでもエラー出たら、作者にバグ報告できるかもしれません。
同じくreviewdog の前のステップで、以下を加えます。
(9999は対象のPRの番号に変えて)
- run:
name: Define CIRCLE_PR_NUMBER Environment Variable at Runtime
command: |
echo 'export CIRCLE_PR_NUMBER =9999' >> $BASH_ENV
source $BASH_ENV
PRの番号ってどこから取得できるのですか?
reviewdogがプルリクしてくれないので、PR番号の発行ができないから多分失敗しているように思いまして、先にPR番号を手動でセットだと思うのですが、そうした場合そもそも存在しないPR番号を探すという矛盾が発生しているような気がしてしまいまして🤔
あれ?今回の CI のトリガーはどれかの PR じゃないですか?
この例のように、
1.この PR が CI を発火します。(16が番号です)
2.CI build 始めます。
3.結果を見て、このPR の差分の箇所にコメントが作られます。
ユータさんは以下と認識しているようですが、
textlintで検知した実行結果をGitHubにプルリクしてくれるものがreviewdogと呼ばれるGoで記述されたOSSです。
調べたところ、公式の github のページの英語もそうですが、
各種linterの実行結果をプルリクエストのコメントで指摘してくれます。
https://dev.classmethod.jp/articles/shuntaka-github-actions-reviewdog/
もしかすると私がいろいろと勘違いしていたかもしれません。
①実行していたCircleCIのブランチはマスターでした。
私が初歩的な勘違いをしていましたが、同一レポジトリ、同一ブランチ内でPRを出すことはできなくて作成失敗しているような気がします。
②上記のgit push
を実行してから、GitHub上で新規ブランチを作成して適当にファイル内改行をしてPRを出しました。
③PRを出したらCircleCIが実行されましたが、reviewdogでparse error
が実行されるという結果になりました。
私のイメージでは、CircleCI内のreviewdogがtextlintなどのlinterツールが出力した内容を基にGitHubのPRを自動生成してくれると思ってましたが、そういうことではなくてトピックブランチからマスターへPRを出す時にCircleCI内のreviewdogが動いて自分で作ったPRにコメントが追記されるものなのかなと思いました。
課題
ただそれでも最後に書かれている通りparse errorが出てしまい、linterの出力結果がPRに載らないのでもう少し調査してみる必要がありそうです。
今日は vscode の extension の remote-container 試したくて、試す課題として、この件を追ってみました。
ここでこけると言うことは、textlint の問題です。
試したい remote-container に textlint 入れてみました。
操作してみたら、ユータさんのkeyword が辞書に入っていないのと、
おそらく、最初の段階、module もいれていない可能性はあります。
- run:
name: "textlintをインストールする"
command: npm install --save-dev textlint textlint-rule-no-mix-dearu-desumasu
以下のように変える必要があるのと、
- run:
name: "textlintをインストールする"
command: npm install --save-dev textlint textlint-rule-common-misspellings
README.md の先頭に it is abouta.
でも入れてみたら、キャッチしてくれると思います。
CI のエラーのデバッグが手間かかるので、ローカルでできることを使い捨ての docker で立てて試すと答えが見えることが多いと思います〜
色々とありがとうございます。
.textlint.log
の中にtextlintの出力結果はちゃんと取り込まれていることは確認できているのです。
例えばブランチのマージを行うためにマスターブランチへのPRを行うとCircleCIが実行されてLintチェックが走るのですが、textlintにはちゃんと実行結果ログが記録されるのは確認できるのですが、なぜかreviewdogでエラーが出るという結果になっている感じです。
#!/bin/bash -eo pipefail
cat .textlint.log
cat .textlint.log | ./bin/reviewdog -f=checkstyle -name="textlint" -reporter="github-pr-review"
/home/circleci/project/README.md
2:6 ✓ error This is a commonly misspelled word. Correct it to isn't common-misspellings
✖ 1 problem (1 error, 0 warnings)
✓ 1 fixable problem.
Try to run: $ textlint --fix [file]
#~~~~~ここまでが textlint.logの中身~~~~~
reviewdog: parse error: EOF
Exited with code exit status 1
CircleCI received exit code 1
個人的にはreviewdog側の問題かCircleCIとの相性が悪い気がしてきて、ちょっとGitHub Actionsで試してみようと思います。
(GitHub Actionsを活用したreviewdogの使い方記事がけっこうあるので)
@Sonia Liang
解決できました💡
色々とお手伝いしてくれましたので、解決方法を共有致します。
原因
上記の実行内容で.textlint.log
の中身はちゃんとtextlintの実行結果が記録されていますが、その中身をreviewdogに渡そうとすると、上記のようにreviewdog: parse error: EOF
となり、reviewdogがPRにコメントを残してくれませんでした。
いろんな文献をあさりましたが、textlintの設定に不備が有りました。
誤 npx textlint README.md >> .textlint.log
正 npx textlint -f checkstyle README.md >> .textlint.log
どうやら色々とソースコードをいじっているうちにtextlintのオプションで必要なものが抜けていることがわかりました。
-f checkstype
をつければ画像のようにreviewdogがGitHubにPRを出して文章のミスを教えてくれました。
お騒がせいたしましたm(_ _)m