diff --git a/Cargo.lock b/Cargo.lock index a3ffd879cb..b6b758915e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2560,6 +2560,15 @@ dependencies = [ "syn", ] +[[package]] +name = "env" +version = "0.0.1" +dependencies = [ + "dotenv", + "easyenv", + "errors", +] + [[package]] name = "env_logger" version = "0.7.1" @@ -6433,6 +6442,7 @@ dependencies = [ "dotenv", "easyenv", "enums", + "env", "errors", "files", "futures 0.1.31", diff --git a/Cargo.toml b/Cargo.toml index 5e9df00d54..8b3edde56c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,8 @@ members = [ "crates/lib/datetimes", "crates/lib/deprecated/config", # TODO(bt, 2023-02-13): Deprecate or repurpose "crates/lib/deprecated/container_common", # TODO(bt, 2023-02-13): Pull apart and rehome pieces - "crates/lib/deprecated/http_server_common", + "crates/lib/deprecated/http_server_common", # TODO(bt, 2023-03-20): Move useful pieces to actix_helpers + "crates/lib/env", "crates/lib/errors", "crates/lib/files", "crates/lib/hashing", diff --git a/crates/lib/env/Cargo.toml b/crates/lib/env/Cargo.toml new file mode 100644 index 0000000000..79a226e9f1 --- /dev/null +++ b/crates/lib/env/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "env" +edition = "2018" +version = "0.0.1" +authors = [ + "Brandon Thomas ", + "Brandon Thomas ", +] +publish = false + +[lib] +# NB: Public "env" crate is name-squatted, so we're fine to use this internally. +name = "env" +path = "src/lib.rs" + +[dependencies] +# Internal +errors = { path = "../errors" } + +# External +dotenv = "0.15.0" +easyenv = "0.0.6" + +[dev-dependencies] +# None yet diff --git a/crates/lib/env/src/lib.rs b/crates/lib/env/src/lib.rs new file mode 100644 index 0000000000..8d69e04213 --- /dev/null +++ b/crates/lib/env/src/lib.rs @@ -0,0 +1,43 @@ +//! env +//! +//! The purpose of this library is to handle reading environment variables. +//! + +// Never allow these +#![forbid(private_in_public)] +#![forbid(unused_must_use)] // NB: It's unsafe to not close/check some things + +// Okay to toggle +#![forbid(unreachable_patterns)] +#![forbid(unused_imports)] +#![forbid(unused_mut)] +#![forbid(unused_variables)] + +// Always allow +#![allow(dead_code)] +#![allow(non_snake_case)] + +use std::path::{Path, PathBuf}; +use errors::{anyhow, AnyhowResult}; + +pub fn read_from_filename>(filename: P) -> AnyhowResult { + let result = dotenv::from_filename(filename)?; + Ok(result) +} + +/// Try loading in an environment file across many search paths (first found wins). +/// Returns an error if no file could be read or if in attempting to read a file there was an error. +pub fn read_from_filename_and_paths>(filename: P, paths: &[P]) -> AnyhowResult<()> { + for path in paths.iter() { + let path = path.as_ref().join(filename.as_ref()); + let path = std::fs::canonicalize(path)?; + + if path.exists() && path.is_file() { + return Ok(dotenv::from_path(path)?); + } + } + + Err(anyhow!("No env file existed for filename {:?} in the search paths {:?}", + filename.as_ref(), + paths.iter().map(|p| p.as_ref().to_path_buf()).collect::>())) +} diff --git a/crates/lib/errors/Cargo.toml b/crates/lib/errors/Cargo.toml index 5993c618d8..c90b83bb80 100644 --- a/crates/lib/errors/Cargo.toml +++ b/crates/lib/errors/Cargo.toml @@ -14,6 +14,8 @@ name = "errors" path = "src/lib.rs" [dependencies] +# NB: This is one of the most central crates in the monorepo and everything depends on it. +# Consider the dependencies here wisely. anyhow = "1.0.40" [dev-dependencies] diff --git a/crates/service/web/storyteller_web/Cargo.toml b/crates/service/web/storyteller_web/Cargo.toml index 83182737b7..c1b5edda3a 100644 --- a/crates/service/web/storyteller_web/Cargo.toml +++ b/crates/service/web/storyteller_web/Cargo.toml @@ -23,6 +23,7 @@ config = { path = "../../../lib/deprecated/config" } container_common = { path = "../../../lib/deprecated/container_common" } datetimes = { path = "../../../lib/datetimes" } enums = { path = "../../../_types/enums" } +env = { path = "../../../lib/env" } errors = { path = "../../../lib/errors" } files = { path = "../../../lib/files" } google_drive_common = { path = "../../../lib/api_clients/google_drive_common" }