Compare commits

...
6 changed files with 123 additions and 5 deletions

No files matched your search

@@ -0,0 +1,50 @@
import { Platform } from '@expo/eas-build-job';
import spawn from '@expo/turtle-spawn';
import fs from 'fs-extra';
import { runGradleCommand } from '../gradle';
jest.mock('@expo/turtle-spawn', () => ({
__esModule: true,
default: jest.fn(),
}));
jest.mock('fs-extra', () => ({
chmod: jest.fn().mockResolvedValue(undefined),
}));
describe(runGradleCommand, () => {
beforeEach(() => {
const spawnPromise = Promise.resolve(undefined) as any;
spawnPromise.child = { pid: 123 };
(spawn as jest.Mock).mockReturnValue(spawnPromise);
(fs.chmod as unknown as jest.Mock).mockClear();
(spawn as jest.Mock).mockClear();
});
it('allows Sentry upload failures by default', async () => {
await runGradleCommand(
{
env: { EAS_BUILD_RUNNER: 'eas-build' },
job: {
platform: Platform.ANDROID,
},
} as any,
{
logger: { info: jest.fn() } as any,
gradleCommand: ':app:bundleRelease',
androidDir: '/app/android',
}
);
expect(spawn).toHaveBeenCalledWith(
'bash',
['-c', './gradlew :app:bundleRelease --profile '],
expect.objectContaining({
env: expect.objectContaining({
SENTRY_ALLOW_FAILURE: 'true',
}),
})
);
});
});
+4 -2
View File
@@ -7,6 +7,7 @@ import path from 'path';
import { BuildContext } from '../context';
import { getParentAndDescendantProcessPidsAsync } from '../utils/processes';
import { resolveSentryUploadEnv } from '../utils/buildEnv';
export async function ensureLFLineEndingsInGradlewScript<TJob extends Job>(
ctx: BuildContext<TJob>
@@ -31,6 +32,7 @@ export async function runGradleCommand(
logger.info(`Running 'gradlew ${gradleCommand}' in ${androidDir}`);
await fs.chmod(path.join(androidDir, 'gradlew'), 0o755);
const verboseFlag = ctx.env['EAS_VERBOSE'] === '1' ? '--info' : '';
const env = { ...ctx.env, ...extraEnv };
const spawnPromise = spawn(
'bash',
@@ -46,8 +48,8 @@ export async function runGradleCommand(
}
},
env: {
...ctx.env,
...extraEnv,
...resolveSentryUploadEnv(env),
...env,
...resolveVersionOverridesEnvs(ctx),
LC_ALL: 'C.UTF-8',
},
@@ -23,13 +23,19 @@ const WORKING_DIR = '/workingdir';
// BuildContext.getReactNativeProjectDirectory() nests the RN project under `${workingdir}/build`.
const IOS_DIR = path.join(WORKING_DIR, 'build', 'ios');
function makeIosBuildContext({ simulator }: { simulator: boolean }): BuildContext<Ios.Job> {
function makeIosBuildContext({
simulator,
env = {},
}: {
simulator: boolean;
env?: Record<string, string>;
}): BuildContext<Ios.Job> {
const job: Ios.Job = { ...createTestIosJob(), simulator };
return new BuildContext(job, {
workingdir: WORKING_DIR,
logger: createMockLogger(),
logBuffer: { getLogs: () => [], getPhaseLogs: () => [] },
env: { __API_SERVER_URL: 'http://api.expo.test' },
env: { __API_SERVER_URL: 'http://api.expo.test', ...env },
uploadArtifact: jest.fn(),
});
}
@@ -125,4 +131,27 @@ describe(runFastlaneGym, () => {
workspacePath: IOS_DIR,
});
});
it('allows Sentry upload failures by default', async () => {
const ctx = makeIosBuildContext({
simulator: false,
env: { EAS_BUILD_RUNNER: 'eas-build' },
});
await runFastlaneGym(ctx, {
scheme: 'App',
credentials: ARCHIVE_CREDENTIALS,
entitlements: null,
});
expect(spawn).toHaveBeenCalledWith(
'fastlane',
['gym'],
expect.objectContaining({
env: expect.objectContaining({
SENTRY_ALLOW_FAILURE: 'true',
}),
})
);
});
});
+3 -1
View File
@@ -13,6 +13,7 @@ import { isTVOS } from './tvos';
import { XcodeBuildLogger } from './xcpretty';
import { COMMON_FASTLANE_ENV } from '../common/fastlane';
import { BuildContext, SkipNativeBuildError } from '../context';
import { resolveSentryUploadEnv } from '../utils/buildEnv';
export async function runFastlaneGym<TJob extends Ios.Job>(
ctx: BuildContext<TJob>,
@@ -48,11 +49,12 @@ export async function runFastlaneGym<TJob extends Ios.Job>(
}
const buildLogger = new XcodeBuildLogger(ctx.logger, ctx.getReactNativeProjectDirectory());
void buildLogger.watchLogFiles(ctx.buildLogsDirectory);
const env = { ...ctx.env, ...extraEnv };
try {
await runFastlane(['gym'], {
cwd: workspacePath,
logger: ctx.logger,
env: { ...ctx.env, ...extraEnv },
env: { ...resolveSentryUploadEnv(env), ...env },
});
} finally {
await buildLogger.flush();
@@ -0,0 +1,22 @@
import { resolveSentryUploadEnv } from '../buildEnv';
describe(resolveSentryUploadEnv, () => {
it('allows Sentry upload failures by default', () => {
expect(resolveSentryUploadEnv({ EAS_BUILD_RUNNER: 'eas-build' })).toEqual({
SENTRY_ALLOW_FAILURE: 'true',
});
});
it('does not change Sentry upload behavior outside hosted EAS Build', () => {
expect(resolveSentryUploadEnv({})).toEqual({});
});
it('preserves explicit Sentry upload behavior', () => {
expect(
resolveSentryUploadEnv({ EAS_BUILD_RUNNER: 'eas-build', SENTRY_ALLOW_FAILURE: 'false' })
).toEqual({});
expect(
resolveSentryUploadEnv({ EAS_BUILD_RUNNER: 'eas-build', SENTRY_DISABLE_AUTO_UPLOAD: 'true' })
).toEqual({});
});
});
@@ -0,0 +1,13 @@
import type { Env } from '@expo/eas-build-job';
export function resolveSentryUploadEnv(env: Env): Env {
if (
env.EAS_BUILD_RUNNER !== 'eas-build' ||
env.SENTRY_ALLOW_FAILURE ||
env.SENTRY_DISABLE_AUTO_UPLOAD
) {
return {};
}
return { SENTRY_ALLOW_FAILURE: 'true' };
}