LoginSignup
0
0

More than 3 years have passed since last update.

Golang + Sonarqube + Codebuild

Last updated at Posted at 2020-08-11

https://qiita.com/fake-deli-ca/items/e01a42a9d04cf0bab8c4
の後にJenkinsじゃなくてCodeBuildも対応してみたんだけど、異様にわかりにくくて、時間かかった…。

結論

最初に結論から。
関係する箇所のみ抜粋してある。

buildspec.yml
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
build.gradle
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で全部書き直すことも考えたが、なんかそこまでして綺麗にする理由もなかったのでやめ。

buildspec.yml
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登録そのものとは関係なく、別の問題を解決することになった。

うーん。

なんかもうちょっと綺麗にしたい気分ではあるんだけど…。
というのと、情報が少なくてきついですね。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0