BUG: Environment variables not set when deployed separately but set when deployed together

Here is a minimal reproduction:


The environment logging code looks like this:

and this:


When the bundled deploy script that looks like this:

is run, we get output that looks like this

image


When the individual deploy script that looks like this:

is run, we get output that looks like this

image


Notice that the individual deploy script has None returned for canister ID values other than itself. This is buggy behaviour and should be rectified.

In this simple example, we can get away with using dfx deploy --all but in a large project that has dfx.json entries for:

  • internet identity canister
  • dynamically created canisters that are not deployed with dfx
  • frontend canister that is deployed as part of a separate worflow

There is no other alternative but to selectively build canisters

Please help rectify this behaviour

Thank you @saikatdas0790 for such a neat bug report. I wish all of them were as nicely packaged :smile:

I haven’t tried it, but maybe it works: what happens if you dfx build --network ic --all and then just dfx canister install <one canister>? Would that be an acceptable workaround for now?

Comment from @ericswanson: If you set canisters as dependencies in dfx.json the ENV vars should be available. Example from dfx new:

{
  "canisters": {
    "hello_backend": {
      <snip>
    },
    "hello_frontend": {
      "type": "assets",
      "source": [
        "src/hello_frontend/assets"
      ],
      "dependencies": [
        "hello_backend"
      ]
    }
  }
}

That being said, it’s worth considering setting the ENV vars anyways, even when no dependency is set.

1 Like

I will try this and get back. For now, I ended up setting the values myself.

My deployment script looks like this now:

cargo test

dfx canister create --no-wallet canister_1
dfx canister create --no-wallet canister_2

export CANISTER_ID_canister_1=$(dfx canister id canister_1)
export CANISTER_ID_canister_2=$(dfx canister id canister_2)

dfx build canister_1
dfx build canister_2

dfx canister install canister_1
dfx canister install canister_2

dfx generate canister_1
dfx generate canister_2

Not sure if there’s a drawback for re-setting the env variables but seems to be working for now.
But would love for dfx to set this automatically without having to jump through hoops.

I don’t believe there’s any disadvantages of setting all the available project canister IDs as env variables since dfx canister id makes them available anyway

1 Like

The only drawback I can see is if you switch networks - there you may run into problems if you still have the variables set from another one

Right, of course. So, we have separate bash scripts for deployment to local vs mainnet

Is there a sample Rust + env variable repo somewhere @Severin ?

In my project I got few constants which I manually have to edit to build for local development, I would be super happy to replace these with an environment variables.

No, we do not have an official example for this situation. Maybe someone else can share a sample repo?

My reproduction example above uses environment variables to make the point. What specifically are you trying to do?

Same as I would do with .env in JavaScript.

// .env.local
HELLO=world
// => used with "npm run dev"

// .env.production
HELLO=yolo
// => used with "npm run build"

I would need different variables per environment with dfx.

// ??????
HELLO=world
// => used with "dfx deploy"

// ?????
HELLO=yolo
// => used with "dfx deploy --nework ic"

So not sure how to do that. As in your repo I know option_env.

ic_cdk::println!("{:?}", option_env!("HELLO"));

But not sure where to set that in dfx for local and ic networks.

I do that in separate build.sh files.

build.dev.sh & build.prod.sh

Each one sets it something like this:

export HELLO="WORLD"

dfx ...

Gotcha! I was hoping it would be built-in dfx but seems like a nice workaround, thanks for the share.

1 Like