Code Monkey home page Code Monkey logo

environ's Introduction

Environ

Environ is a Clojure library for managing environment settings from a number of different sources. It works well for applications following the 12 Factor App pattern.

Currently, Environ supports four sources, resolved in the following order:

  1. A .lein-env file in the project directory
  2. A .boot-env file on the classpath
  3. Environment variables
  4. Java system properties

The first two sources are set by the lein-environ and boot-environ plugins respectively, and should not be edited manually.

The .lein-env file is populated with the content of the :env key in the Leiningen project map. The .boot-env file is populated by the environ.boot/environ Boot task.

Installation

Include the following dependency in your project.clj file:

:dependencies [[environ "1.2.0"]]

If you want to be able to draw settings from the Leiningen project map, you'll also need the following plugin:

:plugins [[lein-environ "1.2.0"]]

If you are using the Boot toolchain, you may want to read and write settings from build pipelines. In build.boot, add the dependency:

:dependencies '[[boot-environ "1.2.0"]]

Then require the environ boot task.

(require '[environ.boot :refer [environ]])

Usage

Let's say you have an application that requires a database connection. Often you'll need three different databases, one for development, one for testing, and one for production.

Lets pull the database connection details from the key :database-url on the environ.core/env map.

(require '[environ.core :refer [env]])

(def database-url
  (env :database-url))

The value of this key can be set in several different ways. The most common way during development is to use a local profiles.clj file in your project directory. This file contains a map with profiles that will be merged with the profiles specified in the standard project.clj, but can be kept out of version control and reserved for local development options.

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

In this case we add a database URL for the dev and test environments. This means that if you run lein repl, the dev database will be used, and if you run lein test, the test database will be used.

So that profiles you define in profiles.clj are merged into, rather than replacing profiles defined in project.clj, a composite profile can be created in project.clj:

:profiles {:dev [:project/dev :profiles/dev]
           :test [:project/test :profiles/test]
           ;; only edit :profiles/* in profiles.clj
           :profiles/dev  {}
           :profiles/test {}
           :project/dev {:source-paths ["src" "tool-src"]
                         :dependencies [[midje "1.6.3"]]
                         :plugins [[lein-auto "0.1.3"]]}
           :project/test {}}

And then use the :profiles/dev key in your profiles.clj.

Keywords with a project namespace are looked up in the project map. For example:

{:env {:app-version :project/version}}

This looks up the :version key in the Leiningen project map. You can view the full project map by using lein-pprint.

In the case of Boot, you have the full flexibility of tasks and build pipelines, meaning that all the following are valid:

$ boot environ -e database-url=jdbc:postgresql://localhost/dev repl
(environ :env {:database-url "jdbc:postgresql://localhost/dev"})

The latter form can be included in custom pipelines and `task-options!'.

The task also creates or updates a .boot-env file in the fileset. This is useful for tasks that create their own pods like boot-test, which won't see changes in the environ vars.

When you deploy to a production environment, you can make use of environment variables, like so:

DATABASE_URL=jdbc:postgresql://localhost/prod java -jar standalone.jar

Or use Java system properties:

java -Ddatabase.url=jdbc:postgresql://localhost/prod -jar standalone.jar

Note that Environ automatically lowercases keys, and replaces the characters "_" and "." with "-". The environment variable DATABASE_URL and the system property database.url are therefore both converted to the same keyword :database-url.

Important -- environ will not pick up configuration settings from the project.clj when called from a compiled uberjar. So for any compiled code you produce with lein uberjar, you will want to set your configuration values via shell environment and/or system properties.

License

Copyright © 2020 James Reeves

Distributed under the Eclipse Public License, the same as Clojure.

environ's People

Contributors

a-helberg avatar adstage-david avatar ardumont avatar danielcompton avatar danielsz avatar estsauver avatar hypirion avatar joelittlejohn avatar malesch avatar micahasmith avatar r0man avatar serhiikozachenko avatar visibletrap avatar weavejester avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

environ's Issues

environ not reloading changes (even after refresh)

Hi,
I am using environ and develop using emacs and cider. Cider has the C-c C-x for refresh which in turns reloads all the code and namespaces.

I had changed my profiles.clj, and was expecting that the data in the file would turn up when I did 'refresh' and evaluated the 'env' fn. However I had to restart my repl for the changes to show up.

What am I doing wrong ? How do I get environ to load changes in the profiles.clj file ?

Thanks,
Murtaza

provide some sort of way to refresh from the repl

I am sure there is a great reason why this isn't already in the project, but I threw this at the bottom of my user.clj and its quite useful (albeit, a giant hack).

(ns environ.core)

(defn refresh-env
  []
  (alter-var-root #'env
                  (fn [_]
                    (merge
                     (read-env-file)
                     (read-system-env)
                     (read-system-props)))))

I know that wouldnt work in all use-cases, but i think it would be useful as a "dev only" thing a large percentage of the time

boot-environ/environ weird precedence

In a new project, let's create this task:

(deftask run-tests
  []
  (comp
    (environ :env {:config-path "path-test.edn"})
    (test)))

and add this test

(deftest environ-precendence  
  (is (= "path-test.edn" (environ/env :config-path))))

It works fine until environment variable CONFIG_PATH is declared.

$ export CONFIG_PATH=path-prod
...
FAIL in (environ-precendence) (core_test.clj:8)
expected: "path-test.edn"
  actual: "path-prod"
    diff: - "path-test.edn"
          + "path-prod"

Shouldn't binding in deftask (environ :env {:config-path "path-test.edn"}) have precedence over environment variable?

passwords as java system properties

Environ allows you to override settings as java system properties which in itself can come in very handy. But security wise it might not be the best idea. A non privileged user on a shared system can see for example all arguments that were given to a certain program. So if passwords are passed this way one can see all arguments with a simple ps command.

I suggest that at least the documentation is warning about this.

Environ can even add some regexes to the keywords so it can warn if something "passwordish" is passed as java system property.

creating of shell script for environment

Noob question: any suggestions for programmatically creating a production shell script with environment variables from the map in profiles.clj? I know I can just hard code the values. It's just that doing it programmatically with save spelling mistakes, omissions and other changes.

Where the production configuration should be stored?

According to the environ documentation dev environment is used when one runs repl, test environment is used for lein test. But what is the proper way for defining production environment with environ? Should I define prod profile and use it when building uberjar before deploying application to the server? Or should I consider to use environment variables or Java properties instead? Thank you!

Needs to be updated on clojars

boot-environ has not yet been pushed to Clojars, and it looks like there are some commits to environ.core that are not yet in Clojars. Is there anything preventing this from being updated? Is there anything I can do to help out? Right now I literally copied the environ.boot namespace and code into my src directory so I could use it

Always cast value to string?

This could be only my own stupidity. It took quite a bit of time for me to debug my application and found out that the cause of the bug is values retrieving from environment variables are always be in string type. My application is working fine in local machine because I was testing it in against a number value as profiles.clj (edn) differentiates number from string (which it's designed to be).

I would propose environ to convert all number values which are set in profiles.clj to be string as environment variables and Java system properties are only returns string value.

If you think it makes sense to do this, I could come up with a patch.

lein test merges test into dev?

I'm sure I must be missing something somewhere, but I discovered the following using a new app, using environ and lein-environ 1.1.0. With the following profiles.clj:

{:dev  {:env {:somevar "dev" :somevar2 "dev3"}}
 :test {:env {:somevar "test"}}}

When I "lein run", .lein-env is:

{:somevar "dev", :somevar2 "dev3"}

When I "lein test", .lein-env is:

{:somevar "test", :somevar2 "dev3"}

But I don't see where in the docs (or in the code for that matter :-() dev gets merged into test. I can't unset a dev-set variable, either, like:

{:dev  {:env {:somevar "dev" :somevar2 "dev3"}}
 :test {:env {:somevar "test" :somevar2 nil}}}

I'm chasing down a more complex setup but this definitely threw me for a loop!

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)

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?

Warn when environment defaults are not strings

It seems fishy to me that one can set

:env {:port 5000}

And that this is loaded as the number 5000, but if one's environment variables override this with (for example) PORT=5001 lein run, then :port will be set to the string "5001". This can lead to subtle bugs.

It makes more sense to me to only allow string values in the environment map. Or at least, to log a warning when non-string environment default values are loaded.

(run-tests) in repl gets :dev environment variables

In my development workflow, I normally run my tests in the repl with (run-tests). Assume that my profiles.clj has this content:

{:dev  {:env {:database-url "jdbc:postgres://localhost/dev"}}
 :test {:env {:database-url "jdbc:postgres://localhost/test"}}}
  • When I run tests through lein test, database-url from :test is used as expected
  • When running tests in repl, the tests always use :database-url from :dev.

I know that env in :dev is loaded on repl start, they can't be modified and the (run-tests) uses them.

Is there a way to let (run-tests) uses env from :test and at the same time same repl, if I eval code manually, env from :dev are used?

NodeJS compatibility

Would it make sense to make environ a wrapper around process.env? I have some code that does at least part of it, and I'll try my luck with a pull request if it's at all a sensible feature:

(ns environ.core
  (:require [clojure.string :as str]))

(defn- s->k [s]
  (-> s
      str/lower-case
      (str/replace "_" "-")
      keyword))

(def env
  (->> js/process.env
       js/Object.keys
       js->clj
       (map (fn [k] [(s->k k) (aget js/process.env k)]))
       (into {})))

How to merge multiple config files, just like config.edn , config-local.edn

I am bothering abount setting up multiple config files.

I wish I can config some common settings which can be used for everyone, so I can put the common config file into git repo. And some different config for everyone, I can create a local cofig file , which will cover the settings in common setting file.

So I want the featue like django can use global config and local config.

Override dev config w/ env vars

Is there a way to override the values in the :dev profile when running tests w/ lein test, such that environment variables take precedence?

E.g. when developing locally, I've

{:profiles {:dev {:env {:foo-bar "foo"}}}}

But when running tests in a different environment as part of the build process, where FOO_BAR=bar, I want the environment variables to take precedence over the:dev profile, such that I get bar instead of foo.

The only way I know of is to set the variable before the test command, like FOO_BAR=bar lein test. But it'd be useful to be able to do that implicitly.

FileNotFoundException thrown when .lein-env file is not found

We have a project where we use environ and in dev we have a profiles.clj, but when building we providing everything via system environment vars. When building the project in Jenkins, we get a FileNotFoundException when it tries to read the .lein-env file, which just stops the entire build and never gets an opportunity to even read the system vars. Is it possible to add a try-catch block to read-env to handle these Exceptions?

Make env var dynamic?

Would make it easy (for testing and such) to temporarily override the environment variables.

(binding [environ/env (merge environ/env {:some "override"})]
  (some-function-using-env))

ClojureScript use?

I'm trying to write code that works for both clojure and clojurescript, where applicable. Using env vars is something I'd like to do on both sides. Do you have plans to add clojurescript support, or else could you point me to an alternative? Perhaps there is some way to pass certain vars on through leiningen (figwheel / devcards) or boot to a frontend app? Planck is another context I'd like to run stuff with from the cli...

Lein test changes profiles in existing repls started under non-test profiles

Repro is pretty straightforward:

  1. Start a REPL in a lein project, check that environ detected dev profile correctly
  2. Run lein test from the CLI somewhere.
  3. Run (require 'environ.core :reload-all) within the REPL created in 1.
  4. Environ in the REPL will use test profile from now on.

The issue is that .lein-env gets clobbered by test runs, affecting existing REPLs that run a :reload-all.

This prevents one from opening a REPL (including connecting to it with vim/emacs/whatever), run a bunch of tests as part of regular development flow, and being able to perform a full reload afterwards.

Sample REPL output: http://pastebin.com/2bL5cSp3

optional config file

I've run into a number of situations where I wanted to be able to package a config file right in the application. I ended up extending environ to add an extra function that checks for a file called config.edn in the resource path.

(defn- read-config-file []
  (try
    (with-open [r (-> "config.edn" io/resource io/reader PushbackReader.)]
    (edn/read r))
    (catch Exception _)))

(defonce ^{:doc "A map of environment variables."}
  env
  (merge
   (read-config-file)
   (read-system-env)
   (read-system-props)))

This doesn't change the default behavior in any way and allows providing a default configuration that can be overwritten at runtime.

Since all the environ functions are private I ended up having to copy the library, but I'd rather not duplicate the effort. Would you be open to adding the above extension to environ or changing the visibility of the functions to allow extension?

Is it possible to use environ in the leiningen project file?

I thought that would be a good place to document how to do this. Key use case is that i have a collection of database entries in my profiles.clj and I would like to reuse that data to drive ragtime which is also defined in my project.clj.

Look for .env, rather than .lein-env

What is the rationale behind having a lein specific .lein-env file, as opposed to the more common .env file that most other 12factor projects follow?

I'd be happy to open a PR which moves to the .env variant.

Make environ.core/keywordize public

In my case I have to construct some env keys from strings. It would be nice not to worry about format of input strings and use environ.core/keywordize to ensure keys I lookup in environ.core/env are in appropriate format:

(environ.core/env (environ.core/keywordize "my_KEY")) 

Automatically add .lein-env to .gitignore generated by Leiningen template

This isn't a big deal, but I think it would be cool if using environ.lein somehow extended Leiningen to ensure that .lein-env would be ignored by Git. Or perhaps it could emit a warning if it detects that .lein-env isn't present in the .gitignore... Just something to keep me from accidentally committing or deploying information I shouldn't. =)

Granted, I don't know enough about Leiningen internals to know if this is possible, but once I do I'll be happy to give this feature a shot.

lein run

Right now the repl works but when I run on my local system, is there a way to force running in development mode? Basically when not on production I still want to run the full script against different environments. is there something like lein run --env dev as an option?

Boot Environ doesn't work in boot-test

Been trying to track down why environ isn't working in our test environment. Initially I looked at issue #46, but as it was solved I spent some time looking elsewhere. When I finally started drilling down, it became clear that only the values from the environ boot task were missing and only in the test environment, which indicates #46 might not have been fully solved.

Specifically, it looks like some of the refactoring that happened in #47 might have broken the functionality:

#47 (comment)

(doto fileset ....) returns fileset, but we need it to return a mutated version of the fileset with the new .boot-env file added and committed. I inlined my own version of the environ boot task with this change and my environ properties are making it through in a .boot-env file to the test directory.

Why cast to string?

Why does environ cast values to strings?
I am passing the port (which is a number) as a number,
but environ casts it to string.

Can disable this behavior?

System properties to take precedence over the environment and profiles

Hi, I was wondering whether Java system properties should take precedence over the environment and the env file (profile)?

That is: Java system properties over environment over profiles

The reasoning behind that is, that we compile default values into the project using the profiles, then there can be machine-dependent defaults in the environment, and we could still overwrite these default using system properties on the command line.

System properties also feel "closer" to the process than the environment.

The change would be trivial (but also changing the behaviour):

(def ^{:doc "A map of environment variables."}
  env
  (merge
   (read-env-file)
   (read-system-env)
   (read-system-props)))

How should I handle maps/vectors?

Greetings.
The docs for this project are pretty slim because the principle is quite simple, so no big deal. But what happens if I want to pass a map or a vector? This is REAL easy in dev/test because the profiles.clj file is edn. But what happens when I build on my CI server? What happens when I go to production?

environ is expecting a bunch of strings either setup as bash variables or java variables. What happens to my maps? I'll tell you, they get destroyed.

Has anyone else tried to pass anything other than strings/numbers? What do you do for a collection of things?

{:env {:connections [{:uri "amqp://guest:guest@localhost:5672/abc"
                      :queue-names [ "foo" "bar" "baz" ]}
                     {:uri "amqp://guest:guest@localhost:5672/xyz"
                      :queue-names [ "foo" "bar" "baz" ]}]}}

Thanks.

Feature request: Support Boolean variables

For a map key/value pair in the profiles file like ":dev-environment false", it looks like environ will issue this warning:

"Warning: environ value false for key :in-dev has been cast to string"

and then turn the value false into the string "false", which of course evaluates to true. Could environ be extended to support Boolean map keys like this? Thanks.

.boot-env file causing errors when starting from uberjar

I haven't been able to get boot-environ working with a simple uberjar. Attached is a minimal example of what happens:

environ-bug.zip

If I run this with

boot bug
java -jar target/project.jar

I get an exception

Caused by: java.lang.IllegalArgumentException: Not a file: jar:file:/home/hinton/temp/environ-bug/target/project.jar!/.boot-env
	at clojure.java.io$fn__10864.invokeStatic(io.clj:61)
	at clojure.java.io$fn__10864.invoke(io.clj:44)
	at clojure.java.io$fn__10838$G__10820__10843.invoke(io.clj:35)
	at clojure.java.io$file.invokeStatic(io.clj:424)
	at clojure.java.io$file.invoke(io.clj:418)
	at environ.core$read_env_file.invokeStatic(core.clj:34)
	at environ.core$read_env_file.invoke(core.clj:33)
	at environ.core$fn__226.invokeStatic(core.clj:43)
	at environ.core$fn__226.invoke(core.clj:39)
	at environ.core__init.load(Unknown Source)
	at environ.core__init.<clinit>(Unknown Source)
	... 42 more

Whereas I expect it to print "spork" and exit.

Lein 2.6.1 plus uberjar aot results in compile error

The following combination results in a compile error.

Update to lein 2.6.1.

Create a new lein project and add [environ "1.0.2"] as a dependency. Also add this config item to project.clj:
:profiles {:uberjar {:aot :all}}

Then run "lein uberjar".

Result:
Compiling test-lein.core
java.lang.RuntimeException: No dispatch macro for: =, compiling:(core.clj:39:1)
Exception in thread "main" java.lang.RuntimeException: No dispatch macro for: =, compiling:(core.clj:39:1)
at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3657)
at clojure.lang.Compiler.compile1(Compiler.java:7474)
at clojure.lang.Compiler.compile(Compiler.java:7541)
at clojure.lang.RT.compile(RT.java:406)
at clojure.lang.RT.load(RT.java:451)
at clojure.lang.RT.load(RT.java:419)
at clojure.core$load$fn__5677.invoke(core.clj:5893)
at clojure.core$load.invokeStatic(core.clj:5892)
at clojure.core$load.doInvoke(core.clj:5876)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invokeStatic(core.clj:5697)
at clojure.core$load_one.invoke(core.clj:5692)
at clojure.core$load_lib$fn__5626.invoke(core.clj:5737)
at clojure.core$load_lib.invokeStatic(core.clj:5736)
at clojure.core$load_lib.doInvoke(core.clj:5717)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invokeStatic(core.clj:648)
at clojure.core$load_libs.invokeStatic(core.clj:5774)
at clojure.core$load_libs.doInvoke(core.clj:5758)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invokeStatic(core.clj:648)
at clojure.core$require.invokeStatic(core.clj:5796)
at clojure.core$require.doInvoke(core.clj:5796)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at test_lein.core$loading__5569__auto____36.invoke(core.clj:1)
at clojure.lang.AFn.applyToHelper(AFn.java:152)
at clojure.lang.AFn.applyTo(AFn.java:144)
at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3652)
at clojure.lang.Compiler.compile1(Compiler.java:7474)
at clojure.lang.Compiler.compile1(Compiler.java:7464)
at clojure.lang.Compiler.compile(Compiler.java:7541)
at clojure.lang.RT.compile(RT.java:406)
at clojure.lang.RT.load(RT.java:451)
at clojure.lang.RT.load(RT.java:419)
at clojure.core$load$fn__5677.invoke(core.clj:5893)
at clojure.core$load.invokeStatic(core.clj:5892)
at clojure.core$load.doInvoke(core.clj:5876)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invokeStatic(core.clj:5697)
at clojure.core$compile$fn__5682.invoke(core.clj:5903)
at clojure.core$compile.invokeStatic(core.clj:5903)
at clojure.core$compile.invoke(core.clj:5895)
at user$eval20$fn__29.invoke(form-init4296858325558218276.clj:1)
at user$eval20.invokeStatic(form-init4296858325558218276.clj:1)
at user$eval20.invoke(form-init4296858325558218276.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6927)
at clojure.lang.Compiler.eval(Compiler.java:6917)
at clojure.lang.Compiler.eval(Compiler.java:6917)
at clojure.lang.Compiler.load(Compiler.java:7379)
at clojure.lang.Compiler.loadFile(Compiler.java:7317)
at clojure.main$load_script.invokeStatic(main.clj:275)
at clojure.main$init_opt.invokeStatic(main.clj:277)
at clojure.main$init_opt.invoke(main.clj:277)
at clojure.main$initialize.invokeStatic(main.clj:308)
at clojure.main$null_opt.invokeStatic(main.clj:342)
at clojure.main$null_opt.invoke(main.clj:339)
at clojure.main$main.invokeStatic(main.clj:421)
at clojure.main$main.doInvoke(main.clj:384)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:383)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.Var.applyTo(Var.java:700)
at clojure.main.main(main.java:37)
Caused by: java.lang.RuntimeException: No dispatch macro for: =
at clojure.lang.Util.runtimeException(Util.java:221)
at clojure.lang.EdnReader$DispatchReader.invoke(EdnReader.java:500)
at clojure.lang.EdnReader.read(EdnReader.java:142)
at clojure.lang.EdnReader.read(EdnReader.java:108)
at clojure.lang.EdnReader.readString(EdnReader.java:64)
at clojure.edn$read_string.invokeStatic(edn.clj:46)
at clojure.edn$read_string.invokeStatic(edn.clj:37)
at clojure.edn$read_string.invoke(edn.clj:37)
at environ.core$read_env_file.invokeStatic(core.clj:36)
at environ.core$read_env_file.invoke(core.clj:33)
at environ.core$fn__73.invokeStatic(core.clj:42)
at environ.core$fn__73.invoke(core.clj:39)
at clojure.lang.AFn.applyToHelper(AFn.java:152)
at clojure.lang.AFn.applyTo(AFn.java:144)
at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3652)
... 62 more
Compilation failed: Subprocess failed

Note that the error goes away if you downgrade to lein 2.6.0 or if you remove the :profiles {:uberjar {:aot :all}} item.

boot-environ does not update environment in pods

The current boot-environ task updates the internal var containing the environment and passes this on to subsequent tasks. However, this does not work for tasks that create their own pods (such as the boot-test task) because modified objects are not passed into pods when they are initialized. This makes testing code which uses environ for configuration difficult (or at least non-intuitive). If the task were to manage a .lein-env file in the fileset in parallel with changes to the var, then the task should work identically for all tasks and make the task more useful.

I have a modified task which does this and can make a pull request if you agree with the suggested change.

Keywordize keys read from .lein-env

When setting properties via lein project.clj and reading them in the app, it's quite easy to use the wrong delimiter and have your app function perfectly until you get into production (and find that setting environment variables or system properties doesn't have the desired affect).

E.g. in project.clj:

:env {:my.key "somevalue"}

in application:

(env :my.key)

this works fine when running lein builds, but fails when running outside of lein like:

$ MY_KEY=value
$ java -jar myapp.jar

or

$ java -Dmy.key=value -jar myapp.jar

Maybe it would be a good idea to re-keywordize the map keys when reading from .lein-env?

IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol

Hi,
I have trouble to use environ in a new clojure project https://github.com/reevoo/elsa (just starting with clojure, sorry if it's something trivial I've forgot). When I try to run the app or just repl I'm getting following error when requiring environ.core:

With clojure 1.7.0:

user=> (use 'environ.core :verbose)
(clojure.core/load "/environ/core")
(clojure.core/load "/clojure/edn")

CompilerException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol, compiling:(environ/core.clj:39:1)

When I tried to downgrade to clojure 1.5.1 (same as is used in this lib):

user=> (use 'environ.core :verbose)
(clojure.core/load "/environ/core")
(clojure.core/load "/clojure/edn")

IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Symbol  clojure.lang.RT.seqFrom (RT.java:505)

Do you have any idea what could couse it? Thanks.

dynamic system properties

Using System/setProperty does not allow that property to be included in the environ.core/env map.

Is that intentional? Would you consider a dyna-env or current-env that calls System/getProperties on every invocation?

Use vector as environment variable

I don't know if I'm using this library correct. But every environment variable from my profiles.clj file gets converted to a string. However I would like to be able to use a vector with some sets in it as an enironment variable.
Something like
{:env {:my-var [{:key1 "val1" key2 val2} {:key1 "val3" key2 val4}]}}
Within my clojure code I would like to be able to use the [...] part as defined above. Number of sets within the vector might be different based on the deployment of the application.
However, this is read in as a string "[{:key1 "val1" :key2 val2} {:key1 "val3" :key2 val4}]"

Is there a way to keep this as the defined vector with sets withtout the need to parse this in my application?

Environ when running as an uberjar

Should environ work if I compile the project with lein uberjar and then run it directly from java:

 java -jar path/to/standalone.jar

or is it only meant to work when running with lein?

File .lein-env is emptied by lein uberjar command

I'm using environ "1.1.0" as dependency and lein-environ "1.1.0" as plugin. If I run my project with lein run the information from my profiles.clj is copied to a file .lein-env and the application runs as expected.
However if I try to build the jar file (lein uberjar) the file .lein-env is left emptied which result in a "java.lang.NumberFormatException: null, compiling:(" error because the environment variables can't be found.
Am I missing some dependency or some setting in my project.clj?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.