From b42b3daaf6f5655b03c5fe4e395c81973d533ca6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20Sj=C3=B6berg?= Date: Wed, 7 Jul 2021 08:04:16 +0200 Subject: [PATCH] Lucky aware loading --- spec/lucky_env_spec.cr | 59 ++++++++++++++++++++++++++++++++++++ spec/support/.env | 1 + spec/support/.env.production | 2 ++ spec/support/.env.test | 1 + spec/support/production_env | 1 - src/lucky_env.cr | 45 ++++++++++++++++++++++++--- src/lucky_env/errors.cr | 3 ++ 7 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 spec/support/.env.production delete mode 100644 spec/support/production_env diff --git a/spec/lucky_env_spec.cr b/spec/lucky_env_spec.cr index 33ad3a5..c0d2ff4 100644 --- a/spec/lucky_env_spec.cr +++ b/spec/lucky_env_spec.cr @@ -1,5 +1,11 @@ require "./spec_helper" +# The default environments are configured to look for Lucky-specific environment +# files. We redefine them here for testing purposes. +LuckyEnv.add_env :development, env_file: "./spec/support/.env" +LuckyEnv.add_env :production, env_file: "./spec/support/.env.production" +LuckyEnv.add_env :test, env_file: "./spec/support/.env.test" + describe LuckyEnv do original_env = ENV.to_h @@ -25,6 +31,36 @@ describe LuckyEnv do ENV["LUCKY_ENV"].should eq "test" ENV["DEV_PORT"].should eq "3500" end + + context "when no file path is provided" do + it "reads the environment file based on the current environment" do + ENV["LUCKY_ENV"] = "development" + LuckyEnv.load + ENV["ENV_FILE"]?.should eq(".env") + + ENV["LUCKY_ENV"] = "production" + LuckyEnv.load + ENV["ENV_FILE"]?.should eq(".env.production") + + ENV["LUCKY_ENV"] = "test" + LuckyEnv.load + ENV["ENV_FILE"]?.should eq(".env.test") + end + + context "when environment does not exist" do + it "raises an error" do + ENV["LUCKY_ENV"] = "staging" + expected_msg = <<-MSG + Unknown environment staging. Have you forgotten to add it? + + LuckyEnv.add_env :staging, env_file: File.expand_path(".env.staging") + MSG + expect_raises(LuckyEnv::UnknownEnvironmentError, expected_msg) do + LuckyEnv.load + end + end + end + end end describe "load?" do @@ -40,6 +76,29 @@ describe LuckyEnv do data["LUCKY_ENV"].should eq "test" ENV["LUCKY_ENV"].should eq "test" end + + context "when no file path is provided" do + it "reads the environment file based on the current environment" do + ENV["LUCKY_ENV"] = "development" + LuckyEnv.load? + ENV["ENV_FILE"]?.should eq(".env") + + ENV["LUCKY_ENV"] = "production" + LuckyEnv.load? + ENV["ENV_FILE"]?.should eq(".env.production") + + ENV["LUCKY_ENV"] = "test" + LuckyEnv.load? + ENV["ENV_FILE"]?.should eq(".env.test") + end + + context "when environment does not exist" do + it "returns nil" do + ENV["LUCKY_ENV"] = "staging" + LuckyEnv.load?.should be_nil + end + end + end end describe ".development?" do diff --git a/spec/support/.env b/spec/support/.env index 39709e4..9d8192c 100644 --- a/spec/support/.env +++ b/spec/support/.env @@ -4,3 +4,4 @@ DEV_PORT=3500 SECRET_KEY_BASE=j5I0VrpzT1Of7dhCA= ASSET_HOST="https://luckyframework.org" ENV_WITH_SPACE= start_end +ENV_FILE=".env" diff --git a/spec/support/.env.production b/spec/support/.env.production new file mode 100644 index 0000000..7128194 --- /dev/null +++ b/spec/support/.env.production @@ -0,0 +1,2 @@ +LUCKY_ENV=production +ENV_FILE=.env.production diff --git a/spec/support/.env.test b/spec/support/.env.test index a855296..ad9c48c 100644 --- a/spec/support/.env.test +++ b/spec/support/.env.test @@ -1 +1,2 @@ LUCKY_ENV=test +ENV_FILE=.env.test diff --git a/spec/support/production_env b/spec/support/production_env deleted file mode 100644 index 4a982c7..0000000 --- a/spec/support/production_env +++ /dev/null @@ -1 +0,0 @@ -LUCKY_ENV=production diff --git a/src/lucky_env.cr b/src/lucky_env.cr index 591ea44..cc127c9 100644 --- a/src/lucky_env.cr +++ b/src/lucky_env.cr @@ -3,14 +3,35 @@ require "./lucky_env/string_modifier" require "./lucky_env/*" module LuckyEnv - VERSION = {{ `shards version "#{__DIR__}"`.chomp.stringify }} + VERSION = {{ `shards version "#{__DIR__}"`.chomp.stringify }} + ENVIRONMENTS = {} of String => String - macro add_env(name) + macro add_env(name, env_file) + LuckyEnv::ENVIRONMENTS[{{ name.id.stringify }}] = {{ env_file }} + + # Check if the current `environment` is `{{ name.id.stringify }}`. def LuckyEnv.{{ name.id }}? environment == {{ name.id.stringify }} end end + # Load the results of parsing the env file (see `add_env`) associated with the + # current Lucky `environment` into `ENV`. + # + # If the environment is unknown, it raises an `UnknownEnvironmentError`. + # If the associated env file does not exist, it raises a `MissingFileError`. + def self.load : Hash(String, String) + if ENVIRONMENTS.has_key?(environment) + load(ENVIRONMENTS[environment]) + else + raise UnknownEnvironmentError.new <<-ERROR + Unknown environment #{environment}. Have you forgotten to add it? + + LuckyEnv.add_env :#{environment}, env_file: File.expand_path(".env.#{environment}") + ERROR + end + end + # Parses the `file_path`, and loads the results in to `ENV` # raises `LuckyEnv::MissingFileError` if the file is missing def self.load(file_path : String) : Hash(String, String) @@ -23,6 +44,15 @@ module LuckyEnv data end + # Load the results of parsing the env file (see `add_env`) associated with the + # current Lucky `environment` into `ENV`. + # + # If the environment is unknown or the associated env file does not exist, it + # returns `Nil`. + def self.load? : Hash(String, String)? + load?(ENVIRONMENTS[environment]) if ENVIRONMENTS.has_key?(environment) + end + # Returns `nil` if the file is missing def self.load?(file_path : String) : Hash(String, String)? if File.exists?(file_path) || File.symlink?(file_path) @@ -30,15 +60,20 @@ module LuckyEnv end end + # Check if a [LuckyTask](https://github.com/luckyframework/lucky_task) is + # currently running. def self.task? ENV["LUCKY_TASK"] == "true" || ENV["LUCKY_TASK"] == "1" end + # Returns the current Lucky environment (`ENV["LUCKY_ENV"]`). + # + # If `ENV["LUCKY_ENV"]` is not set, it defaults to `"development"`. def self.environment ENV.fetch("LUCKY_ENV", "development") end - add_env :development - add_env :production - add_env :test + add_env :development, env_file: File.expand_path(".env") + add_env :production, env_file: File.expand_path(".env.production") + add_env :test, env_file: File.expand_path(".env.test") end diff --git a/src/lucky_env/errors.cr b/src/lucky_env/errors.cr index 37aaefb..06291c0 100644 --- a/src/lucky_env/errors.cr +++ b/src/lucky_env/errors.cr @@ -4,4 +4,7 @@ module LuckyEnv class MissingFileError < Exception end + + class UnknownEnvironmentError < Exception + end end