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

chore: refactor environment variables #234

Closed

Conversation

DylanVann
Copy link
Contributor

Description

This is refactors environment variables so that all validation of them is done in one location (@app/config/src/index.ts).

This is only used by the server package in this PR, if accepted a followup can change the usage in other packages as well.

Performance impact

In the Express docs:

If you need to write environment-specific code, you can check the value of NODE_ENV with process.env.NODE_ENV. Be aware that checking the value of any environment variable incurs a performance penalty, and so should be done sparingly.

Some notes about this in relation to React SSR.

I haven't profiled as I don't think it would make a big difference, but that makes some intuitive sense.

Security impact

Developers need to be careful not to import secrets from @app/config in client code, or their secrets could get leaked, I believe Next.js might prevent this though, by not passing through environment variables to the browser. I can check this

Checklist

  • My code matches the project's code style and yarn lint:fix passes.
  • I've added tests for the new feature, and yarn test passes.
  • I have detailed the new feature in the relevant documentation.
  • I have added this feature to 'Pending' in the RELEASE_NOTES.md file (if one exists).
  • If this is a breaking change I've explained why.

}),
30000
).value;
export const HIDE_QUERY_COST: boolean =
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really understand what this one was doing in the original code, but I think this functions the same.

export default async function installSSR(app: Express) {
// @ts-ignore Next had a bad typing file, they claim `export default` but should have `export =`
// Ref: https://unpkg.com/[email protected]/dist/server/next.js
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and the comment at the top of this file seem to have been resolved. Also // Foo below may have been resolved 🤔 .

@DylanVann DylanVann force-pushed the refactor-environment-variables branch 2 times, most recently from daa29f1 to 78daf3a Compare January 14, 2021 11:02
@DylanVann
Copy link
Contributor Author

I don't know that much about the docker setup. A hint about how to make sure the docker tests get SECRET and JWT_SECRET (which are now validated/required) would be appreciated 😄

Doesn't the docker version currently need the SECRET to function correctly? The results seem to be saying that it is not defined.

@DylanVann DylanVann force-pushed the refactor-environment-variables branch 2 times, most recently from 5d83d70 to 12e6dca Compare January 14, 2021 12:24
* Validation functions for environment variables.
*
* `name` is passed with `value` so that bundlers that replace
* process.env.MY_VAR with the value will still provide useful error messages.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A mini validation framework:

  • required
  • defaultNumber
  • minLength
  • parseInteger

Other options were using envalid, io-ts, etc. I think it's simple enough that isn't needed.

@DylanVann DylanVann force-pushed the refactor-environment-variables branch from 12e6dca to dbcb5d8 Compare January 14, 2021 12:26
Copy link
Member

@benjie benjie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting approach. I'm concerned about this being easily misused; could you move most of the new variables to a new path @app/config/server so that it makes it very obvious it should not be required in the client? (You'll may need to create a server.js file that just contains module.exports = require('./dist/server.js') so you can write a src/server.ts. I'm not ready to use the fancy package.json module mapping features yet.)

This isn't a full review.

Comment on lines +8 to +12
export const fromEmail: string = `"PostGraphile Starter" <[email protected]>`;
export const awsRegion: string = "us-east-1";
export const projectName: string = packageJson.name.replace(/[-_]/g, " ");
export const companyName: string = projectName; // For copyright ownership
export const emailLegalText: string =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised the linter does not complain about unnecessary type definitions here (since they can be implied by the values).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd usually go for inferred but I wanted to ensure that people changing the validators didn't accidentally do something like change the exported type from string to string | undefined without making it explicit.

@benjie
Copy link
Member

benjie commented Jan 15, 2021

This approach might not be the best since it enforces variables whenever process.env would have been referenced, this is what is causing the Docker issues. The docker image should be able to build just fine without the SECRET being provided - the SECRET should only be required at runtime (whereas other variables like NODE_ENV are required at build time). Switching it to an "on demand" model where the first time an envvar is referenced it's validated and cached might be a better approach.

Another concern is that it references all envvars in any place any of them are referenced, whereas the previous code only references the required envvars in each place (so if you just run the worker you only read the envvars relevant to the worker). This may or may not have an effect on webpacking your server/etc. It will have an effect if you only expose the envvars each service needs to that service (e.g. the server has different envvar requirements to the worker, in an advanced deployment you might like to separate these out but this would prevent you doing that).

@DylanVann
Copy link
Contributor Author

Thank you for the feedback! I'll take a second attempt at this soon.

I think you're right that this ties too many things together. The different components should only validate the environment variables they need.

@benjie
Copy link
Member

benjie commented Mar 2, 2023

[semi-automated message] Hi, there has been no activity in this issue for a while so I'm closing it to keep the issues/pull requests manageable. If this is still an issue, please re-open with additional details.

@benjie benjie closed this Mar 2, 2023
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

Successfully merging this pull request may close these issues.

2 participants