Compare commits

...
Author SHA1 Message Date
Will Schurman bcf2c62066 [eas-cli] fix env overriding in getExpoConfig 2022-11-17 13:50:00 -08:00
2 changed files with 92 additions and 1 deletions

No files matched your search

@@ -0,0 +1,67 @@
import { ProjectConfig, getConfig } from '@expo/config';
import { getExpoConfig } from '../expoConfig';
jest.mock('@expo/config');
describe(getExpoConfig, () => {
it('correctly restores process.env as best as possible', () => {
process.env.BEFORE_CALL_KEY = 'BEFORE';
process.env.BEFORE_CALL_KEY_OVERRIDDEN_BY_WITHIN = 'BEFORE_OVERRIDDEN_BY_WITHIN';
process.env.BEFORE_CALL_KEY_OVERRIDDEN_BY_OPTS = 'BEFORE_OVERRIDDEN_BY_OPTS';
process.env.BEFORE_CALL_KEY_OVERRIDDEN_BY_OPTS_AND_WITHIN =
'BEFORE_CALL_KEY_OVERRIDDEN_BY_OPTS_AND_WITHIN';
jest.mocked(getConfig).mockImplementation(() => {
process.env.WITHIN_CALL_KEY = 'WITHIN';
process.env.BEFORE_CALL_KEY_OVERRIDDEN_BY_WITHIN = 'OVERRIDDEN_VALUE';
process.env.OPTS_KEY_OVERRIDDEN_BY_WITHIN = 'OVERRIDDEN_VALUE';
process.env.OPTS_KEY_OVERRIDDEN_BY_WITHIN_TO_SAME_VALUE =
'OPTS_KEY_OVERRIDDEN_BY_WITHIN_TO_SAME_VALUE';
process.env.BEFORE_CALL_KEY_OVERRIDDEN_BY_OPTS_AND_WITHIN = 'OVERRIDDEN_WITHIN';
return {} as ProjectConfig;
});
// ensure idempotent (run N times)
for (let i = 0; i < 2; i++) {
getExpoConfig('', {
env: {
OPTS_KEY: 'OPTS',
BEFORE_CALL_KEY_OVERRIDDEN_BY_OPTS: 'OVERRIDDEN_VALUE',
OPTS_KEY_OVERRIDDEN_BY_WITHIN: 'OPTS_KEY_OVERRIDDEN_BY_WITHIN',
OPTS_KEY_OVERRIDDEN_BY_WITHIN_TO_SAME_VALUE:
'OPTS_KEY_OVERRIDDEN_BY_WITHIN_TO_SAME_VALUE',
BEFORE_CALL_KEY_OVERRIDDEN_BY_OPTS_AND_WITHIN: 'OVERRIDDEN_OPTS',
},
});
// env from before the call should be restored
expect(process.env.BEFORE_CALL_KEY).toEqual('BEFORE');
// env from before the call but overridden within the call should not be restored
expect(process.env.BEFORE_CALL_KEY_OVERRIDDEN_BY_WITHIN).toEqual('OVERRIDDEN_VALUE');
// env from before the call but overridden by opts should be restored
expect(process.env.BEFORE_CALL_KEY_OVERRIDDEN_BY_OPTS).toEqual('BEFORE_OVERRIDDEN_BY_OPTS');
// env added within the call should be kept
expect(process.env.WITHIN_CALL_KEY).toEqual('WITHIN');
// env added by opts should be removed
expect(process.env.OPTS_KEY).toBeUndefined();
// env added by opts but overridden within the call should be retained and have overridden value
expect(process.env.OPTS_KEY_OVERRIDDEN_BY_WITHIN).toEqual('OVERRIDDEN_VALUE');
// env added by opts but overridden within the call to the same value will be removed
// note that this is a known bug/limitation of this approach
expect(process.env.OPTS_KEY_OVERRIDDEN_BY_WITHIN_TO_SAME_VALUE).toBeUndefined();
// env from before but overridden within the call and by opts should retain value from
// within the call
expect(process.env.BEFORE_CALL_KEY_OVERRIDDEN_BY_OPTS_AND_WITHIN).toEqual(
'OVERRIDDEN_WITHIN'
);
}
});
});
+25 -1
View File
@@ -1,5 +1,6 @@
import { ExpoConfig, getConfig } from '@expo/config';
import { Env } from '@expo/eas-build-job';
import nullthrows from 'nullthrows';
export interface ExpoConfigOptions {
env?: Env;
@@ -9,6 +10,11 @@ export interface ExpoConfigOptions {
export function getExpoConfig(projectDir: string, opts: ExpoConfigOptions = {}): ExpoConfig {
const originalProcessEnv: NodeJS.ProcessEnv = process.env;
const optsEnvKeys = opts.env ? Object.keys(opts.env) : [];
const originalEnvKeys = new Set(Object.keys(process.env));
const newKeysAddedToProcessEnv = new Set(optsEnvKeys.filter(k => !originalEnvKeys.has(k)));
try {
process.env = {
...process.env,
@@ -20,6 +26,24 @@ export function getExpoConfig(projectDir: string, opts: ExpoConfigOptions = {}):
});
return exp;
} finally {
process.env = originalProcessEnv;
optsEnvKeys.forEach(k => {
// if new key added, remove unless it was modified
if (newKeysAddedToProcessEnv.has(k)) {
if (k in originalProcessEnv) {
if (process.env[k] === originalProcessEnv[k]) {
delete process.env[k];
}
} else {
if (nullthrows(opts.env)[k] === process.env[k]) {
delete process.env[k];
}
}
} else {
// opts key overrode env key, but only if the value is equal to the one declared by opts
if (process.env[k] === nullthrows(opts.env)[k]) {
process.env[k] = originalProcessEnv[k];
}
}
});
}
}