clojureleiningenluminusenviron

What does :provided mean in profiles.clj?


Luminus right now is creating a profiles.clj with this content:

{:provided {:env {;;when set the application start the nREPL server on load
                  :nrepl-port "7001"
                  :database-url "jdbc:mysql://localhost:3306/mysqlkorma_dev?user=db_user_name_here&password=db_user_password_here"}}}

What does :provided do here? In environ's documentation it seems to point to having two entries, one for dev and one for test https://github.com/weavejester/environ.


Solution

  • TL;DR: The provided profile is used in profiles.clj as an alternative to the dev profile, because if dev is used there it would overwrite the entire dev profile specified in project.clj.


    The most common use of :provided is to specify dependencies that should be available during jar creation, but will be provided by the runtime environment. But I think here is used as a way to prevent the :env configured in profiles.clj (which is intended to not be committed into your source code repository) to overwrite the :env configured in project.clj.

    Luminus would have used the :dev profile instead of :provided in profiles.clj, if it wasn't by the fact that they already put stuff in an :env entry in the :dev profile in project.clj which would be overwritten by what's in profiles.clj.

    See this example repo. If you run it right away, without any change (with :provided in profiles.clj) the output will be:

    › lein run
    Hello, world
    Db config: some:db://localhost
    

    If you change :provided to :dev in profiles.clj, the output changes to:

    › lein run
    Hello, nil
    Db config: some:db://localhost
    

    They didn't get merged, but the :env in profiles.clj overwrote the :env in profile.clj


    EDIT: I just found out that not only the :env entry would be overwritten if :dev was used in profiles.clj. The entire :dev profile would be overwritten. This is explained in the profiles documentation:

    Remember that if a profile with the same name is specified in multiple locations, only the profile with the highest "priority" is picked – no merging is done. The "priority" is – from highest to lowest – profiles.clj, project.clj, user-wide profiles, and finally system-wide profiles.

    So using :provided in profiles.clj is a little hack around the merging strategy of leiningen profiles.

    It has at least one downside: if you need to define a :provided profile in project.clj to specify dependencies that will be available in the runtime environment it would be overwritten by the one defined in profiles.clj.