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

[ENG-755] add --non-interactive flag for eas submit #600

Merged
merged 4 commits into from
Sep 9, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ This is the log of notable changes to EAS CLI and related packages.
### 🎉 New features

- Implement support for `--platform all` in `eas submit`. ([#598](https://github.com/expo/eas-cli/pull/598) by [@dsokal](https://github.com/dsokal))
- Implement support for `--non-interactive` in `eas submit`. ([#600](https://github.com/expo/eas-cli/pull/600) by [@dsokal](https://github.com/dsokal))

### 🐛 Bug fixes

Expand Down
22 changes: 20 additions & 2 deletions packages/eas-cli/src/commands/submit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ interface RawFlags {
url?: string;
verbose: boolean;
wait: boolean;
'non-interactive': boolean;
}

interface Flags {
Expand All @@ -46,6 +47,7 @@ interface Flags {
archiveFlags: SubmitArchiveFlags;
verbose: boolean;
wait: boolean;
nonInteractive: boolean;
}

export default class Submit extends EasCommand {
Expand Down Expand Up @@ -89,6 +91,10 @@ See how to configure submits with eas.json: ${learnMore('https://docs.expo.dev/s
default: true,
allowNo: true,
}),
'non-interactive': flags.boolean({
default: false,
description: 'Run command in non-interactive mode',
}),
};

async run(): Promise<void> {
Expand Down Expand Up @@ -116,6 +122,7 @@ See how to configure submits with eas.json: ${learnMore('https://docs.expo.dev/s
projectId,
profile,
archiveFlags: flags.archiveFlags,
nonInteractive: flags.nonInteractive,
});

if (platforms.length > 1) {
Expand All @@ -141,10 +148,20 @@ See how to configure submits with eas.json: ${learnMore('https://docs.expo.dev/s
}

private async sanitizeFlagsAsync(flags: RawFlags): Promise<Flags> {
const { platform, verbose, wait, profile, ...archiveFlags } = flags;
const {
platform,
verbose,
wait,
profile,
'non-interactive': nonInteractive,
...archiveFlags
} = flags;

const requestedPlatform = await selectRequestedPlatformAsync(flags.platform);
if (!flags.platform && nonInteractive) {
error('--platform is required when building in non-interactive mode', { exit: 1 });
}

const requestedPlatform = await selectRequestedPlatformAsync(flags.platform);
if (requestedPlatform === RequestedPlatform.All) {
if (archiveFlags.id || archiveFlags.path || archiveFlags.url) {
error(
Expand All @@ -160,6 +177,7 @@ See how to configure submits with eas.json: ${learnMore('https://docs.expo.dev/s
verbose,
wait,
profile,
nonInteractive,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,29 @@ import { jester as mockJester } from '../../../../credentials/__tests__/fixtures
import { testKeystore } from '../../../__tests__/fixtures-android';
import { createCtxMock } from '../../../__tests__/fixtures-context';
import { askForUserProvidedAsync } from '../../../utils/promptForCredentials';
import { generateRandomKeystoreAsync } from '../../utils/keystore';
import { getAppLookupParamsFromContextAsync } from '../BuildCredentialsUtils';
import { CreateKeystore } from '../CreateKeystore';

jest.mock('../../../utils/promptForCredentials');
jest.mock('../../../../project/ensureProjectExists');
jest.mock('../../../../prompts', () => ({ confirmAsync: jest.fn(() => true) }));
jest.mock('../../../../user/actions', () => ({ ensureLoggedInAsync: jest.fn(() => mockJester) }));
jest.mock('../../../utils/promptForCredentials');
jest.mock('../../utils/keystore', () => ({ generateRandomKeystoreAsync: jest.fn() }));

describe('CreateKeystore', () => {
beforeEach(() => {
asMock(generateRandomKeystoreAsync).mockReset();
});
it('creates a keystore in Interactive Mode', async () => {
const ctx = createCtxMock({ nonInteractive: false });
const appLookupParams = await getAppLookupParamsFromContextAsync(ctx);
const createKeystoreAction = new CreateKeystore(appLookupParams.account);
await createKeystoreAction.runAsync(ctx);

// expect keystore to be created on expo servers
expect(ctx.android.createKeystoreAsync as any).toHaveBeenCalledTimes(1);
expect(ctx.android.createKeystoreAsync).toHaveBeenCalled();
expect(generateRandomKeystoreAsync).toHaveBeenCalled();
});
it('creates a keystore by uploading', async () => {
asMock(askForUserProvidedAsync).mockImplementationOnce(() => testKeystore);
Expand All @@ -29,11 +35,11 @@ describe('CreateKeystore', () => {
await createKeystoreAction.runAsync(ctx);

// expect keystore to be created on expo servers
expect(ctx.android.createKeystoreAsync as any).toHaveBeenCalledTimes(1);
expect(ctx.android.createKeystoreAsync as any).toHaveBeenCalledWith(
expect(ctx.android.createKeystoreAsync).toHaveBeenCalledWith(
appLookupParams.account,
expect.objectContaining(testKeystore)
);
expect(generateRandomKeystoreAsync).not.toHaveBeenCalled();
});
it('errors in Non-Interactive Mode', async () => {
const ctx = createCtxMock({ nonInteractive: true });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { asMock } from '../../../../__tests__/utils';
import {
getNewAndroidApiMock,
testAndroidBuildCredentialsFragment,
Expand All @@ -16,6 +17,10 @@ jest.mock('../../../../prompts', () => ({ confirmAsync: jest.fn(() => true) }));
jest.mock('../../utils/keystore', () => ({ generateRandomKeystoreAsync: jest.fn() }));

describe('SetupBuildCredentials', () => {
beforeEach(() => {
asMock(generateRandomKeystoreAsync).mockReset();
});

it('skips setup when there are prior credentials', async () => {
const ctx = createCtxMock({
nonInteractive: false,
Expand Down
12 changes: 10 additions & 2 deletions packages/eas-cli/src/submissions/android/AndroidSubmitCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export default class AndroidSubmitCommand {
if (errored.length > 0) {
const message = errored.map(err => err.reason?.message).join('\n');
Log.error(message);
throw new Error('Failed to submit the app');
throw new Error('Submission failed');
}

return {
Expand Down Expand Up @@ -75,6 +75,8 @@ export default class AndroidSubmitCommand {
sourceType: AndroidPackageSourceType.userDefined,
androidPackage,
});
} else if (this.ctx.nonInteractive) {
return result(new Error("Couldn't resolve the Android package."));
} else {
return result({
sourceType: AndroidPackageSourceType.prompt,
Expand Down Expand Up @@ -127,7 +129,11 @@ export default class AndroidSubmitCommand {
}

private resolveArchiveSource(): Result<ArchiveSource> {
return result(resolveArchiveSource(this.ctx, Platform.ANDROID));
try {
return result(resolveArchiveSource(this.ctx, Platform.ANDROID));
} catch (err: any) {
return result(err);
}
}

private resolveServiceAccountSource(): Result<ServiceAccountSource> {
Expand All @@ -137,6 +143,8 @@ export default class AndroidSubmitCommand {
sourceType: ServiceAccountSourceType.path,
path: serviceAccountKeyPath,
});
} else if (this.ctx.nonInteractive) {
return result(new Error('Set serviceAccountKeyPath in the submit profile (eas.json).'));
} else {
return result({
sourceType: ServiceAccountSourceType.detect,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,29 @@ describe(AndroidSubmitCommand, () => {
asMock(getProjectIdAsync).mockClear();
});

describe('non-interactive mode', () => {
it("throws error if didn't provide serviceAccountKeyPath in the submit profile", async () => {
const projectId = uuidv4();

const ctx = createSubmissionContext({
platform: Platform.ANDROID,
projectDir: testProject.projectRoot,
projectId,
archiveFlags: {
url: 'http://expo.dev/fake.apk',
},
profile: {
track: AndroidReleaseTrack.internal,
releaseStatus: AndroidReleaseStatus.draft,
changesNotSentForReview: false,
},
nonInteractive: true,
});
const command = new AndroidSubmitCommand(ctx);
await expect(command.runAsync()).rejects.toThrowError();
});
});

describe('sending submission', () => {
it('sends a request to Submission Service', async () => {
const projectId = uuidv4();
Expand All @@ -90,6 +113,7 @@ describe(AndroidSubmitCommand, () => {
releaseStatus: AndroidReleaseStatus.draft,
changesNotSentForReview: false,
},
nonInteractive: false,
});
const command = new AndroidSubmitCommand(ctx);
await command.runAsync();
Expand Down Expand Up @@ -124,6 +148,7 @@ describe(AndroidSubmitCommand, () => {
releaseStatus: AndroidReleaseStatus.draft,
changesNotSentForReview: false,
},
nonInteractive: false,
});
const command = new AndroidSubmitCommand(ctx);
await command.runAsync();
Expand Down
2 changes: 2 additions & 0 deletions packages/eas-cli/src/submissions/commons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ export function resolveArchiveSource<T extends Platform>(
platform,
projectId: ctx.projectId,
};
} else if (ctx.nonInteractive) {
throw new Error('You need to specify the archive source when running in non-interactive mode ');
} else {
return {
sourceType: ArchiveSourceType.prompt,
Expand Down
2 changes: 2 additions & 0 deletions packages/eas-cli/src/submissions/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export interface SubmissionContext<T extends Platform> {
profile: SubmitProfile<T>;
projectDir: string;
projectId: string;
nonInteractive: boolean;
}

export interface SubmitArchiveFlags {
Expand All @@ -22,6 +23,7 @@ export function createSubmissionContext<T extends Platform>(params: {
profile: SubmitProfile<T>;
projectDir: string;
projectId: string;
nonInteractive: boolean;
}): SubmissionContext<T> {
return params;
}
5 changes: 1 addition & 4 deletions packages/eas-cli/src/submissions/ios/AppProduce.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,8 @@ type AppStoreResult = {
export async function ensureAppStoreConnectAppExistsAsync(
ctx: SubmissionContext<Platform.IOS>
): Promise<AppStoreResult> {
const projectConfig = getConfig(ctx.projectDir, { skipSDKVersionRequirement: true });
const { exp } = projectConfig;

const { exp } = getConfig(ctx.projectDir, { skipSDKVersionRequirement: true });
const { appName, language } = ctx.profile;

const options = {
...ctx.profile,
bundleIdentifier: await getBundleIdentifierAsync(ctx.projectDir, exp),
Expand Down
Loading