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

[eas-cli] Use credentials types from eas-build-job where possible #2191

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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 @@ -13,6 +13,7 @@ This is the log of notable changes to EAS CLI and related packages.
### 🧹 Chores

- Remove support for classic updates release channel in 50+. ([#2189](https://github.com/expo/eas-cli/pull/2189) by [@wschurman](https://github.com/wschurman))
- Migrate to using credentials types from `eas-build-job` where possible. ([#2191](https://github.com/expo/eas-cli/pull/2191) by [@sjchmiela](https://github.com/sjchmiela))

## [7.0.0](https://github.com/expo/eas-cli/releases/tag/v7.0.0) - 2024-01-19

Expand Down
3 changes: 1 addition & 2 deletions packages/eas-cli/src/build/ios/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { transformJob } from './graphql';
import { prepareJobAsync } from './prepareJob';
import { syncProjectConfigurationAsync } from './syncProjectConfiguration';
import { resolveRemoteBuildNumberAsync } from './version';
import { IosCredentials } from '../../credentials/ios/types';
import { BuildParamsInput } from '../../graphql/generated';
import { BuildMutation, BuildResult } from '../../graphql/mutations/BuildMutation';
import { ensureBundleIdentifierIsDefinedForManagedProjectAsync } from '../../project/ios/bundleIdentifier';
Expand Down Expand Up @@ -93,7 +92,7 @@ export async function prepareIosBuildAsync(
},
prepareJobAsync: async (
ctx: BuildContext<Platform.IOS>,
jobData: JobData<IosCredentials>
jobData: JobData<Ios.BuildCredentials>
): Promise<Job> => {
return await prepareJobAsync(ctx, {
...jobData,
Expand Down
8 changes: 4 additions & 4 deletions packages/eas-cli/src/build/ios/credentials.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { Platform } from '@expo/eas-build-job';
import { Ios, Platform } from '@expo/eas-build-job';
import { BuildProfile } from '@expo/eas-json';

import { CredentialsContext } from '../../credentials/context';
import IosCredentialsProvider from '../../credentials/ios/IosCredentialsProvider';
import { getAppFromContextAsync } from '../../credentials/ios/actions/BuildCredentialsUtils';
import { IosCredentials, Target } from '../../credentials/ios/types';
import { Target } from '../../credentials/ios/types';
import { CredentialsResult } from '../build';
import { BuildContext } from '../context';
import { logCredentialsSource } from '../utils/credentials';

export async function ensureIosCredentialsAsync(
buildCtx: BuildContext<Platform.IOS>,
targets: Target[]
): Promise<CredentialsResult<IosCredentials> | undefined> {
): Promise<CredentialsResult<Ios.BuildCredentials> | undefined> {
if (!shouldProvideCredentials(buildCtx)) {
return;
}
Expand All @@ -37,7 +37,7 @@ export async function ensureIosCredentialsForBuildResignAsync(
credentialsCtx: CredentialsContext,
targets: Target[],
buildProfile: BuildProfile<Platform.IOS>
): Promise<CredentialsResult<IosCredentials>> {
): Promise<CredentialsResult<Ios.BuildCredentials>> {
const provider = new IosCredentialsProvider(credentialsCtx, {
app: await getAppFromContextAsync(credentialsCtx),
targets,
Expand Down
23 changes: 6 additions & 17 deletions packages/eas-cli/src/build/ios/prepareJob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,14 @@ import nullthrows from 'nullthrows';
import path from 'path';
import slash from 'slash';

import { IosCredentials, TargetCredentials } from '../../credentials/ios/types';
import { IosJobSecretsInput } from '../../graphql/generated';
import { getCustomBuildConfigPath } from '../../project/customBuildConfig';
import { getUsername } from '../../project/projectUtils';
import { BuildContext } from '../context';

interface JobData {
projectArchive: ArchiveSource;
credentials?: IosCredentials;
credentials?: Ios.BuildCredentials;
buildScheme: string;
}

Expand All @@ -41,7 +40,7 @@ export async function prepareJobAsync(
if (jobData.credentials) {
const targetNames = Object.keys(jobData.credentials);
for (const targetName of targetNames) {
buildCredentials[targetName] = prepareTargetCredentials(jobData.credentials[targetName]);
buildCredentials[targetName] = jobData.credentials[targetName];
}
}

Expand Down Expand Up @@ -102,28 +101,18 @@ export async function prepareJobAsync(
return sanitizeJob(job);
}

export function prepareCredentialsToResign(credentials: IosCredentials): IosJobSecretsInput {
export function prepareCredentialsToResign(credentials: Ios.BuildCredentials): IosJobSecretsInput {
const buildCredentials: IosJobSecretsInput['buildCredentials'] = [];
for (const targetName of Object.keys(credentials ?? {})) {
buildCredentials.push({
targetName,
provisioningProfileBase64: nullthrows(credentials?.[targetName].provisioningProfile),
provisioningProfileBase64: nullthrows(credentials?.[targetName].provisioningProfileBase64),
distributionCertificate: {
dataBase64: nullthrows(credentials?.[targetName].distributionCertificate.certificateP12),
password: nullthrows(credentials?.[targetName].distributionCertificate.certificatePassword),
dataBase64: nullthrows(credentials?.[targetName].distributionCertificate.dataBase64),
password: nullthrows(credentials?.[targetName].distributionCertificate.password),
},
});
}

return { buildCredentials };
}

function prepareTargetCredentials(targetCredentials: TargetCredentials): Ios.TargetCredentials {
return {
provisioningProfileBase64: targetCredentials.provisioningProfile,
distributionCertificate: {
dataBase64: targetCredentials.distributionCertificate.certificateP12,
password: targetCredentials.distributionCertificate.certificatePassword,
},
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,10 @@ describe('credentialsJson', () => {
const result = await credentialsJsonReader.readIosCredentialsAsync('.', applicationTarget);
expect(result).toEqual({
[applicationTarget.targetName]: {
provisioningProfile: 'c29tZWJpbmFyeWNvbnRlbnQ=',
provisioningProfileBase64: 'c29tZWJpbmFyeWNvbnRlbnQ=',
distributionCertificate: {
certificateP12: 'c29tZWJpbmFyeWNvbnRlbnQy',
certificatePassword: 'certPass',
dataBase64: 'c29tZWJpbmFyeWNvbnRlbnQy',
password: 'certPass',
},
},
});
Expand Down Expand Up @@ -230,17 +230,17 @@ describe('credentialsJson', () => {
);
expect(result).toEqual({
target1: {
provisioningProfile: 'cHByb2ZpbGUtMS1zb21lYmluYXJ5Y29udGVudA==',
provisioningProfileBase64: 'cHByb2ZpbGUtMS1zb21lYmluYXJ5Y29udGVudA==',
distributionCertificate: {
certificateP12: 'Y2VydC0xLXNvbWViaW5hcnljb250ZW50',
certificatePassword: 'cert-pass-1',
dataBase64: 'Y2VydC0xLXNvbWViaW5hcnljb250ZW50',
password: 'cert-pass-1',
},
},
target2: {
provisioningProfile: 'cHByb2ZpbGUtMi1zb21lYmluYXJ5Y29udGVudA==',
provisioningProfileBase64: 'cHByb2ZpbGUtMi1zb21lYmluYXJ5Y29udGVudA==',
distributionCertificate: {
certificateP12: 'Y2VydC0yLXNvbWViaW5hcnljb250ZW50',
certificatePassword: 'cert-pass-2',
dataBase64: 'Y2VydC0yLXNvbWViaW5hcnljb250ZW50',
password: 'cert-pass-2',
},
},
});
Expand Down
20 changes: 9 additions & 11 deletions packages/eas-cli/src/credentials/credentialsJson/read.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { Ios } from '@expo/eas-build-job';
import fs from 'fs-extra';
import path from 'path';

import {
AndroidCredentials,
CredentialsJson,
CredentialsJsonIosCredentials,
CredentialsJsonIosTargetCredentials,
CredentialsJsonSchema,
IosCredentials,
IosTargetCredentials,
} from './types';
import { getCredentialsJsonPath } from './utils';
import { Target } from '../ios/types';
Expand All @@ -32,15 +30,15 @@ export async function readAndroidCredentialsAsync(projectDir: string): Promise<A
export async function readIosCredentialsAsync(
projectDir: string,
applicationTarget: Target
): Promise<IosCredentials> {
): Promise<Ios.BuildCredentials> {
const credentialsJson = await readAsync(projectDir);
if (!credentialsJson.ios) {
throw new Error('iOS credentials are missing in credentials.json');
}

if (isCredentialsMap(credentialsJson.ios)) {
const targets = Object.keys(credentialsJson.ios);
const iosCredentials: IosCredentials = {};
const iosCredentials: Ios.BuildCredentials = {};
for (const target of targets) {
iosCredentials[target] = await readCredentialsForTargetAsync(
projectDir,
Expand All @@ -60,26 +58,26 @@ export async function readIosCredentialsAsync(
}

function isCredentialsMap(
ios: CredentialsJsonIosTargetCredentials | CredentialsJsonIosCredentials
): ios is CredentialsJsonIosCredentials {
ios: Exclude<CredentialsJson['ios'], undefined>
): ios is Record<string, CredentialsJsonIosTargetCredentials> {
return typeof ios.provisioningProfilePath !== 'string';
}

async function readCredentialsForTargetAsync(
projectDir: string,
targetCredentials: CredentialsJsonIosTargetCredentials
): Promise<IosTargetCredentials> {
): Promise<Ios.TargetCredentials> {
return {
provisioningProfile: await fs.readFile(
provisioningProfileBase64: await fs.readFile(
getAbsolutePath(projectDir, targetCredentials.provisioningProfilePath),
'base64'
),
distributionCertificate: {
certificateP12: await fs.readFile(
dataBase64: await fs.readFile(
getAbsolutePath(projectDir, targetCredentials.distributionCertificate.path),
'base64'
),
certificatePassword: targetCredentials.distributionCertificate.password,
password: targetCredentials.distributionCertificate.password,
},
};
}
Expand Down
40 changes: 14 additions & 26 deletions packages/eas-cli/src/credentials/credentialsJson/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,39 @@ import Joi from 'joi';

import { Keystore } from '../android/credentials';

export interface CredentialsJson {
android?: CredentialsJsonAndroidCredentials;
ios?: CredentialsJsonIosTargetCredentials | CredentialsJsonIosCredentials;
}

export interface CredentialsJsonAndroidCredentials {
keystore: {
keystorePath: string;
keystorePassword: string;
keyAlias: string;
keyPassword?: string;
};
}

export interface CredentialsJsonIosTargetCredentials {
provisioningProfilePath: string;
distributionCertificate: {
path: string;
password: string;
};
}
export type CredentialsJsonIosCredentials = Record<string, CredentialsJsonIosTargetCredentials>;

export interface AndroidCredentials {
keystore: Keystore;
}

export interface IosTargetCredentials {
provisioningProfile: string;
distributionCertificate: {
certificateP12: string;
certificatePassword: string;
};
}
export type IosCredentials = Record<string, IosTargetCredentials>;

const CredentialsJsonIosTargetCredentialsSchema = Joi.object({
const CredentialsJsonIosTargetCredentialsSchema = Joi.object<CredentialsJsonIosTargetCredentials>({
provisioningProfilePath: Joi.string().required(),
distributionCertificate: Joi.object({
path: Joi.string().required(),
password: Joi.string().allow('').required(),
}).required(),
});

export const CredentialsJsonSchema = Joi.object({
export type CredentialsJson = {
android?: {
keystore: {
keystorePath: string;
keystorePassword: string;
keyAlias: string;
keyPassword?: string;
};
};
ios?: CredentialsJsonIosTargetCredentials | Record<string, CredentialsJsonIosTargetCredentials>;
};

export const CredentialsJsonSchema = Joi.object<CredentialsJson>({
android: Joi.object({
keystore: Joi.object({
keystorePath: Joi.string().required(),
Expand Down
31 changes: 14 additions & 17 deletions packages/eas-cli/src/credentials/credentialsJson/update.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { Ios } from '@expo/eas-build-job';
import fs from 'fs-extra';
import nullthrows from 'nullthrows';
import path from 'path';

import { readRawAsync } from './read';
import {
CredentialsJson,
CredentialsJsonIosCredentials,
CredentialsJsonIosTargetCredentials,
} from './types';
import { CredentialsJson, CredentialsJsonIosTargetCredentials } from './types';
import { getCredentialsJsonPath } from './utils';
import { AndroidAppBuildCredentialsFragment, IosDistributionType } from '../../graphql/generated';
import Log from '../../log';
Expand All @@ -16,7 +13,7 @@ import zipObject from '../../utils/expodash/zipObject';
import GitClient from '../../vcs/clients/git';
import { Client } from '../../vcs/vcs';
import { CredentialsContext } from '../context';
import { App, Target, TargetCredentials } from '../ios/types';
import { App, Target } from '../ios/types';

/**
* Update Android credentials.json with values from www, content of credentials.json
Expand Down Expand Up @@ -112,7 +109,7 @@ export async function updateIosCredentialsAsync(
throw new Error(errorMessage);
}

const iosCredentials: CredentialsJsonIosCredentials = {};
const iosCredentials: CredentialsJson['ios'] = {};
const targetCredentialsPathsMap = createTargetCredentialsPathsMap(
targets,
rawCredentialsJson.ios
Expand Down Expand Up @@ -209,7 +206,7 @@ async function getTargetBuildCredentialsAsync(
app: App,
target: Target,
iosDistributionType: IosDistributionType
): Promise<TargetCredentials | null> {
): Promise<Ios.TargetCredentials | null> {
const appCredentials = await ctx.ios.getIosAppCredentialsWithCommonFieldsAsync(
ctx.graphqlClient,
{
Expand Down Expand Up @@ -237,12 +234,12 @@ async function getTargetBuildCredentialsAsync(
}
return {
distributionCertificate: {
certificateP12: nullthrows(appBuildCredentials.distributionCertificate.certificateP12),
certificatePassword: nullthrows(
appBuildCredentials.distributionCertificate.certificatePassword
),
dataBase64: nullthrows(appBuildCredentials.distributionCertificate.certificateP12),
password: nullthrows(appBuildCredentials.distributionCertificate.certificatePassword),
},
provisioningProfile: nullthrows(appBuildCredentials.provisioningProfile.provisioningProfile),
provisioningProfileBase64: nullthrows(
appBuildCredentials.provisioningProfile.provisioningProfile
),
};
}

Expand All @@ -252,7 +249,7 @@ async function backupTargetCredentialsAsync(
targetCredentials,
targetCredentialsPaths,
}: {
targetCredentials: TargetCredentials;
targetCredentials: Ios.TargetCredentials;
targetCredentialsPaths: TargetCredentialsPaths;
}
): Promise<CredentialsJsonIosTargetCredentials> {
Expand All @@ -262,20 +259,20 @@ async function backupTargetCredentialsAsync(
await updateFileAsync(
ctx.projectDir,
provisioningProfilePath,
targetCredentials.provisioningProfile
targetCredentials.provisioningProfileBase64
);

Log.log(`Writing Distribution Certificate to ${distCertPath}`);
await updateFileAsync(
ctx.projectDir,
distCertPath,
targetCredentials.distributionCertificate.certificateP12
targetCredentials.distributionCertificate.dataBase64
);

return {
distributionCertificate: {
path: distCertPath,
password: targetCredentials.distributionCertificate.certificatePassword,
password: targetCredentials.distributionCertificate.password,
},
provisioningProfilePath,
};
Expand Down
4 changes: 2 additions & 2 deletions packages/eas-cli/src/credentials/credentialsJson/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Ios } from '@expo/eas-build-job';
import path from 'path';

import { IosCredentials } from './types';
import { Target } from '../ios/types';

export function getCredentialsJsonPath(projectDir: string): string {
Expand All @@ -9,7 +9,7 @@ export function getCredentialsJsonPath(projectDir: string): string {

export function ensureAllTargetsAreConfigured(
targets: Target[],
credentialsJson: IosCredentials
credentialsJson: Ios.BuildCredentials
): void {
const notConfiguredTargets: string[] = [];
for (const target of targets) {
Expand Down
Loading
Loading