Skip to content
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
5 changes: 4 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 `eas credentials:configure-build` subcommand.
([#2282](https://github.com/expo/eas-cli/pull/2282) by [@fiberjw](https://github.com/fiberjw))

### 🐛 Bug fixes

### 🧹 Chores
Expand Down Expand Up @@ -61,7 +64,7 @@ This is the log of notable changes to EAS CLI and related packages.
- Upgrade [`eas-build`](https://github.com/expo/eas-build) dependencies. ([#2237](https://github.com/expo/eas-cli/pull/2237) by [@expo-bot](https://github.com/expo-bot))
- Upgrade [`eas-build`](https://github.com/expo/eas-build) dependencies. ([#2240](https://github.com/expo/eas-cli/pull/2240) by [@expo-bot](https://github.com/expo-bot))
- Upgrade [`eas-build`](https://github.com/expo/eas-build) dependencies. ([#2253](https://github.com/expo/eas-cli/pull/2253) by [@expo-bot](https://github.com/expo-bot))
- Include src/**/build directories in vscode search and replace. ([#2250](https://github.com/expo/eas-cli/pull/2250) by [@wschurman](https://github.com/wschurman))
- Include src/\*\*/build directories in vscode search and replace. ([#2250](https://github.com/expo/eas-cli/pull/2250) by [@wschurman](https://github.com/wschurman))
- Upgrade [`eas-build`](https://github.com/expo/eas-build) dependencies. ([#2259](https://github.com/expo/eas-cli/pull/2259) by [@expo-bot](https://github.com/expo-bot))

## [7.3.0](https://github.com/expo/eas-cli/releases/tag/v7.3.0) - 2024-02-19
Expand Down
64 changes: 64 additions & 0 deletions packages/eas-cli/src/commands/credentials/configure-build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Platform } from '@expo/eas-build-job';
import { Flags } from '@oclif/core';

import EasCommand from '../../commandUtils/EasCommand';
import { SelectBuildProfileFromEasJson } from '../../credentials/manager/SelectBuildProfileFromEasJson';
import { SetUpBuildCredentialsCommandAction } from '../../credentials/manager/SetUpBuildCredentialsCommandAction';
import { selectPlatformAsync } from '../../platform';

export default class InitializeBuildCredentials extends EasCommand {
static override description = 'Set up credentials for building your project.';

static override flags = {
platform: Flags.enum({
char: 'p',
options: [Platform.ANDROID, Platform.IOS],
}),
profile: Flags.string({
char: 'e',
description: 'The name of the build profile in eas.json.',
helpValue: 'PROFILE_NAME',
}),
};

static override contextDefinition = {
...this.ContextOptions.LoggedIn,
...this.ContextOptions.ProjectConfig,
...this.ContextOptions.DynamicProjectConfig,
...this.ContextOptions.Analytics,
...this.ContextOptions.Vcs,
};

async runAsync(): Promise<void> {
const { flags } = await this.parse(InitializeBuildCredentials);
const {
loggedIn: { actor, graphqlClient },
privateProjectConfig,
getDynamicPrivateProjectConfigAsync,
analytics,
vcsClient,
} = await this.getContextAsync(InitializeBuildCredentials, {
nonInteractive: false,
});

const platform = await selectPlatformAsync(flags.platform);

const buildProfile =
flags.profile ??
(await new SelectBuildProfileFromEasJson(
privateProjectConfig.projectDir,
Platform.IOS
).getProfileNameFromEasConfigAsync());

await new SetUpBuildCredentialsCommandAction(
actor,
graphqlClient,
vcsClient,
analytics,
privateProjectConfig ?? null,
getDynamicPrivateProjectConfigAsync,
platform,
buildProfile
).runAsync();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Flags } from '@oclif/core';

import EasCommand from '../commandUtils/EasCommand';
import { SelectPlatform } from '../credentials/manager/SelectPlatform';
import EasCommand from '../../commandUtils/EasCommand';
import { SelectPlatform } from '../../credentials/manager/SelectPlatform';

export default class Credentials extends EasCommand {
static override description = 'manage credentials';
Expand Down
1 change: 1 addition & 0 deletions packages/eas-cli/src/credentials/manager/Actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export enum AndroidActionType {
SetUpGsaKeyForFcmV1,
UpdateCredentialsJson,
SetUpBuildCredentialsFromCredentialsJson,
SetUpBuildCredentials,
}

export enum IosActionType {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Platform } from '@expo/eas-build-job';
import { BuildProfile, EasJsonAccessor, EasJsonUtils } from '@expo/eas-json';

import Log from '../../log';

export class CheckBuildProfileFlagAgainstEasJson<T extends Platform> {
private easJsonAccessor: EasJsonAccessor;

constructor(
projectDir: string,
private platform: T,
private profileNameFromFlag: string
) {
this.easJsonAccessor = EasJsonAccessor.fromProjectPath(projectDir);
}

async runAsync(): Promise<BuildProfile<T>> {
const profileName = await this.getProfileNameFromEasConfigAsync();
const easConfig = await EasJsonUtils.getBuildProfileAsync<T>(
this.easJsonAccessor,
this.platform,
profileName
);
Log.succeed(`Using build profile: ${profileName}`);
return easConfig;
}

async getProfileNameFromEasConfigAsync(): Promise<string> {
const buildProfileNames = await EasJsonUtils.getBuildProfileNamesAsync(this.easJsonAccessor);
if (buildProfileNames.length === 0) {
throw new Error(
'You need at least one iOS build profile declared in eas.json. Go to https://docs.expo.dev/build/eas-json/ for more details'
);
} else if (buildProfileNames.length === 1) {
return buildProfileNames[0];
}

if (buildProfileNames.includes(this.profileNameFromFlag)) {
return this.profileNameFromFlag;
} else {
throw new Error(
`Build profile ${this.profileNameFromFlag} does not exist in eas.json. Go to https://docs.expo.dev/build/eas-json/ for more details`
);
}
}
}
11 changes: 7 additions & 4 deletions packages/eas-cli/src/credentials/manager/ManageAndroid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { DownloadKeystore } from '../android/actions/DownloadKeystore';
import { RemoveFcm } from '../android/actions/RemoveFcm';
import { SelectAndRemoveGoogleServiceAccountKey } from '../android/actions/RemoveGoogleServiceAccountKey';
import { RemoveKeystore } from '../android/actions/RemoveKeystore';
import { SetUpBuildCredentials } from '../android/actions/SetUpBuildCredentials';
import { SetUpBuildCredentialsFromCredentialsJson } from '../android/actions/SetUpBuildCredentialsFromCredentialsJson';
import { SetUpGoogleServiceAccountKeyForFcmV1 } from '../android/actions/SetUpGoogleServiceAccountKeyForFcmV1';
import { SetUpGoogleServiceAccountKeyForSubmissions } from '../android/actions/SetUpGoogleServiceAccountKeyForSubmissions';
Expand All @@ -48,8 +49,8 @@ import { AndroidPackageNotDefinedError } from '../errors';

export class ManageAndroid {
constructor(
private callingAction: Action,
private projectDir: string
protected callingAction: Action,
protected projectDir: string
) {}

async runAsync(currentActions: ActionInfo[] = highLevelActions): Promise<void> {
Expand Down Expand Up @@ -164,15 +165,15 @@ export class ManageAndroid {
}
}

private async createProjectContextAsync(
protected async createProjectContextAsync(
ctx: CredentialsContext,
buildProfile: BuildProfile<Platform.ANDROID>
): Promise<GradleBuildContext | undefined> {
assert(ctx.hasProjectContext, 'createProjectContextAsync: must have project context.');
return await resolveGradleBuildContextAsync(ctx.projectDir, buildProfile, ctx.vcsClient);
}

private async runProjectSpecificActionAsync(
protected async runProjectSpecificActionAsync(
ctx: CredentialsContext,
action: AndroidActionType,
gradleContext?: GradleBuildContext
Expand Down Expand Up @@ -239,6 +240,8 @@ export class ManageAndroid {
}
} else if (action === AndroidActionType.SetUpBuildCredentialsFromCredentialsJson) {
await new SetUpBuildCredentialsFromCredentialsJson(appLookupParams).runAsync(ctx);
} else if (action === AndroidActionType.SetUpBuildCredentials) {
await new SetUpBuildCredentials({ app: appLookupParams }).runAsync(ctx);
}
}
}
14 changes: 7 additions & 7 deletions packages/eas-cli/src/credentials/manager/ManageIos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ import { displayIosCredentials } from '../ios/utils/printCredentials';

export class ManageIos {
constructor(
private callingAction: Action,
private projectDir: string
protected callingAction: Action,
protected projectDir: string
) {}

async runAsync(currentActions: ActionInfo[] = highLevelActions): Promise<void> {
Expand Down Expand Up @@ -182,7 +182,7 @@ export class ManageIos {
}
}

private async createProjectContextAsync(
protected async createProjectContextAsync(
ctx: CredentialsContext,
account: AccountFragment,
buildProfile: BuildProfile<Platform.IOS>
Expand Down Expand Up @@ -215,7 +215,7 @@ export class ManageIos {
};
}

private async runAccountSpecificActionAsync(
protected async runAccountSpecificActionAsync(
ctx: CredentialsContext,
account: AccountFragment,
action: IosActionType
Expand All @@ -235,7 +235,7 @@ export class ManageIos {
}
}

private async runProjectSpecificActionAsync(
protected async runProjectSpecificActionAsync(
ctx: CredentialsContext,
app: App,
targets: Target[],
Expand Down Expand Up @@ -396,7 +396,7 @@ export class ManageIos {
}
}

private async setupProvisioningProfileWithSpecificDistCertAsync(
protected async setupProvisioningProfileWithSpecificDistCertAsync(
ctx: CredentialsContext,
target: Target,
appLookupParams: AppLookupParams,
Expand All @@ -419,7 +419,7 @@ export class ManageIos {
}
}

private async selectTargetAsync(targets: Target[]): Promise<Target> {
protected async selectTargetAsync(targets: Target[]): Promise<Target> {
if (targets.length === 1) {
return targets[0];
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Platform } from '@expo/eas-build-job';
import assert from 'assert';

import { AndroidActionType } from './Actions';
import { CheckBuildProfileFlagAgainstEasJson } from './CheckBuildProfileFlagAgainstEasJson';
import { Action } from './HelperActions';
import { ManageAndroid } from './ManageAndroid';
import { CredentialsContext, CredentialsContextProjectInfo } from '../context';

export class SetUpAndroidBuildCredentials extends ManageAndroid {
constructor(
callingAction: Action,
projectDir: string,
private setUpBuildCredentialsWithProfileNameFromFlag: string
) {
super(callingAction, projectDir);
}

override async runAsync(): Promise<void> {
const hasProjectContext = !!this.callingAction.projectInfo;
const buildProfile = hasProjectContext
? await new CheckBuildProfileFlagAgainstEasJson(
this.projectDir,
Platform.ANDROID,
this.setUpBuildCredentialsWithProfileNameFromFlag
).runAsync()
: null;
let projectInfo: CredentialsContextProjectInfo | null = null;
if (hasProjectContext) {
const { exp, projectId } = await this.callingAction.getDynamicPrivateProjectConfigAsync({
env: buildProfile?.env,
});
projectInfo = { exp, projectId };
}
const ctx = new CredentialsContext({
projectDir: process.cwd(),
projectInfo,
user: this.callingAction.actor,
graphqlClient: this.callingAction.graphqlClient,
analytics: this.callingAction.analytics,
env: buildProfile?.env,
nonInteractive: false,
vcsClient: this.callingAction.vcsClient,
});

let gradleContext;
if (ctx.hasProjectContext) {
assert(buildProfile, 'buildProfile must be defined in a project context');
gradleContext = await this.createProjectContextAsync(ctx, buildProfile);
}

if (this.setUpBuildCredentialsWithProfileNameFromFlag) {
await this.runProjectSpecificActionAsync(
ctx,
AndroidActionType.SetUpBuildCredentials,
gradleContext
);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Platform } from '@expo/eas-build-job';

import { Analytics } from '../../analytics/AnalyticsManager';
import { DynamicConfigContextFn } from '../../commandUtils/context/DynamicProjectConfigContextField';
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
import { Actor } from '../../user/User';
import { Client } from '../../vcs/vcs';
import { CredentialsContextProjectInfo } from '../context';
import { SetUpAndroidBuildCredentials } from '../manager/SetUpAndroidBuildCredentials';
import { SetUpIosBuildCredentials } from '../manager/SetUpIosBuildCredentials';

export class SetUpBuildCredentialsCommandAction {
constructor(
public readonly actor: Actor,
public readonly graphqlClient: ExpoGraphqlClient,
public readonly vcsClient: Client,
public readonly analytics: Analytics,
public readonly projectInfo: CredentialsContextProjectInfo | null,
public readonly getDynamicPrivateProjectConfigAsync: DynamicConfigContextFn,
private readonly platform: Platform,
private readonly profileName: string
) {}

async runAsync(): Promise<void> {
if (this.platform === Platform.IOS) {
return await new SetUpIosBuildCredentials(this, process.cwd(), this.profileName).runAsync();
}
return await new SetUpAndroidBuildCredentials(this, process.cwd(), this.profileName).runAsync();
}
}
Loading