Compare commits

..
8 Commits
Author SHA1 Message Date
Szymon Dziedzic 52a4e9b78d v2.3.0 2022-10-10 13:32:41 +02:00
Szymon Dziedzic b3b0350556 [ENG-6571][eas-cli] use resource class flag to select M1 resource class (#1425)
* [eas-cli] use env variable to select M1 resource class

* [eas-cli] create `m1-experimental` option for `--resource-class` flag

* improvements after code review

* throw an error instead of using oclif/errors in resolveResourceClass function

* update CHANGELOG.md
2022-10-10 11:54:20 +02:00
Expo CI afd445721c update CHANGELOG.md 2022-10-05 09:25:36 +00:00
Dominik Sokal b36ac56851 v2.2.1 2022-10-05 11:14:27 +02:00
Dominik Sokal 2ff5dbe5fb actually read file when creating secret file (#1423)
* actually read file when creating secret file

* update CHANGELOG.md
2022-10-05 11:12:59 +02:00
Dominik Sokal d5fe7890cd use double quotes for app config fields 2022-10-05 09:26:03 +02:00
Quinlan JungandDominik Sokal 0c183b447c [cli] more robust platform check (#1417)
* [cli] more robust platform check

* update CHANGELOG.md

* pr feedback

* extra docs

* csv or number

* Update packages/eas-cli/src/project/ios/__tests__/target-test.ts

Co-authored-by: Dominik Sokal <[email protected]>

* update changelog, fix tsc

Co-authored-by: Dominik Sokal <[email protected]>
2022-10-05 00:11:41 +02:00
Expo CI b3c2ebb9e5 update CHANGELOG.md 2022-10-04 18:10:49 +00:00
19 changed files with 1272 additions and 118 deletions

No files matched your search

+20 -1
View File
@@ -6,6 +6,25 @@ This is the log of notable changes to EAS CLI and related packages.
### 🛠 Breaking changes
### 🎉 New features
- Add new experimental resource class for M1 Macs. ([#1425](https://github.com/expo/eas-cli/pull/1425) by [@szdziedzic](https://github.com/szdziedzic))
### 🐛 Bug fixes
### 🧹 Chores
## [2.2.1](https://github.com/expo/eas-cli/releases/tag/v2.2.1) - 2022-10-05
### 🐛 Bug fixes
- Make Apple Platform detection more robust. ([#1417](https://github.com/expo/eas-cli/pull/1417) by [@quinlanj](https://github.com/quinlanj))
- Fix creating EAS secret from file. ([#1423](https://github.com/expo/eas-cli/pull/1423) by [@dsokal](https://github.com/dsokal))
## [2.2.0](https://github.com/expo/eas-cli/releases/tag/v2.2.0) - 2022-10-04
### 🛠 Breaking changes
- Prompt before configuring EAS project. ([#1356](https://github.com/expo/eas-cli/pull/1356) by [@wschurman](https://github.com/wschurman))
- Adds paginated support to device commands. Removes the ability to delete multiple devices at once. ([#1381](https://github.com/expo/eas-cli/pull/1381) by [@kgc00](https://github.com/kgc00))
@@ -32,7 +51,7 @@ This is the log of notable changes to EAS CLI and related packages.
- Remove 'owner' app config field dependency. ([#1368](https://github.com/expo/eas-cli/pull/1368), [#1369](https://github.com/expo/eas-cli/pull/1369), [#1371](https://github.com/expo/eas-cli/pull/1371), [#1372](https://github.com/expo/eas-cli/pull/1372), [#1373](https://github.com/expo/eas-cli/pull/1373), by [@wschurman](https://github.com/wschurman))
- Add Xcode 14 image. ([#1365](https://github.com/expo/eas-cli/pull/1365) by [@szdziedzic](https://github.com/szdziedzic))
- Update max `versionCode` for Android. ([#1400](https://github.com/expo/eas-cli/pull/1400) by [@wkozyra95](https://github.com/wkozyra95))
- Add and use command context to declare command dependencies. ([#1383](https://github.com/expo/eas-cli/pull/1383), [#1384](https://github.com/expo/eas-cli/pull/1384), [#1387](https://github.com/expo/eas-cli/pull/1387), [#1388](https://github.com/expo/eas-cli/pull/1388), [#1390](https://github.com/expo/eas-cli/pull/1390), [#1391](https://github.com/expo/eas-cli/pull/1391), [#1394](https://github.com/expo/eas-cli/pull/1394), [#1402](https://github.com/expo/eas-cli/pull/1402), [#1403](https://github.com/expo/eas-cli/pull/1403), by [@wschurman](https://github.com/wschurman))
- Add and use command context to declare command dependencies. ([#1383](https://github.com/expo/eas-cli/pull/1383), [#1384](https://github.com/expo/eas-cli/pull/1384), [#1387](https://github.com/expo/eas-cli/pull/1387), [#1388](https://github.com/expo/eas-cli/pull/1388), [#1390](https://github.com/expo/eas-cli/pull/1390), [#1391](https://github.com/expo/eas-cli/pull/1391), [#1394](https://github.com/expo/eas-cli/pull/1394), [#1402](https://github.com/expo/eas-cli/pull/1402), [#1403](https://github.com/expo/eas-cli/pull/1403), by [@wschurman](https://github.com/wschurman))
- Fix typo in the ad hoc build message. ([#1407](https://github.com/expo/eas-cli/pull/1407) by [@Simek](https://github.com/Simek))
- Improve errors and error messages formatting related to **eas.json**. ([#1414](https://github.com/expo/eas-cli/pull/1414) by [@Simek](https://github.com/Simek))
- Handle errors from platform-specific kill switches to disable free tier builds. ([#1401](https://github.com/expo/eas-cli/pull/1401) by [@szdziedzic](https://github.com/szdziedzic))
+1 -1
View File
@@ -1,5 +1,5 @@
{
"npmClient": "yarn",
"useWorkspaces": true,
"version": "2.2.0"
"version": "2.3.0"
}
File diff suppressed because it is too large. Load diff
+6 -65
View File
@@ -2037,71 +2037,6 @@
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "subscribeToProduct",
"description": "Add a subscription",
"args": [
{
"name": "accountName",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "paymentSource",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "productId",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "Account",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
@@ -14758,6 +14693,12 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "IOS_M1_LARGE",
"description": "@experimental This resource class is not yet ready to be used in production. For testing purposes only.",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "LEGACY",
"description": "",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "eas-cli",
"description": "EAS command line tool",
"version": "2.2.0",
"version": "2.3.0",
"author": "Expo <[email protected]>",
"bin": {
"eas": "./bin/run"
+38 -15
View File
@@ -76,20 +76,43 @@ export interface BuildFlags {
message?: string;
}
const platformToGraphQLResourceClassMapping: Record<
Platform,
Record<UserInputResourceClass, BuildResourceClass>
const iosUserInputResourceClassToBuildResourceClassMapping: Record<
UserInputResourceClass,
BuildResourceClass
> = {
[Platform.ANDROID]: {
[UserInputResourceClass.DEFAULT]: BuildResourceClass.AndroidDefault,
[UserInputResourceClass.LARGE]: BuildResourceClass.AndroidLarge,
},
[Platform.IOS]: {
[UserInputResourceClass.DEFAULT]: BuildResourceClass.IosDefault,
[UserInputResourceClass.LARGE]: BuildResourceClass.IosLarge,
},
[UserInputResourceClass.DEFAULT]: BuildResourceClass.IosDefault,
[UserInputResourceClass.LARGE]: BuildResourceClass.IosLarge,
[UserInputResourceClass.M1_EXPERIMENTAL]: BuildResourceClass.IosM1Large,
};
const androidUserInputResourceClassToBuildResourceClassMapping: Record<
Exclude<UserInputResourceClass, UserInputResourceClass.M1_EXPERIMENTAL>,
BuildResourceClass
> = {
[UserInputResourceClass.DEFAULT]: BuildResourceClass.AndroidDefault,
[UserInputResourceClass.LARGE]: BuildResourceClass.AndroidLarge,
};
function resolveResourceClass(
platform: Platform,
resourceClassInput: UserInputResourceClass
): BuildResourceClass {
if (platform !== Platform.IOS && resourceClassInput === UserInputResourceClass.M1_EXPERIMENTAL) {
throw new Error(
`Resource class ${UserInputResourceClass.M1_EXPERIMENTAL} is only available for iOS builds`
);
}
return platform === Platform.ANDROID
? androidUserInputResourceClassToBuildResourceClassMapping[
resourceClassInput as Exclude<
UserInputResourceClass,
UserInputResourceClass.M1_EXPERIMENTAL
>
]
: iosUserInputResourceClassToBuildResourceClassMapping[resourceClassInput];
}
export async function runBuildAndSubmitAsync(
projectDir: string,
flags: BuildFlags,
@@ -137,10 +160,10 @@ export async function runBuildAndSubmitAsync(
flags,
moreBuilds: platforms.length > 1,
buildProfile,
resourceClass:
platformToGraphQLResourceClassMapping[buildProfile.platform][
flags.userInputResourceClass ?? UserInputResourceClass.DEFAULT
],
resourceClass: resolveResourceClass(
buildProfile.platform,
flags.userInputResourceClass ?? UserInputResourceClass.DEFAULT
),
easJsonCliConfig,
actor,
getDynamicProjectConfigAsync,
+5
View File
@@ -16,4 +16,9 @@ export enum BuildDistributionType {
export enum UserInputResourceClass {
DEFAULT = 'default',
LARGE = 'large',
/**
* @experimental
* This resource class is not yet ready to be used in production. For testing purposes only. Might be deprecated / deleted at any time.
*/
M1_EXPERIMENTAL = 'm1-experimental',
}
@@ -43,9 +43,9 @@ export async function saveProjectIdToAppConfigAsync(
);
Log.warn();
Log.warn(
`To complete the setup process, set the ${chalk.bold(
`To complete the setup process, set "${chalk.bold(
'extra.eas.projectId'
)} in your ${chalk.bold(getProjectConfigDescription(projectDir))}:`
)}" in your ${chalk.bold(getProjectConfigDescription(projectDir))}:`
);
Log.warn();
Log.warn(chalk.bold(JSON.stringify({ expo: { extra: { eas: { projectId } } } }, null, 2)));
@@ -147,6 +147,17 @@ export default class Build extends EasCommand {
if (flags.json && !nonInteractive) {
Errors.error('--json is allowed only when building in non-interactive mode', { exit: 1 });
}
if (
flags['resource-class'] === UserInputResourceClass.M1_EXPERIMENTAL &&
flags.platform !== Platform.IOS
) {
Errors.error(
`Resource class ${UserInputResourceClass.M1_EXPERIMENTAL} is only available for iOS builds`,
{
exit: 1,
}
);
}
const requestedPlatform =
flags.platform &&
@@ -110,7 +110,7 @@ export default class ProjectInit extends EasCommand {
Log.succeed(
`Project already linked (ID: ${chalk.bold(
existingProjectId
)}). To re-configure, remove the extra.eas.projectId field from your app config.`
)}). To re-configure, remove the "extra.eas.projectId" field from your app config.`
);
return;
}
@@ -172,6 +172,7 @@ export default class EnvironmentSecretCreate extends EasCommand {
if (!(await fs.pathExists(secretFilePath))) {
throw new Error(`File "${secretValue}" does not exist`);
}
secretValue = await fs.readFile(secretFilePath, 'base64');
}
if (scope === EnvironmentSecretScope.PROJECT) {
@@ -7,7 +7,7 @@ import {
} from '../../../graphql/generated';
import Log from '../../../log';
import { ora } from '../../../ora';
import { getApplePlatformFromSdkRoot } from '../../../project/ios/target';
import { getApplePlatformFromTarget } from '../../../project/ios/target';
import { CredentialsContext } from '../../context';
import { MissingCredentialsNonInteractiveError } from '../../errors';
import { AppleProvisioningProfileMutationResult } from '../api/graphql/mutations/AppleProvisioningProfileMutation';
@@ -46,7 +46,7 @@ export class ConfigureProvisioningProfile {
return null;
}
const applePlatform = await getApplePlatformFromSdkRoot(this.target);
const applePlatform = await getApplePlatformFromTarget(this.target);
const profilesFromApple = await ctx.appStore.listProvisioningProfilesAsync(
this.app.bundleIdentifier,
applePlatform
@@ -1,6 +1,6 @@
import chalk from 'chalk';
import { getApplePlatformFromSdkRoot } from '../../../project/ios/target';
import { getApplePlatformFromTarget } from '../../../project/ios/target';
import { CredentialsContext } from '../../context';
import {
DistributionCertificate,
@@ -29,7 +29,7 @@ export async function generateProvisioningProfileAsync(
const appleAuthCtx = await ctx.appStore.ensureAuthenticatedAsync();
const type = appleAuthCtx.team.inHouse ? 'Enterprise ' : 'AppStore';
const profileName = `*[expo] ${bundleIdentifier} ${type} ${new Date().toISOString()}`; // Apple drops [ if its the first char (!!)
const applePlatform = await getApplePlatformFromSdkRoot(target);
const applePlatform = await getApplePlatformFromTarget(target);
return await ctx.appStore.createProvisioningProfileAsync(
bundleIdentifier,
distCert,
@@ -13,7 +13,7 @@ import {
IosDistributionType,
} from '../../../graphql/generated';
import Log from '../../../log';
import { getApplePlatformFromSdkRoot } from '../../../project/ios/target';
import { getApplePlatformFromTarget } from '../../../project/ios/target';
import { confirmAsync, pressAnyKeyToContinueAsync, promptAsync } from '../../../prompts';
import differenceBy from '../../../utils/expodash/differenceBy';
import { CredentialsContext } from '../../context';
@@ -121,7 +121,7 @@ export class SetUpAdhocProvisioningProfile {
);
// 4. Reuse or create the profile on Apple Developer Portal
const applePlatform = await getApplePlatformFromSdkRoot(target);
const applePlatform = await getApplePlatformFromTarget(target);
const profileType =
applePlatform === ApplePlatform.TV_OS
? ProfileType.TVOS_APP_ADHOC
@@ -6,7 +6,7 @@ import {
IosAppBuildCredentialsFragment,
IosDistributionType,
} from '../../../graphql/generated';
import { getApplePlatformFromSdkRoot } from '../../../project/ios/target';
import { getApplePlatformFromTarget } from '../../../project/ios/target';
import { confirmAsync } from '../../../prompts';
import { CredentialsContext } from '../../context';
import { MissingCredentialsNonInteractiveError } from '../../errors';
@@ -114,7 +114,7 @@ export class SetUpProvisioningProfile {
}
// See if the profile we have exists on the Apple Servers
const applePlatform = await getApplePlatformFromSdkRoot(this.target);
const applePlatform = await getApplePlatformFromTarget(this.target);
const existingProfiles = await ctx.appStore.listProvisioningProfilesAsync(
this.app.bundleIdentifier,
applePlatform
@@ -6,7 +6,7 @@ import nullthrows from 'nullthrows';
import { IosAppBuildCredentialsFragment, IosDistributionType } from '../../../graphql/generated';
import Log from '../../../log';
import { getApplePlatformFromSdkRoot } from '../../../project/ios/target';
import { getApplePlatformFromTarget } from '../../../project/ios/target';
import { CredentialsContext } from '../../context';
import { AppLookupParams } from '../api/graphql/types/AppLookupParams';
import { ProfileClass } from '../appstore/provisioningProfile';
@@ -94,7 +94,7 @@ async function validateProvisioningProfileWithAppleAsync(
assert(buildCredentials.provisioningProfile, 'Provisioning Profile must be defined');
const { developerPortalIdentifier, provisioningProfile } = buildCredentials.provisioningProfile;
const applePlatform = await getApplePlatformFromSdkRoot(target);
const applePlatform = await getApplePlatformFromTarget(target);
const profilesFromApple = await ctx.appStore.listProvisioningProfilesAsync(
app.bundleIdentifier,
applePlatform,
+2 -9
View File
@@ -297,8 +297,6 @@ export type AccountMutation = {
setPaymentSource: Account;
/** Require authorization to send push notifications for experiences owned by this account */
setPushSecurityEnabled: Account;
/** Add a subscription */
subscribeToProduct: Account;
};
@@ -372,13 +370,6 @@ export type AccountMutationSetPushSecurityEnabledArgs = {
pushSecurityEnabled: Scalars['Boolean'];
};
export type AccountMutationSubscribeToProductArgs = {
accountName: Scalars['ID'];
paymentSource: Scalars['ID'];
productId: Scalars['ID'];
};
export type AccountQuery = {
__typename?: 'AccountQuery';
/** Query an Account by ID */
@@ -2124,6 +2115,8 @@ export enum BuildResourceClass {
AndroidLarge = 'ANDROID_LARGE',
IosDefault = 'IOS_DEFAULT',
IosLarge = 'IOS_LARGE',
/** @experimental This resource class is not yet ready to be used in production. For testing purposes only. */
IosM1Large = 'IOS_M1_LARGE',
Legacy = 'LEGACY'
}
@@ -1,8 +1,9 @@
import { testTarget } from '../../../credentials/__tests__/fixtures-ios';
import { ApplePlatform } from '../../../credentials/ios/appstore/constants';
import { getApplePlatformFromSdkRoot } from '../target';
import { Target } from '../../../credentials/ios/types';
import { getApplePlatformFromDeviceFamily, getApplePlatformFromSdkRoot } from '../target';
function getApplePlatform(sdkRoot: string): ApplePlatform {
function getApplePlatformWithSdkRoot(sdkRoot: string): ApplePlatform | null {
const target = {
...testTarget,
buildSettings: {
@@ -12,6 +13,18 @@ function getApplePlatform(sdkRoot: string): ApplePlatform {
return getApplePlatformFromSdkRoot(target);
}
function getApplePlatformWithDeviceFamily(
deviceFamily: string | number | undefined
): ApplePlatform | null {
const target: Target = {
...testTarget,
buildSettings: {
TARGETED_DEVICE_FAMILY: deviceFamily,
},
};
return getApplePlatformFromDeviceFamily(target);
}
describe(getApplePlatformFromSdkRoot, () => {
// Update `getApplePlatformFromSdkRoot` to be compatible with new Apple Platforms
test('all enumerations work with the function', () => {
@@ -21,13 +34,25 @@ describe(getApplePlatformFromSdkRoot, () => {
});
test('existing SDKs work with the function', () => {
// sdks from `xcodebuild -showsdks`
expect(getApplePlatform('iphoneos14.4')).toBe(ApplePlatform.IOS);
expect(getApplePlatform('iphonesimulator14.4')).toBe(ApplePlatform.IOS);
expect(getApplePlatform('driverkit.macosx20.2 ')).toBe(ApplePlatform.MAC_OS);
expect(getApplePlatform('macosx11.1')).toBe(ApplePlatform.MAC_OS);
expect(getApplePlatform('appletvos14.3')).toBe(ApplePlatform.TV_OS);
expect(getApplePlatform('appletvsimulator14.3')).toBe(ApplePlatform.IOS);
expect(getApplePlatform('watchos7.2')).toBe(ApplePlatform.IOS);
expect(getApplePlatform('watchsimulator7.2')).toBe(ApplePlatform.IOS);
expect(getApplePlatformWithSdkRoot('iphoneos14.4')).toBe(ApplePlatform.IOS);
expect(getApplePlatformWithSdkRoot('iphonesimulator14.4')).toBe(null);
expect(getApplePlatformWithSdkRoot('driverkit.macosx20.2 ')).toBe(ApplePlatform.MAC_OS);
expect(getApplePlatformWithSdkRoot('macosx11.1')).toBe(ApplePlatform.MAC_OS);
expect(getApplePlatformWithSdkRoot('appletvos14.3')).toBe(ApplePlatform.TV_OS);
expect(getApplePlatformWithSdkRoot('appletvsimulator14.3')).toBe(null);
expect(getApplePlatformWithSdkRoot('watchos7.2')).toBe(null);
expect(getApplePlatformWithSdkRoot('watchsimulator7.2')).toBe(null);
});
});
describe(getApplePlatformFromDeviceFamily, () => {
test('apple platform can be obtained from device family types', () => {
expect(getApplePlatformWithDeviceFamily('1,2')).toBe(ApplePlatform.IOS);
expect(getApplePlatformWithDeviceFamily('1')).toBe(ApplePlatform.IOS);
expect(getApplePlatformWithDeviceFamily('3')).toBe(ApplePlatform.TV_OS);
expect(getApplePlatformWithDeviceFamily(1)).toBe(ApplePlatform.IOS);
expect(getApplePlatformWithDeviceFamily(3)).toBe(ApplePlatform.TV_OS);
expect(getApplePlatformWithDeviceFamily(undefined)).toBe(null);
expect(getApplePlatformWithDeviceFamily('ilovecats')).toBe(null);
});
});
+52 -3
View File
@@ -229,13 +229,25 @@ function resolveBareProjectBuildSettings(
}
/**
* Get Apple Platform from the Xcode SDKROOT where possible.
* Get Apple Platform from the Xcode Target where possible.
* @returns - Apple Platform when known, defaults to IOS when unknown
*/
export function getApplePlatformFromSdkRoot(target: Target): ApplePlatform {
export function getApplePlatformFromTarget(target: Target): ApplePlatform {
return (
getApplePlatformFromSdkRoot(target) ??
getApplePlatformFromDeviceFamily(target) ??
ApplePlatform.IOS
);
}
/**
* Get Apple Platform from the Xcode SDKROOT where possible.
* @returns - Apple Platform when known, defaults to null when unknown
*/
export function getApplePlatformFromSdkRoot(target: Target): ApplePlatform | null {
const sdkRoot = target.buildSettings?.SDKROOT;
if (!sdkRoot) {
return ApplePlatform.IOS;
return null;
}
if (sdkRoot.includes('iphoneos')) {
return ApplePlatform.IOS;
@@ -244,6 +256,43 @@ export function getApplePlatformFromSdkRoot(target: Target): ApplePlatform {
} else if (sdkRoot.includes('macosx')) {
return ApplePlatform.MAC_OS;
} else {
return null;
}
}
/**
* Get Apple Platform from the Xcode TARGETED_DEVICE_FAMILY where possible.
*
* References:
* https://developer.apple.com/library/archive/documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html
* https://stackoverflow.com/questions/39677524/xcode-8-how-to-change-targeted-device-family#comment100316573_39677659
*
* @returns - Apple Platform when known, defaults to null when unknown
*/
export function getApplePlatformFromDeviceFamily(target: Target): ApplePlatform | null {
const deviceFamily = target.buildSettings?.TARGETED_DEVICE_FAMILY;
if (!deviceFamily) {
return null;
}
if (typeof deviceFamily === 'string') {
const devices = deviceFamily.split(',');
const arbitraryDevice = devices[0];
const deviceFamilyNumber = Number(arbitraryDevice);
return deviceFamilyToPlatform(deviceFamilyNumber);
} else if (typeof deviceFamily === 'number') {
return deviceFamilyToPlatform(deviceFamily);
}
throw new Error(
`Unexpected device family type in XCode build settings: ${JSON.stringify(deviceFamily)}`
);
}
function deviceFamilyToPlatform(deviceFamily: number): ApplePlatform | null {
if (deviceFamily === 1 || deviceFamily === 2) {
return ApplePlatform.IOS;
} else if (deviceFamily === 3) {
return ApplePlatform.TV_OS;
} else {
return null;
}
}