feat(dialyzer): add typecheck stage to full CI pipelines
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/promote/production Build is failing

This commit is contained in:
Moritz 2026-06-01 23:45:07 +02:00
parent ce57d046b9
commit 263857ee26
6 changed files with 68 additions and 2 deletions

11
.dialyzer_ignore.exs Normal file
View file

@ -0,0 +1,11 @@
# Dialyzer ignore list.
#
# This file is for PROVEN false positives only. Each entry must carry a
# `# why:` comment explaining why Dialyzer is wrong about the call site.
# Real findings get fixed by adjusting @spec, return types, or pattern
# matches — never silenced here.
#
# Format: each entry is either a path string, a {path, warning} tuple,
# or a {path, warning, line} tuple. See:
# https://hexdocs.pm/dialyxir/readme.html#elixir-format
[]

View file

@ -27,7 +27,7 @@ local step_compute_cache = {
local step_restore_cache = {
name: 'restore-cache',
image: 'drillster/drone-volume-cache',
settings: { restore: true, mount: ['./deps', './_build'], ttl: 30 },
settings: { restore: true, mount: ['./deps', './_build', './priv/plts'], ttl: 30 },
volumes: cache_mount,
};
@ -47,6 +47,20 @@ local step_lint = {
],
};
local step_typecheck = {
name: 'typecheck',
image: elixir,
commands: [
'mix local.hex --force',
'mix deps.get',
'mkdir -p priv/plts',
// Build/refresh PLT no-op on cache hit, full build (5-15 min) on cache miss.
'mix dialyzer --plt',
// Actual typecheck. --format short keeps log noise down on red builds.
'mix dialyzer --format short',
],
};
local step_wait_postgres = {
name: 'wait_for_postgres',
image: postgres_image,
@ -69,7 +83,7 @@ local step_wait_postgres = {
local step_rebuild_cache = {
name: 'rebuild-cache',
image: 'drillster/drone-volume-cache',
settings: { rebuild: true, mount: ['./deps', './_build'] },
settings: { rebuild: true, mount: ['./deps', './_build', './priv/plts'] },
volumes: cache_mount,
};
@ -99,6 +113,7 @@ local check_pipeline(name, trigger, test) = {
step_compute_cache,
step_restore_cache,
step_lint,
] + (if test.name == 'test-all' then [step_typecheck] else []) + [
step_wait_postgres,
test,
step_rebuild_cache,

4
.gitignore vendored
View file

@ -49,3 +49,7 @@ notes.md
# Do NOT commit these — they are local to the dev machine
.pipeline/
.claude/
# Dialyzer PLT files — built locally and in CI cache, never tracked.
/priv/plts/*.plt
/priv/plts/*.plt.hash

View file

@ -31,6 +31,21 @@ start-database:
ci-dev: lint audit test-fast
# Build the Dialyzer PLT. Idempotent — no-op once the PLT is up to date.
# First build takes 515 min; subsequent runs are seconds. PLT files live in
# priv/plts/ and are gitignored.
plt: install-dependencies
@mkdir -p priv/plts
mix dialyzer --plt
# Typecheck via Dialyzer. Slow stage, NOT part of ci-dev.
typecheck: plt
mix dialyzer --format short
# Full CI: inner loop plus typecheck. Use locally before pushing; Drone CI
# runs equivalent steps with PLT caching.
ci: ci-dev typecheck
gettext:
mix gettext.extract
mix gettext.merge priv/gettext --on-obsolete=mark_as_obsolete

19
mix.exs
View file

@ -12,6 +12,7 @@ defmodule Mv.MixProject do
compilers: [:phoenix_live_view] ++ Mix.compilers(),
aliases: aliases(),
deps: deps(),
dialyzer: dialyzer(),
listeners: [Phoenix.CodeReloader],
gettext: [write_reference_line_numbers: false]
]
@ -80,6 +81,7 @@ defmodule Mv.MixProject do
{:sobelow, "~> 0.14", only: [:dev, :test], runtime: false},
{:bypass, "~> 2.1", only: [:dev, :test]},
{:credo, "~> 1.7", only: [:dev, :test], runtime: false},
{:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false},
{:picosat_elixir, "~> 0.1"},
{:ecto_commons, "~> 0.3"},
{:slugify, "~> 1.3"},
@ -112,4 +114,21 @@ defmodule Mv.MixProject do
"phx.routes": ["phx.routes", "ash_authentication.phoenix.routes"]
]
end
defp dialyzer do
[
plt_file: {:no_warn, "priv/plts/dialyzer.plt"},
plt_core_path: "priv/plts/core.plt",
plt_add_apps: [:mix, :ex_unit],
flags: [
:error_handling,
:unmatched_returns,
:extra_return,
:missing_return,
:underspecs
],
ignore_warnings: ".dialyzer_ignore.exs",
list_unused_filters: true
]
end
end

View file

@ -23,11 +23,13 @@
"crux": {:hex, :crux, "0.1.2", "4441c9e3a34f1e340954ce96b9ad5a2de13ceb4f97b3f910211227bb92e2ca90", [:mix], [{:picosat_elixir, "~> 0.2", [hex: :picosat_elixir, repo: "hexpm", optional: true]}, {:simple_sat, ">= 0.1.1 and < 1.0.0-0", [hex: :simple_sat, repo: "hexpm", optional: true]}, {:stream_data, "~> 1.0", [hex: :stream_data, repo: "hexpm", optional: true]}], "hexpm", "563ea3748ebfba9cc078e6d198a1d6a06015a8fae503f0b721363139f0ddb350"},
"db_connection": {:hex, :db_connection, "2.10.1", "d5465f6bcc125c1b8981c1dbf23c193ca16f446ec0b25832dc174f74f18be510", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "18ed94c6e627b4bf452dbd4df61b69a35a1e768525140bc1917b7a685026a6a3"},
"decimal": {:hex, :decimal, "3.1.0", "9ede268cff827e6f0c4fb1b34747c82630dce5d7b877dfb22ec8f0cb25855fce", [:mix], [], "hexpm", "e8b3efb3bb3a13cb5e4268ffe128569067b1972e9dee013537c71a5b073168f9"},
"dialyxir": {:hex, :dialyxir, "1.4.7", "dda948fcee52962e4b6c5b4b16b2d8fa7d50d8645bbae8b8685c3f9ecb7f5f4d", [:mix], [{:erlex, ">= 0.2.8", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "b34527202e6eb8cee198efec110996c25c5898f43a4094df157f8d28f27d9efe"},
"dns_cluster": {:hex, :dns_cluster, "0.2.0", "aa8eb46e3bd0326bd67b84790c561733b25c5ba2fe3c7e36f28e88f384ebcb33", [:mix], [], "hexpm", "ba6f1893411c69c01b9e8e8f772062535a4cf70f3f35bcc964a324078d8c8240"},
"ecto": {:hex, :ecto, "3.13.6", "352135b474f91d1ab99a1b502171d207e9db60421c9e3d0ecab4c7ab96b24d14", [:mix], [{:decimal, "~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "8afa059bc16cd2c94739ec0a11e3e5df69d828125119109bef35f20a21a76af2"},
"ecto_commons": {:hex, :ecto_commons, "0.3.7", "f33c162a6f63695d5939af02c65a0e76aa6e7278b82c7bfc357ffbfea353bf0f", [:mix], [{:burnex, "~> 3.0", [hex: :burnex, repo: "hexpm", optional: true]}, {:ecto, "~> 3.4", [hex: :ecto, repo: "hexpm", optional: false]}, {:ex_phone_number, "~> 0.4", [hex: :ex_phone_number, repo: "hexpm", optional: false]}, {:luhn, "~> 0.3.0", [hex: :luhn, repo: "hexpm", optional: false]}], "hexpm", "9c33771ebd38cd83d3f90fab6069826ba9d4f7580f1481b3c0913f8b9795c5fd"},
"ecto_sql": {:hex, :ecto_sql, "3.13.5", "2f8282b2ad97bf0f0d3217ea0a6fff320ead9e2f8770f810141189d182dc304e", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.13.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "aa36751f4e6a2b56ae79efb0e088042e010ff4935fc8684e74c23b1f49e25fdc"},
"elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"},
"erlex": {:hex, :erlex, "0.2.9", "7debbbaa9f4f368b8cd648983e0f1d7963028508e9c59e9d4ed504e94ef52a55", [:mix], [], "hexpm", "8cfffc0ec7159e6d73de2ab28a588064de80f88b2798d5cbe4482cbbc200178b"},
"esbuild": {:hex, :esbuild, "0.10.0", "b0aa3388a1c23e727c5a3e7427c932d89ee791746b0081bbe56103e9ef3d291f", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "468489cda427b974a7cc9f03ace55368a83e1a7be12fba7e30969af78e5f8c70"},
"ets": {:hex, :ets, "0.9.0", "79c6a6c205436780486f72d84230c6cba2f8a9920456750ddd1e47389107d5fd", [:mix], [], "hexpm", "2861fdfb04bcaeff370f1a5904eec864f0a56dcfebe5921ea9aadf2a481c822b"},
"ex_phone_number": {:hex, :ex_phone_number, "0.4.10", "11809f6600b2ecb0a2e75d496c2ec2f273d49d1e2f58b2be2667decb0aabfb43", [:mix], [{:sweet_xml, "~> 0.7", [hex: :sweet_xml, repo: "hexpm", optional: false]}], "hexpm", "eefccf58d8149d64af658721bff0edcb9e9b8943f74000ede151948ef03046c1"},