Skip to content

Commit 5c9968a

Browse files
authored
Merge pull request #102 from yknx4/feature/pr-message
feat: pr message with diff data
2 parents 22ef4f8 + d00acf0 commit 5c9968a

File tree

20 files changed

+1156
-38
lines changed

20 files changed

+1156
-38
lines changed

.github/workflows/tests.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ jobs:
3737
mix deps.get
3838
mix deps.compile
3939
mix dialyzer --plt
40+
mix compile
4041
4142
static-code-analysis:
4243
needs: dependencies
@@ -118,14 +119,16 @@ jobs:
118119
files: cover/excoveralls.json
119120
fail_ci_if_error: true
120121
- name: LibreCov
121-
continue-on-error: true
122122
env:
123123
SHA: ${{github.sha}}
124-
BRANCH: ${{ steps.extract_branch.outputs.branch }}
124+
BRANCH: ${{ github.ref }}
125125
TOKEN: ${{ secrets.OPENCOV_TOKEN }}
126126
COVERALLS_ENDPOINT: ${{ secrets.OPENCOV_ENDPOINT }}
127+
RUN_NUMBER: ${{ github.run_id }}
127128
run: |
128129
MIX_ENV=test mix coveralls.post \
130+
--name github-actions \
131+
--build "$RUN_NUMBER" \
129132
--sha "$SHA" \
130133
--committer "$(git log -1 $SHA --pretty=format:'%cN')" \
131134
--message "$(git log -1 $SHA --pretty=format:'%s')" \

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ config/local.exs
1111
*.coverdata
1212

1313
*.dump
14-
*.pem
14+
*.pem
15+
cover

config/prod.exs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use Mix.Config
22

3+
config :tesla, Tesla.Middleware.Logger, filter_headers: ["authorization"]
4+
35
config :librecov, Librecov.Endpoint,
46
http: [port: {:system, "PORT"}, compress: true],
57
url: [
@@ -42,7 +44,7 @@ config :sentry,
4244
tags: %{
4345
env: "production"
4446
},
45-
included_environments: [:production]
47+
included_environments: ["production"]
4648

4749
if File.exists?(Path.join(__DIR__, "prod.secret.exs")) do
4850
import_config "prod.secret.exs"

lib/opencov/helpers/coverage.ex

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
defmodule Librecov.Helpers.Coverage do
2+
@doc """
3+
Print friendly percentage of coverage.
4+
5+
## Examples
6+
iex> Librecov.Helpers.Coverage.format_coverage(65.215478)
7+
"65.22%"
8+
"""
9+
def format_coverage(coverage), do: "#{Float.round(coverage, 2)}%"
10+
11+
@doc """
12+
Coverage differ with null handling.
13+
14+
## Examples
15+
iex> Librecov.Helpers.Coverage.coverage_diff(65.215478, nil)
16+
65.215478
17+
iex> Librecov.Helpers.Coverage.coverage_diff(65.0, 70.0)
18+
-5.0
19+
"""
20+
def coverage_diff(coverage, nil), do: coverage
21+
def coverage_diff(coverage, previous_coverage), do: coverage - previous_coverage
22+
end

lib/opencov/services/github/checks.ex

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,32 @@ defmodule Librecov.Services.Github.Checks do
33
alias ExOctocat.Connection
44
alias ExOctocat.Api.Checks
55
alias Librecov.Build
6+
import Librecov.Helpers.Coverage
67

7-
def finish_check(token, owner, repo, %Build{
8-
coverage: coverage,
9-
previous_coverage: previous_coverage,
10-
commit_sha: commit
11-
}) do
12-
cov_dif = coverage_diff(coverage, previous_coverage) |> format_coverage()
8+
def finish_check(
9+
token,
10+
owner,
11+
repo,
12+
%Build{
13+
coverage: coverage,
14+
previous_coverage: previous_coverage,
15+
commit_sha: commit
16+
},
17+
base_coverage
18+
) do
19+
real_previous_coverage = base_coverage || previous_coverage || 0.0
20+
cov_dif = coverage_diff(coverage, real_previous_coverage) |> format_coverage()
1321
cov = coverage |> format_coverage()
1422

23+
Logger.info("""
24+
Repo: #{owner}/#{repo}
25+
Commit: #{commit}
26+
Coverage: #{cov}
27+
Coverage diff: #{cov_dif}
28+
Project Previous Coverage: #{base_coverage}
29+
Build Previous Coverage: #{previous_coverage}
30+
""")
31+
1532
conn =
1633
token
1734
|> Connection.new()
@@ -35,7 +52,7 @@ defmodule Librecov.Services.Github.Checks do
3552
body: %{
3653
name: "LibreCov/diff",
3754
head_sha: commit,
38-
conclusion: coverage_diff(coverage, previous_coverage) |> diff_conclusion(),
55+
conclusion: coverage_diff(coverage, real_previous_coverage) |> diff_conclusion(),
3956
output: %{
4057
title: "Coverage changed #{cov_dif}",
4158
summary: "changed #{cov_dif}"
@@ -65,9 +82,4 @@ defmodule Librecov.Services.Github.Checks do
6582
defp diff_conclusion(diff) when diff == 0, do: "neutral"
6683
defp diff_conclusion(diff) when diff < 0, do: "failure"
6784
defp diff_conclusion(diff) when diff > 0, do: "success"
68-
69-
defp format_coverage(coverage), do: "#{Float.round(coverage, 2)}%"
70-
71-
defp coverage_diff(coverage, nil), do: coverage
72-
defp coverage_diff(coverage, previous_coverage), do: coverage - previous_coverage
7385
end
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
defmodule Librecov.Services.Github.Comments do
2+
require Logger
3+
alias ExOctocat.Connection
4+
alias ExOctocat.Api.Issues
5+
alias Librecov.Services.Github.PullRequests
6+
alias ExOctocat.Model.PullRequestSimple
7+
8+
def add_pr_comment(_, _, _, _, nil) do
9+
Logger.warn("Skipping because branch is nil.")
10+
end
11+
12+
def add_pr_comment(pr_message, token, owner, repo, branch) do
13+
case token |> PullRequests.find_prs_for_branch(owner, repo, branch) do
14+
{:ok, []} ->
15+
Logger.info("No pull requests found for branch #{branch}")
16+
{:error, :pr_not_found}
17+
18+
{:ok, prs} when is_list(prs) ->
19+
{:ok, prs |> Enum.map(&add_pr_message(token, pr_message, &1))}
20+
21+
{_, e} when is_exception(e) ->
22+
Logger.error(e |> Exception.message())
23+
Sentry.capture_exception(e)
24+
{:error, e}
25+
26+
{_, %{message: message}} ->
27+
Logger.error(message)
28+
29+
raise(
30+
"Error processing add_pr_comment(pr_message, #{token}, #{owner}, #{repo}, #{branch}): #{message}."
31+
)
32+
33+
e ->
34+
raise(
35+
"Error processing add_pr_comment(pr_message, #{token}, #{owner}, #{repo}, #{branch})."
36+
)
37+
end
38+
end
39+
40+
def add_pr_message(token, pr_message, %PullRequestSimple{
41+
number: issue_number,
42+
base: %{repo: %{name: repo, owner: %{login: owner}}}
43+
}) do
44+
Logger.info("Sending pr_message to #{owner}/#{repo}##{issue_number}.")
45+
46+
{:ok, %{id: id} = comment} =
47+
token
48+
|> Connection.new()
49+
|> Issues.issues_create_comment(owner, repo, issue_number, body: %{body: pr_message})
50+
51+
Logger.info(
52+
"Succesfully sent message to #{owner}/#{repo}##{issue_number}. IssueComment##{id}"
53+
)
54+
55+
comment
56+
end
57+
end
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
defmodule Librecov.Services.Github.PullRequests do
2+
require Logger
3+
alias ExOctocat.Connection
4+
alias ExOctocat.Api.Pulls
5+
6+
def find_prs_for_branch(token, owner, repo, branch) do
7+
token
8+
|> Connection.new()
9+
|> Pulls.pulls_list(owner, repo, state: "open", sort: "updated", head: "#{owner}:#{branch}")
10+
end
11+
end
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
defmodule Librecov.Templates.CommentTemplate do
2+
alias Librecov.Build
3+
alias Librecov.Project
4+
alias Librecov.Endpoint
5+
alias Librecov.JobManager
6+
alias Librecov.File
7+
alias Librecov.Job
8+
import Librecov.Router.Helpers
9+
import Librecov.Helpers.Coverage
10+
11+
def coverage_message(
12+
%Project{
13+
current_coverage: project_coverage
14+
},
15+
%Build{
16+
id: build_id,
17+
coverage: coverage,
18+
previous_coverage: previous_coverage,
19+
commit_sha: commit,
20+
branch: branch
21+
},
22+
%Job{} = job
23+
) do
24+
real_previous_coverage = project_coverage || previous_coverage || 0.0
25+
cov_dif = coverage_diff(coverage, real_previous_coverage)
26+
27+
report_url = build_url(Endpoint, :show, build_id)
28+
29+
job =
30+
job
31+
|> JobManager.preload_files()
32+
33+
files =
34+
job.files
35+
|> Enum.filter(fn %File{coverage: coverage, previous_coverage: previous_coverage} ->
36+
coverage_diff(coverage, previous_coverage) != 0
37+
end)
38+
39+
"""
40+
# [Librecov](#{report_url}) Report
41+
#{merge_message(cov_dif, branch, commit, report_url)}
42+
#{diff_message(cov_dif, coverage)}
43+
#{impacted_files_message(report_url, files)}
44+
------
45+
46+
[Continue to review full report at Librecov](#{report_url}).
47+
> **Legend**
48+
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
49+
> Powered by [Librecov](#{project_url(Endpoint, :index)}).
50+
"""
51+
end
52+
53+
defp merge_message(_, nil, _, _), do: ""
54+
defp merge_message(_, _, nil, _), do: ""
55+
56+
defp merge_message(0.0, branch, commit, report_url),
57+
do:
58+
"> Merging [#{branch |> format_branch()}](#{report_url}) (#{commit |> format_commit()}) will **not change** coverage."
59+
60+
defp merge_message(cov_dif, branch, commit, report_url),
61+
do:
62+
"> Merging [#{branch |> format_branch()}](#{report_url}) (#{commit |> format_commit()}) will **#{cov_dif |> diff_verb()}** coverage by `#{cov_dif |> format_coverage()}`."
63+
64+
defp diff_message(0.0, _), do: "> The diff coverage is `n/a`."
65+
defp diff_message(_, coverage), do: "> The diff coverage is `#{coverage |> format_coverage()}`."
66+
67+
defp impacted_files_message(_, []), do: ""
68+
69+
defp impacted_files_message(report_url, files) do
70+
"""
71+
72+
| [Impacted Files](#{report_url}) | Coverage Δ | |
73+
|---|---|---|
74+
#{files |> Enum.map(&file_line/1) |> Enum.join("\n")}
75+
76+
"""
77+
end
78+
79+
defp file_line(%File{
80+
id: file_id,
81+
name: filename,
82+
coverage: coverage,
83+
previous_coverage: previous_coverage
84+
}) do
85+
cov_diff = coverage_diff(coverage, previous_coverage)
86+
87+
"| [#{filename}](#{file_url(Endpoint, :show, file_id)}) | `#{coverage |> format_coverage()} <#{cov_diff |> format_coverage()}> (#{cov_diff |> file_icon()})` | #{cov_diff |> diff_emoji()} |"
88+
end
89+
90+
defp diff_emoji(diff) when diff == 0, do: ""
91+
defp diff_emoji(diff) when diff < 0, do: "⬇️"
92+
defp diff_emoji(diff) when diff > 0, do: "⬆️"
93+
94+
defp file_icon(diff) when diff >= 0.0 and diff <= 0.01, do: "ø"
95+
defp file_icon(_diff), do: "Δ"
96+
97+
defp format_commit(commit), do: String.slice(commit, 0, 7)
98+
99+
defp format_branch(""), do: "this"
100+
defp format_branch(nil), do: "this"
101+
defp format_branch("refs/heads/" <> branch), do: branch
102+
defp format_branch(branch), do: branch
103+
104+
defp diff_verb(diff) when diff == 0, do: "mantain"
105+
defp diff_verb(diff) when diff < 0, do: "decrease"
106+
defp diff_verb(diff) when diff > 0, do: "increase"
107+
end

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ defmodule Librecov.Mixfile do
7272
{:meck, "~> 0.9", override: true},
7373
{:tesla, "~> 1.2"},
7474
{:poison, "~> 3.0"},
75-
{:ex_octocat, github: "yknx4/ex_octocat", tag: "v1.1.4"}
75+
{:ex_octocat, github: "yknx4/ex_octocat", tag: "v1.1.4.1"}
7676
]
7777
end
7878

mix.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
2121
"ex_crypto": {:hex, :ex_crypto, "0.10.0", "af600a89b784b36613a989da6e998c1b200ff1214c3cfbaf8deca4aa2f0a1739", [:mix], [{:poison, ">= 2.0.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm", "ccc7472cfe8a0f4565f97dce7e9280119bf15a5ea51c6535e5b65f00660cde1c"},
2222
"ex_machina": {:hex, :ex_machina, "2.7.0", "b792cc3127fd0680fecdb6299235b4727a4944a09ff0fa904cc639272cd92dc7", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "419aa7a39bde11894c87a615c4ecaa52d8f107bbdd81d810465186f783245bf8"},
23-
"ex_octocat": {:git, "https://github.com/yknx4/ex_octocat.git", "a244cb0c183015c44d5deaa2ebf9b7d492dfb775", [tag: "v1.1.4"]},
23+
"ex_octocat": {:git, "https://github.com/yknx4/ex_octocat.git", "034c249fe1476667a6def8f8977d74e3d47c7d4a", [tag: "v1.1.4.1"]},
2424
"excoveralls": {:hex, :excoveralls, "0.14.2", "f9f5fd0004d7bbeaa28ea9606251bb643c313c3d60710bad1f5809c845b748f0", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "ca6fd358621cb4d29311b29d4732c4d47dac70e622850979bc54ed9a3e50f3e1"},
2525
"exgravatar": {:hex, :exgravatar, "2.0.2", "638412896170409da114f98947d3f8d4f38e851b0e329c1cc4cd324d5e2ea081", [:mix], [], "hexpm", "f3deb5baa6fcf354a965d794ee73a956d95f1f79f41bddf69800c713cfb014a1"},
2626
"exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm", "32e95820a97cffea67830e91514a2ad53b888850442d6d395f53a1ac60c82e07"},

0 commit comments

Comments
 (0)