# Purge any INSTALLED archive from the code path so the source tree wins # while developing. Both names matter: our modules are still namespaced # `Phx.New.*` (deliberately — it keeps the upstream rebase clean), so a # stock phx_new archive would clash with them just as an older cms_new would. for path <- :code.get_path(), Regex.match?(~r/(cms_new|phx_new)-[\w\.\-]+\/ebin$/, List.to_string(path)) do Code.delete_path(path) end defmodule Phx.New.MixProject do use Mix.Project # Ours, and it bumps on our schedule — this is published to hex, so the # version has to move when what we ship moves. # # It started life equal to the Phoenix installer version this forks, which # made it read like a statement about upstream and left nothing to increment # without lying about which Phoenix it tracks. `@phoenix_version` carries that # fact now, so the two can move independently: a patch of ours bumps the # version below and leaves the fork point alone, and taking a new upstream # tree onto `vendor` bumps both. @version "1.8.9" # Upstream fork point: Phoenix installer 1.8.8, which is what `vendor` holds. # A comment rather than an attribute because nothing reads it — it is recorded # so the fork point survives, since the rebase workflow depends on knowing # which tree the squashed patch commit sits on top of. @scm_url "https://github.com/Code-My-Spec/cms_new" # If the elixir requirement is updated, we need to update: # # 1. all mix.exs generated by the installer # 2. guides/introduction/installation.md # 3. guides/deployment/releases.md # 4. test/test_helper.exs at the root # 5. installer/lib/mix/tasks/phx.new.ex # @elixir_requirement "~> 1.20" def project do [ app: :cms_new, start_permanent: Mix.env() == :prod, version: @version, elixir: @elixir_requirement, deps: deps(), aliases: aliases(), package: [ maintainers: [ "Chris McCord", "José Valim", "Gary Rennie", "Jason Stiebs" ], licenses: ["MIT"], links: %{"GitHub" => @scm_url}, files: ~w(lib templates mix.exs README.md) ], source_url: @scm_url, docs: docs(), homepage_url: "https://codemyspec.com", description: """ CodeMySpec project generator. Provides a `mix cms.new` task to bootstrap a new Phoenix application that already satisfies every CodeMySpec harness convention — no model-driven setup pass required. """ ] end def cli do [preferred_envs: [docs: :docs]] end def application do [ extra_applications: [:eex, :crypto, :public_key] ] end def deps do [ {:ex_doc, "~> 0.24", only: :docs} ] end defp docs do [ source_url_pattern: "#{@scm_url}/blob/v#{@version}/installer/%{path}#L%{line}" ] end defp aliases do [ "hex.publish": [ ©_agents_md/1, "hex.publish" ] ] end # Refresh the vendored usage rules from a sibling checkout, when there is one. # # Upstream regenerates these from its own `usage-rules` sibling on every # publish. This fork has no such sibling — upstream gitignores the copied # directory, so ours is force-added and tracked, and the tracked copy is the # source of truth here. # # It was an unconditional `cp_r!`, which meant `mix hex.publish` died with a # `File.CopyError` about a directory that is not supposed to exist, before # publishing began. The failure named the missing sibling rather than the # convention, so it read like a broken checkout instead of an inherited step # that does not apply. # # Says which it did, because "refreshed from upstream" and "shipped what is # committed" are different claims about what is in the package, and silently # doing the second while somebody believes the first is how stale rules ship. defp copy_agents_md(_) do source = Path.expand("../usage-rules", __DIR__) target = Path.expand("./templates/phoenix-usage-rules", __DIR__) cond do File.dir?(source) -> File.cp_r!(source, target) Mix.shell().info("usage rules: refreshed from #{source}") File.dir?(target) -> Mix.shell().info("usage rules: shipping the committed copy (no sibling checkout)") true -> Mix.raise(""" No usage rules to ship. #{target} does not exist and there is no sibling checkout at #{source} to build it from. The generated app expects these, so publishing without them would ship a generator that produces projects missing their usage rules. """) end end end