mirror of
https://github.com/expo/eas-cli.git
synced 2026-11-15 13:08:11 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
977546c8c9 | ||
|
|
53dcd4cb43 | ||
|
|
9e18e738eb | ||
|
|
252c7187d5 | ||
|
|
90852b9557 | ||
|
|
0df16236a2 | ||
|
|
ecaf5a4318 | ||
|
|
86e5e1a7b1 | ||
|
|
ab10094071 | ||
|
|
2d536d73fe | ||
|
|
80ea8ee50b | ||
|
|
b49c5f47d1 | ||
|
|
a9da78946b | ||
|
|
b6d9accea4 | ||
|
|
4611a65bce | ||
|
|
db29b3fc18 | ||
|
|
2534a46bd3 | ||
|
|
7def4b502e | ||
|
|
4ea26d7ca3 | ||
|
|
c4c8075b1f | ||
|
|
266545d2a0 | ||
|
|
ddd7046513 | ||
|
|
7a44eeb22b | ||
|
|
5bcf8263cf | ||
|
|
f380ba0106 |
No files matched your search
+46
-2
@@ -6,6 +6,52 @@ This is the log of notable changes to EAS CLI and related packages.
|
||||
|
||||
### 🛠 Breaking changes
|
||||
|
||||
### 🎉 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))
|
||||
|
||||
## [0.18.1](https://github.com/expo/eas-cli/releases/tag/v0.18.1) - 2021-06-24
|
||||
|
||||
### 🎉 New features
|
||||
|
||||
- Add basic printing support for Apple App Specific Password. ([#474](https://github.com/expo/eas-cli/pull/474) by [@quinlanj](https://github.com/quinlanj))
|
||||
|
||||
### 🐛 Bug fixes
|
||||
|
||||
- Fix CLI UI getting blocked on credentials migration, leading to partially migrated state. ([#477](https://github.com/expo/eas-cli/pull/477) by [@brentvatne](https://github.com/brentvatne))
|
||||
|
||||
## [0.18.0](https://github.com/expo/eas-cli/releases/tag/v0.18.0) - 2021-06-24
|
||||
|
||||
### 🛠 Breaking changes
|
||||
|
||||
- Drop support for `experimental.npmToken` in credentials.json, EAS Secrets can be used instead. ([#444](https://github.com/expo/eas-cli/pull/444) by [@dsokal](https://github.com/dsokal))
|
||||
- Remove `--allow-experimental` flag from `eas build:configure` as it has no effect now. ([#444](https://github.com/expo/eas-cli/pull/444) by [@dsokal](https://github.com/dsokal))
|
||||
|
||||
@@ -20,8 +66,6 @@ This is the log of notable changes to EAS CLI and related packages.
|
||||
- iOS push key setup and management now available in `eas-cli credentials`. ([#469](https://github.com/expo/eas-cli/pull/469) [#470](https://github.com/expo/eas-cli/pull/470) by [@quinlanj](https://github.com/quinlanj))
|
||||
- Support new build status: `new`. ([#475](https://github.com/expo/eas-cli/pull/475) by [@dsokal](https://github.com/dsokal))
|
||||
|
||||
### 🐛 Bug fixes
|
||||
|
||||
### 🧹 Chores
|
||||
|
||||
- Deprecate `--skip-credentials-check` flag because it doesn't do anything and is no longer needed. ([#442](https://github.com/expo/eas-cli/pull/442) by [@brentvatne](https://github.com/brentvatne))
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"version": "0.18.0"
|
||||
"version": "0.19.0"
|
||||
}
|
||||
+22
-22
@@ -69,7 +69,7 @@ ALIASES
|
||||
$ eas login
|
||||
```
|
||||
|
||||
_See code: [src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v0.18.0/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.0/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.0/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.0/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.0/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.0/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.0/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.0/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.0/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.0/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.0/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.0/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.0/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.0/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.0/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.0/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)`
|
||||
|
||||
@@ -368,7 +368,7 @@ EXAMPLES
|
||||
and provide its App ID
|
||||
```
|
||||
|
||||
_See code: [src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v0.18.0/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`
|
||||
|
||||
@@ -387,7 +387,7 @@ OPTIONS
|
||||
--url=url Webhook URL
|
||||
```
|
||||
|
||||
_See code: [src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v0.18.0/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]`
|
||||
|
||||
@@ -401,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.0/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`
|
||||
|
||||
@@ -415,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.0/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`
|
||||
|
||||
@@ -435,7 +435,7 @@ OPTIONS
|
||||
--url=url Webhook URL
|
||||
```
|
||||
|
||||
_See code: [src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v0.18.0/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`
|
||||
|
||||
@@ -449,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.0/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 -->
|
||||
@@ -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",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "eas-cli",
|
||||
"description": "EAS command line tool",
|
||||
"version": "0.18.0",
|
||||
"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.0",
|
||||
"@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",
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ArchiveSource, Cache, Ios, Job, Workflow, sanitizeJob } from '@expo/eas-build-job';
|
||||
import { IosGenericBuildProfile, IosManagedBuildProfile } from '@expo/eas-json';
|
||||
import path from 'path';
|
||||
import semver from 'semver';
|
||||
|
||||
import { IosCredentials, TargetCredentials } from '../../credentials/ios/types';
|
||||
import { getUsername } from '../../project/projectUtils';
|
||||
@@ -59,7 +60,7 @@ async function prepareJobCommonAsync(
|
||||
projectArchive,
|
||||
distribution: ctx.buildProfile.distribution,
|
||||
builderEnvironment: {
|
||||
image: ctx.buildProfile.image,
|
||||
image: resolveImage(ctx),
|
||||
node: ctx.buildProfile.node,
|
||||
yarn: ctx.buildProfile.yarn,
|
||||
bundler: ctx.buildProfile.bundler,
|
||||
@@ -78,6 +79,17 @@ async function prepareJobCommonAsync(
|
||||
};
|
||||
}
|
||||
|
||||
function resolveImage(ctx: BuildContext<Platform.IOS>): Ios.BuilderEnvironment['image'] {
|
||||
// see https://linear.app/expo/issue/ENG-1396/make-default-image-dependent-on-sdk-version
|
||||
if (!ctx.buildProfile.image && ctx.commandCtx.exp.sdkVersion) {
|
||||
const majorSdkVersion = semver.major(ctx.commandCtx.exp.sdkVersion);
|
||||
if (majorSdkVersion <= 41) {
|
||||
return 'macos-catalina-10.15-xcode-12.4';
|
||||
}
|
||||
}
|
||||
return ctx.buildProfile.image ?? 'default';
|
||||
}
|
||||
|
||||
function prepareTargetCredentials(targetCredentials: TargetCredentials): Ios.TargetCredentials {
|
||||
return {
|
||||
provisioningProfileBase64: targetCredentials.provisioningProfile,
|
||||
@@ -92,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 {
|
||||
@@ -114,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());
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -13,7 +13,7 @@ import { endTimer, formatMilliseconds, startTimer } from '../../utils/timer';
|
||||
import vcs from '../../vcs';
|
||||
|
||||
export async function maybeBailOnRepoStatusAsync(): Promise<void> {
|
||||
if (await vcs.hasUncommittedChangesAsync()) {
|
||||
if (!(await vcs.hasUncommittedChangesAsync())) {
|
||||
return;
|
||||
}
|
||||
Log.addNewLineIfNone();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -40,6 +40,7 @@ export const testPushKey: ApplePushKeyFragment = {
|
||||
keyIdentifier: 'test-key-identifier',
|
||||
appleTeam: { ...testAppleTeamFragment },
|
||||
updatedAt: new Date(),
|
||||
iosAppCredentialsList: [],
|
||||
};
|
||||
|
||||
export const testTargets: Target[] = [{ targetName: 'testapp', bundleIdentifier: 'foo.bar.com' }];
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,10 +3,9 @@ import { nanoid } from 'nanoid';
|
||||
import ora from 'ora';
|
||||
|
||||
import { AndroidAppBuildCredentialsFragment } from '../../../graphql/generated';
|
||||
import Log from '../../../log';
|
||||
import { getApplicationId } from '../../../project/android/applicationId';
|
||||
import { getProjectAccountName, getProjectConfigDescription } from '../../../project/projectUtils';
|
||||
import { confirmAsync, promptAsync } from '../../../prompts';
|
||||
import { promptAsync } from '../../../prompts';
|
||||
import { findAccountByName } from '../../../user/Account';
|
||||
import { Context } from '../../context';
|
||||
import { AppLookupParams } from '../api/GraphqlClient';
|
||||
@@ -34,62 +33,57 @@ export async function promptUserAndCopyLegacyCredentialsAsync(
|
||||
ctx: Context,
|
||||
app: AppLookupParams
|
||||
): Promise<void> {
|
||||
assert(
|
||||
!ctx.nonInteractive,
|
||||
'Copying over Expo Classic credentials cannot be run in non-interactive mode'
|
||||
);
|
||||
assert(
|
||||
await canCopyLegacyCredentialsAsync(ctx, app),
|
||||
'User not eligible to copy Expo Classic credentials to EAS'
|
||||
'User not eligible to copy classic build credentials to EAS'
|
||||
);
|
||||
const shouldCopy = await confirmAsync({
|
||||
message: `We've detected credentials from Expo Classic (expo-cli). Would you like to copy them over to Expo Application Services (EAS)?`,
|
||||
});
|
||||
if (!shouldCopy) {
|
||||
return;
|
||||
}
|
||||
|
||||
Log.log('Copying credentials...');
|
||||
const spinner = ora().start();
|
||||
const spinner = ora('Classic credentials detected, copying to EAS...').start();
|
||||
|
||||
const legacyAppCredentials = await ctx.android.getLegacyAndroidAppCredentialsWithCommonFieldsAsync(
|
||||
app
|
||||
);
|
||||
if (!legacyAppCredentials) {
|
||||
return;
|
||||
}
|
||||
|
||||
const appCredentials = await ctx.android.createOrGetExistingAndroidAppCredentialsWithBuildCredentialsAsync(
|
||||
app
|
||||
);
|
||||
const legacyFcm = legacyAppCredentials.androidFcm;
|
||||
if (legacyFcm) {
|
||||
const clonedFcm = await ctx.android.createFcmAsync(
|
||||
app.account,
|
||||
legacyFcm.credential,
|
||||
legacyFcm.version
|
||||
try {
|
||||
const legacyAppCredentials = await ctx.android.getLegacyAndroidAppCredentialsWithCommonFieldsAsync(
|
||||
app
|
||||
);
|
||||
await ctx.android.updateAndroidAppCredentialsAsync(appCredentials, {
|
||||
androidFcmId: clonedFcm.id,
|
||||
});
|
||||
if (!legacyAppCredentials) {
|
||||
return;
|
||||
}
|
||||
|
||||
const appCredentials = await ctx.android.createOrGetExistingAndroidAppCredentialsWithBuildCredentialsAsync(
|
||||
app
|
||||
);
|
||||
const legacyFcm = legacyAppCredentials.androidFcm;
|
||||
if (legacyFcm) {
|
||||
const clonedFcm = await ctx.android.createFcmAsync(
|
||||
app.account,
|
||||
legacyFcm.credential,
|
||||
legacyFcm.version
|
||||
);
|
||||
await ctx.android.updateAndroidAppCredentialsAsync(appCredentials, {
|
||||
androidFcmId: clonedFcm.id,
|
||||
});
|
||||
}
|
||||
|
||||
const legacyBuildCredentials = await ctx.android.getLegacyAndroidAppBuildCredentialsAsync(app);
|
||||
const legacyKeystore = legacyBuildCredentials?.androidKeystore ?? null;
|
||||
|
||||
if (legacyKeystore) {
|
||||
const clonedKeystore = await ctx.android.createKeystoreAsync(app.account, {
|
||||
keystore: legacyKeystore.keystore,
|
||||
keystorePassword: legacyKeystore.keystorePassword,
|
||||
keyAlias: legacyKeystore.keyAlias,
|
||||
keyPassword: legacyKeystore.keyPassword ?? undefined,
|
||||
type: legacyKeystore.type,
|
||||
});
|
||||
await createOrUpdateDefaultAndroidAppBuildCredentialsAsync(ctx, app, {
|
||||
androidKeystoreId: clonedKeystore.id,
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
spinner.fail(`Unable to migrate credentials to EAS.`);
|
||||
throw e;
|
||||
}
|
||||
|
||||
const legacyBuildCredentials = await ctx.android.getLegacyAndroidAppBuildCredentialsAsync(app);
|
||||
const legacyKeystore = legacyBuildCredentials?.androidKeystore ?? null;
|
||||
|
||||
if (legacyKeystore) {
|
||||
const clonedKeystore = await ctx.android.createKeystoreAsync(app.account, {
|
||||
keystore: legacyKeystore.keystore,
|
||||
keystorePassword: legacyKeystore.keystorePassword,
|
||||
keyAlias: legacyKeystore.keyAlias,
|
||||
keyPassword: legacyKeystore.keyPassword ?? undefined,
|
||||
type: legacyKeystore.type,
|
||||
});
|
||||
await createOrUpdateDefaultAndroidAppBuildCredentialsAsync(ctx, app, {
|
||||
androidKeystoreId: clonedKeystore.id,
|
||||
});
|
||||
}
|
||||
spinner.succeed('Credentials successfully copied');
|
||||
spinner.succeed('Credentials copied to EAS.');
|
||||
}
|
||||
|
||||
export function getAppLookupParamsFromContext(ctx: Context): AppLookupParams {
|
||||
@@ -135,9 +129,8 @@ export async function createOrUpdateDefaultAndroidAppBuildCredentialsAsync(
|
||||
{ androidKeystoreId }
|
||||
);
|
||||
}
|
||||
const providedName = await promptForNameAsync();
|
||||
return await ctx.android.createAndroidAppBuildCredentialsAsync(appLookupParams, {
|
||||
name: providedName,
|
||||
name: generateRandomName(),
|
||||
isDefault: true,
|
||||
androidKeystoreId,
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import nullthrows from 'nullthrows';
|
||||
import ora from 'ora';
|
||||
|
||||
import {
|
||||
AndroidAppBuildCredentialsFragment,
|
||||
@@ -94,9 +95,9 @@ export class SetupBuildCredentials {
|
||||
);
|
||||
const defaultKeystore = defaultBuildCredentials?.androidKeystore ?? null;
|
||||
if (defaultKeystore) {
|
||||
Log.log(
|
||||
ora(
|
||||
`Using Keystore from configuration: ${nullthrows(defaultBuildCredentials).name} (default)`
|
||||
);
|
||||
).succeed();
|
||||
return defaultBuildCredentials;
|
||||
}
|
||||
return null;
|
||||
@@ -118,11 +119,11 @@ export class SetupBuildCredentials {
|
||||
const keystore = maybeBuildCredentials?.androidKeystore ?? null;
|
||||
if (keystore) {
|
||||
const buildCredentials = nullthrows(maybeBuildCredentials);
|
||||
Log.log(
|
||||
ora(
|
||||
`Using Keystore from configuration: ${buildCredentials.name}${
|
||||
buildCredentials.isDefault ? ' (default)' : ''
|
||||
}`
|
||||
);
|
||||
).succeed();
|
||||
return buildCredentials;
|
||||
}
|
||||
Log.log(
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -2,7 +2,6 @@ import { ApplePushKeyFragment, CommonIosAppCredentialsFragment } from '../../../
|
||||
import Log from '../../../log';
|
||||
import { Context } from '../../context';
|
||||
import { AppLookupParams } from '../api/GraphqlClient';
|
||||
import { AppleTeamMissingError } from '../errors';
|
||||
import { resolveAppleTeamIfAuthenticatedAsync } from './AppleTeamUtils';
|
||||
|
||||
export class AssignPushKey {
|
||||
@@ -14,15 +13,9 @@ export class AssignPushKey {
|
||||
): Promise<CommonIosAppCredentialsFragment> {
|
||||
const appleTeam =
|
||||
(await resolveAppleTeamIfAuthenticatedAsync(ctx, this.app)) ?? pushKey.appleTeam ?? null;
|
||||
if (!appleTeam) {
|
||||
// TODO(quin): make this optional
|
||||
throw new AppleTeamMissingError(
|
||||
'An Apple Team is required to proceed. You must be authenticated to your Apple account'
|
||||
);
|
||||
}
|
||||
const appCredentials = await ctx.ios.createOrGetIosAppCredentialsWithCommonFieldsAsync(
|
||||
this.app,
|
||||
{ appleTeam }
|
||||
{ appleTeam: appleTeam ?? undefined }
|
||||
);
|
||||
const updatedAppCredentials = await ctx.ios.updateIosAppCredentialsAsync(appCredentials, {
|
||||
applePushKeyId: pushKey.id,
|
||||
|
||||
@@ -187,6 +187,12 @@ export function formatPushKey(
|
||||
line += ` ${appleTeam ? `, ${formatAppleTeam(appleTeam)}` : ''}`;
|
||||
line += chalk.gray(`\n Updated: ${fromNow(new Date(updatedAt))} ago,`);
|
||||
|
||||
const apps = pushKey.iosAppCredentialsList.map(appCredentials => appCredentials.app);
|
||||
if (apps.length) {
|
||||
const appFullNames = apps.map(app => app.fullName).join(',');
|
||||
line += chalk.gray(`\n 📲 Used by: ${appFullNames}`);
|
||||
}
|
||||
|
||||
if (validPushKeyIdentifiers?.includes(keyIdentifier)) {
|
||||
line += chalk.gray("\n ✅ Currently valid on Apple's servers.");
|
||||
} else {
|
||||
|
||||
@@ -26,13 +26,16 @@ export class RemovePushKey {
|
||||
throw new Error(`Cannot remove push keys in non-interactive mode`);
|
||||
}
|
||||
|
||||
// TODO(quin): show the projects that rely on this
|
||||
const confirm = await confirmAsync({
|
||||
message: `Removing this push key will disable push notifications for projects that rely on it. Do you want to continue?`,
|
||||
});
|
||||
|
||||
if (!confirm) {
|
||||
return;
|
||||
const apps = this.pushKey.iosAppCredentialsList.map(appCredentials => appCredentials.app);
|
||||
if (apps.length !== 0) {
|
||||
const appFullNames = apps.map(app => app.fullName).join(',');
|
||||
const confirm = await confirmAsync({
|
||||
message: `Removing this push key will disable push notifications for ${appFullNames}. Do you want to continue?`,
|
||||
});
|
||||
if (!confirm) {
|
||||
Log.log('Aborting');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Log.log('Removing Push Key');
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
IosAppBuildCredentialsFragment,
|
||||
IosDistributionType,
|
||||
} from '../../../graphql/generated';
|
||||
import { isWildcardBundleIdentifier } from '../../../project/ios/bundleIdentifier';
|
||||
import { Account } from '../../../user/Account';
|
||||
import { DistributionCertificate, PushKey } from '../appstore/Credentials.types';
|
||||
import { AppleTeamMissingError } from '../errors';
|
||||
@@ -138,7 +139,7 @@ export async function createOrGetIosAppCredentialsWithCommonFieldsAsync(
|
||||
{
|
||||
appleTeam,
|
||||
}: {
|
||||
appleTeam: AppleTeamFragment;
|
||||
appleTeam?: AppleTeamFragment;
|
||||
}
|
||||
): Promise<CommonIosAppCredentialsFragment> {
|
||||
const maybeIosAppCredentials = await getIosAppCredentialsWithCommonFieldsAsync(appLookupParams);
|
||||
@@ -147,10 +148,10 @@ export async function createOrGetIosAppCredentialsWithCommonFieldsAsync(
|
||||
}
|
||||
const [app, appleAppIdentifier] = await Promise.all([
|
||||
getAppAsync(appLookupParams),
|
||||
createOrGetExistingAppleAppIdentifierAsync(appLookupParams, appleTeam),
|
||||
createOrGetExistingAppleAppIdentifierAsync(appLookupParams, appleTeam ?? null),
|
||||
]);
|
||||
return await IosAppCredentialsMutation.createIosAppCredentialsAsync(
|
||||
{ appleTeamId: appleTeam.id },
|
||||
{ appleTeamId: appleTeam?.id },
|
||||
app.id,
|
||||
appleAppIdentifier.id
|
||||
);
|
||||
@@ -181,7 +182,7 @@ async function createOrGetExistingIosAppCredentialsWithBuildCredentialsAsync(
|
||||
appleAppIdentifierId,
|
||||
iosDistributionType,
|
||||
}: {
|
||||
appleTeam: AppleTeamFragment;
|
||||
appleTeam?: AppleTeamFragment;
|
||||
appleAppIdentifierId: string;
|
||||
iosDistributionType: IosDistributionType;
|
||||
}
|
||||
@@ -197,10 +198,10 @@ async function createOrGetExistingIosAppCredentialsWithBuildCredentialsAsync(
|
||||
} else {
|
||||
const [app, appleAppIdentifier] = await Promise.all([
|
||||
getAppAsync(appLookupParams),
|
||||
createOrGetExistingAppleAppIdentifierAsync(appLookupParams, appleTeam),
|
||||
createOrGetExistingAppleAppIdentifierAsync(appLookupParams, appleTeam ?? null),
|
||||
]);
|
||||
await IosAppCredentialsMutation.createIosAppCredentialsAsync(
|
||||
{ appleTeamId: appleTeam.id },
|
||||
{ appleTeamId: appleTeam?.id },
|
||||
app.id,
|
||||
appleAppIdentifier.id
|
||||
);
|
||||
@@ -243,8 +244,10 @@ export async function createOrGetExistingAppleAppIdentifierAsync(
|
||||
if (appleAppIdentifier) {
|
||||
return appleAppIdentifier;
|
||||
} else {
|
||||
if (!appleTeam) {
|
||||
throw new AppleTeamMissingError();
|
||||
if (isWildcardBundleIdentifier(bundleIdentifier) && !appleTeam) {
|
||||
throw new AppleTeamMissingError(
|
||||
`An Apple Team is required for wildcard bundle identifier: ${bundleIdentifier}`
|
||||
);
|
||||
}
|
||||
const parentAppleAppIdentifier = parentBundleIdentifier
|
||||
? await createOrGetExistingAppleAppIdentifierAsync(
|
||||
@@ -255,7 +258,7 @@ export async function createOrGetExistingAppleAppIdentifierAsync(
|
||||
return await AppleAppIdentifierMutation.createAppleAppIdentifierAsync(
|
||||
{
|
||||
bundleIdentifier,
|
||||
appleTeamId: appleTeam.id,
|
||||
appleTeamId: appleTeam?.id,
|
||||
parentAppleAppId: parentAppleAppIdentifier?.id,
|
||||
},
|
||||
account.id
|
||||
|
||||
+7
@@ -30,6 +30,13 @@ const IosAppCredentialsQuery = {
|
||||
},
|
||||
__typename: 'ApplePushKey',
|
||||
},
|
||||
appSpecificPassword: {
|
||||
id: '64bdd007-da7b-4190-a571-edb87e9324a1',
|
||||
appleIdUsername: '[email protected]',
|
||||
passwordLabel: 'description for super secret password',
|
||||
updatedAt: '2020-10-13T18:39:04.463Z',
|
||||
__typename: 'AppleAppSpecificPassword',
|
||||
},
|
||||
iosAppBuildCredentialsList: [
|
||||
{
|
||||
id: '6f8d0175-0caf-4922-b09b-eae757b83144',
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`print credentials prints the IosAppCredentials map 1`] = `"iOS Credentials Project: @quinlanj/test52 Bundle Identifier: com.quinlanj.test52 Apple Team: test-apple-identifier Push Key: Developer Portal ID: 9839M6AY8W Apple Team: 77KQ969CHE Updated 6 months ago Configuration: App Store Distribution Certificate: Serial Number: test-serial Expiration Date: Wed, 13 Oct 2021 18:28:44 GMT+0000 Apple Team: test-apple-identifier Updated 6 months ago Provisioning Profile: Developer Portal ID: test-profile-id Status: active Expiration Date: Wed, 13 Oct 2021 18:28:44 GMT+0000 Apple Team: test-apple-identifier Updated 5 months ago Configuration: Ad Hoc Distribution Certificate: Serial Number: test-serial Expiration Date: Wed, 13 Oct 2021 18:28:44 GMT+0000 Apple Team: test-apple-identifier Updated 6 months ago Provisioning Profile: Developer Portal ID: test-profile-id Status: active Expiration Date: Wed, 13 Oct 2021 18:28:44 GMT+0000 Apple Team: test-apple-identifier Updated 5 months ago"`;
|
||||
exports[`print credentials prints the IosAppCredentials map 1`] = `"iOS Credentials Project: @quinlanj/test52 Bundle Identifier: com.quinlanj.test52 Apple Team: test-apple-identifier Push Key: Developer Portal ID: 9839M6AY8W Apple Team: 77KQ969CHE Updated 6 months ago App Specific Password: Apple ID Username: [email protected] Password Label: description for super secret password Updated 6 months ago Configuration: App Store Distribution Certificate: Serial Number: test-serial Expiration Date: Wed, 13 Oct 2021 18:28:44 GMT+0000 Apple Team: test-apple-identifier Updated 6 months ago Provisioning Profile: Developer Portal ID: test-profile-id Status: active Expiration Date: Wed, 13 Oct 2021 18:28:44 GMT+0000 Apple Team: test-apple-identifier Updated 5 months ago Configuration: Ad Hoc Distribution Certificate: Serial Number: test-serial Expiration Date: Wed, 13 Oct 2021 18:28:44 GMT+0000 Apple Team: test-apple-identifier Updated 6 months ago Provisioning Profile: Developer Portal ID: test-profile-id Status: active Expiration Date: Wed, 13 Oct 2021 18:28:44 GMT+0000 Apple Team: test-apple-identifier Updated 5 months ago"`;
|
||||
@@ -2,6 +2,7 @@ import chalk from 'chalk';
|
||||
import dateformat from 'dateformat';
|
||||
|
||||
import {
|
||||
AppleAppSpecificPasswordFragment,
|
||||
AppleDeviceFragment,
|
||||
ApplePushKeyFragment,
|
||||
IosAppBuildCredentialsFragment,
|
||||
@@ -77,14 +78,14 @@ 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();
|
||||
continue;
|
||||
}
|
||||
|
||||
const { appleTeam, pushKey } = targetAppCredentials;
|
||||
const { appleTeam, pushKey, appSpecificPassword } = targetAppCredentials;
|
||||
if (appleTeam) {
|
||||
const { appleTeamIdentifier, appleTeamName } = appleTeam;
|
||||
Log.log(` Apple Team: ${appleTeamIdentifier} ${appleTeamName ? `(${appleTeamName})` : ''}`);
|
||||
@@ -95,6 +96,10 @@ export function displayIosCredentials(
|
||||
displayApplePushKey(pushKey);
|
||||
}
|
||||
|
||||
if (appSpecificPassword) {
|
||||
displayAppSpecificPassword(appSpecificPassword);
|
||||
}
|
||||
|
||||
const sortedIosAppBuildCredentialsList = sortBuildCredentialsByDistributionType(
|
||||
targetAppCredentials.iosAppBuildCredentialsList
|
||||
);
|
||||
@@ -189,6 +194,23 @@ function displayIosAppBuildCredentials(buildCredentials: IosAppBuildCredentialsF
|
||||
Log.newLine();
|
||||
}
|
||||
|
||||
function displayAppSpecificPassword(
|
||||
maybeAppSpecificPassword: AppleAppSpecificPasswordFragment | null
|
||||
): void {
|
||||
Log.log(` App Specific Password:`);
|
||||
if (maybeAppSpecificPassword) {
|
||||
const { appleIdUsername, passwordLabel, updatedAt } = maybeAppSpecificPassword;
|
||||
Log.log(` Apple ID Username: ${appleIdUsername}`);
|
||||
if (passwordLabel) {
|
||||
Log.log(` Password Label: ${passwordLabel}`);
|
||||
}
|
||||
Log.log(` Updated ${fromNow(new Date(updatedAt))} ago`);
|
||||
} else {
|
||||
Log.log(` None assigned yet`);
|
||||
}
|
||||
Log.newLine();
|
||||
}
|
||||
|
||||
function displayApplePushKey(maybePushKey: ApplePushKeyFragment | null): void {
|
||||
Log.log(` Push Key:`);
|
||||
if (maybePushKey) {
|
||||
|
||||
@@ -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' }
|
||||
@@ -5088,6 +5107,11 @@ export type AppleAppIdentifierFragment = (
|
||||
& Pick<AppleAppIdentifier, 'id' | 'bundleIdentifier'>
|
||||
);
|
||||
|
||||
export type AppleAppSpecificPasswordFragment = (
|
||||
{ __typename?: 'AppleAppSpecificPassword' }
|
||||
& Pick<AppleAppSpecificPassword, 'id' | 'appleIdUsername' | 'passwordLabel' | 'updatedAt'>
|
||||
);
|
||||
|
||||
export type AppleDeviceFragment = (
|
||||
{ __typename?: 'AppleDevice' }
|
||||
& Pick<AppleDevice, 'id' | 'identifier' | 'name' | 'model' | 'deviceClass'>
|
||||
@@ -5154,6 +5178,18 @@ export type ApplePushKeyFragment = (
|
||||
{ __typename?: 'AppleTeam' }
|
||||
& Pick<AppleTeam, 'id'>
|
||||
& AppleTeamFragment
|
||||
)>, iosAppCredentialsList: Array<(
|
||||
{ __typename?: 'IosAppCredentials' }
|
||||
& Pick<IosAppCredentials, 'id'>
|
||||
& { app: (
|
||||
{ __typename?: 'App' }
|
||||
& Pick<App, 'id'>
|
||||
& AppFragment
|
||||
), appleAppIdentifier: (
|
||||
{ __typename?: 'AppleAppIdentifier' }
|
||||
& Pick<AppleAppIdentifier, 'id'>
|
||||
& AppleAppIdentifierFragment
|
||||
) }
|
||||
)> }
|
||||
);
|
||||
|
||||
@@ -5195,6 +5231,10 @@ export type CommonIosAppCredentialsWithoutBuildCredentialsFragment = (
|
||||
{ __typename?: 'ApplePushKey' }
|
||||
& Pick<ApplePushKey, 'id'>
|
||||
& ApplePushKeyFragment
|
||||
)>, appSpecificPassword?: Maybe<(
|
||||
{ __typename?: 'AppleAppSpecificPassword' }
|
||||
& Pick<AppleAppSpecificPassword, 'id'>
|
||||
& AppleAppSpecificPasswordFragment
|
||||
)> }
|
||||
);
|
||||
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import gql from 'graphql-tag';
|
||||
import { graphqlClient, withErrorHandlingAsync } from '../client';
|
||||
import {
|
||||
AppPlatform,
|
||||
Build,
|
||||
BuildFragment,
|
||||
BuildStatus,
|
||||
BuildsByIdQuery,
|
||||
@@ -21,8 +20,6 @@ type Filters = {
|
||||
limit?: number;
|
||||
};
|
||||
|
||||
type PendingBuildQueryResult = Pick<Build, 'id' | 'platform'>;
|
||||
|
||||
export const BuildQuery = {
|
||||
async byIdAsync(
|
||||
buildId: string,
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const AppleAppSpecificPasswordFragmentNode = gql`
|
||||
fragment AppleAppSpecificPasswordFragment on AppleAppSpecificPassword {
|
||||
id
|
||||
appleIdUsername
|
||||
passwordLabel
|
||||
updatedAt
|
||||
}
|
||||
`;
|
||||
@@ -1,6 +1,8 @@
|
||||
import { print } from 'graphql';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
import { AppFragmentNode } from '../App';
|
||||
import { AppleAppIdentifierFragmentNode } from './AppleAppIdentifier';
|
||||
import { AppleTeamFragmentNode } from './AppleTeam';
|
||||
|
||||
export const ApplePushKeyFragmentNode = gql`
|
||||
@@ -12,6 +14,19 @@ export const ApplePushKeyFragmentNode = gql`
|
||||
id
|
||||
...AppleTeamFragment
|
||||
}
|
||||
iosAppCredentialsList {
|
||||
id
|
||||
app {
|
||||
id
|
||||
...AppFragment
|
||||
}
|
||||
appleAppIdentifier {
|
||||
id
|
||||
...AppleAppIdentifierFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
${print(AppleTeamFragmentNode)}
|
||||
${print(AppFragmentNode)}
|
||||
${print(AppleAppIdentifierFragmentNode)}
|
||||
`;
|
||||
@@ -2,6 +2,7 @@ import gql from 'graphql-tag';
|
||||
|
||||
import { AppFragmentNode } from '../App';
|
||||
import { AppleAppIdentifierFragmentNode } from './AppleAppIdentifier';
|
||||
import { AppleAppSpecificPasswordFragmentNode } from './AppleAppSpecificPassword';
|
||||
import { ApplePushKeyFragmentNode } from './ApplePushKey';
|
||||
import { AppleTeamFragmentNode } from './AppleTeam';
|
||||
import { IosAppBuildCredentialsFragmentNode } from './IosAppBuildCredentials';
|
||||
@@ -25,11 +26,16 @@ export const CommonIosAppCredentialsWithoutBuildCredentialsFragmentNode = gql`
|
||||
id
|
||||
...ApplePushKeyFragment
|
||||
}
|
||||
appSpecificPassword {
|
||||
id
|
||||
...AppleAppSpecificPasswordFragment
|
||||
}
|
||||
}
|
||||
${AppFragmentNode}
|
||||
${AppleTeamFragmentNode}
|
||||
${AppleAppIdentifierFragmentNode}
|
||||
${ApplePushKeyFragmentNode}
|
||||
${AppleAppSpecificPasswordFragmentNode}
|
||||
`;
|
||||
|
||||
export const CommonIosAppCredentialsFragmentNode = gql`
|
||||
|
||||
@@ -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,18 +4,23 @@ 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,
|
||||
getBundleIdentifier,
|
||||
isWildcardBundleIdentifier,
|
||||
} from '../bundleIdentifier';
|
||||
|
||||
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(() => {
|
||||
@@ -30,6 +35,7 @@ beforeEach(() => {
|
||||
afterAll(() => {
|
||||
fs.removeSync(os.tmpdir());
|
||||
console.warn = originalConsoleWarn;
|
||||
console.log = originalConsoleLog;
|
||||
});
|
||||
|
||||
const originalFs = jest.requireActual('fs');
|
||||
@@ -141,3 +147,15 @@ describe(ensureBundleIdentifierIsDefinedForManagedProjectAsync, () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe(isWildcardBundleIdentifier, () => {
|
||||
it('classifies wildcard bundle identifiers correctly', async () => {
|
||||
expect(isWildcardBundleIdentifier('doge.doge.*')).toBe(true);
|
||||
expect(isWildcardBundleIdentifier('doge*')).toBe(true);
|
||||
|
||||
expect(isWildcardBundleIdentifier('*')).toBe(false);
|
||||
expect(isWildcardBundleIdentifier('*.doge')).toBe(false);
|
||||
expect(isWildcardBundleIdentifier('doge')).toBe(false);
|
||||
expect(isWildcardBundleIdentifier('doge.doge.doge')).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -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(
|
||||
@@ -130,3 +141,24 @@ function _warnIfBundleIdentifierDefinedInAppConfigForGenericProject(
|
||||
export const warnIfBundleIdentifierDefinedInAppConfigForGenericProject = once(
|
||||
_warnIfBundleIdentifierDefinedInAppConfigForGenericProject
|
||||
);
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -56,7 +56,7 @@ export default class GitClient extends Client {
|
||||
|
||||
public async hasUncommittedChangesAsync(): Promise<boolean> {
|
||||
const changes = await gitStatusAsync({ showUntracked: true });
|
||||
return changes.length !== 0;
|
||||
return changes.length > 0;
|
||||
}
|
||||
|
||||
public async getRootPathAsync(): Promise<string> {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "@expo/eas-json",
|
||||
"description": "A library for interacting with the eas.json",
|
||||
"version": "0.18.0",
|
||||
"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"
|
||||
|
||||
@@ -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;
|
||||
@@ -35,19 +35,20 @@ export interface AndroidGenericBuildProfile extends Android.BuilderEnvironment {
|
||||
cache: Cache;
|
||||
}
|
||||
|
||||
export interface IosManagedBuildProfile extends Ios.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;
|
||||
enterpriseProvisioning?: IosEnterpriseProvisioning;
|
||||
autoIncrement: VersionAutoIncrement;
|
||||
cache: Cache;
|
||||
image?: Ios.BuilderEnvironment['image'];
|
||||
}
|
||||
|
||||
export interface IosGenericBuildProfile extends Ios.BuilderEnvironment {
|
||||
export interface IosGenericBuildProfile extends Omit<Ios.BuilderEnvironment, 'image'> {
|
||||
workflow: Workflow.GENERIC;
|
||||
credentialsSource: CredentialsSource;
|
||||
scheme?: string;
|
||||
@@ -59,6 +60,7 @@ export interface IosGenericBuildProfile extends Ios.BuilderEnvironment {
|
||||
enterpriseProvisioning?: IosEnterpriseProvisioning;
|
||||
autoIncrement: VersionAutoIncrement;
|
||||
cache: Cache;
|
||||
image?: Ios.BuilderEnvironment['image'];
|
||||
}
|
||||
|
||||
export type AndroidBuildProfile = AndroidManagedBuildProfile | AndroidGenericBuildProfile;
|
||||
|
||||
@@ -21,9 +21,7 @@ const AndroidBuilderEnvironmentSchema = Joi.object({
|
||||
});
|
||||
|
||||
const IosBuilderEnvironmentSchema = Joi.object({
|
||||
image: Joi.string()
|
||||
.valid(...Ios.builderBaseImages)
|
||||
.default('default'),
|
||||
image: Joi.string().valid(...Ios.builderBaseImages),
|
||||
node: Joi.string().empty(null).custom(semverSchemaCheck),
|
||||
yarn: Joi.string().empty(null).custom(semverSchemaCheck),
|
||||
bundler: Joi.string().empty(null).custom(semverSchemaCheck),
|
||||
@@ -100,7 +98,7 @@ const IosManagedSchema = Joi.object({
|
||||
cache: CacheSchema.default(),
|
||||
}).concat(IosBuilderEnvironmentSchema);
|
||||
|
||||
const schemaBuildProfileMap: Record<string, Record<string, Joi.Schema>> = {
|
||||
export const schemaBuildProfileMap: Record<string, Record<string, Joi.Schema>> = {
|
||||
android: {
|
||||
generic: AndroidGenericSchema,
|
||||
managed: AndroidManagedSchema,
|
||||
@@ -111,7 +109,7 @@ const schemaBuildProfileMap: Record<string, Record<string, Joi.Schema>> = {
|
||||
},
|
||||
};
|
||||
|
||||
const EasJsonSchema = Joi.object({
|
||||
export const EasJsonSchema = Joi.object({
|
||||
builds: Joi.object({
|
||||
android: Joi.object().pattern(
|
||||
Joi.string(),
|
||||
@@ -127,5 +125,3 @@ const EasJsonSchema = Joi.object({
|
||||
),
|
||||
}),
|
||||
});
|
||||
|
||||
export { EasJsonSchema, schemaBuildProfileMap };
|
||||
@@ -56,7 +56,6 @@ test('minimal valid ios eas.json', async () => {
|
||||
autoIncrement: false,
|
||||
env: {},
|
||||
cache: { disabled: false, cacheDefaultPaths: true, customPaths: [] },
|
||||
image: 'default',
|
||||
},
|
||||
},
|
||||
}).toEqual(easJson);
|
||||
@@ -94,7 +93,6 @@ test('minimal valid eas.json for both platforms', async () => {
|
||||
autoIncrement: false,
|
||||
env: {},
|
||||
cache: { disabled: false, cacheDefaultPaths: true, customPaths: [] },
|
||||
image: 'default',
|
||||
},
|
||||
},
|
||||
}).toEqual(easJson);
|
||||
@@ -165,7 +163,6 @@ test('valid eas.json for development client builds', async () => {
|
||||
distribution: 'store',
|
||||
autoIncrement: false,
|
||||
env: {},
|
||||
image: 'default',
|
||||
cache: { disabled: false, cacheDefaultPaths: true, customPaths: [] },
|
||||
buildType: 'development-client',
|
||||
},
|
||||
|
||||
@@ -1917,17 +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==
|
||||
dependencies:
|
||||
"@hapi/joi" "^17.1.1"
|
||||
|
||||
"@expo/[email protected]":
|
||||
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"
|
||||
|
||||
|
||||
Reference in new issue
Block a user