diff --git a/cli/args/mod.rs b/cli/args/mod.rs index e0eff6171d..553af51a17 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -793,19 +793,7 @@ impl CliOptions { ) .with_context(|| "Resolving node_modules folder.")?; - if let Some(env_file_name) = &flags.env_file { - match from_filename(env_file_name) { - Ok(_) => (), - Err(error) => { - match error { - dotenvy::Error::LineParse(line, index)=> log::info!("{} Parsing failed within the specified environment file: {} at index: {} of the value: {}",colors::yellow("Warning"), env_file_name, index, line), - dotenvy::Error::Io(_)=> log::info!("{} The `--env` flag was used, but the environment file specified '{}' was not found.",colors::yellow("Warning"),env_file_name), - dotenvy::Error::EnvVar(_)=>log::info!("{} One or more of the environment variables isn't present or not unicode within the specified environment file: {}",colors::yellow("Warning"),env_file_name), - _ => log::info!("{} Unknown failure occurred with the specified environment file: {}", colors::yellow("Warning"), env_file_name), - } - } - } - } + load_env_variables_from_env_file(flags.env_file.as_ref()); let disable_deprecated_api_warning = flags.log_level == Some(log::Level::Error) @@ -1118,6 +1106,10 @@ impl CliOptions { } } + pub fn env_file_name(&self) -> Option<&String> { + self.flags.env_file.as_ref() + } + pub fn enable_future_features(&self) -> bool { *DENO_FUTURE } @@ -1871,6 +1863,23 @@ pub fn config_to_deno_graph_workspace_member( }) } +fn load_env_variables_from_env_file(filename: Option<&String>) { + let Some(env_file_name) = filename else { + return; + }; + match from_filename(env_file_name) { + Ok(_) => (), + Err(error) => { + match error { + dotenvy::Error::LineParse(line, index)=> log::info!("{} Parsing failed within the specified environment file: {} at index: {} of the value: {}",colors::yellow("Warning"), env_file_name, index, line), + dotenvy::Error::Io(_)=> log::info!("{} The `--env` flag was used, but the environment file specified '{}' was not found.",colors::yellow("Warning"),env_file_name), + dotenvy::Error::EnvVar(_)=> log::info!("{} One or more of the environment variables isn't present or not unicode within the specified environment file: {}",colors::yellow("Warning"),env_file_name), + _ => log::info!("{} Unknown failure occurred with the specified environment file: {}", colors::yellow("Warning"), env_file_name), + } + } + } +} + #[cfg(test)] mod test { use pretty_assertions::assert_eq; diff --git a/cli/mainrt.rs b/cli/mainrt.rs index 6a363c04b5..d4f0f558ea 100644 --- a/cli/mainrt.rs +++ b/cli/mainrt.rs @@ -31,6 +31,7 @@ pub use deno_runtime::UNSTABLE_GRANULAR_FLAGS; use deno_terminal::colors; use std::borrow::Cow; +use std::collections::HashMap; use std::env; use std::env::current_exe; @@ -70,6 +71,14 @@ fn unwrap_or_exit(result: Result) -> T { } } +fn load_env_vars(env_vars: &HashMap) { + env_vars.iter().for_each(|env_var| { + if env::var(env_var.0).is_err() { + std::env::set_var(env_var.0, env_var.1); + } + }) +} + fn main() { let args: Vec<_> = env::args_os().collect(); let current_exe_path = current_exe().unwrap(); @@ -79,6 +88,8 @@ fn main() { match standalone { Ok(Some(future)) => { let (metadata, eszip) = future.await?; + util::logger::init(metadata.log_level); + load_env_vars(&metadata.env_vars_from_env_file); let exit_code = standalone::run(eszip, metadata).await?; std::process::exit(exit_code); } diff --git a/cli/standalone/binary.rs b/cli/standalone/binary.rs index c9371d853e..4d6b32b7df 100644 --- a/cli/standalone/binary.rs +++ b/cli/standalone/binary.rs @@ -2,6 +2,7 @@ use std::borrow::Cow; use std::collections::BTreeMap; +use std::collections::HashMap; use std::collections::VecDeque; use std::env::current_exe; use std::ffi::OsString; @@ -96,6 +97,7 @@ pub struct Metadata { pub ca_stores: Option>, pub ca_data: Option>, pub unsafely_ignore_certificate_errors: Option>, + pub env_vars_from_env_file: HashMap, pub workspace_resolver: SerializedWorkspaceResolver, pub entrypoint_key: String, pub node_modules: Option, @@ -584,6 +586,14 @@ impl<'a> DenoCompileBinaryWriter<'a> { } }; + let env_vars_from_env_file = match cli_options.env_file_name() { + Some(env_filename) => { + log::info!("{} Environment variables from the file \"{}\" were embedded in the generated executable file", crate::colors::yellow("Warning"), env_filename); + get_file_env_vars(env_filename.to_string())? + } + None => Default::default(), + }; + let metadata = Metadata { argv: compile_flags.args.clone(), seed: cli_options.seed(), @@ -596,6 +606,7 @@ impl<'a> DenoCompileBinaryWriter<'a> { log_level: cli_options.log_level(), ca_stores: cli_options.ca_stores().clone(), ca_data, + env_vars_from_env_file, entrypoint_key: root_dir_url.specifier_key(entrypoint).into_owned(), workspace_resolver: SerializedWorkspaceResolver { import_map: self.workspace_resolver.maybe_import_map().map(|i| { @@ -757,6 +768,21 @@ impl<'a> DenoCompileBinaryWriter<'a> { } } +/// This function returns the environment variables specified +/// in the passed environment file. +fn get_file_env_vars( + filename: String, +) -> Result, dotenvy::Error> { + let mut file_env_vars = HashMap::new(); + for item in dotenvy::from_filename_iter(filename)? { + let Ok((key, val)) = item else { + continue; // this failure will be warned about on load + }; + file_env_vars.insert(key, val); + } + Ok(file_env_vars) +} + /// This function sets the subsystem field in the PE header to 2 (GUI subsystem) /// For more information about the PE header: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format fn set_windows_binary_to_gui(bin: &mut [u8]) -> Result<(), AnyError> { diff --git a/tests/specs/compile/env_vars_support/__test__.jsonc b/tests/specs/compile/env_vars_support/__test__.jsonc new file mode 100644 index 0000000000..4fc80e1e4d --- /dev/null +++ b/tests/specs/compile/env_vars_support/__test__.jsonc @@ -0,0 +1,14 @@ +{ + "tempDir": true, + "steps": [ + { + "args": "compile -A --output out --env=environment.env main.ts", + "output": "compile.out" + }, + { + "commandName": "./out", + "args": [], + "output": "main.out" + } + ] +} diff --git a/tests/specs/compile/env_vars_support/compile.out b/tests/specs/compile/env_vars_support/compile.out new file mode 100644 index 0000000000..2d004e7cb1 --- /dev/null +++ b/tests/specs/compile/env_vars_support/compile.out @@ -0,0 +1,4 @@ +Warning Parsing failed within the specified environment file: environment.env at index: 3 of the value: c:\path +Check [WILDCARD]main.ts +Compile [WILDCARD]main.ts to out[WILDCARD] +Warning Environment variables from the file "environment.env" were embedded in the generated executable file diff --git a/tests/specs/compile/env_vars_support/environment.env b/tests/specs/compile/env_vars_support/environment.env new file mode 100644 index 0000000000..3da867c500 --- /dev/null +++ b/tests/specs/compile/env_vars_support/environment.env @@ -0,0 +1,4 @@ +FOO=valid +MULTILINE="First Line +Second Line" +ANOTHER_FOO=c:\path \ No newline at end of file diff --git a/tests/specs/compile/env_vars_support/main.out b/tests/specs/compile/env_vars_support/main.out new file mode 100644 index 0000000000..f8f0130abb --- /dev/null +++ b/tests/specs/compile/env_vars_support/main.out @@ -0,0 +1,4 @@ +valid +undefined +First Line +Second Line diff --git a/tests/specs/compile/env_vars_support/main.ts b/tests/specs/compile/env_vars_support/main.ts new file mode 100644 index 0000000000..48488ce721 --- /dev/null +++ b/tests/specs/compile/env_vars_support/main.ts @@ -0,0 +1,3 @@ +console.log(Deno.env.get("FOO")); +console.log(Deno.env.get("ANOTHER_FOO")); +console.log(Deno.env.get("MULTILINE"));