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

allow for registering devices when building app for internal distribution #340

Merged
merged 2 commits into from
Apr 19, 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
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ This is the log of notable changes to EAS CLI and related packages.

### 🎉 New features

- Add validation when setting up ad-hoc provisioning profile in non-interactive mode. ([#338](https://github.com/expo/eas-cli/pull/338))
- Allow for registering devices when running an ad-hoc build for the first time. ([#340](https://github.com/expo/eas-cli/pull/340) by [@dsokal](https://github.com/dsokal))

### 🐛 Bug fixes

### 🧹 Chores
Expand All @@ -22,7 +25,6 @@ This is the log of notable changes to EAS CLI and related packages.
### 🎉 New features

- Use special Expo SDK runtime version for managed projects ([#336](https://github.com/expo/eas-cli/pull/336)) by [@wschurman](https://github.com/wschurman))
- Add validation when setting up ad-hoc provisioning profile in non-interactive mode. ([#338](https://github.com/expo/eas-cli/pull/338) by [@dsokal](https://github.com/dsokal))

### 🐛 Bug fixes

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import assert from 'assert';
import chalk from 'chalk';
import differenceBy from 'lodash/differenceBy';
import isEqual from 'lodash/isEqual';
import nullthrows from 'nullthrows';

import DeviceCreateAction, { RegistrationMethod } from '../../../../devices/actions/create/action';
import {
AppleDeviceFragment,
AppleProvisioningProfileFragment,
AppleTeamFragment,
IosAppBuildCredentialsFragment,
IosDistributionType,
} from '../../../../graphql/generated';
import Log from '../../../../log';
import { confirmAsync } from '../../../../prompts';
import { confirmAsync, pressAnyKeyToContinueAsync } from '../../../../prompts';
import { Context } from '../../../context';
import { AppLookupParams } from '../../api/GraphqlClient';
import { MissingCredentialsNonInteractiveError } from '../../errors';
Expand Down Expand Up @@ -63,16 +66,18 @@ export class SetupAdhocProvisioningProfile {
assert(appleTeam, 'Apple Team must be defined here');

// 2. Fetch devices registered on EAS servers
const registeredAppleDevices = await ctx.newIos.getDevicesForAppleTeamAsync(
this.app,
appleTeam
);
const registeredAppleDeviceIdentifiers = registeredAppleDevices.map(
({ identifier }) => identifier
);
if (registeredAppleDeviceIdentifiers.length === 0) {
// TODO: implement device registration
throw new Error(`Run 'eas device:create' to register your devices first`);
let registeredAppleDevices = await ctx.newIos.getDevicesForAppleTeamAsync(this.app, appleTeam);
if (registeredAppleDevices.length === 0) {
const shouldRegisterDevices = await confirmAsync({
message: `You don't have any registered devices yet. Would you like to register them now?`,
initial: true,
});

if (shouldRegisterDevices) {
registeredAppleDevices = await this.registerDevicesAsync(ctx, appleTeam);
} else {
throw new Error(`Run 'eas device:create' to register your devices first`);
}
}

// 3. Choose devices for internal distribution
Expand Down Expand Up @@ -181,6 +186,36 @@ export class SetupAdhocProvisioningProfile {
}));
}
}

private async registerDevicesAsync(
ctx: Context,
appleTeam: AppleTeamFragment
): Promise<AppleDeviceFragment[]> {
const action = new DeviceCreateAction(this.app.account, appleTeam);
const method = await action.runAsync();

while (true) {
if (method !== RegistrationMethod.INPUT) {
Log.newLine();
Log.log(chalk.bold("Press any key if you've already finished device registration."));
await pressAnyKeyToContinueAsync();
}
Log.newLine();

const devices = await ctx.newIos.getDevicesForAppleTeamAsync(this.app, appleTeam, {
useCache: false,
});
if (devices.length === 0) {
Log.warn('There are still no registered devices.');
// if the user used the input method there should be some devices available
if (method === RegistrationMethod.INPUT) {
throw new Error('Input registration method has failed');
}
} else {
return devices;
}
}
}
}

function doUDIDsMatch(udidsA: string[], udidsB: string[]): boolean {
Expand Down
15 changes: 8 additions & 7 deletions packages/eas-cli/src/credentials/ios/api/GraphqlClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import nullthrows from 'nullthrows';
import {
AppFragment,
AppleAppIdentifierFragment,
AppleDeviceFragment,
AppleDistributionCertificateFragment,
AppleTeamFragment,
CommonIosAppCredentialsFragment,
Expand All @@ -26,10 +27,7 @@ import { IosAppBuildCredentialsMutation } from './graphql/mutations/IosAppBuildC
import { IosAppCredentialsMutation } from './graphql/mutations/IosAppCredentialsMutation';
import { AppQuery } from './graphql/queries/AppQuery';
import { AppleAppIdentifierQuery } from './graphql/queries/AppleAppIdentifierQuery';
import {
AppleDeviceFragmentWithAppleTeam,
AppleDeviceQuery,
} from './graphql/queries/AppleDeviceQuery';
import { AppleDeviceQuery } from './graphql/queries/AppleDeviceQuery';
import { AppleDistributionCertificateQuery } from './graphql/queries/AppleDistributionCertificateQuery';
import {
AppleProvisioningProfileQuery,
Expand Down Expand Up @@ -215,9 +213,12 @@ export async function createOrGetExistingAppleAppIdentifierAsync(

export async function getDevicesForAppleTeamAsync(
{ account }: AppLookupParams,
{ appleTeamIdentifier }: AppleTeamFragment
): Promise<AppleDeviceFragmentWithAppleTeam[]> {
return await AppleDeviceQuery.getAllByAppleTeamIdentifierAsync(account.id, appleTeamIdentifier);
{ appleTeamIdentifier }: AppleTeamFragment,
{ useCache = true }: { useCache?: boolean } = {}
): Promise<AppleDeviceFragment[]> {
return await AppleDeviceQuery.getAllByAppleTeamIdentifierAsync(account.id, appleTeamIdentifier, {
useCache,
});
}

export async function createProvisioningProfileAsync(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ export type AppleDevicesByIdentifierQueryResult = AppleDeviceQueryResult & {
const AppleDeviceQuery = {
async getAllByAppleTeamIdentifierAsync(
accountId: string,
appleTeamIdentifier: string
appleTeamIdentifier: string,
{ useCache = true }: { useCache?: boolean } = {}
): Promise<AppleDeviceFragmentWithAppleTeam[]> {
const data = await withErrorHandlingAsync(
graphqlClient
Expand Down Expand Up @@ -63,7 +64,10 @@ const AppleDeviceQuery = {
accountId,
appleTeamIdentifier,
},
{ additionalTypenames: ['AppleDevice'] }
{
additionalTypenames: ['AppleDevice'],
requestPolicy: useCache ? 'cache-first' : 'network-only',
}
)
.toPromise()
);
Expand Down
3 changes: 2 additions & 1 deletion packages/eas-cli/src/devices/actions/create/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default class DeviceCreateAction {
private appleTeam: Pick<AppleTeam, 'appleTeamIdentifier' | 'appleTeamName' | 'id'>
) {}

public async runAsync(): Promise<void> {
public async runAsync(): Promise<RegistrationMethod> {
const method = await this.askForRegistrationMethodAsync();
if (method === RegistrationMethod.WEBSITE) {
await runRegistrationUrlMethodAsync(this.account.id, this.appleTeam);
Expand All @@ -29,6 +29,7 @@ export default class DeviceCreateAction {
Log.log('Bye!');
process.exit(0);
}
return method;
}

private async askForRegistrationMethodAsync(): Promise<RegistrationMethod> {
Expand Down