Dotenvy Generators

Provides alternative Phoenix generators (phx.new et al) that leverage Dotenvy for application configuration.

The following generators are included:

The Phoenix tasks are intended to replace any existing Phoenix installers (available as the phx_new archive).

Based off version 1.7.18 of the Phoenix installers.

This repo provides Mix tasks as an archive.

Installation

Hex installation

Because these variants are designed to replace their Phoenix counterparts, it is advised to first uninstall any existing Phoenix generators:

mix archive.uninstall phx_new
mix archive.install hex dotenvy_generators

To build and install locally

Ensure the conflicting Phoenix generators are removed:

mix archive.uninstall phx_new

Then run:

cd dotenvy_generators
MIX_ENV=prod mix do archive.build, archive.install

Development

During development/testing of the generators, you will first build the generators to see if there are any errors:

mix archive.build

Then you can run mix help to verify that any new tasks have been compiled and are visible:

mix help

If everything looks ok, then you can run archive.install and try running the generator elsewhere.

Updating the generators

This repo must play cat and mouse with the original Phoenix generators, which are updated separately. Periodically, we will need to update these generators so they follow whatever updates have been introduced to

  1. Clone the phoenix repo.

  2. Checkout the latest tag.

  3. Recursively copy the contents of the installer/lib/ and installer/templates/ directories into the root of this repo. Make sure you merge the contents -- don't just overwrite because we want to preserve the dot_new folder and custom mix tasks.

  4. Inside the Phx.New.Single module, update the

     {
         :config,
         :project,
         "phx_single/config/config.exs": "config/config.exs",
         "phx_single/config/dev.exs": "config/dev.exs",
         "phx_single/config/prod.exs": "config/prod.exs",
         "phx_single/config/runtime.exs": "config/runtime.exs",
         "phx_single/config/test.exs": "config/test.exs"
     },
     {
         :eex,
         :project,
         "phx_single/envs/.env": "envs/.env",
         "phx_single/envs/.dev.env": "envs/.dev.env",
         "phx_single/envs/.test.env": "envs/.test.env",
         "phx_single/envs/.prod.env": "envs/.prod.env"
     },

Inside Phx.New.Single we have to comment out the call to gen_ecto_config because it deviates from how we want to configure our app. In particular, we want to be wary about any environment sniffing, e.g. if config_env() == :prod do, because that can be used in ways that are problematic.

    def gen_ecto(project) do
        copy_from(project, __MODULE__, :ecto)
        # This function is opinionated about how things are configured :(
        # gen_ecto_config(project)
    end

Inside Phx.New.Generator, we need to decouple the version of the Phoenix app being generated from the version of this repo (i.e. dotenvy_generators). We need to change

@phoenix_version Version.parse!(Mix.Project.config()[:version])

To this:

@phoenix_version Version.parse!(Mix.Project.config()[:phoenix_version])`

Make sure the mix.exs references the appropriate version/tag of phoenix that you cloned!

Update the templates/phx_single/mix.exs so it includes overlays in its releases:

defp releases do
    [
        <%= @app_name %>: [
            overlays: ["envs/"]
        ]
    ]
end

and ensure the latest dotenvy in the dependencies, e.g.

    {:dotenvy, "~> 0.9.0"}

The templates/phx_single/gitignore file should include a line to ignore .overrides.env:

    # Ignore custom overrides of .env files
    .overrides.env

phx.new.ex should update its @moduledoce description so it mentions Dotenvy:

    Creates a new Phoenix project using `Dotenvy` for configuration.

And do the same for its @shortdoc:

    @shortdoc "Creates a new Phoenix v#{@version} application using Dotenvy"

Update the @version attribute and some of the info so it's clear that this is a modified version of the original generator:

    @version Mix.Project.config()[:phoenix_version]

    Mix.shell().info("Phoenix installer (Dotenvy) v#{@version}")

We can delete the local.phx.ex task for now.