問題
CircleCI で codecov の Orb(codecov/codecov)を使い、go testでデフォルトのフォーマットで出力したカバレッジ計測結果のファイルをアップロードする際に、以下のようなエラーが発生していた。
CircleCIのログ
[yyyy-mm-ddTHH:MM:SS.SSSZ] ['info'] Could not read coverage file (<カバレッジ計測結果のファイルパス>): Error: There was an error reading the coverage file: Error: Cannot create a string longer than 0x1fffffe8 characters
調査した結果、codecov の Orb は nodejs をベースにしているのだが、入力ファイル(=カバレッジ計測結果のファイル)を読み込んだ段階で nodejs の文字列サイズ上限に引っかかってしまっているらしいことがわかった。
となると、Orbの設定を調整してもどうにもならなそうなので、Orb の入力ファイルに含まれる文字数自体を減らす方向で解決策を考えることにした。
解決策
カバレッジファイル内を観察すると、以下のように(あくまでイメージですが)同じブロックが繰り返し出現していた。
mode: atomic
xxx/xxx.go:25.13,26.27 1 1
xxx/xxx.go:26.27,28.3 1 1
yyy/yyy.go:9.45,12.17 3 9
yyy/yyy.go:12.17,14.3 1 9
xxx/xxx.go:25.13,26.27 1 2
xxx/xxx.go:26.27,28.3 1 0
yyy/yyy.go:9.45,12.17 3 3
yyy/yyy.go:12.17,14.3 1 0
これらの行を統合(重複削除 + 末尾の通過回数は加算)できれば、かなりファイルサイズを圧縮できそう。
色々調べつつ試していたところ、
というコマンドを使ってフォーマットをlcovへ変換すると、副次的に望む結果を得られることが確認できたため、これをCircleCIに組み込むことにした。
jobs:
...
- run:
name: convert format of coverage profile file for data compression
command: |
go install github.com/jandelgado/gcov2lcov@latest
gcov2lcov -infile=<デフォルトフォーマットのカバレッジ計測結果ファイルパス> -outfile=<lcovフォーマットのカバレッジ計測結果ファイルパス>
参考
↑は、atomicで出力した結果に対して、set相当に変換するロジックをプロジェクト独自に用意している例。