Compare commits

...
12 Commits
Author SHA1 Message Date
Wojciech Kozyra 977546c8c9 v0.19.0 2021-07-01 12:05:57 +02:00
Brent Vatne 53dcd4cb43 [eas-cli] Support configuring one platform at a time when running eas build (#483) 2021-06-30 17:52:37 -07:00
Wojciech Kozyra 9e18e738eb [eas-cli] use new build mutation (#485) 2021-06-29 11:54:11 +02:00
Dominik Sokal 252c7187d5 [ENG-1377] auto-suggest application id and bundle identifier (#487)
* Auto-suggest application id and bundle identifier

* update CHANGELOG

* address PR feedback
2021-06-29 10:51:48 +02:00
Quinlan Jung 90852b9557 update changelog 2021-06-28 16:01:48 -07:00
Quinlan Jung 0df16236a2 v0.18.3 2021-06-28 14:54:56 -07:00
Quinlan Jung ecaf5a4318 changelog stuff 2021-06-28 14:44:00 -07:00
Quinlan Jung 86e5e1a7b1 [eas-cli] integrate push key setup in ios builds (#473)
* [eas-cli] integrate push key setup in build flow

* nits

* fix lint

* pr feedback

* pr feedback
2021-06-28 14:43:15 -07:00
Quinlan Jung ab10094071 [eas-cli] remove nullthrows on keystore keyPassword (#484)
* [eas-cli] remove nullthrows on keystore keyPassword

* changelog
2021-06-28 10:34:45 -07:00
Dominik Sokal 2d536d73fe mock fs-extra so tests don't produce files (#480) 2021-06-28 09:43:43 +02:00
Evan Bacon 80ea8ee50b Support bundle identifiers that start with a dot (#459) 2021-06-25 15:41:48 -07:00
Brent Vatne b49c5f47d1 Update CHANGELOG 2021-06-25 15:16:06 -07:00
29 changed files with 836 additions and 295 deletions

No files matched your search

+24 -2
View File
@@ -8,14 +8,36 @@ This is the log of notable changes to EAS CLI and related packages.
### 🎉 New features
- Auto-suggest application id and bundle identifier when running `eas build:configure` for a managed project. ([#487](https://github.com/expo/eas-cli/pull/487) by [@dsokal](https://github.com/dsokal))
- Support configuring one platform at a time when running `eas build`. ([#483](https://github.com/expo/eas-cli/pull/483) by [@brentvatne](https://github.com/brentvatne))
### 🐛 Bug fixes
### 🧹 Chores
## [0.18.3](https://github.com/expo/eas-cli/releases/tag/v0.18.3) - 2021-06-28
### 🎉 New features
- Support bundle identifiers that begin with `.`. ([#459](https://github.com/expo/eas-cli/pull/459) by [@EvanBacon](https://github.com/EvanBacon))
- Push Key setup integrated with ios build command ([#473](https://github.com/expo/eas-cli/pull/473) by [@quinlanj](https://github.com/quinlanj))
### 🐛 Bug fixes
- Fix android builds for PKCS12 keystores. ([#484](https://github.com/expo/eas-cli/pull/484) by [@quinlanj](https://github.com/quinlanj))
## [0.18.2](https://github.com/expo/eas-cli/releases/tag/v0.18.2) - 2021-06-25
### 🎉 New features
- Change default iOS image for projects with Expo SDK <= 41 (SDK 41 won't build with Xcode 12.5). ([#479](https://github.com/expo/eas-cli/pull/479) by [@dsokal](https://github.com/dsokal))
- Make Apple team optional in appropriate cases. ([#468](https://github.com/expo/eas-cli/pull/468) by [@quinlanj](https://github.com/quinlanj))
- Show projects that depend on a push key. ([#472](https://github.com/expo/eas-cli/pull/472) by [@quinlanj](https://github.com/quinlanj))
### 🐛 Bug fixes
- Fix inverted conditional so we actually only prompt about commit when index is dirty. ([#481](https://github.com/expo/eas-cli/pull/481) by [@brentvatne](https://github.com/brentvatne))
### 🧹 Chores
## [0.18.1](https://github.com/expo/eas-cli/releases/tag/v0.18.1) - 2021-06-24
### 🎉 New features
+1 -1
View File
@@ -1,5 +1,5 @@
{
"npmClient": "yarn",
"useWorkspaces": true,
"version": "0.18.2"
"version": "0.19.0"
}
+24 -23
View File
@@ -69,7 +69,7 @@ ALIASES
$ eas login
```
_See code: [src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/account/login.ts)_
_See code: [src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/account/login.ts)_
## `eas account:logout`
@@ -83,7 +83,7 @@ ALIASES
$ eas logout
```
_See code: [src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/account/logout.ts)_
_See code: [src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/account/logout.ts)_
## `eas account:view`
@@ -97,7 +97,7 @@ ALIASES
$ eas whoami
```
_See code: [src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/account/view.ts)_
_See code: [src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/account/view.ts)_
## `eas analytics [STATUS]`
@@ -108,7 +108,7 @@ USAGE
$ eas analytics [STATUS]
```
_See code: [src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/analytics.ts)_
_See code: [src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/analytics.ts)_
## `eas build`
@@ -128,7 +128,7 @@ OPTIONS
--[no-]wait Wait for build(s) to complete
```
_See code: [src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/build/index.ts)_
_See code: [src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/build/index.ts)_
## `eas build:cancel [BUILD_ID]`
@@ -139,7 +139,7 @@ USAGE
$ eas build:cancel [BUILD_ID]
```
_See code: [src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/build/cancel.ts)_
_See code: [src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/build/cancel.ts)_
## `eas build:configure`
@@ -153,7 +153,7 @@ OPTIONS
-p, --platform=(android|ios|all) Platform to configure
```
_See code: [src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/build/configure.ts)_
_See code: [src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/build/configure.ts)_
## `eas build:list`
@@ -169,7 +169,7 @@ OPTIONS
--status=(new|in-queue|in-progress|errored|finished|canceled)
```
_See code: [src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/build/list.ts)_
_See code: [src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/build/list.ts)_
## `eas build:view [BUILD_ID]`
@@ -180,7 +180,7 @@ USAGE
$ eas build:view [BUILD_ID]
```
_See code: [src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/build/view.ts)_
_See code: [src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/build/view.ts)_
## `eas credentials`
@@ -191,7 +191,7 @@ USAGE
$ eas credentials
```
_See code: [src/commands/credentials.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/credentials.ts)_
_See code: [src/commands/credentials.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/credentials.ts)_
## `eas device:create`
@@ -202,7 +202,7 @@ USAGE
$ eas device:create
```
_See code: [src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/device/create.ts)_
_See code: [src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/device/create.ts)_
## `eas device:list`
@@ -216,7 +216,7 @@ OPTIONS
--apple-team-id=apple-team-id
```
_See code: [src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/device/list.ts)_
_See code: [src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/device/list.ts)_
## `eas device:view [UDID]`
@@ -227,7 +227,7 @@ USAGE
$ eas device:view [UDID]
```
_See code: [src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/device/view.ts)_
_See code: [src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/device/view.ts)_
## `eas help [COMMAND]`
@@ -260,7 +260,7 @@ OPTIONS
--value=value Value of the secret
```
_See code: [src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/secret/create.ts)_
_See code: [src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/secret/create.ts)_
## `eas secret:delete`
@@ -277,7 +277,7 @@ DESCRIPTION
Unsure where to find the secret's ID? Run eas secrets:list
```
_See code: [src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/secret/delete.ts)_
_See code: [src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/secret/delete.ts)_
## `eas secret:list`
@@ -288,7 +288,7 @@ USAGE
$ eas secret:list
```
_See code: [src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/secret/list.ts)_
_See code: [src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/secret/list.ts)_
## `eas submit --platform=(android|ios)`
@@ -314,7 +314,8 @@ OPTIONS
iOS specific options=asc-app-id App Store Connect unique application Apple ID
number. Providing this param results in skipping
app creation step. Learn more.
app creation step. Learn more:
https://expo.fyi/asc-app-id
iOS specific options=bundle-identifier Your iOS Bundle Identifier (default:
expo.ios.bundleIdentifier from app config)
@@ -367,7 +368,7 @@ EXAMPLES
and provide its App ID
```
_See code: [src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/submit.ts)_
_See code: [src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/submit.ts)_
## `eas webhook:create`
@@ -386,7 +387,7 @@ OPTIONS
--url=url Webhook URL
```
_See code: [src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/webhook/create.ts)_
_See code: [src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/webhook/create.ts)_
## `eas webhook:delete [ID]`
@@ -400,7 +401,7 @@ ARGUMENTS
ID ID of the webhook to delete
```
_See code: [src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/webhook/delete.ts)_
_See code: [src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/webhook/delete.ts)_
## `eas webhook:list`
@@ -414,7 +415,7 @@ OPTIONS
--event=(BUILD) Event type that triggers the webhook
```
_See code: [src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/webhook/list.ts)_
_See code: [src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/webhook/list.ts)_
## `eas webhook:update`
@@ -434,7 +435,7 @@ OPTIONS
--url=url Webhook URL
```
_See code: [src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/webhook/update.ts)_
_See code: [src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/webhook/update.ts)_
## `eas webhook:view ID`
@@ -448,5 +449,5 @@ ARGUMENTS
ID ID of the webhook to view
```
_See code: [src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v0.18.2/packages/eas-cli/src/commands/webhook/view.ts)_
_See code: [src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v0.19.0/packages/eas-cli/src/commands/webhook/view.ts)_
<!-- commandsstop -->
+470 -2
View File
@@ -15455,8 +15455,8 @@
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
"isDeprecated": true,
"deprecationReason": "Use createAndroidBuild instead"
},
{
"name": "createAndroidManagedBuild",
@@ -15510,6 +15510,61 @@
"ofType": null
}
},
"isDeprecated": true,
"deprecationReason": "Use createAndroidBuild instead"
},
{
"name": "createAndroidBuild",
"description": "Create an Android build",
"args": [
{
"name": "appId",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "job",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "AndroidJobInput",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "metadata",
"description": null,
"type": {
"kind": "INPUT_OBJECT",
"name": "BuildMetadataInput",
"ofType": null
},
"defaultValue": null
}
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "CreateBuildResult",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
@@ -15622,6 +15677,61 @@
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "createIosBuild",
"description": "Create an iOS build",
"args": [
{
"name": "appId",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "job",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "IosJobInput",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "metadata",
"description": null,
"type": {
"kind": "INPUT_OBJECT",
"name": "BuildMetadataInput",
"ofType": null
},
"defaultValue": null
}
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "CreateBuildResult",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
@@ -16532,6 +16642,178 @@
],
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "AndroidJobInput",
"description": "",
"fields": null,
"inputFields": [
{
"name": "type",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "ENUM",
"name": "BuildWorkflow",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "projectArchive",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "ProjectArchiveSourceInput",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "projectRootDirectory",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "releaseChannel",
"description": "",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "updates",
"description": "",
"type": {
"kind": "INPUT_OBJECT",
"name": "BuildUpdatesInput",
"ofType": null
},
"defaultValue": null
},
{
"name": "secrets",
"description": "",
"type": {
"kind": "INPUT_OBJECT",
"name": "AndroidJobSecretsInput",
"ofType": null
},
"defaultValue": null
},
{
"name": "builderEnvironment",
"description": "",
"type": {
"kind": "INPUT_OBJECT",
"name": "AndroidBuilderEnvironmentInput",
"ofType": null
},
"defaultValue": null
},
{
"name": "cache",
"description": "",
"type": {
"kind": "INPUT_OBJECT",
"name": "BuildCacheInput",
"ofType": null
},
"defaultValue": null
},
{
"name": "gradleCommand",
"description": "",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "artifactPath",
"description": "",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "buildType",
"description": "",
"type": {
"kind": "ENUM",
"name": "AndroidBuildType",
"ofType": null
},
"defaultValue": null
},
{
"name": "username",
"description": "",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "ENUM",
"name": "AndroidBuildType",
"description": "",
"fields": null,
"inputFields": null,
"interfaces": null,
"enumValues": [
{
"name": "APK",
"description": "",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "APP_BUNDLE",
"description": "",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "DEVELOPMENT_CLIENT",
"description": "",
"isDeprecated": false,
"deprecationReason": null
}
],
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "IosGenericJobInput",
@@ -17058,6 +17340,192 @@
],
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "IosJobInput",
"description": "",
"fields": null,
"inputFields": [
{
"name": "type",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "ENUM",
"name": "BuildWorkflow",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "projectArchive",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "ProjectArchiveSourceInput",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "projectRootDirectory",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "releaseChannel",
"description": "",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "updates",
"description": "",
"type": {
"kind": "INPUT_OBJECT",
"name": "BuildUpdatesInput",
"ofType": null
},
"defaultValue": null
},
{
"name": "distribution",
"description": "",
"type": {
"kind": "ENUM",
"name": "DistributionType",
"ofType": null
},
"defaultValue": null
},
{
"name": "secrets",
"description": "",
"type": {
"kind": "INPUT_OBJECT",
"name": "IosJobSecretsInput",
"ofType": null
},
"defaultValue": null
},
{
"name": "builderEnvironment",
"description": "",
"type": {
"kind": "INPUT_OBJECT",
"name": "IosBuilderEnvironmentInput",
"ofType": null
},
"defaultValue": null
},
{
"name": "cache",
"description": "",
"type": {
"kind": "INPUT_OBJECT",
"name": "BuildCacheInput",
"ofType": null
},
"defaultValue": null
},
{
"name": "scheme",
"description": "",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "buildConfiguration",
"description": "",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "artifactPath",
"description": "",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "buildType",
"description": "",
"type": {
"kind": "ENUM",
"name": "IosBuildType",
"ofType": null
},
"defaultValue": null
},
{
"name": "username",
"description": "",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "ENUM",
"name": "IosBuildType",
"description": "",
"fields": null,
"inputFields": null,
"interfaces": null,
"enumValues": [
{
"name": "RELEASE",
"description": "",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "DEVELOPMENT_CLIENT",
"description": "",
"isDeprecated": false,
"deprecationReason": null
}
],
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "IosAppBuildCredentialsMutation",
+3 -3
View File
@@ -1,7 +1,7 @@
{
"name": "eas-cli",
"description": "EAS command line tool",
"version": "0.18.2",
"version": "0.19.0",
"author": "Expo <[email protected]>",
"bin": {
"eas": "./bin/run"
@@ -13,8 +13,8 @@
"@expo/apple-utils": "0.0.0-alpha.20",
"@expo/config": "3.3.42",
"@expo/config-plugins": "2.0.2",
"@expo/eas-build-job": "0.2.37",
"@expo/eas-json": "^0.18.2",
"@expo/eas-build-job": "0.2.41",
"@expo/eas-json": "^0.19.0",
"@expo/json-file": "8.2.25",
"@expo/pkcs12": "0.0.4",
"@expo/plist": "0.0.11",
+7 -16
View File
@@ -23,7 +23,7 @@ import { transformMetadata } from '../graphql';
import { Platform } from '../types';
import { logCredentialsSource } from '../utils/credentials';
import { validateAndSyncProjectConfigurationAsync } from './configure';
import { transformGenericJob, transformManagedJob } from './graphql';
import { transformJob } from './graphql';
import { prepareJobAsync } from './prepareJob';
export async function prepareAndroidBuildAsync(
@@ -87,21 +87,12 @@ This means that it will most likely produce an AAB and you will not be able to i
metadata: Metadata
): Promise<BuildResult> => {
const graphqlMetadata = transformMetadata(metadata);
if (job.type === Workflow.GENERIC) {
const graphqlJob = transformGenericJob(job);
return await BuildMutation.createAndroidGenericBuildAsync({
appId,
job: graphqlJob,
metadata: graphqlMetadata,
});
} else {
const graphqlJob = transformManagedJob(job);
return await BuildMutation.createAndroidManagedBuildAsync({
appId,
job: graphqlJob,
metadata: graphqlMetadata,
});
}
const graphqlJob = transformJob(job);
return await BuildMutation.createAndroidBuildAsync({
appId,
job: graphqlJob,
metadata: graphqlMetadata,
});
},
});
}
+11 -26
View File
@@ -1,14 +1,11 @@
import { Android } from '@expo/eas-build-job';
import {
AndroidGenericJobInput,
AndroidManagedBuildType,
AndroidManagedJobInput,
} from '../../graphql/generated';
import { transformProjectArchive } from '../graphql';
import { AndroidBuildType, AndroidJobInput } from '../../graphql/generated';
import { transformProjectArchive, transformWorkflow } from '../graphql';
export function transformGenericJob(job: Android.GenericJob): AndroidGenericJobInput {
export function transformJob(job: Android.Job): AndroidJobInput {
return {
type: transformWorkflow(job.type),
projectArchive: transformProjectArchive(job.projectArchive),
projectRootDirectory: job.projectRootDirectory,
releaseChannel: job.releaseChannel,
@@ -18,29 +15,17 @@ export function transformGenericJob(job: Android.GenericJob): AndroidGenericJobI
cache: job.cache,
gradleCommand: job.gradleCommand,
artifactPath: job.artifactPath,
};
}
export function transformManagedJob(job: Android.ManagedJob): AndroidManagedJobInput {
return {
projectArchive: transformProjectArchive(job.projectArchive),
projectRootDirectory: job.projectRootDirectory,
releaseChannel: job.releaseChannel,
updates: job.updates,
secrets: job.secrets,
builderEnvironment: job.builderEnvironment,
cache: job.cache,
username: job.username,
buildType: transformBuildType(job.buildType),
buildType: job.buildType && transformBuildType(job.buildType),
};
}
function transformBuildType(buildType: Android.ManagedBuildType): AndroidManagedBuildType {
if (buildType === Android.ManagedBuildType.APK) {
return AndroidManagedBuildType.Apk;
} else if (buildType === Android.ManagedBuildType.APP_BUNDLE) {
return AndroidManagedBuildType.AppBundle;
function transformBuildType(buildType: Android.BuildType): AndroidBuildType {
if (buildType === Android.BuildType.APK) {
return AndroidBuildType.Apk;
} else if (buildType === Android.BuildType.APP_BUNDLE) {
return AndroidBuildType.AppBundle;
} else {
return AndroidManagedBuildType.DevelopmentClient;
return AndroidBuildType.DevelopmentClient;
}
}
@@ -84,7 +84,7 @@ async function prepareGenericJobAsync(
ctx: BuildContext<Platform.ANDROID>,
jobData: JobData,
buildProfile: AndroidGenericBuildProfile
): Promise<Partial<Android.GenericJob>> {
): Promise<Partial<Android.Job>> {
const projectRootDirectory =
path.relative(await vcs.getRootPathAsync(), ctx.commandCtx.projectDir) || '.';
return {
@@ -102,7 +102,7 @@ async function prepareManagedJobAsync(
ctx: BuildContext<Platform.ANDROID>,
jobData: JobData,
buildProfile: AndroidManagedBuildProfile
): Promise<Partial<Android.ManagedJob>> {
): Promise<Partial<Android.Job>> {
const projectRootDirectory =
path.relative(await vcs.getRootPathAsync(), ctx.commandCtx.projectDir) || '.';
const username = getUsername(ctx.commandCtx.exp, await ensureLoggedInAsync());
+1 -1
View File
@@ -121,7 +121,7 @@ export async function ensureEasJsonExistsAsync(ctx: ConfigureContext): Promise<v
const easJson = {
builds: {
...existingEasJson,
...existingEasJson?.builds,
...(shouldInitAndroid
? {
android: ctx.hasAndroidNativeProject ? ANDROID_GENERIC_DEFAULTS : MANAGED_DEFAULTS,
+1 -1
View File
@@ -55,7 +55,7 @@ function transformDistribution(distribution: Metadata['distribution']): Distribu
}
}
function transformWorkflow(workflow: Metadata['workflow']): BuildWorkflow {
export function transformWorkflow(workflow: Workflow): BuildWorkflow {
if (workflow === Workflow.GENERIC) {
return BuildWorkflow.Generic;
} else {
+7 -16
View File
@@ -15,7 +15,7 @@ import { transformMetadata } from '../graphql';
import { Platform } from '../types';
import { validateAndSyncProjectConfigurationAsync } from './configure';
import { ensureIosCredentialsAsync } from './credentials';
import { transformGenericJob, transformManagedJob } from './graphql';
import { transformJob } from './graphql';
import { prepareJobAsync } from './prepareJob';
export async function prepareIosBuildAsync(
@@ -87,21 +87,12 @@ export async function prepareIosBuildAsync(
metadata: Metadata
): Promise<BuildResult> => {
const graphqlMetadata = transformMetadata(metadata);
if (job.type === Workflow.GENERIC) {
const graphqlJob = transformGenericJob(job);
return await BuildMutation.createIosGenericBuildAsync({
appId,
job: graphqlJob,
metadata: graphqlMetadata,
});
} else {
const graphqlJob = transformManagedJob(job);
return await BuildMutation.createIosManagedBuildAsync({
appId,
job: graphqlJob,
metadata: graphqlMetadata,
});
}
const graphqlJob = transformJob(job);
return await BuildMutation.createIosBuildAsync({
appId,
job: graphqlJob,
metadata: graphqlMetadata,
});
},
});
}
+10 -21
View File
@@ -3,15 +3,15 @@ import nullthrows from 'nullthrows';
import {
DistributionType,
IosGenericJobInput,
IosBuildType,
IosJobInput,
IosJobSecretsInput,
IosManagedBuildType,
IosManagedJobInput,
} from '../../graphql/generated';
import { transformProjectArchive } from '../graphql';
import { transformProjectArchive, transformWorkflow } from '../graphql';
export function transformGenericJob(job: Ios.GenericJob): IosGenericJobInput {
export function transformJob(job: Ios.Job): IosJobInput {
return {
type: transformWorkflow(job.type),
projectArchive: transformProjectArchive(job.projectArchive),
projectRootDirectory: job.projectRootDirectory,
releaseChannel: job.releaseChannel,
@@ -20,22 +20,11 @@ export function transformGenericJob(job: Ios.GenericJob): IosGenericJobInput {
secrets: transformIosSecrets(job.secrets),
builderEnvironment: job.builderEnvironment,
cache: job.cache,
scheme: job.scheme,
buildConfiguration: job.buildConfiguration,
artifactPath: job.artifactPath,
};
}
export function transformManagedJob(job: Ios.ManagedJob): IosManagedJobInput {
return {
projectArchive: transformProjectArchive(job.projectArchive),
projectRootDirectory: job.projectRootDirectory,
releaseChannel: job.releaseChannel,
updates: job.updates,
distribution: job.distribution && transformDistributionType(job.distribution),
secrets: transformIosSecrets(job.secrets),
builderEnvironment: job.builderEnvironment,
cache: job.cache,
buildType: job.buildType && transformBuildType(job.buildType),
username: job.username,
};
@@ -73,10 +62,10 @@ function transformIosSecrets(secrets: {
};
}
function transformBuildType(buildType: Ios.ManagedBuildType): IosManagedBuildType {
if (buildType === Ios.ManagedBuildType.DEVELOPMENT_CLIENT) {
return IosManagedBuildType.DevelopmentClient;
function transformBuildType(buildType: Ios.BuildType): IosBuildType {
if (buildType === Ios.BuildType.DEVELOPMENT_CLIENT) {
return IosBuildType.DevelopmentClient;
} else {
return IosManagedBuildType.Release;
return IosBuildType.Release;
}
}
+2 -2
View File
@@ -104,7 +104,7 @@ async function prepareGenericJobAsync(
ctx: BuildContext<Platform.IOS>,
jobData: JobData,
buildProfile: IosGenericBuildProfile
): Promise<Partial<Ios.GenericJob>> {
): Promise<Partial<Ios.Job>> {
const projectRootDirectory =
path.relative(await vcs.getRootPathAsync(), ctx.commandCtx.projectDir) || '.';
return {
@@ -126,7 +126,7 @@ async function prepareManagedJobAsync(
ctx: BuildContext<Platform.IOS>,
jobData: JobData,
buildProfile: IosManagedBuildProfile
): Promise<Partial<Ios.ManagedJob>> {
): Promise<Partial<Ios.Job>> {
const projectRootDirectory =
path.relative(await vcs.getRootPathAsync(), ctx.commandCtx.projectDir) || '.';
const username = getUsername(ctx.commandCtx.exp, await ensureLoggedInAsync());
-3
View File
@@ -37,9 +37,6 @@ export async function collectMetadata<T extends Platform>(
): Promise<Metadata> {
const channelOrReleaseChannel = await resolveChannelOrReleaseChannelAsync(ctx);
return {
// TODO: type error fixed in https://github.com/expo/eas-build/pull/34
// remove @ts-expect-error after upgrading @expo/eas-build-job
// @ts-expect-error error TS2322: not assignable to type 'Record<string, string | number>'
trackingContext: ctx.trackingCtx,
appVersion: await resolveAppVersionAsync(ctx),
appBuildVersion: await resolveAppBuildVersionAsync(ctx),
+48 -7
View File
@@ -1,4 +1,5 @@
import { ExpoConfig, getConfig } from '@expo/config';
import { EasJsonReader } from '@expo/eas-json';
import { flags } from '@oclif/command';
import chalk from 'chalk';
import fs from 'fs-extra';
@@ -87,7 +88,7 @@ export default class Build extends EasCommand {
return;
}
exp = (await ensureProjectConfiguredAsync(projectDir)) ?? exp;
exp = (await ensureProjectConfiguredAsync(projectDir, platform)) ?? exp;
const commandCtx = await createCommandContextAsync({
requestedPlatform: platform,
@@ -101,6 +102,7 @@ export default class Build extends EasCommand {
skipProjectConfiguration: flags['skip-project-configuration'],
waitForBuildEnd: flags.wait,
});
await buildAsync(commandCtx);
}
}
@@ -140,17 +142,29 @@ async function promptForPlatformAsync(): Promise<RequestedPlatform> {
return platform;
}
async function ensureProjectConfiguredAsync(projectDir: string): Promise<ExpoConfig | null> {
if (await fs.pathExists(path.join(projectDir, 'eas.json'))) {
async function ensureProjectConfiguredAsync(
projectDir: string,
platform: RequestedPlatform
): Promise<ExpoConfig | null> {
const platformsToConfigure = await getPlatformsToConfigureAsync(projectDir, platform);
if (!platformsToConfigure) {
return null;
}
const confirm = await confirmAsync({
message: 'This app is not set up for building with EAS. Set it up now?',
});
// Ensure the prompt is consistent with the platforms we need to configure
let message = 'This project is not configured to build with EAS. Set it up now?';
if (platformsToConfigure === RequestedPlatform.Ios) {
message = 'Your iOS project is not configured to build with EAS. Set it up now?';
} else if (platformsToConfigure === RequestedPlatform.Android) {
message = 'Your Android project is not configured to build with EAS. Set it up now?';
}
const confirm = await confirmAsync({ message });
if (confirm) {
await configureAsync({
projectDir,
platform: RequestedPlatform.All,
platform: platformsToConfigure,
});
if (await vcs.hasUncommittedChangesAsync()) {
throw new Error(
@@ -167,3 +181,30 @@ async function ensureProjectConfiguredAsync(projectDir: string): Promise<ExpoCon
);
}
}
async function getPlatformsToConfigureAsync(
projectDir: string,
platform: RequestedPlatform
): Promise<RequestedPlatform | null> {
if (!(await fs.pathExists(path.join(projectDir, 'eas.json')))) {
return platform;
}
const easConfig = await new EasJsonReader(projectDir, platform).readRawAsync();
if (platform === RequestedPlatform.All) {
if (easConfig.builds?.android && easConfig.builds?.ios) {
return null;
} else if (easConfig.builds?.ios) {
return RequestedPlatform.Android;
} else if (easConfig.builds?.android) {
return RequestedPlatform.Ios;
}
} else if (
(platform === RequestedPlatform.Android || platform === RequestedPlatform.Ios) &&
easConfig.builds?.[platform]
) {
return null;
}
return platform;
}
@@ -47,7 +47,7 @@ export default class AndroidCredentialsProvider {
keystore: nullthrows(androidBuildCredentials.androidKeystore?.keystore),
keystorePassword: nullthrows(androidBuildCredentials.androidKeystore?.keystorePassword),
keyAlias: nullthrows(androidBuildCredentials.androidKeystore?.keyAlias),
keyPassword: nullthrows(androidBuildCredentials.androidKeystore?.keyPassword),
keyPassword: androidBuildCredentials.androidKeystore?.keyPassword ?? undefined,
},
};
}
@@ -5,6 +5,8 @@ import { createCtxMock } from '../../../__tests__/fixtures-context';
import { getAppLookupParamsFromContext } from '../BuildCredentialsUtils';
import { DownloadKeystore } from '../DownloadKeystore';
jest.mock('fs-extra');
const originalConsoleLog = console.log;
const originalConsoleWarn = console.warn;
beforeAll(() => {
@@ -4,6 +4,7 @@ import { createCtxMock } from '../../../__tests__/fixtures-context';
import { getAppLookupParamsFromContext } from '../BuildCredentialsUtils';
import { RemoveKeystore } from '../RemoveKeystore';
jest.mock('fs-extra');
jest.mock('../../../../prompts');
(confirmAsync as jest.Mock).mockImplementation(() => true);
@@ -1,11 +1,16 @@
import { Platform } from '@expo/eas-build-job';
import { CredentialsSource, IosDistributionType, IosEnterpriseProvisioning } from '@expo/eas-json';
import { CommonIosAppCredentialsFragment } from '../../graphql/generated';
import Log from '../../log';
import { findApplicationTarget } from '../../project/ios/target';
import { confirmAsync } from '../../prompts';
import { Context } from '../context';
import * as credentialsJsonReader from '../credentialsJson/read';
import { ensureAllTargetsAreConfigured } from '../credentialsJson/utils';
import { getAppFromContext } from './actions/BuildCredentialsUtils';
import { SetupBuildCredentials } from './actions/SetupBuildCredentials';
import { SetupPushKey } from './actions/SetupPushKey';
import { IosCapabilitiesOptions } from './appstore/ensureAppExists';
import { App, IosCredentials, Target } from './types';
import { isAdHocProfile } from './utils/provisioningProfile';
@@ -26,11 +31,14 @@ export default class IosCredentialsProvider {
public async getCredentialsAsync(
src: CredentialsSource.LOCAL | CredentialsSource.REMOTE
): Promise<IosCredentials> {
let buildCredentials;
if (src === CredentialsSource.LOCAL) {
return await this.getLocalAsync();
buildCredentials = await this.getLocalAsync();
} else {
return await this.getRemoteAsync();
buildCredentials = await this.getRemoteAsync();
}
await this.getPushKeyAsync(this.ctx, this.options.targets);
return buildCredentials;
}
private async getLocalAsync(): Promise<IosCredentials> {
@@ -59,6 +67,40 @@ export default class IosCredentialsProvider {
}).runAsync(this.ctx);
}
private async getPushKeyAsync(
ctx: Context,
targets: Target[]
): Promise<CommonIosAppCredentialsFragment | null> {
if (ctx.nonInteractive) {
return null;
}
const applicationTarget = findApplicationTarget(targets);
const app = getAppFromContext(ctx);
const appLookupParams = {
...app,
bundleIdentifier: applicationTarget.bundleIdentifier,
parentBundleIdentifier: applicationTarget.parentBundleIdentifier,
};
const setupPushKeyAction = new SetupPushKey(appLookupParams);
const isPushKeySetup = await setupPushKeyAction.isPushKeySetupAsync(ctx);
if (isPushKeySetup) {
Log.succeed(
`Push Notifications setup for ${app.projectName}:${applicationTarget.bundleIdentifier}`
);
return null;
}
const confirmSetup = await confirmAsync({
message: `Would you like to setup Push Notifications for your project?`,
});
if (!confirmSetup) {
return null;
}
return await setupPushKeyAction.runAsync(ctx);
}
private assertProvisioningProfileType(provisioningProfile: string, targetName?: string): void {
const isAdHoc = isAdHocProfile(provisioningProfile);
if (this.options.distribution === 'internal' && !isAdHoc) {
@@ -78,7 +78,7 @@ export function displayIosCredentials(
}
Log.log(` Bundle Identifier: ${chalk.bold(bundleIdentifier)}`);
const targetAppCredentials = appCredentialsMap[targetName];
if (!targetAppCredentials || targetAppCredentials.iosAppBuildCredentialsList.length === 0) {
if (!targetAppCredentials) {
Log.newLine();
Log.log(` No credentials set up yet!`);
Log.newLine();
+77 -58
View File
@@ -2352,14 +2352,24 @@ export type BuildMutation = {
* @deprecated Use cancelBuild instead
*/
cancel: Build;
/** Create an Android generic build */
/**
* Create an Android generic build
* @deprecated Use createAndroidBuild instead
*/
createAndroidGenericBuild: CreateBuildResult;
/** Create an Android managed build */
/**
* Create an Android managed build
* @deprecated Use createAndroidBuild instead
*/
createAndroidManagedBuild: CreateBuildResult;
/** Create an Android build */
createAndroidBuild: CreateBuildResult;
/** Create an iOS generic build */
createIosGenericBuild: CreateBuildResult;
/** Create an iOS managed build */
createIosManagedBuild: CreateBuildResult;
/** Create an iOS build */
createIosBuild: CreateBuildResult;
};
@@ -2387,6 +2397,13 @@ export type BuildMutationCreateAndroidManagedBuildArgs = {
};
export type BuildMutationCreateAndroidBuildArgs = {
appId: Scalars['ID'];
job: AndroidJobInput;
metadata?: Maybe<BuildMetadataInput>;
};
export type BuildMutationCreateIosGenericBuildArgs = {
appId: Scalars['ID'];
job: IosGenericJobInput;
@@ -2400,6 +2417,13 @@ export type BuildMutationCreateIosManagedBuildArgs = {
metadata?: Maybe<BuildMetadataInput>;
};
export type BuildMutationCreateIosBuildArgs = {
appId: Scalars['ID'];
job: IosJobInput;
metadata?: Maybe<BuildMetadataInput>;
};
export type AndroidGenericJobInput = {
projectArchive: ProjectArchiveSourceInput;
projectRootDirectory: Scalars['String'];
@@ -2523,6 +2547,27 @@ export enum AndroidManagedBuildType {
DevelopmentClient = 'DEVELOPMENT_CLIENT'
}
export type AndroidJobInput = {
type: BuildWorkflow;
projectArchive: ProjectArchiveSourceInput;
projectRootDirectory: Scalars['String'];
releaseChannel?: Maybe<Scalars['String']>;
updates?: Maybe<BuildUpdatesInput>;
secrets?: Maybe<AndroidJobSecretsInput>;
builderEnvironment?: Maybe<AndroidBuilderEnvironmentInput>;
cache?: Maybe<BuildCacheInput>;
gradleCommand?: Maybe<Scalars['String']>;
artifactPath?: Maybe<Scalars['String']>;
buildType?: Maybe<AndroidBuildType>;
username?: Maybe<Scalars['String']>;
};
export enum AndroidBuildType {
Apk = 'APK',
AppBundle = 'APP_BUNDLE',
DevelopmentClient = 'DEVELOPMENT_CLIENT'
}
export type IosGenericJobInput = {
projectArchive: ProjectArchiveSourceInput;
projectRootDirectory: Scalars['String'];
@@ -2588,6 +2633,28 @@ export enum IosManagedBuildType {
DevelopmentClient = 'DEVELOPMENT_CLIENT'
}
export type IosJobInput = {
type: BuildWorkflow;
projectArchive: ProjectArchiveSourceInput;
projectRootDirectory: Scalars['String'];
releaseChannel?: Maybe<Scalars['String']>;
updates?: Maybe<BuildUpdatesInput>;
distribution?: Maybe<DistributionType>;
secrets?: Maybe<IosJobSecretsInput>;
builderEnvironment?: Maybe<IosBuilderEnvironmentInput>;
cache?: Maybe<BuildCacheInput>;
scheme?: Maybe<Scalars['String']>;
buildConfiguration?: Maybe<Scalars['String']>;
artifactPath?: Maybe<Scalars['String']>;
buildType?: Maybe<IosBuildType>;
username?: Maybe<Scalars['String']>;
};
export enum IosBuildType {
Release = 'RELEASE',
DevelopmentClient = 'DEVELOPMENT_CLIENT'
}
export type IosAppBuildCredentialsMutation = {
__typename?: 'IosAppBuildCredentialsMutation';
/** Create a set of build credentials for an iOS app */
@@ -4497,18 +4564,18 @@ export type CreateAppMutation = (
)> }
);
export type CreateAndroidGenericBuildMutationVariables = Exact<{
export type CreateAndroidBuildMutationVariables = Exact<{
appId: Scalars['ID'];
job: AndroidGenericJobInput;
job: AndroidJobInput;
metadata?: Maybe<BuildMetadataInput>;
}>;
export type CreateAndroidGenericBuildMutation = (
export type CreateAndroidBuildMutation = (
{ __typename?: 'RootMutation' }
& { build?: Maybe<(
{ __typename?: 'BuildMutation' }
& { createAndroidGenericBuild: (
& { createAndroidBuild: (
{ __typename?: 'CreateBuildResult' }
& { build: (
{ __typename?: 'Build' }
@@ -4521,66 +4588,18 @@ export type CreateAndroidGenericBuildMutation = (
)> }
);
export type CreateAndroidManagedBuildMutationVariables = Exact<{
export type CreateIosBuildMutationVariables = Exact<{
appId: Scalars['ID'];
job: AndroidManagedJobInput;
job: IosJobInput;
metadata?: Maybe<BuildMetadataInput>;
}>;
export type CreateAndroidManagedBuildMutation = (
export type CreateIosBuildMutation = (
{ __typename?: 'RootMutation' }
& { build?: Maybe<(
{ __typename?: 'BuildMutation' }
& { createAndroidManagedBuild: (
{ __typename?: 'CreateBuildResult' }
& { build: (
{ __typename?: 'Build' }
& Pick<Build, 'id'>
), deprecationInfo?: Maybe<(
{ __typename?: 'EASBuildDeprecationInfo' }
& Pick<EasBuildDeprecationInfo, 'type' | 'message'>
)> }
) }
)> }
);
export type CreateIosGenericBuildMutationVariables = Exact<{
appId: Scalars['ID'];
job: IosGenericJobInput;
metadata?: Maybe<BuildMetadataInput>;
}>;
export type CreateIosGenericBuildMutation = (
{ __typename?: 'RootMutation' }
& { build?: Maybe<(
{ __typename?: 'BuildMutation' }
& { createIosGenericBuild: (
{ __typename?: 'CreateBuildResult' }
& { build: (
{ __typename?: 'Build' }
& Pick<Build, 'id'>
), deprecationInfo?: Maybe<(
{ __typename?: 'EASBuildDeprecationInfo' }
& Pick<EasBuildDeprecationInfo, 'type' | 'message'>
)> }
) }
)> }
);
export type CreateIosManagedBuildMutationVariables = Exact<{
appId: Scalars['ID'];
job: IosManagedJobInput;
metadata?: Maybe<BuildMetadataInput>;
}>;
export type CreateIosManagedBuildMutation = (
{ __typename?: 'RootMutation' }
& { build?: Maybe<(
{ __typename?: 'BuildMutation' }
& { createIosManagedBuild: (
& { createIosBuild: (
{ __typename?: 'CreateBuildResult' }
& { build: (
{ __typename?: 'Build' }
@@ -3,20 +3,14 @@ import nullthrows from 'nullthrows';
import { graphqlClient, withErrorHandlingAsync } from '../client';
import {
AndroidGenericJobInput,
AndroidManagedJobInput,
AndroidJobInput,
BuildMetadataInput,
CreateAndroidGenericBuildMutation,
CreateAndroidGenericBuildMutationVariables,
CreateAndroidManagedBuildMutation,
CreateAndroidManagedBuildMutationVariables,
CreateIosGenericBuildMutation,
CreateIosGenericBuildMutationVariables,
CreateIosManagedBuildMutation,
CreateIosManagedBuildMutationVariables,
CreateAndroidBuildMutation,
CreateAndroidBuildMutationVariables,
CreateIosBuildMutation,
CreateIosBuildMutationVariables,
EasBuildDeprecationInfo,
IosGenericJobInput,
IosManagedJobInput,
IosJobInput,
} from '../generated';
export interface BuildResult {
@@ -25,22 +19,22 @@ export interface BuildResult {
}
const BuildMutation = {
async createAndroidGenericBuildAsync(input: {
async createAndroidBuildAsync(input: {
appId: string;
job: AndroidGenericJobInput;
job: AndroidJobInput;
metadata: BuildMetadataInput;
}): Promise<BuildResult> {
const data = await withErrorHandlingAsync(
graphqlClient
.mutation<CreateAndroidGenericBuildMutation, CreateAndroidGenericBuildMutationVariables>(
.mutation<CreateAndroidBuildMutation, CreateAndroidBuildMutationVariables>(
gql`
mutation CreateAndroidGenericBuildMutation(
mutation CreateAndroidBuildMutation(
$appId: ID!
$job: AndroidGenericJobInput!
$job: AndroidJobInput!
$metadata: BuildMetadataInput
) {
build {
createAndroidGenericBuild(appId: $appId, job: $job, metadata: $metadata) {
createAndroidBuild(appId: $appId, job: $job, metadata: $metadata) {
build {
id
}
@@ -56,24 +50,24 @@ const BuildMutation = {
)
.toPromise()
);
return nullthrows(data.build?.createAndroidGenericBuild);
return nullthrows(data.build?.createAndroidBuild);
},
async createAndroidManagedBuildAsync(input: {
async createIosBuildAsync(input: {
appId: string;
job: AndroidManagedJobInput;
job: IosJobInput;
metadata: BuildMetadataInput;
}): Promise<BuildResult> {
const data = await withErrorHandlingAsync(
graphqlClient
.mutation<CreateAndroidManagedBuildMutation, CreateAndroidManagedBuildMutationVariables>(
.mutation<CreateIosBuildMutation, CreateIosBuildMutationVariables>(
gql`
mutation CreateAndroidManagedBuildMutation(
mutation CreateIosBuildMutation(
$appId: ID!
$job: AndroidManagedJobInput!
$job: IosJobInput!
$metadata: BuildMetadataInput
) {
build {
createAndroidManagedBuild(appId: $appId, job: $job, metadata: $metadata) {
createIosBuild(appId: $appId, job: $job, metadata: $metadata) {
build {
id
}
@@ -89,73 +83,7 @@ const BuildMutation = {
)
.toPromise()
);
return nullthrows(data.build?.createAndroidManagedBuild);
},
async createIosGenericBuildAsync(input: {
appId: string;
job: IosGenericJobInput;
metadata: BuildMetadataInput;
}): Promise<BuildResult> {
const data = await withErrorHandlingAsync(
graphqlClient
.mutation<CreateIosGenericBuildMutation, CreateIosGenericBuildMutationVariables>(
gql`
mutation CreateIosGenericBuildMutation(
$appId: ID!
$job: IosGenericJobInput!
$metadata: BuildMetadataInput
) {
build {
createIosGenericBuild(appId: $appId, job: $job, metadata: $metadata) {
build {
id
}
deprecationInfo {
type
message
}
}
}
}
`,
input
)
.toPromise()
);
return nullthrows(data.build?.createIosGenericBuild);
},
async createIosManagedBuildAsync(input: {
appId: string;
job: IosManagedJobInput;
metadata: BuildMetadataInput;
}): Promise<BuildResult> {
const data = await withErrorHandlingAsync(
graphqlClient
.mutation<CreateIosManagedBuildMutation, CreateIosManagedBuildMutationVariables>(
gql`
mutation CreateIosManagedBuildMutation(
$appId: ID!
$job: IosManagedJobInput!
$metadata: BuildMetadataInput
) {
build {
createIosManagedBuild(appId: $appId, job: $job, metadata: $metadata) {
build {
id
}
deprecationInfo {
type
message
}
}
}
}
`,
input
)
.toPromise()
);
return nullthrows(data.build?.createIosManagedBuild);
return nullthrows(data.build?.createIosBuild);
},
};
@@ -3,6 +3,7 @@ import { vol } from 'memfs';
import os from 'os';
import { asMock } from '../../../__tests__/utils';
import { jester as mockJester } from '../../../credentials/__tests__/fixtures-constants';
import { promptAsync } from '../../../prompts';
import {
ensureApplicationIdIsDefinedForManagedProjectAsync,
@@ -11,10 +12,13 @@ import {
jest.mock('fs');
jest.mock('../../../prompts');
jest.mock('../../../user/actions', () => ({ ensureLoggedInAsync: jest.fn(() => mockJester) }));
const originalConsoleWarn = console.warn;
const originalConsoleLog = console.log;
beforeAll(() => {
console.warn = jest.fn();
console.log = jest.fn();
});
beforeEach(() => {
@@ -29,6 +33,7 @@ beforeEach(() => {
afterAll(() => {
fs.removeSync(os.tmpdir());
console.warn = originalConsoleWarn;
console.log = originalConsoleLog;
});
describe(getApplicationId, () => {
@@ -1,14 +1,16 @@
import { ExpoConfig, getConfigFilePaths } from '@expo/config';
import { AndroidConfig } from '@expo/config-plugins';
import { AndroidConfig, IOSConfig } from '@expo/config-plugins';
import { Platform, Workflow } from '@expo/eas-build-job';
import assert from 'assert';
import chalk from 'chalk';
import fs from 'fs-extra';
import once from 'lodash/once';
import nullthrows from 'nullthrows';
import Log from '../../log';
import { getProjectConfigDescription } from '../../project/projectUtils';
import Log, { learnMore } from '../../log';
import { getProjectConfigDescription, getUsername } from '../../project/projectUtils';
import { promptAsync } from '../../prompts';
import { ensureLoggedInAsync } from '../../user/actions';
import { resolveWorkflow } from '../workflow';
const INVALID_APPLICATION_ID_MESSAGE = `Invalid format of Android applicationId. Only alphanumeric characters, '.' and '_' are allowed, and each '.' must be followed by a letter.`;
@@ -71,10 +73,19 @@ async function configureApplicationIdAsync(projectDir: string, exp: ExpoConfig):
assert(paths.staticConfigPath, 'app.json must exist');
Log.addNewLineIfNone();
Log.log(
`${chalk.bold(`📝 Android application id`)} ${chalk.dim(
learnMore('https://expo.fyi/android-package')
)}`
);
const suggestedAndroidApplicationId = await getSuggestedApplicationIdAsync(exp);
const { packageName } = await promptAsync({
name: 'packageName',
type: 'text',
message: `What would you like your Android application id to be?`,
initial: suggestedAndroidApplicationId,
validate: value => (isApplicationIdValid(value) ? true : INVALID_APPLICATION_ID_MESSAGE),
});
@@ -111,3 +122,19 @@ function _warnIfAndroidPackageDefinedInAppConfigForGenericProject(
export const warnIfAndroidPackageDefinedInAppConfigForGenericProject = once(
_warnIfAndroidPackageDefinedInAppConfigForGenericProject
);
async function getSuggestedApplicationIdAsync(exp: ExpoConfig): Promise<string | undefined> {
// Attempt to use the ios bundle id first since it's convenient to have them aligned.
const maybeBundleId = IOSConfig.BundleIdentifier.getBundleIdentifier(exp);
if (maybeBundleId && isApplicationIdValid(maybeBundleId)) {
return maybeBundleId;
} else {
const username = getUsername(exp, await ensureLoggedInAsync());
// It's common to use dashes in your node project name, strip them from the suggested package name.
const possibleId = `com.${username}.${exp.slug}`.split('-').join('');
if (isApplicationIdValid(possibleId)) {
return possibleId;
}
}
return undefined;
}
@@ -4,6 +4,7 @@ import os from 'os';
import path from 'path';
import { asMock } from '../../../__tests__/utils';
import { jester as mockJester } from '../../../credentials/__tests__/fixtures-constants';
import { promptAsync } from '../../../prompts';
import {
ensureBundleIdentifierIsDefinedForManagedProjectAsync,
@@ -13,10 +14,13 @@ import {
jest.mock('fs');
jest.mock('../../../prompts');
jest.mock('../../../user/actions', () => ({ ensureLoggedInAsync: jest.fn(() => mockJester) }));
const originalConsoleWarn = console.warn;
const originalConsoleLog = console.log;
beforeAll(() => {
console.warn = jest.fn();
console.log = jest.fn();
});
beforeEach(() => {
@@ -31,6 +35,7 @@ beforeEach(() => {
afterAll(() => {
fs.removeSync(os.tmpdir());
console.warn = originalConsoleWarn;
console.log = originalConsoleLog;
});
const originalFs = jest.requireActual('fs');
@@ -1,13 +1,15 @@
import { ExpoConfig, getConfigFilePaths } from '@expo/config';
import { IOSConfig } from '@expo/config-plugins';
import { AndroidConfig, IOSConfig } from '@expo/config-plugins';
import { Platform, Workflow } from '@expo/eas-build-job';
import assert from 'assert';
import chalk from 'chalk';
import fs from 'fs-extra';
import once from 'lodash/once';
import Log from '../../log';
import Log, { learnMore } from '../../log';
import { promptAsync } from '../../prompts';
import { getProjectConfigDescription, sanitizedProjectName } from '../projectUtils';
import { ensureLoggedInAsync } from '../../user/actions';
import { getProjectConfigDescription, getUsername, sanitizedProjectName } from '../projectUtils';
import { resolveWorkflow } from '../workflow';
const INVALID_BUNDLE_IDENTIFIER_MESSAGE = `Invalid format of iOS bundle identifier. Only alphanumeric characters, '.' and '-' are allowed, and each '.' must be followed by a letter.`;
@@ -90,10 +92,19 @@ async function configureBundleIdentifierAsync(
assert(paths.staticConfigPath, 'app.json must exist');
Log.addNewLineIfNone();
Log.log(
`${chalk.bold(`📝 iOS Bundle Identifier`)} ${chalk.dim(
learnMore('https://expo.fyi/bundle-identifier')
)}`
);
const suggestedBundleIdentifier = await getSuggestedBundleIdentifierAsync(exp);
const { bundleIdentifier } = await promptAsync({
name: 'bundleIdentifier',
type: 'text',
message: `What would you like your iOS bundle identifier to be?`,
initial: suggestedBundleIdentifier,
validate: value => (isBundleIdentifierValid(value) ? true : INVALID_BUNDLE_IDENTIFIER_MESSAGE),
});
@@ -110,7 +121,7 @@ async function configureBundleIdentifierAsync(
}
function isBundleIdentifierValid(bundleIdentifier: string): boolean {
return /^[a-zA-Z]+(\.[a-zA-Z0-9-]+)*$/.test(bundleIdentifier);
return /^[a-zA-Z0-9-.]+$/.test(bundleIdentifier);
}
function _warnIfBundleIdentifierDefinedInAppConfigForGenericProject(
@@ -135,3 +146,19 @@ export function isWildcardBundleIdentifier(bundleIdentifier: string): boolean {
const wildcardRegex = /^[A-Za-z0-9.-]+\*$/;
return wildcardRegex.test(bundleIdentifier);
}
async function getSuggestedBundleIdentifierAsync(exp: ExpoConfig): Promise<string | undefined> {
// Attempt to use the android package name first since it's convenient to have them aligned.
const maybeAndroidPackage = AndroidConfig.Package.getPackage(exp);
if (maybeAndroidPackage && isBundleIdentifierValid(maybeAndroidPackage)) {
return maybeAndroidPackage;
} else {
const username = getUsername(exp, await ensureLoggedInAsync());
// It's common to use dashes in your node project name, strip them from the suggested package name.
const possibleId = `com.${username}.${exp.slug}`.split('-').join('');
if (isBundleIdentifierValid(possibleId)) {
return possibleId;
}
}
return undefined;
}
+2 -2
View File
@@ -1,11 +1,11 @@
{
"name": "@expo/eas-json",
"description": "A library for interacting with the eas.json",
"version": "0.18.2",
"version": "0.19.0",
"author": "Expo <[email protected]>",
"bugs": "https://github.com/expo/eas-cli/issues",
"dependencies": {
"@expo/eas-build-job": "0.2.37",
"@expo/eas-build-job": "0.2.41",
"@hapi/joi": "17.1.1",
"fs-extra": "9.0.1",
"tslib": "1.14.1"
+2 -2
View File
@@ -16,7 +16,7 @@ export type VersionAutoIncrement = boolean | 'version' | 'buildNumber';
export interface AndroidManagedBuildProfile extends Android.BuilderEnvironment {
workflow: Workflow.MANAGED;
credentialsSource: CredentialsSource;
buildType?: Android.ManagedBuildType;
buildType?: Android.BuildType;
releaseChannel?: string;
channel?: string;
distribution: AndroidDistributionType;
@@ -38,7 +38,7 @@ export interface AndroidGenericBuildProfile extends Android.BuilderEnvironment {
export interface IosManagedBuildProfile extends Omit<Ios.BuilderEnvironment, 'image'> {
workflow: Workflow.MANAGED;
credentialsSource: CredentialsSource;
buildType?: Ios.ManagedBuildType;
buildType?: Ios.BuildType;
releaseChannel?: string;
channel?: string;
distribution: IosDistributionType;
+4 -4
View File
@@ -1917,10 +1917,10 @@
xcode "^3.0.0"
xml-js "^1.6.11"
"@expo/[email protected].37":
version "0.2.37"
resolved "https://registry.yarnpkg.com/@expo/eas-build-job/-/eas-build-job-0.2.37.tgz#fd6cb911e33774239d1ab7662c0ccc8efa22f7a2"
integrity sha512-B9gahwTTYs0pWQP2HnfYWcbsqmUIAdnr+iwounVqpcxHhERxGJby2JEw+Vxtl2+VMARM4w9RLgNduP5Vk/zeQw==
"@expo/[email protected].41":
version "0.2.41"
resolved "https://registry.yarnpkg.com/@expo/eas-build-job/-/eas-build-job-0.2.41.tgz#d44ce7f5e7a1f08caa415913fed43f875fce4d52"
integrity sha512-tp3i7EZRMGvlJ3NyhpBpLdIxg6+CI6z6P3JgZVh57s2skN5zjzHcfjXPcw0gVH9fCouUnvhSSye8O+g2Zo1oaA==
dependencies:
"@hapi/joi" "^17.1.1"