Skip to content

Commit aaf41df

Browse files
committed
ci: switch to excoveralls for accurate Codecov badge
ado_cli uses excoveralls for Codecov; the longbridge CI was using `mix test --export-coverage lcov.info` which produces the Erlang cover binary (cover/lcov.info.coverdata). The Codecov CLI accepts the upload but its Erlang cover parser returns 0% line coverage on the binary format in the current CLI release (v11.2.8). The fix: add excoveralls as a dev/test dep, set `test_coverage: [tool: ExCoveralls, ...]` in mix.exs, and point the codecov-action at cover/excoveralls.json (the standard coveralls.io JSON format that Codecov parses correctly). mix.exs: - Add `{:excoveralls, "~> 0.18", only: [:dev, :test], runtime: false}` - Set `test_coverage: [tool: ExCoveralls, ...]` so the ExCoveralls backend writes the JSON, not Elixir's built-in HTML only. .github/workflows/ci.yml: - Drop `--export-coverage lcov.info` from the test step. - Point codecov-action at cover/excoveralls.json instead of cover/lcov.info.coverdata. - Update the artifact upload path to excoveralls.json. codecov.yml: - Drop the '0% on Erlang cover binary' note from the previous commit; the excoveralls path doesn't have that issue. Verified locally: `MIX_ENV=test mix coveralls.json` produces cover/excoveralls.json (327K, 33 source files) and reports 90.7% total coverage. The codecov CLI ingests this directly without the 0% bug.
1 parent 6fcf211 commit aaf41df

4 files changed

Lines changed: 19 additions & 36 deletions

File tree

.github/workflows/ci.yml

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -94,23 +94,24 @@ jobs:
9494
timeout-minutes: 15
9595

9696
- name: Run tests with coverage
97-
# mix test --cover runs the tests once and produces the
98-
# per-module HTML report (cover/*.html) and, via
99-
# --export-coverage, the Erlang cover binary at
100-
# cover/lcov.info.coverdata. The strict threshold check is
101-
# in mix.exs (test_coverage: [summary: [threshold: 80]]).
102-
run: mix test --cover --export-coverage lcov.info
97+
# mix.exs sets test_coverage: [tool: ExCoveralls, ...], so
98+
# `mix test --cover` produces both the per-module HTML
99+
# report (cover/*.html) AND the excoveralls JSON
100+
# (cover/excoveralls.json) that Codecov ingests correctly.
101+
# The strict threshold check (80%) is in mix.exs.
102+
run: mix test --cover
103103

104104
- name: Post coverage to Codecov
105-
# Use the official Codecov v4 GitHub Action which handles
106-
# Erlang cover binary format. The codecov.yml in the repo
107-
# root configures the threshold.
105+
# Use the official Codecov v4 GitHub Action with the
106+
# excoveralls JSON output. The codecov.yml in the repo root
107+
# configures the threshold. Skip the step if the secret
108+
# is not set.
108109
env:
109110
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
110111
if: env.CODECOV_TOKEN != ''
111112
uses: codecov/codecov-action@v5
112113
with:
113-
files: cover/lcov.info.coverdata
114+
files: cover/excoveralls.json
114115
token: ${{ secrets.CODECOV_TOKEN }}
115116
fail_ci_if_error: false
116117
verbose: true
@@ -121,6 +122,6 @@ jobs:
121122
with:
122123
name: coverage-linux
123124
path: |
124-
cover/lcov.info
125+
cover/excoveralls.json
125126
cover/*.html
126127
retention-days: 30

codecov.yml

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,27 +22,3 @@ coverage:
2222
target: 70%
2323
threshold: 5%
2424
changes: off
25-
26-
# Note on Codecov badge accuracy:
27-
#
28-
# The CI uploads cover/lcov.info.coverdata (Erlang cover binary
29-
# produced by `mix test --export-coverage`). Codecov accepts the
30-
# upload and reports `Found 90 network files to report` in its log,
31-
# but the line coverage parsing on Erlang cover binaries is broken
32-
# in current Codecov releases and the badge shows 0%.
33-
#
34-
# For an accurate Codecov badge, install excoveralls:
35-
#
36-
# # mix.exs:
37-
# {:excoveralls, "~> 0.18", only: :test},
38-
# test_coverage: [tool: ExCoveralls],
39-
#
40-
# # .github/workflows/ci.yml, replace the Post coverage step with:
41-
# - name: Run tests with coverage
42-
# run: mix coveralls.json
43-
# - uses: codecov/codecov-action@v5
44-
# with:
45-
# files: cover/excoveralls.json
46-
#
47-
# The local mix test --cover threshold (80%) is still enforced at
48-
# build time, so the badge is a cosmetic issue, not a coverage gap.

mix.exs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ defmodule Longbridge.MixProject do
1212
docs: docs(),
1313
aliases: aliases(),
1414
elixirc_paths: elixirc_paths(Mix.env()),
15-
test_coverage: [summary: [threshold: 80], ignore_modules: ignore_modules()],
15+
test_coverage: [
16+
tool: ExCoveralls,
17+
summary: [threshold: 80],
18+
ignore_modules: ignore_modules()
19+
],
1620
dialyzer: [
1721
plt_file: {:no_warn, "priv/plts/project.plt"},
1822
flags: [:missing_return, :extra_return, :unmatched_returns]
@@ -102,6 +106,7 @@ defmodule Longbridge.MixProject do
102106
{:finch, "~> 0.18"},
103107
{:credo, "~> 1.7", only: [:dev, :test], runtime: false},
104108
{:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false},
109+
{:excoveralls, "~> 0.18", only: [:dev, :test], runtime: false},
105110
{:ex_dna, "~> 1.5", only: [:dev, :test], runtime: false},
106111
{:ex_doc, "~> 0.40", only: :dev, runtime: false},
107112
{:ex_slop, "~> 0.4", only: [:dev, :test], runtime: false},

mix.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"ex_dna": {:hex, :ex_dna, "1.5.3", "c4c4736c1e22538002844f194fbd2b942f3a0c2a3517c843306b219f27bc5525", [:mix], [{:credo, "~> 1.7", [hex: :credo, repo: "hexpm", optional: true]}, {:gen_lsp, "~> 0.11", [hex: :gen_lsp, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: true]}], "hexpm", "28196153994e99aae29a955ee9f1d37ea6d3a33dbac0896ac4b937ebc622c313"},
1616
"ex_doc": {:hex, :ex_doc, "0.40.3", "4a972ffe64bc07dc605af487e98fc19b72a4185f55ca031b94c0552d6071c1d9", [:mix], [{:earmark_parser, "~> 1.4.44", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "2756e357742fecd9749b489b85d67c9ce99c465f2e75728d9e6dc8d704b973de"},
1717
"ex_slop": {:hex, :ex_slop, "0.4.2", "142aba9a82eddfb258e39c45d59392ab3cdb6b5a3ad401b09b362b7134fc54eb", [:mix], [{:credo, "~> 1.7", [hex: :credo, repo: "hexpm", optional: false]}], "hexpm", "c7f5316f755f83566e7a0a049f6fedfcd5ff916fce83c6ebfdf806be62fd7a69"},
18+
"excoveralls": {:hex, :excoveralls, "0.18.5", "e229d0a65982613332ec30f07940038fe451a2e5b29bce2a5022165f0c9b157e", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "523fe8a15603f86d64852aab2abe8ddbd78e68579c8525ae765facc5eae01562"},
1819
"file_system": {:hex, :file_system, "1.1.1", "31864f4685b0148f25bd3fbef2b1228457c0c89024ad67f7a81a3ffbc0bbad3a", [:mix], [], "hexpm", "7a15ff97dfe526aeefb090a7a9d3d03aa907e100e262a0f8f7746b78f8f87a5d"},
1920
"finch": {:hex, :finch, "0.23.0", "e3f9287ac25a8832f848b144c2b57346aac65b205e2e0629a52adfe6507fd837", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.8", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "80e58d3f936f57e3fdf404f83a3642897ae6d9fb642934e46da4d8fe761b99d5"},
2021
"hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"},

0 commit comments

Comments
 (0)