defmodule Towerops.MixProject do use Mix.Project def project do [ app: :towerops, version: "0.1.0", elixir: "~> 1.20", elixirc_paths: elixirc_paths(Mix.env()), start_permanent: Mix.env() == :prod, aliases: aliases(), deps: deps(), # NIF compiled by `make -C c_src` in dev shell (nix/shell.nix) and # pre-built by `towerops-nif` Nix package in CI/prod. Not an auto-compiler # because Mix.Tasks.Compile.ToweropsNif is part of the project source and # isn't available on the code path when Mix first resolves the compilers # list in a fresh build. Run `mix compile.towerops_nif` manually when # changing C source between `mix compile` runs in dev. compilers: [:phoenix_live_view] ++ Mix.compilers(), prune_code_paths: false, listeners: [Phoenix.CodeReloader], dialyzer: dialyzer(), test_coverage: [ignore_modules: ignore_modules_for_coverage()] ] end # Vendored SnmpKit library, generated protobuf modules, and purely # declarative Phoenix/Absinthe type modules are excluded from coverage # calculations since they are third-party, generated, or data-only code. defp ignore_modules_for_coverage do [ ~r/^SnmpKit/, ~r/^Towerops\.Agent\./, ~r/^Inspect\./, ~r/^ToweropsWeb\.GraphQL\.Types\./, ~r/HTML$/, # Test helpers (compiled into :test env so they show up in coverage) ToweropsWeb.LiveViewTestHelpers, ToweropsWeb.ConnCase, Towerops.DataCase, Towerops.Lidar.Test.FakeParser, Towerops.Test.StubTerrain, # Release-only DB migrate/rollback task — only meaningful in a deployed # release where Mix isn't loaded; can't be exercised under ExUnit. Towerops.Release, # Mix compile task that shells out to `make` to build the C NIF — tested # implicitly by every other test (the NIF must build for the suite to load). Mix.Tasks.Compile.ToweropsNif, # Postgrex types macro emits a defmodule but no testable code paths. Towerops.PostgrexTypes, # Absinthe schema DSL — every `field/arg/middleware` line registers # metadata at compile time. Resolvers are tested via GraphQL integration # tests; the schema declarations themselves carry no runtime behaviour. ToweropsWeb.GraphQL.Schema, # OTP boot — runs once at app start; covered implicitly by every test # (the app must boot for ExUnit to run) but the boot-time conditionals # for prod/dev paths can't be exercised under :test. Towerops.Application ] end # Configuration for the OTP application. # # Type `mix help compile.app` for more information. def application do [ mod: {Towerops.Application, []}, extra_applications: [:logger, :runtime_tools, :os_mon] ] end def cli do [ preferred_envs: [precommit: :test] ] end # Specifies which paths to compile per environment. defp elixirc_paths(:test), do: ["lib", "test/support"] defp elixirc_paths(_), do: ["lib"] # Specifies your project dependencies. # # Type `mix help deps` for examples and options. defp deps do [ {:argon2_elixir, "~> 4.0"}, {:nimble_totp, "~> 1.0"}, {:eqrcode, "~> 0.2.1"}, {:phoenix, "~> 1.8.3"}, {:phoenix_ecto, "~> 4.5"}, {:ecto_sql, "~> 3.13"}, {:postgrex, ">= 0.0.0"}, {:phoenix_html, "~> 4.1"}, {:phoenix_live_reload, "~> 1.2", only: :dev}, {:phoenix_live_view, "~> 1.2"}, {:lazy_html, ">= 0.1.0", only: :test}, {:phoenix_live_dashboard, "~> 0.8.3"}, {:esbuild, "~> 0.10", runtime: Mix.env() == :dev}, {:tailwind, "~> 0.3", runtime: Mix.env() == :dev}, {:heroicons, github: "tailwindlabs/heroicons", tag: "v2.2.0", sparse: "optimized", app: false, compile: false, depth: 1}, {:swoosh, "~> 1.24"}, {:gen_smtp, "~> 1.0"}, {:req, "~> 0.5"}, {:gaiia, path: "vendor/gaiia"}, {:castore, "~> 1.0"}, {:sweet_xml, "~> 0.7"}, {:yaml_elixir, "~> 2.9"}, {:telemetry_metrics, "~> 1.0"}, {:telemetry_poller, "~> 1.0"}, {:prom_ex, "~> 1.11"}, {:gettext, "~> 1.0"}, {:jason, "~> 1.2"}, {:dns_cluster, "~> 0.2.0"}, {:libcluster, "~> 3.4"}, {:oban_pro, "~> 1.7", path: "vendor/oban_pro"}, {:oban_met, "~> 1.0", path: "vendor/oban_met", override: true}, {:oban_web, "~> 2.11", path: "vendor/oban_web"}, {:bandit, "~> 1.5"}, {:phoenix_pubsub_redis, "~> 3.0"}, {:ecto_psql_extras, "~> 0.6"}, {:mox, "~> 1.0", only: :test}, {:absinthe, "~> 1.7"}, {:absinthe_plug, "~> 1.5"}, {:absinthe_phoenix, "~> 2.0"}, {:error_tracker, "~> 0.7"}, {:error_tracker_notifier, "~> 0.2"}, {:stream_data, "~> 1.1", only: :test}, {:tzdata, "~> 1.1"}, {:styler, "~> 1.10", only: [:dev, :test], runtime: false}, {:mix_test_watch, "~> 1.0", only: [:dev, :test], runtime: false}, {:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false}, {:credo, "~> 1.7", only: [:dev, :test], runtime: false}, {:jump_credo_checks, "~> 0.4", only: [:dev, :test], runtime: false}, {:mix_audit, "~> 2.1", only: [:dev, :test], runtime: false}, {:inet_cidr, "~> 1.0"}, {:cloak_ecto, "~> 1.3"}, {:geo_postgis, "~> 3.7"}, {:logger_file_backend, "~> 0.0.13", only: :dev}, {:logger_backends, "~> 1.0", only: :dev}, # Force hackney 4.x to fix CVEs (GHSA-gp9c-pm5m-5cxr, GHSA-j9wq-vxxc-94wf, etc.) {:hackney, "~> 4.6", override: true}, {:httpoison, "~> 3.0", override: true}, # Force mint 1.9.3+ to fix CVE-2026-59249 (HTTP/1 chunk-size parser) {:mint, "~> 1.9", override: true} ] end # Dialyzer configuration for static analysis defp dialyzer do [ plt_file: {:no_warn, "priv/plts/dialyzer.plt"}, plt_add_deps: :apps_direct, plt_add_apps: [ :mix, :ex_unit, :ecto, :plug, :plug_crypto, :phoenix, :phoenix_pubsub, :phoenix_live_view, :phoenix_template, :oban, :decimal, :redix, :telemetry, :ssl, :public_key, :geo, :geo_postgis, :db_connection, :tools ], flags: [:unmatched_returns, :error_handling, :underspecs, :unknown], ignore_warnings: ".dialyzer_ignore.exs" ] end # Aliases are shortcuts or tasks specific to the current project. # For example, to install project dependencies and perform other setup tasks, run: # # $ mix setup # # See the documentation for `Mix` for more info on aliases. defp aliases do [ setup: ["deps.get", "ecto.setup", "assets.setup", "assets.build"], "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"], "ecto.reset": ["ecto.drop", "ecto.setup"], test: ["ecto.create --quiet", "ecto.load --quiet --skip-if-loaded", "ecto.migrate --quiet", "test"], "assets.setup": ["tailwind.install --if-missing", "esbuild.install --if-missing"], "assets.build": ["compile", "tailwind towerops", "esbuild towerops"], "assets.deploy": [ "tailwind towerops --minify", "esbuild towerops --minify", "phx.digest" ], precommit: [ "compile", "deps.unlock --unused", "format", "test" ] ] end end