Assign different values to an env var for each target


#1

In the graphcool.yml file I want to assign a different value to a WEBHOOK_URL environment variable based on wich target i am deploying on.
I think this could be achieved using the ${opt:target} variable, but i’m not sure how.

Any ideas?


[1.0] Different Environments - Different `graphcool.yml` files?
#2

Thanks for bringing this up @lcatallo!
On the top-level of a graphcool.yml file, you can define a custom section.
Together with the variable interpolation logic, you can achieve staged-dependend values in your graphcool.yml like this:

custom:
  dev:
    WEBHOOK_URL: "http://test.com/dev"
  prod:
    WEBHOOK_URL: "http://test.com/prod"


types: ./types.graphql


functions:
  hello:
    handler:
      webhook:
        url: ${self:custom.${opt:target}.WEBHOOK_URL}
    type: resolver
    schema: src/hello.graphql


permissions:
- operation: "*"

rootTokens:
- mytoken

If you now deploy with

graphcool deploy --target dev

or

graphcool deploy --target prod

the according variable will be taken out of the custom field.

This is available in the latest alpha graphcool@0.8.0-alpha.1


#3

@tim It’s not possible to add those stage-specific env vars to .graphcoolrc?


#4

@agartha no, that’s not possible. We intentionally didn’t add that functionality as the described method already solves the target-dependent env var use case.

There is some likelihood that mid-term we go for a better solution for the .graphcoolrc file. So we want to keep it as simple and clean as possible right now so moving away from it hurts less.


#5

Can I reference these top level variables inside of a function? Do I need to pass that reference down into the Function definition in the yml file? Thanks!


#6

Follow-up: Is there a way to inject variables into graphcool.yml? So that I don’t need to store secrets in git. Something like http://torus.sh maybe? Curious about your thoughts on this.


#7
  • You can use ${env:VAR} to inject environment variables into the graphcool.yml file. Example:
functions:
  hello:
    type: resolver
    schema: ./src/${env:HELLO_FUNCTION}.graphql
    handler:
      code:
        src: ./src/${env:HELLO_FUNCTION}.js

  • For code function handlers, you can use the environment key to create new environment variables in the function context itself. Note that you can inject environment variables, custom variables from within the graphcool.yml or constant strings like that. Example:
custom:
  dev:
    MIDDLE_NAME: Bob
  prod:
    MIDDLE_NAME: Noone

functions:
  hello:
    type: resolver
    schema: ./src/hello.graphql
    handler:
      code:
        src: ./src/hello.js
      environment:
        NAME: Alice
        MIDDLE_NAME: ${self:custom.${opt:target}.MIDDLE_NAME}
        LAST_NAME: ${env:LAST_NAME}

You can use a tool like direnv to manage your environment variables. direnv looks at a potential file .envrc in the current directory and makes variables in their part of your current environment. You would add .envrc to your .gitignore and create it, like this:

export HELLO_FUNCTION=hello

Then, saying direnv allow . adds the HELLO_FUNCTION env variable with the value hello.


#8

Thanks so much for the detailed reply.

A point of clarification. Can I do this?

custom:
  dev:
    SENDGRID_KEY: ${env:SENDGRID_KEY}

and then reference that sendgrid key inside multiple functions? Or do I have reference the env variable within the scope of each function, like:

functions:
   hello:
    type: resolver
    schema: ./src/hello.graphql
    handler:
      code:
        src: ./src/hello.js
      environment:
        SENDGRID_KEY: ${env:SENDGRID_KEY}
goodbye:
    type: resolver
    schema: ./src/goodbye.graphql
    handler:
      code:
        src: ./src/goodbye.js
      environment:
        SENDGRID_KEY: ${env:SENDGRID_KEY}

#9

This should work:

custom:
  dev:
    SENDGRID_KEY: ${env:SENDGRID_KEY}

functions:
   hello:
    type: resolver
    schema: ./src/hello.graphql
    handler:
      code:
        src: ./src/hello.js
        environment:
          SENDGRID_KEY: ${self:custom.${opt:target}.SENDGRID_KEY}
  goodbye:
    type: resolver
    schema: ./src/goodbye.graphql
    handler:
      code:
        src: ./src/goodbye.js
        environment:
          SENDGRID_KEY: ${self:custom.${opt:target}.SENDGRID_KEY}

#10

Howdy!

Can I use something like dotenv and a .env file instead to work with graphcool.yml since we already use it? Or do we have to use direnv and .envrc?

Thanks!


#11

@peter Thank you for the suggesting. I’m fighting for dotenv support for a while now, but an extra vote would be very helpful.


#12

Hey @nilan,

Is the example that you’re doing supported? We are currently getting:

data.functions['functionName'].handler should NOT have additional properties

we have:

  functionName:
    handler:
      code:
        src: ./src/processActiveContact.js
      environment:
        API_URL: ${self:custom.${opt:target}.API_URL}

#13

Just corrected my example, environment needs to be a sub-property of code, instead of handler.


#14

It would be so nice to be able to define Env. variables in .env file OR at least in a .yml


#15

I am trying to set up envs, things work but I am getting this warnings, not sure why.

Trying to populate non string value into a string for variable ${opt:target}. Please make sure the value of the 
property is a string.

#16

I found a possible solution here: How to use environment variables?

tl;dr: node -r dotenv/config $(which graphcool) deploy dotenv_config_path=../.env