weavejester/environ

Creating a :dev profile in profiles.clj overrules the :dev profile in projects.clj (Or: I don't understand how this is supposed to work)

Peeja opened this issue · 11 comments

The Readme suggests storing config data as a profiles.clj, not in source control, like so:

{:dev  {:env {:database-url "jdbc:postgres://localhost/dev"}}
 :test {:env {:database-url "jdbc:postgres://localhost/test"}}}

But I also have dependencies in my :dev profile in my project.clj:

  :profiles {:dev {:dependencies [[javax.servlet/servlet-api "2.5"]
                                  [ring-mock "0.1.5"]]}}

Having a :dev profile defined in profiles.clj means that Leiningen ignores those dependencies. I don't want to move those dependencies into the profiles.clj, because they're not deploy-specific config, and they should be checked into source control.

Did I misunderstand the Readme? How is this supposed to work?

I forgot that Leiningen profiles of the same name override rather than merge with the project map.

This isn't particularly difficult to get around, however. Perhaps a better solution would be to introduce a new set of profiles:

{:local-dev  {:env {:database-url "jdbc:postgres://localhost/dev"}}
 :local-test {:env {:database-url "jdbc:postgres://localhost/test"}}}

From there you can include those profiles in your default operations in project.clj:

:profiles {:defaults [:base :system :user :provided :dev :local-dev]}
:aliases {"test" ["with-profile" "+local-test" "test"]}

Oh, good, that's what I did. I'm glad that was right. :)

FYI, There is an issue that describes this exact scenario of creating composite profiles.

technomancy/leiningen#1503

@weavejester - I might have this wrong, but the https://github.com/technomancy/leiningen/blob/master/doc/PROFILES.md document states

The :default profile specifies the profiles that are active by default when running lein tasks. If not overridden, this is set to :leiningen/default, which is a composite profile with [:base :system :user :provided :dev].

So I believe your project.clj should have the following entries

:profile {:default [:base :system :user :provided :dev :local-dev]}
:aliases {"test" ["with-profile" "+local-test" "test"]}

Note that in your comment you said :defaults (with an s).

A semi-complete entry might look like this -

:profiles {:dev {:jvm-opts ["-Dlogfile.path=development"]
                 :dependencies [[http-kit.fake "0.2.2"]]
                 :plugins [[com.jakemccrary/lein-test-refresh "0.7.0"]]}
           :test {:jvm-opts ["-Dlogfile.path=test"]}
           :production {:jvm-opts ["-Dlogfile.path=production"]}
           :default [:base :system :user :provided :dev :local-dev]}
:aliases {"test" ["with-profile" "+local-test" "test"]}

Please correct me if I am wrong, but this seems to work for me. And thank you @Peeja for this issue. It had me wondering if I had it all wrong as well :)

Right, sorry, I accidentally made it into a plural.

For what it's worth, my web projects nowadays tend to be setup:

   :dev  [:project/dev  :profiles/dev]
   :test [:project/test :profiles/test]
   :profiles/dev  {}
   :profiles/test {}
   :project/dev  { ... }
   :project/test { ... }
lvh commented

I also got bitten by this, and the PR up fixes the issue for me.

Thanks @lvh - I should have proposed a change in the docs :-/

FWIW, I just got stung by this whilst following the README. #19 also helped me get around technomancy/leiningen#1666

Same, is there any plan to update the Readme?

If someone sends me a PR, sure.

Just to make explicit #15 (comment) for anyone who stumbles across something like this in a project without explanation:

   :dev  [:project/dev  :profiles/dev]
   :test [:project/test :profiles/test]
   :profiles/dev  {}
   :profiles/test {}
   :project/dev  { ... }
   :project/test { ... }

Leiningen will merge the keys in :project/dev and :profiles/dev to create the :dev profile. Custom settings that you want to inject into a :dev or :test profile only for yourself can be placed into your ~/.lein/profiles.clj file under the :profiles/dev or :profiles/test key respectively. If there is anything here, it will override the empty :profiles/dev map specified in the project.clj. The empty map for :profiles/dev {} needs to exist because otherwise Leiningen will complain about a missing profile.