1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-02 06:07:06 +01:00
metamask-extension/development/build/config.js
Mark Stacey f465089c2a
Make environment variables higher precedence than config (#15858)
Environment variables are now considered as higher-precedence than
configuration by our build system. This means that if the same value is
set in `.metamaskrc` and in an environment variable, the environment
variable is what will be used. Previously the reverse was true, the
configuration would take precedence.

It is conventional for CLI tools to consider environment variables as
higher precedence than configuration. This makes our build system less
surprising for most people.
2022-09-16 14:28:43 -02:30

125 lines
3.4 KiB
JavaScript

const path = require('path');
const { readFile } = require('fs/promises');
const ini = require('ini');
const { BuildType } = require('../lib/build-type');
const commonConfigurationPropertyNames = ['PUBNUB_PUB_KEY', 'PUBNUB_SUB_KEY'];
const configurationPropertyNames = [
...commonConfigurationPropertyNames,
'COLLECTIBLES_V1',
'INFURA_PROJECT_ID',
'ONBOARDING_V2',
'PHISHING_WARNING_PAGE_URL',
'PORTFOLIO_URL',
'SEGMENT_HOST',
'SEGMENT_WRITE_KEY',
'SENTRY_DSN_DEV',
'SIWE_V1',
'SWAPS_USE_DEV_APIS',
];
const productionConfigurationPropertyNames = [
...commonConfigurationPropertyNames,
'INFURA_BETA_PROJECT_ID',
'INFURA_FLASK_PROJECT_ID',
'INFURA_PROD_PROJECT_ID',
'SEGMENT_BETA_WRITE_KEY',
'SEGMENT_FLASK_WRITE_KEY',
'SEGMENT_PROD_WRITE_KEY',
'SENTRY_DSN',
];
/**
* Get configuration for non-production builds.
*
* @returns {object} The production configuration.
*/
async function getConfig() {
const configPath = path.resolve(__dirname, '..', '..', '.metamaskrc');
let configContents = '';
try {
configContents = await readFile(configPath, {
encoding: 'utf8',
});
} catch (error) {
if (error.code !== 'ENOENT') {
throw error;
}
}
const environmentVariables = {};
for (const propertyName of configurationPropertyNames) {
if (process.env[propertyName]) {
environmentVariables[propertyName] = process.env[propertyName];
}
}
return {
...ini.parse(configContents),
...environmentVariables,
};
}
/**
* Get configuration for production builds and perform validation.
*
* This function validates that all required variables are present, and that
* the production configuration file doesn't include any extraneous entries.
*
* @param {BuildType} buildType - The current build type (e.g. "main", "flask",
* etc.).
* @returns {object} The production configuration.
*/
async function getProductionConfig(buildType) {
const prodConfigPath = path.resolve(__dirname, '..', '..', '.metamaskprodrc');
let prodConfigContents = '';
try {
prodConfigContents = await readFile(prodConfigPath, {
encoding: 'utf8',
});
} catch (error) {
if (error.code !== 'ENOENT') {
throw error;
}
}
const environmentVariables = {};
for (const propertyName of productionConfigurationPropertyNames) {
if (process.env[propertyName]) {
environmentVariables[propertyName] = process.env[propertyName];
}
}
const prodConfig = {
...ini.parse(prodConfigContents),
...environmentVariables,
};
const requiredEnvironmentVariables = {
all: ['PUBNUB_PUB_KEY', 'PUBNUB_SUB_KEY', 'SENTRY_DSN'],
[BuildType.beta]: ['INFURA_BETA_PROJECT_ID', 'SEGMENT_BETA_WRITE_KEY'],
[BuildType.flask]: ['INFURA_FLASK_PROJECT_ID', 'SEGMENT_FLASK_WRITE_KEY'],
[BuildType.main]: ['INFURA_PROD_PROJECT_ID', 'SEGMENT_PROD_WRITE_KEY'],
};
for (const required of [
...requiredEnvironmentVariables.all,
...requiredEnvironmentVariables[buildType],
]) {
if (!prodConfig[required]) {
throw new Error(`Missing '${required}' environment variable`);
}
}
const allValid = Object.values(requiredEnvironmentVariables).flat();
for (const environmentVariable of Object.keys(prodConfig)) {
if (!allValid.includes(environmentVariable)) {
throw new Error(`Invalid environment variable: '${environmentVariable}'`);
}
}
return prodConfig;
}
module.exports = { getConfig, getProductionConfig };