https://qiita.com/fake-deli-ca/items/e01a42a9d04cf0bab8c4
の後にJenkinsじゃなくてCodeBuildも対応してみたんだけど、異様にわかりにくくて、時間かかった…。
結論
最初に結論から。
関係する箇所のみ抜粋してある。
version: 0.2
env:
variables:
GO_VERSION : ""
PROJECT_VERSION : ""
# 本来はParameter-Storeにすべき
SONARQUBE_TOKEN : "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
phases:
install:
runtime-versions:
golang: ${GO_VERSION}
commands:
- type go && go version
- chmod +x ./gradlew
- export REGOPATH=`echo $GOPATH | cut -c 5-`
- export PATH=${GOPATH}/bin:${PATH} && echo ${PATH}
pre_build:
commands:
- echo 'setup'
- make setup
build:
commands:
- echo 'make & test'
- make
- make test
- ./gradlew sonarqube -Dsonar.projectBaseDir=${REGOPATH}/src -Dsonar.login=${SONARQUBE_TOKEN} -Dsonar.projectVersion=${PROJECT_VERSION} --info
下記のMakefileはBuildの記載がないので、このままでは動作しない。
.PHONY: all
all: build
.PHONY: setup
setup:
go get -u github.com/ory/go-acc
.PHONY: test
test:
go test ./... -json > reports/test.json
go-acc ./... -o reports/coverage.out
plugins {
id "org.sonarqube" version "3.0"
}
sonarqube {
properties {
//FIXME
property "sonar.host.url","https://sonarqube.foo.jp"
property "sonar.projectKey", "hogehoge"
property "sonar.projectName", "hogehoge Project"
property "sonar.go.coverage.reportPaths", "(gitのpass)/reports/coverage.out"
property "sonar.go.tests.reportPaths", "(gitのpass)/reports/test.json"
//FIXME
property "sonar.sources", "."
property "sonar.exclusions", "**/*_test.go"
property "sonar.tests", "."
property "sonar.test.inclusions", "**/*_test.go"
property "sonar.test.exclusions", "**/vendor/**"
property "sonar.sourceEncoding", "UTF-8"
}
}
確認すべき点
is not included in the project, ignoring coverage
Sensor Go Cover sensor for Go coverage [go]
Load coverage report from '/codebuild/output/src532592822/src/(gitのpass)/coverage.txt'
File '/codebuild/output/src532592822/src/(gitのpass)/AAA/BBB.go' is not included in the project, ignoring coverage
とにかく、is not included in the project, ignoring coverage
にやられた。どう設定していいのか全く分からない。
https://github.com/SonarSource/sonar-go/issues/218
を読むとGOPATHの設定が悪い、と書いてあるが、どうすれば治るのかは書いてない。
酷い…。
結論を言うと、sonar.projectBaseDir
の設定が悪い。ところが、皆様ご存じの通り、Codebuildは/codebuild/output/srcXXXXXXXXXX/src
の部分が毎回異なるため、何らかの利用できる変数で設定しなければならない。
普通に考えるとsonar.projectBaseDir=$GOPATH/src
とすればよいのだが、ところがである。Codebuildの$GOPATH
は/go:/codebuild/output/src532592822
となっており、/go: の部分が心底余計なのである。
上記のように設定すると、
* What went wrong:
Execution failed for task ':sonarqube'.
> The folder '/go:/codebuild/output/src179970974/src' does not exist for 'xxxxx' (base directory = /codebuild/output/src179970974/src/(gitのpass))
みたいなエラーになるのである。まあ当然だが。
というわけで強引にcutで削除して再設定した。本当にこれでいいのかどうかは知らない。
また、本来はbuild.gradleに全部書きたかったのだが、当然環境変数と展開できないので、-Dsonar.projectBaseDir=${REGOPATH}/src
という設定とした。
reportPathsの変更
上記projectBaseDirの変更に伴う対応である。
普通、この辺のPathは$CODEBUILD_SRC_DIR
の直下に置かれるので、gitのpassは本来不要なのであるが、projectBaseDirを変更した関係上、ここも変更が必要である。
property "sonar.go.coverage.reportPaths", "(gitのpass)/reports/coverage.out"
property "sonar.go.tests.reportPaths", "(gitのpass)/reports/test.json"
Gradleの利用
sonarqubeだけgradle使っててなんかおかしな感じではあるのだが、最初こんな感じでやってたらunzipのインストールが必要だったり、sonar-scannerのインストール位置が気持ち悪かったり、なんだか訳がわからなくなりそうだったので、あきらめて素直にgradle使うことにした。別に使わなくてもいいとは思う。ただ↓の設定でうまくいくところまでは試してない。少なくともGOPATHはこのままでは駄目だと思う。
また、gogradleで全部書き直すことも考えたが、なんかそこまでして綺麗にする理由もなかったのでやめ。
phases:
install:
runtime-versions:
golang: ${GO_VERSION}
commands:
- type go && go version
# sonar-scanner install
- yum -y install unzip
- wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.4.0.2170-linux.zip
- unzip ./sonar-scanner-cli-4.4.0.2170-linux.zip
pre_build:
commands:
- echo 'setup'
- export PATH=${GOPATH}/bin:./sonar-scanner-4.4.0.2170-linux/bin:${PATH} && echo ${PATH}
- make setup
build:
commands:
- echo 'make & test'
- make
- make test
- sonar-scanner -X -Dsonar.login=${SONARQUBE_TOKEN}
go-accの利用
ここまで実施してみて、どうもCoverage率が異様に低いことに気が付く。
これも結論だけをいうと、go test -cover
のデフォルト挙動に問題があるということである。なので、go-acc
を利用することとした。
The reason for this was that go test -cover is per default only recording code coverage for the package that is currently tested, not for all the packages from the project. If you have a lot of integration tests, your code coverage might be higher than you think!
…と結論だけなら簡単だが、ここに辿り着くまでに大層時間かかった。
I found a brutal hack of a workaround. I'm trying to report coverage on a project with a single golang module, and all of the module's files are below a single subdirectory in the git repo. We use go-acc to measure coverage, it writes file coverage.txt. I added a step in the build script to rewrite the prefix on the paths in that file, change the module name to the directory name, kinda like this:
sed -i -e 's/^mymodule/ModuleSubdir/' coverage.txt
Then the sonar scanner is happy. I don't know if the coverage numbers are correct, but they ain't zero no more
https://jira.sonarsource.com/browse/SONARSLANG-450
大本は、is not included in the project, ignoring coverage
を解決すべく探していた際に見つけた上記であるが、結果的にソースコードのCoverage登録そのものとは関係なく、別の問題を解決することになった。
うーん。
なんかもうちょっと綺麗にしたい気分ではあるんだけど…。
というのと、情報が少なくてきついですね。