defmodule SvExNew.MixProject do use Mix.Project # `.version` is the single source of truth, spelled the way the parent repo # spells its own. This archive's version is INDEPENDENT of sv_ex's: the two # ship as separate packages on separate cadences, and the root # `scripts/bump_version.exs` bumps THIS file only for commits that touch a path # under `installer/sv_ex_new/`. A commit confined to the hex package leaves it # alone, so the two numbers accumulate at their own rates and are meant to. # # Resolved against __DIR__, never a bare ".version". A relative read resolves # against the CURRENT WORKING DIRECTORY, which is this project's root only by # convention — it is not when the root suite shells in from one directory up, # which is exactly how this project is built and tested. @version_path Path.join(__DIR__, ".version") @external_resource @version_path @version @version_path |> File.read!() |> String.trim() # Hex REFUSES to build without `links` -- "Missing metadata fields: links" -- # so this is not optional metadata. # # It points at the PARENT repository, not at an `sv_ex_new` repository of its # own: this directory is a nested build target inside sv_ex, not a separate # checkout. Two hex packages, one repository -- README.md, "One project, two # outputs": "no second product, no second repository and no second roadmap". # The project this was ported from split the two across repositories and had # to gitignore one inside the other; that is the arrangement being dropped, # not copied. @source_url "https://github.com/wimwian-org/sv_ex" @description "Zero-dependency bootstrap archive for SvEx projects." def project do [ app: :sv_ex_new, version: @version, elixir: "~> 1.20", elixirc_paths: elixirc_paths(Mix.env()), deps: deps(), description: @description, package: package(), test_coverage: [tool: ExCoveralls], dialyzer: [plt_add_apps: [:mix]], docs: [main: "readme", extras: ["README.md"]] ] end def cli do [preferred_envs: [coveralls: :test, "coveralls.json": :test]] end # Deliberately empty, so the shipped .app declares exactly # [:kernel, :stdlib, :elixir] — the archive's zero-dependency claim, asserted # by the root suite's archive_test.exs. # # `extra_applications: [:eex]` would be the intuitive addition, because the # generators this task delegates to (`mix new`, `mix phx.new`) render their # templates through EEx. It is not needed and is not harmless: it appends # :eex to `applications` and breaks that assertion. `extra_applications` # governs release inclusion and application start order, NOT code-path # availability — :eex ships with Elixir and its ebin is already on the path # for any in-process `Mix.Task.run/2`. def application, do: [] defp elixirc_paths(:test), do: ["lib", "test/support"] defp elixirc_paths(_), do: ["lib"] # `files` is spelled out only because `.version` is not one of hex's defaults, # and mix.exs reads it at build time — a package without it builds here and # fails to compile for the consumer. Everything else in the list is what the # default would have included anyway. # defp package do [ description: @description, licenses: ["MIT"], links: %{"GitHub" => @source_url}, files: ~w(.version lib mix.exs README.md .formatter.exs) ] end # RULE: every dep MUST carry an `only:` that EXCLUDES :prod. # # `runtime: false` is NOT the discriminator — {:jason, "~> 1.4", # runtime: false} with no `only:` still emits a full entry in the package's # `requirements`, and this archive's whole point is having none. # # A dep with `only: [:dev, :test]` and the default `runtime: true` also leaks # into the shipped .app's `applications` list while shipping zero BEAMs — # which is why the tooling deps below carry `runtime: false` as well. defp deps do [ {:credo, "~> 1.7", only: [:dev, :test], runtime: false}, {:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false}, {:doctor, "~> 0.21", only: [:dev, :test], runtime: false}, {:ex_doc, "~> 0.34", only: :dev, runtime: false}, {:excoveralls, "~> 0.18", only: :test, runtime: false}, {:ex_machina, "~> 2.8", only: :test, runtime: false}, {:faker, "~> 0.18", only: :test, runtime: false} ] end end