Skip to content

Commit

Permalink
Supports lcov files generated from partitioned test runs
Browse files Browse the repository at this point in the history
  • Loading branch information
brianberlin committed Mar 4, 2024
1 parent 1393654 commit bd9949a
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 66 deletions.
15 changes: 8 additions & 7 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ on:
env:
OTP_VERSION: 26.1.1
ELIXIR_VERSION: 1.15.6-otp-26
MIX_ENV: test

jobs:
test:
Expand All @@ -18,7 +19,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Elixir
uses: erlef/setup-beam@v1
with:
Expand All @@ -31,7 +32,7 @@ jobs:
with:
path: _build
key: build-${{ runner.os }}-${{ env.OTP_VERSION }}-${{ env.ELIXIR_VERSION }}-${{ hashFiles('mix.lock') }}

- name: Deps Cache
uses: actions/cache/restore@v3
id: deps-cache
Expand All @@ -42,7 +43,7 @@ jobs:
- name: Install Mix Dependencies
if: steps.deps-cache.outputs.cache-hit != 'true'
run: mix deps.get

- name: Compile
if: steps.build-cache.outputs.cache-hit != 'true'
run: mix compile
Expand All @@ -54,17 +55,17 @@ jobs:
run: mix credo --strict

- name: Run Tests
run: mix lcov
run: mix test --cover

- name: Coverage Reporter
uses: peek-travel/coverage-reporter@main
id: coverage-reporter
if: github.event_name == 'pull_request'
continue-on-error: true
with:
with:
lcov_path: cover/lcov.info
coverage_threshold: 90

- name: Restore PLT cache
uses: actions/cache@v2
id: plt-cache
Expand Down
39 changes: 39 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Main

on:
push:
tags:
- "v*.*.*"
env:
MIX_ENV: prod
ELIXIR_VERSION: 1.15.6-otp-26
OTP_VERSION: 26.1.1

jobs:
build:
runs-on: ubuntu-latest
steps:

- name: Checkout
uses: actions/checkout@v4

- name: Elixir
uses: erlef/setup-beam@v1
with:
otp-version: ${{ env.OTP_VERSION }}
elixir-version: ${{ env.ELIXIR_VERSION }}

- name: Install Mix Dependencies
run: mix deps.get

- name: Escript Build
run: mix escript.build

- name: Release
uses: softprops/action-gh-release@v1
with:
files: |
coverage_reporter
Dockerfile
entrypoint.sh
action.yml
2 changes: 2 additions & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
elixir 1.15.7-otp-26
erlang 26.1.1
20 changes: 5 additions & 15 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
ARG ELIXIR_VERSION=1.14.4
ARG OTP_VERSION=25.3.1
ARG DEBIAN_VERSION=bullseye-20230227-slim
FROM hexpm/elixir:1.15.7-erlang-26.1.1-ubuntu-jammy-20230126

ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}"
ARG RUNNER_IMAGE="debian:${DEBIAN_VERSION}"
COPY coverage_reporter /
COPY entrypoint.sh /
COPY deps/castore/priv/cacerts.pem /

FROM ${BUILDER_IMAGE} as builder

RUN apt-get update -y && apt-get install -y build-essential git \
&& apt-get clean && rm -f /var/lib/apt/lists/*_*

WORKDIR /app
COPY mix.exs mix.lock entrypoint.sh ./
COPY lib ./lib

ENTRYPOINT ["/app/entrypoint.sh"]
ENTRYPOINT ["/entrypoint.sh"]
10 changes: 3 additions & 7 deletions entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@ set -e
set -o pipefail
echo ">>> Running command"
echo ""
# bash -c "set -e; set -o pipefail; $1"
cd /app
mix local.hex --force
mix local.rebar --force
mix deps.get
mix compile
mix run --no-mix-exs -e "CoverageReporter.run()"


/coverage_reporter
33 changes: 21 additions & 12 deletions lib/coverage_reporter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ defmodule CoverageReporter do
However, The LCOV files produced by excoveralls only include SF, DA, LF, LH, and end_of_record lines.
"""

def run(opts \\ []) do
def main(opts) do
config = get_config(opts)

%{pull_number: pull_number, head_branch: head_branch, repository: repository} = config
changed_files = get_changed_files(config)
{total, module_results} = get_coverage_from_lcov_files(config)
Expand Down Expand Up @@ -96,14 +95,15 @@ defmodule CoverageReporter do
table = :ets.new(__MODULE__, [:set, :private])

module_results =
Enum.flat_map(lcov_paths, fn path ->
Enum.reduce(lcov_paths, %{}, fn path, acc ->
path
|> File.stream!()
|> Stream.map(&String.trim(&1))
|> Stream.chunk_by(&(&1 == "end_of_record"))
|> Stream.reject(&(&1 == ["end_of_record"]))
|> Stream.map(fn record -> process_lcov_record(table, record) end)
|> Enum.reduce(acc, fn record, acc -> process_lcov_record(table, record, acc) end)
end)
|> Map.values()

covered = :ets.select_count(table, [{{{:_, :_}, true}, [], [true]}])
not_covered = :ets.select_count(table, [{{{:_, :_}, false}, [], [true]}])
Expand All @@ -112,7 +112,7 @@ defmodule CoverageReporter do
{total, module_results}
end

defp process_lcov_record(table, record) do
defp process_lcov_record(table, record, acc) do
"SF:" <> path = Enum.find(record, &String.starts_with?(&1, "SF:"))

coverage_by_line =
Expand All @@ -124,19 +124,22 @@ defmodule CoverageReporter do
|> String.split(",")
|> Enum.map(&String.to_integer(&1))

covered = :ets.select_count(table, [{{{path, line_number}, true}, [], [true]}])
insert_line_coverage(table, count, path, line_number)

{line_number, count}
{line_number, count + covered}
end)

covered = :ets.select_count(table, [{{{path, :_}, true}, [], [true]}])
not_covered = :ets.select_count(table, [{{{path, :_}, false}, [], [true]}])
{percentage(covered, not_covered), path, coverage_by_line}
Map.put(acc, path, {percentage(covered, not_covered), path, coverage_by_line})
end

defp insert_line_coverage(table, count, path, line_number) do
if count == 0 do
:ets.insert(table, {{path, line_number}, false})
covered_count = :ets.select_count(table, [{{{path, line_number}, true}, [], [true]}])

if count == 0 and covered_count == 0 do
:ets.insert_new(table, {{path, line_number}, false})
else
Enum.each(1..count, fn _ -> :ets.insert(table, {{path, line_number}, true}) end)
end
Expand Down Expand Up @@ -262,12 +265,12 @@ defmodule CoverageReporter do
|> Enum.reduce(_groups = [], &add_line_to_groups/2)
|> Enum.reduce(
_annotations = [],
&create_annotations(&1, &2, changed_lines, file, source_code)
&do_create_annotations(&1, &2, changed_lines, file, source_code)
)
end)
end

defp create_annotations(line_number_group, annotations, changed_lines, file, source_code) do
defp do_create_annotations(line_number_group, annotations, changed_lines, file, source_code) do
end_line = List.first(line_number_group)
start_line = List.last(line_number_group)

Expand Down Expand Up @@ -400,7 +403,13 @@ defmodule CoverageReporter do
{:user_agent, "CoverageReporter"}
]

options = Keyword.merge(opts, base_url: github_api_url, headers: headers)
options =
Keyword.merge(opts,
base_url: github_api_url,
headers: headers,
connect_options: [transport_opts: [cacertfile: "/cacerts.pem"]]
)

request = Req.new(options)

case Req.request(request) do
Expand Down
9 changes: 6 additions & 3 deletions mix.exs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
defmodule CoverageReporter.MixProject do
use Mix.Project

@app :coverage_reporter

def project do
[
app: :coverage_reporter,
app: @app,
version: "0.1.0",
elixir: "~> 1.14",
start_permanent: Mix.env() == :prod,
deps: deps()
deps: deps(),
test_coverage: [tool: LcovEx],
escript: [main_module: CoverageReporter]
]
end

Expand Down
Loading

0 comments on commit bd9949a

Please sign in to comment.