Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The dotenv! macro looks for the .env in the workspace root dir instead of crate root dir #74

Open
stevepryde opened this issue May 10, 2023 · 7 comments

Comments

@stevepryde
Copy link

I commonly work in a workspace with multiple binary crates that each have their own .env file. However it seems the dotenv!() macro is looking for the .env file in the workspace root instead of the crate root dir.

Any idea why this would be happening?

@stevepryde stevepryde changed the title The dotenvy! macro looks for the .env in the workspace root dir instead of crate root dir The dotenv! macro looks for the .env in the workspace root dir instead of crate root dir May 10, 2023
@allan2
Copy link
Owner

allan2 commented May 10, 2023

Hi Steve,

I was able to reproduce your problem. allan2/dotenvy-workspace-example

The issue is that dotenvy::dotenv and the dotenvy! macro both start finding from std::env::current_dir.
If the user runs from the workspace root, then the current dir is the workspace root.
So your crate .env would only get picked up if you run from the crate root.

One solution is to use CARGO_MANIFEST_DIR to get the crate root.

let manifest_dir = std::env::var("CARGO_MANIFEST_DIR")?;
dotenvy::from_path(format!("{manifest_dir}/.env"))?;
std::env::var("FOO")?;

Of course, this loads at runtime instead of compile time. Let me know if that is acceptable for you.

@stevepryde
Copy link
Author

I was hoping to use the dotenv!() macro to have the best of both worlds between env!() and having a .env file and I don't think this solution works for that. Any chance of a toml file or some way to provide the path at compile time?

@85oskxr
Copy link

85oskxr commented Aug 1, 2023

Has anyone found a reasonable solution to this problem? In my case the .env file needs to be in the parent directory as other language projects will use it.

@cbeck88

This comment was marked as off-topic.

@mcmah309
Copy link

Any fix for this? This should at least be documented. I was banging my head against the wall as to why the rust analyzers macro expansion was fine, but cargo build failed.

@cbeck88
Copy link

cbeck88 commented Aug 22, 2024

What I do personally is,

  • each binary target has its own named envfile, so, foo.env, bar.env, in the workspace root
  • In the directory for each crate, I put a symlink to the master version in workspace root. This makes it so that, e.g. the diesel cli tool just works and picks up the appropriate file when I’m in the appropriate directory

In code I do this:

match dotenvy::from_filename(filename) {

So that I can make io error (“file not found”) logged at info level and not fatal, but errors in the env file format are loud. And for cargo run usages, or cd target/release && ./foo, it finds the dot envfile according to the search pattern.

The main limitation is that the symlink scheme might not work perfectly on windows but that hasn’t been a problem for me since that’s not primarily where we develop or build releases.


The symlink idea might help for the situations described -- but I don't use the dotenv! macro and it doesn't look that there's a place to put the filename. So maybe that's a limitation of the dotenv! macro.

@cbeck88
Copy link

cbeck88 commented Aug 23, 2024

Looking some more:

it looks that the proc macro implementation for dotenv!() does this:

https://docs.rs/dotenvy_macro/0.15.7/src/dotenvy_macro/lib.rs.html#17

However,

A proc macro runs from whichever directory cargo invokes rustc. In the past this used to.be the package root, but it was changed to the workspace root to make error messages relative to the workspace root. I don't think there i sany guarantee that this won't change again in the future.

https://users.rust-lang.org/t/which-directory-does-a-proc-macro-run-from/71917/4

So it looks to me that, what happens when you use dotenv!() probably relies on unspecified behavior of cargo. Maybe dotenv!() proc macro itself should change directory to CARGO_MANIFEST_DIR first, before invoking dotenv ?

Related: rust-lang/rust-analyzer#11079 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants