diff --git a/.gitignore b/.gitignore index 2ffb1c25..170db901 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,6 @@ config/*.secret.exs # Temporary CI build file build.env + +# CI metrics file +metrics.txt diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e3ba6690..9afe89a9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -26,7 +26,7 @@ variables: - name: postgres:12 script: script/cibuild -test: +test_1.10.4: <<: *test_template image: "elixir:1.10.4-alpine" @@ -34,9 +34,14 @@ test_1.11.4: <<: *test_template image: "elixir:1.11.4-alpine" -test_1.12.1: +test: <<: *test_template image: "elixir:1.12.1-alpine" + script: + - script/cibuild covered + artifacts: + paths: + - cover/excoveralls.json credo: stage: test @@ -86,6 +91,19 @@ build_image_for_commit: script: - script/ci-docker-build +report_coverage: + stage: deploy_tags + needs: ['test'] + image: "elixir:1.12.1-alpine" + script: + - mix local.hex --force + - script/coverage-json-to-metrics + - script/coverage-json-to-cobertura + artifacts: + reports: + metrics: metrics.txt + cobertura: cover/cobertura.xml + # If tests pass, tag the commit and update package versions deploy_to_tags: stage: deploy_tags diff --git a/apps/content/lib/content/term_relationship.ex b/apps/content/lib/content/term_relationship.ex index 26febdc2..e3364ba3 100644 --- a/apps/content/lib/content/term_relationship.ex +++ b/apps/content/lib/content/term_relationship.ex @@ -4,7 +4,7 @@ defmodule Legendary.Content.TermRelationship do """ use Ecto.Schema import Ecto.Changeset - alias Legendary.Content.{Post} + alias Legendary.Content.Post @primary_key {:object_id, :integer, []} @primary_key {:term_taxonomy_id, :integer, []} diff --git a/mix.exs b/mix.exs index 01cd4932..a8202386 100644 --- a/mix.exs +++ b/mix.exs @@ -11,9 +11,16 @@ defmodule Legendary.Mixfile do build_embedded: Mix.env() == :prod, start_permanent: Mix.env() == :prod, deps: deps(), - aliases: aliases(), test_coverage: [tool: ExCoveralls], - preferred_cli_env: [coveralls: :test, "coveralls.detail": :test, "coveralls.post": :test, "coveralls.html": :test], + aliases: aliases(), + preferred_cli_env: [ + coveralls: :test, + "coveralls.detail": :test, + "coveralls.post": :test, + "coveralls.html": :test, + "coveralls.json": :test, + "coveralls.xml": :test + ], ] end @@ -24,10 +31,8 @@ defmodule Legendary.Mixfile do defp aliases do [ "deps.get": ["cmd mix deps.get"], - "coveralls.html": ["cmd mix coveralls.html"], "ecto.migrate": ["cmd mix ecto.migrate"], - "npm.install": ["cmd mix npm.install"], - test: ["cmd mix test"] + "npm.install": ["cmd mix npm.install"] ] end end diff --git a/script/cibuild b/script/cibuild index a44bc161..6544bbe7 100755 --- a/script/cibuild +++ b/script/cibuild @@ -12,6 +12,10 @@ mix deps.get mix ecto.create mix ecto.migrate -mix test +if [ $1 == 'covered' ]; then + mix coveralls.json --umbrella +else + mix test +fi; script/restore-timestamps diff --git a/script/coverage-json-to-cobertura b/script/coverage-json-to-cobertura new file mode 100755 index 00000000..e4424100 --- /dev/null +++ b/script/coverage-json-to-cobertura @@ -0,0 +1,124 @@ +#!/usr/bin/env elixir + +Mix.install([ + {:jason, "~> 1.0"}, + {:xml_builder, "~> 2.1"} +]) + +%{"source_files" => data} = + "cover/excoveralls.json" + |> File.read!() + |> Jason.decode!() + +{total_covered, total_total} = + data + |> Enum.reduce({0,0}, fn %{"coverage" => cover}, {covered, total} -> + file_covered = + cover + |> Enum.reduce(0, &(if is_integer(&1) && &1 > 0, do: &2 + 1, else: &2)) + + file_total = + cover + |> Enum.reduce(0, &(if is_nil(&1), do: &2, else: &2 + 1)) + + {covered + file_covered, total + file_total} + end) + +ratio = total_covered / total_total + +files = + data + |> Enum.map(fn %{"coverage" => cover, "name" => name} -> + file_covered = + cover + |> Enum.reduce(0, &(if is_integer(&1) && &1 > 0, do: &2 + 1, else: &2)) + + file_total = + cover + |> Enum.reduce(0, &(if is_nil(&1), do: &2, else: &2 + 1)) + + lines = + cover + |> Enum.with_index + |> Enum.map(fn + {nil, _index} -> + nil + {line, index} -> + {:line, %{"number" => index, "hits" => line}, []} + end) + |> Enum.reject(&is_nil/1) + + ratio = + if file_total == 0 do + 1.0 + else + file_covered / file_total + end + + { + :class, + %{"filename" => name, "line-rate" => ratio}, + [ + { + :lines, + %{}, + lines + } + ] + } + end) + +source = + if System.get_env("CI_PROJECT_NAME") do + "#{System.get_env("CI_BUILDS_DIR")}/#{System.get_env("CI_PROJECT_NAMESPACE")}/#{System.get_env("CI_PROJECT_NAME")}" + else + File.cwd! + end + + +buffer = + XmlBuilder.document([ + XmlBuilder.doctype( + "coverage", + system: ["http://cobertura.sourceforge.net/xml/coverage-03.dtd"] + ), + { + :coverage, + %{ + "line-rate" => ratio, + }, + [ + { + :sources, + %{}, + [ + { + :source, + %{}, + source + } + ] + }, + { + :packages, + %{}, + [ + { + :package, + %{"name" => "", "line-rate" => ratio}, + [ + { + :classes, + %{}, + files + } + ] + } + ] + } + ] + } + ]) + |> XmlBuilder.generate + +File.write!("cover/cobertura.xml", buffer) diff --git a/script/coverage-json-to-metrics b/script/coverage-json-to-metrics new file mode 100755 index 00000000..9216b5d9 --- /dev/null +++ b/script/coverage-json-to-metrics @@ -0,0 +1,30 @@ +#!/usr/bin/env elixir + +Mix.install([ + {:jason, "~> 1.0"} +]) + +%{"source_files" => data} = + "cover/excoveralls.json" + |> File.read!() + |> Jason.decode!() + +{total_covered, total_total} = + data + |> Enum.reduce({0,0}, fn %{"coverage" => cover}, {covered, total} -> + file_covered = + cover + |> Enum.reduce(0, &(if is_integer(&1) && &1 > 0, do: &2 + 1, else: &2)) + + file_total = + cover + |> Enum.reduce(0, &(if is_nil(&1), do: &2, else: &2 + 1)) + + {covered + file_covered, total + file_total} + end) + +ratio = + (total_covered / total_total) + |> Float.round(3) + +File.write!("metrics.txt", "coverage #{ratio}")