Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ This is the log of notable changes to EAS CLI and related packages.

### 🐛 Bug fixes

- [eas-cli] Stop passing inherited dotenv values to local builds. ([#4244](https://github.com/expo/eas-cli/pull/4244) by [@ramonclaudio](https://github.com/ramonclaudio))

### 🧹 Chores

## [22.2.0](https://github.com/expo/eas-cli/releases/tag/v22.2.0) - 2026-08-20
Expand Down
29 changes: 29 additions & 0 deletions packages/eas-cli/src/build/__tests__/local-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,35 @@ describe(runLocalBuildAsync, () => {
expect(decodeInput(input)).toEqual({ job, metadata });
});

it('keeps EAS values and removes dotenv values inherited from the parent process', async () => {
const originalEnv = process.env;
const loadedEnvMarker =
'["BUILD_ENV_VALUE","EAS_LOCAL_BUILD_WORKINGDIR","PARENT_DOTENV_VALUE"]';
process.env = {
...originalEnv,
BUILD_ENV_VALUE: 'from-dotenv',
EAS_LOCAL_BUILD_WORKINGDIR: '/dotenv/workingdir',
PARENT_DOTENV_VALUE: 'from-dotenv',
__EXPO_ENV_LOADED: loadedEnvMarker,
};
const env = { BUILD_ENV_VALUE: 'from-eas' };

try {
await runLocalBuildAsync(job, metadata, { verbose: true }, env);

const spawnEnv = mockSpawnAsync.mock.calls[0][2]?.env;
expect(spawnEnv?.BUILD_ENV_VALUE).toBe('from-eas');
expect(spawnEnv?.EAS_LOCAL_BUILD_WORKINGDIR).toBeUndefined();
expect(spawnEnv?.PARENT_DOTENV_VALUE).toBeUndefined();
expect(spawnEnv?.__EXPO_ENV_LOADED).toBeUndefined();
expect(env).toEqual({ BUILD_ENV_VALUE: 'from-eas' });
expect(process.env.PARENT_DOTENV_VALUE).toBe('from-dotenv');
expect(process.env.__EXPO_ENV_LOADED).toBe(loadedEnvMarker);
} finally {
process.env = originalEnv;
}
});

it('logs a non-secret build context summary and re-throws on failure', async () => {
const richJob = {
type: 'managed',
Expand Down
6 changes: 4 additions & 2 deletions packages/eas-cli/src/build/local.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import semver from 'semver';
import { getExpoApiBaseUrl } from '../api';
import Log from '../log';
import { ora } from '../ora';
import { getEnvWithoutInheritedDotenvValues } from '../utils/originalEnv';

const PLUGIN_PACKAGE_NAME = 'eas-cli-local-build-plugin';
const PLUGIN_PACKAGE_VERSION = version; // should match version of @expo/eas-build-job
Expand Down Expand Up @@ -63,11 +64,12 @@ export async function runLocalBuildAsync(
};
process.on('SIGINT', interruptHandler);
try {
const processEnv = getEnvWithoutInheritedDotenvValues(process.env);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

EXPO_UNSAFE_DOTENV_KEYS and this utility is something I'm not familiar with 🤔 maybe @sjchmiela or @szdziedzic can evaluate this better. I believe, this may be similar to a utility for original-env we have in @expo/env, so not sure if we need to reconsolidate?

@kitten kitten Aug 24, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Revisiting this; assuming we're keeping parity here with EAS Build, is there any way we could just not inherit any env vars and issue a major bump? It might be easier to build up parity than it is to try to pass through filtered process.env vars, and treat the spawned sub-process as "isolated"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yea, that makes sense! I tested local ios and android builds with the runtime var list I added, but can we confirm these are all the vars we want to keep in the isolated env?

https://github.com/expo/eas-cli/pull/4244/changes#diff-a54f38cd6a574317f91ba14ef751c1868db0d9469f924f18b018222c1c956a6aR18-R33

const mergedEnv = {
...env,
...process.env,
...processEnv,
EAS_LOCAL_BUILD_PLUGIN_INPUT: pluginInput,
EAS_LOCAL_BUILD_WORKINGDIR: options.workingdir ?? process.env.EAS_LOCAL_BUILD_WORKINGDIR,
EAS_LOCAL_BUILD_WORKINGDIR: options.workingdir ?? processEnv.EAS_LOCAL_BUILD_WORKINGDIR,
__API_SERVER_URL: getExpoApiBaseUrl(),
...(options.skipCleanup || options.skipNativeBuild
? { EAS_LOCAL_BUILD_SKIP_CLEANUP: '1' }
Expand Down
Loading