mirror of
https://github.com/expo/eas-cli.git
synced 2026-11-13 20:28:08 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
995bdf746b | ||
|
|
ff94be6857 | ||
|
|
bbe9426133 | ||
|
|
29d7f73051 | ||
|
|
9ff1f9e1a9 | ||
|
|
0c83275e05 |
No files matched your search
+1
-92
@@ -8,107 +8,16 @@ This is the log of notable changes to EAS CLI and related packages.
|
||||
|
||||
### 🎉 New features
|
||||
|
||||
- Add `-e` as a shortcut for `--profile` flag. ([#1342](https://github.com/expo/eas-cli/pull/1342) by [@szdziedzic](https://github.com/szdziedzic))
|
||||
- Support JSON5 in **eas.json**. ([#1350](https://github.com/expo/eas-cli/pull/1350) by [@dsokal](https://github.com/dsokal))
|
||||
|
||||
### 🐛 Bug fixes
|
||||
|
||||
### 🧹 Chores
|
||||
|
||||
## [2.1.0](https://github.com/expo/eas-cli/releases/tag/v2.1.0) - 2022-09-05
|
||||
|
||||
### 🎉 New features
|
||||
|
||||
- Add tvOS credentials compatibility for Adhoc and App store builds. ([#1325](https://github.com/expo/eas-cli/pull/1325) by [@quinlanj](https://github.com/quinlanj))
|
||||
- Add `eas open` command for opening project page in web browser. ([#1337](https://github.com/expo/eas-cli/pull/1337) by [@dsokal](https://github.com/dsokal))
|
||||
- Add support for buildArtifactPaths. Rename artifactPath to applicationArchivePath. ([#1321](https://github.com/expo/eas-cli/pull/1321) by [@dsokal](https://github.com/dsokal))
|
||||
|
||||
### 🐛 Bug fixes
|
||||
|
||||
- Fix viewing branch list when a branch has no associated platforms. ([#1326](https://github.com/expo/eas-cli/pull/1326) by [@hbiede](https://github.com/hbiede))
|
||||
- Fix description of `help` command in help prompt. ([#1341](https://github.com/expo/eas-cli/pull/1341) by [@Simek](https://github.com/Simek))
|
||||
- Resolve paths from the root when checking for gitignored values. ([#1336](https://github.com/expo/eas-cli/pull/1336) by [@wkozyra95](https://github.com/wkozyra95))
|
||||
|
||||
### 🧹 Chores
|
||||
|
||||
- Add noImplicitOverride to tsconfigs. ([#1327](https://github.com/expo/eas-cli/pull/1327) by [@wschurman](https://github.com/wschurman))
|
||||
- Fix typos. ([#1340](https://github.com/expo/eas-cli/pull/1340) by [@hbiede](https://github.com/hbiede))
|
||||
|
||||
## [2.0.0](https://github.com/expo/eas-cli/releases/tag/v2.0.0) - 2022-09-01
|
||||
|
||||
### 🛠 Breaking changes
|
||||
|
||||
- Fix typo in `cli.promptToConfigurePushNotifications` field in **eas.json**. EAS CLI will throw an error if the old field name is in **eas.json**. ([#1332](https://github.com/expo/eas-cli/pull/1332) by [@dsokal](https://github.com/dsokal))
|
||||
|
||||
### 🐛 Bug fixes
|
||||
|
||||
- Fix dynamic config update warning. ([#1322](https://github.com/expo/eas-cli/pull/1322) by [@wschurman](https://github.com/wschurman))
|
||||
|
||||
## [1.2.0](https://github.com/expo/eas-cli/releases/tag/v1.2.0) - 2022-08-29
|
||||
|
||||
### 🎉 New features
|
||||
|
||||
- Add 2022 Apple capabilities. ([#1307](https://github.com/expo/eas-cli/pull/1307) by [@EvanBacon](https://github.com/EvanBacon))
|
||||
- Print warning when eas-cli is installed as project dependency. ([#1310](https://github.com/expo/eas-cli/pull/1310) by [@dsokal](https://github.com/dsokal))
|
||||
- Add eas.json to skip push notifications credentials setup. ([#1315](https://github.com/expo/eas-cli/pull/1315) by [@dsokal](https://github.com/dsokal))
|
||||
- Warn about EAS outages when running `build`, `submit`, and `update` commands. ([#1312](https://github.com/expo/eas-cli/pull/1312) by [@szdziedzic](https://github.com/szdziedzic))
|
||||
|
||||
### 🐛 Bug fixes
|
||||
|
||||
- Replace promptToCreateProjectIfNotExistsAsync with getProjectIdAsync. ([#1303](https://github.com/expo/eas-cli/pull/1303) by [@wschurman](https://github.com/wschurman))
|
||||
- Use AppQuery instead of ProjectQuery. ([#1304](https://github.com/expo/eas-cli/pull/1304) by [@wschurman](https://github.com/wschurman))
|
||||
|
||||
### 🧹 Chores
|
||||
|
||||
- Improve instructions on setting `extra.eas.projectId` in app configuration. ([#1316](https://github.com/expo/eas-cli/pull/1316) by [@dsokal](https://github.com/dsokal))
|
||||
- Improve copy in EAS Submit - "e-mail" -> email, and make the link to app on App Store go directly to the TestFlight tab. ([#1318](https://github.com/expo/eas-cli/pull/1318) by [@brentvatne](https://github.com/brentvatne))
|
||||
|
||||
## [1.1.1](https://github.com/expo/eas-cli/releases/tag/v1.1.1) - 2022-08-23
|
||||
|
||||
### 🎉 New features
|
||||
|
||||
- Add support for `autoIncrement` option at the root of the build profile. ([#1298](https://github.com/expo/eas-cli/pull/1298) by [@szdziedzic](https://github.com/szdziedzic))
|
||||
|
||||
### 🐛 Bug fixes
|
||||
|
||||
- Handle trailing backslash in `.gitignore`. ([#1306](https://github.com/expo/eas-cli/pull/1306) by [@wkozyra95](https://github.com/wkozyra95))
|
||||
- Retry ASC Api Key downloads if it has not fully propagated on Apple's infrastructure. ([#1302](https://github.com/expo/eas-cli/pull/1302) by [@quinlanj](https://github.com/quinlanj))
|
||||
|
||||
## [1.1.0](https://github.com/expo/eas-cli/releases/tag/v1.1.0) - 2022-08-23
|
||||
|
||||
### 🎉 New features
|
||||
|
||||
- Add support for passing platform flag to `credentials` command. ([#1277](https://github.com/expo/eas-cli/pull/1277) by [@Simek](https://github.com/Simek))
|
||||
|
||||
### 🐛 Bug fixes
|
||||
|
||||
- Prevent throwing dynamic app config write error when configuring project ID. ([#1301](https://github.com/expo/eas-cli/pull/1301) by [@wschurman](https://github.com/wschurman))
|
||||
|
||||
### 🧹 Chores
|
||||
|
||||
- Remove unused dependency and devDependency from the CLI. ([#1297](https://github.com/expo/eas-cli/pull/1297) by [@Simek](https://github.com/Simek))
|
||||
|
||||
## [1.0.0](https://github.com/expo/eas-cli/releases/tag/v1.0.0) - 2022-08-22
|
||||
|
||||
### 🛠 Breaking changes
|
||||
|
||||
- Remove timeout when waiting for build / submission. ([#1289](https://github.com/expo/eas-cli/pull/1289) by [@dsokal](https://github.com/dsokal))
|
||||
|
||||
### 🎉 New features
|
||||
|
||||
- Add metadata support for dynamic store.config.js files. ([#1270](https://github.com/expo/eas-cli/pull/1270) by [@byCedric](https://github.com/byCedric))
|
||||
- Improve reliability of update asset presigned upload requests. ([#1278](https://github.com/expo/eas-cli/pull/1278) by [@wschurman](https://github.com/wschurman))
|
||||
- Warn for misconfigured channel configuration when using EAS Update. ([#1082](https://github.com/expo/eas-cli/pull/1082)) by [@kbrandwijk](https://github.com/kbrandwijk))
|
||||
|
||||
### 🐛 Bug fixes
|
||||
|
||||
- Rebind `console.info` correctly after `ora` instance stops. ([#1113](https://github.com/expo/eas-cli/pull/1113) by [@EvanBacon](https://github.com/EvanBacon))
|
||||
- Fix initializing git repository in monorepo. ([#1279](https://github.com/expo/eas-cli/pull/1279) by [@dsokal](https://github.com/dsokal))
|
||||
- Limit the number of SignedAssetUploadSpecifications fetched at a time. ([#1287](https://github.com/expo/eas-cli/pull/1287) by [@wschurman](https://github.com/wschurman))
|
||||
|
||||
### 🧹 Chores
|
||||
|
||||
- Remove unused install script. ([#1280](https://github.com/expo/eas-cli/pull/1280), [#1281](https://github.com/expo/eas-cli/pull/1281) by [@wkozyra95](https://github.com/wkozyra95))
|
||||
- Remove "please" from output ([#1250](https://github.com/expo/eas-cli/pull/1250) by [@jonsamp](https://github.com/jonsamp))
|
||||
|
||||
## [0.60.0](https://github.com/expo/eas-cli/releases/tag/v0.60.0) - 2022-08-12
|
||||
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@
|
||||
packages/eas-cli/src/build @dsokal @wkozyra95
|
||||
packages/eas-cli/src/commands/build @dsokal @wkozyra95
|
||||
|
||||
packages/eas-cli/src/submit @dsokal
|
||||
packages/eas-cli/src/commands/submit.ts @dsokal
|
||||
packages/eas-cli/src/submit @barthap @dsokal
|
||||
packages/eas-cli/src/commands/submit.ts @barthap @dsokal
|
||||
|
||||
packages/eas-cli/src/update @kgc00 @wschurman
|
||||
packages/eas-cli/src/commands/update @kgc00 @wschurman
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"version": "2.1.0"
|
||||
"version": "0.60.0"
|
||||
}
|
||||
+50
-90
@@ -19,28 +19,6 @@ npm install -g eas-cli
|
||||
yarn global add eas-cli
|
||||
```
|
||||
|
||||
## Enforcing eas-cli version for your project
|
||||
|
||||
If you want to enforce the `eas-cli` version for your project, use the `"cli.version"` field in **eas.json**. Installing `eas-cli` to your project dependencies is strongly discouraged because it may cause dependency conflicts that are difficult to debug.
|
||||
|
||||
An example of **eas.json** that enforces `eas-cli` in version `1.0.0` or newer:
|
||||
|
||||
```json
|
||||
{
|
||||
"cli": {
|
||||
"version": ">=1.0.0"
|
||||
},
|
||||
"build": {
|
||||
// build profiles
|
||||
},
|
||||
"submit": {
|
||||
// submit profiles
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Learn more: https://docs.expo.dev/build-reference/eas-json/
|
||||
|
||||
# Usage
|
||||
|
||||
```sh
|
||||
@@ -91,7 +69,6 @@ eas --help COMMAND
|
||||
* [`eas logout`](#eas-logout)
|
||||
* [`eas metadata:pull`](#eas-metadatapull)
|
||||
* [`eas metadata:push`](#eas-metadatapush)
|
||||
* [`eas open`](#eas-open)
|
||||
* [`eas project:info`](#eas-projectinfo)
|
||||
* [`eas project:init`](#eas-projectinit)
|
||||
* [`eas secret:create`](#eas-secretcreate)
|
||||
@@ -125,7 +102,7 @@ ALIASES
|
||||
$ eas login
|
||||
```
|
||||
|
||||
_See code: [src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/account/login.ts)_
|
||||
_See code: [src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/account/login.ts)_
|
||||
|
||||
## `eas account:logout`
|
||||
|
||||
@@ -142,7 +119,7 @@ ALIASES
|
||||
$ eas logout
|
||||
```
|
||||
|
||||
_See code: [src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/account/logout.ts)_
|
||||
_See code: [src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/account/logout.ts)_
|
||||
|
||||
## `eas account:view`
|
||||
|
||||
@@ -159,7 +136,7 @@ ALIASES
|
||||
$ eas whoami
|
||||
```
|
||||
|
||||
_See code: [src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/account/view.ts)_
|
||||
_See code: [src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/account/view.ts)_
|
||||
|
||||
## `eas analytics [STATUS]`
|
||||
|
||||
@@ -173,7 +150,7 @@ DESCRIPTION
|
||||
display or change analytics settings
|
||||
```
|
||||
|
||||
_See code: [src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/analytics.ts)_
|
||||
_See code: [src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/analytics.ts)_
|
||||
|
||||
## `eas autocomplete [SHELL]`
|
||||
|
||||
@@ -222,7 +199,7 @@ DESCRIPTION
|
||||
create a branch
|
||||
```
|
||||
|
||||
_See code: [src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/branch/create.ts)_
|
||||
_See code: [src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/branch/create.ts)_
|
||||
|
||||
## `eas branch:delete [NAME]`
|
||||
|
||||
@@ -242,7 +219,7 @@ DESCRIPTION
|
||||
delete a branch
|
||||
```
|
||||
|
||||
_See code: [src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/branch/delete.ts)_
|
||||
_See code: [src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/branch/delete.ts)_
|
||||
|
||||
## `eas branch:list`
|
||||
|
||||
@@ -263,7 +240,7 @@ DESCRIPTION
|
||||
list all branches
|
||||
```
|
||||
|
||||
_See code: [src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/branch/list.ts)_
|
||||
_See code: [src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/branch/list.ts)_
|
||||
|
||||
## `eas branch:rename`
|
||||
|
||||
@@ -282,7 +259,7 @@ DESCRIPTION
|
||||
rename a branch
|
||||
```
|
||||
|
||||
_See code: [src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/branch/rename.ts)_
|
||||
_See code: [src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/branch/rename.ts)_
|
||||
|
||||
## `eas branch:view [NAME]`
|
||||
|
||||
@@ -306,7 +283,7 @@ DESCRIPTION
|
||||
view a branch
|
||||
```
|
||||
|
||||
_See code: [src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/branch/view.ts)_
|
||||
_See code: [src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/branch/view.ts)_
|
||||
|
||||
## `eas build`
|
||||
|
||||
@@ -336,7 +313,7 @@ DESCRIPTION
|
||||
start a build
|
||||
```
|
||||
|
||||
_See code: [src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/build/index.ts)_
|
||||
_See code: [src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/build/index.ts)_
|
||||
|
||||
## `eas build:cancel [BUILD_ID]`
|
||||
|
||||
@@ -350,7 +327,7 @@ DESCRIPTION
|
||||
cancel a build
|
||||
```
|
||||
|
||||
_See code: [src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/build/cancel.ts)_
|
||||
_See code: [src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/build/cancel.ts)_
|
||||
|
||||
## `eas build:configure`
|
||||
|
||||
@@ -367,7 +344,7 @@ DESCRIPTION
|
||||
configure the project to support EAS Build
|
||||
```
|
||||
|
||||
_See code: [src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/build/configure.ts)_
|
||||
_See code: [src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/build/configure.ts)_
|
||||
|
||||
## `eas build:inspect`
|
||||
|
||||
@@ -402,7 +379,7 @@ DESCRIPTION
|
||||
inspect the state of the project at specific build stages, useful for troubleshooting
|
||||
```
|
||||
|
||||
_See code: [src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/build/inspect.ts)_
|
||||
_See code: [src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/build/inspect.ts)_
|
||||
|
||||
## `eas build:list`
|
||||
|
||||
@@ -435,7 +412,7 @@ DESCRIPTION
|
||||
list all builds for your project
|
||||
```
|
||||
|
||||
_See code: [src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/build/list.ts)_
|
||||
_See code: [src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/build/list.ts)_
|
||||
|
||||
## `eas build:submit`
|
||||
|
||||
@@ -482,7 +459,7 @@ DESCRIPTION
|
||||
Update version of an app.
|
||||
```
|
||||
|
||||
_See code: [src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/build/version/set.ts)_
|
||||
_See code: [src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/build/version/set.ts)_
|
||||
|
||||
## `eas build:version:sync`
|
||||
|
||||
@@ -501,7 +478,7 @@ DESCRIPTION
|
||||
Update a version in native code with a value stored on EAS servers
|
||||
```
|
||||
|
||||
_See code: [src/commands/build/version/sync.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/build/version/sync.ts)_
|
||||
_See code: [src/commands/build/version/sync.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/build/version/sync.ts)_
|
||||
|
||||
## `eas build:view [BUILD_ID]`
|
||||
|
||||
@@ -518,7 +495,7 @@ DESCRIPTION
|
||||
view a build for your project
|
||||
```
|
||||
|
||||
_See code: [src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/build/view.ts)_
|
||||
_See code: [src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/build/view.ts)_
|
||||
|
||||
## `eas channel:create [NAME]`
|
||||
|
||||
@@ -538,7 +515,7 @@ DESCRIPTION
|
||||
create a channel
|
||||
```
|
||||
|
||||
_See code: [src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/channel/create.ts)_
|
||||
_See code: [src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/channel/create.ts)_
|
||||
|
||||
## `eas channel:edit [NAME]`
|
||||
|
||||
@@ -559,7 +536,7 @@ DESCRIPTION
|
||||
point a channel at a new branch
|
||||
```
|
||||
|
||||
_See code: [src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/channel/edit.ts)_
|
||||
_See code: [src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/channel/edit.ts)_
|
||||
|
||||
## `eas channel:list`
|
||||
|
||||
@@ -576,7 +553,7 @@ DESCRIPTION
|
||||
list all channels
|
||||
```
|
||||
|
||||
_See code: [src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/channel/list.ts)_
|
||||
_See code: [src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/channel/list.ts)_
|
||||
|
||||
## `eas channel:view [NAME]`
|
||||
|
||||
@@ -596,7 +573,7 @@ DESCRIPTION
|
||||
view a channel
|
||||
```
|
||||
|
||||
_See code: [src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/channel/view.ts)_
|
||||
_See code: [src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/channel/view.ts)_
|
||||
|
||||
## `eas config`
|
||||
|
||||
@@ -614,7 +591,7 @@ DESCRIPTION
|
||||
display project configuration (app.json + eas.json)
|
||||
```
|
||||
|
||||
_See code: [src/commands/config.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/config.ts)_
|
||||
_See code: [src/commands/config.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/config.ts)_
|
||||
|
||||
## `eas credentials`
|
||||
|
||||
@@ -622,16 +599,13 @@ manage credentials
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas credentials [-p android|ios]
|
||||
|
||||
FLAGS
|
||||
-p, --platform=(android|ios)
|
||||
$ eas credentials
|
||||
|
||||
DESCRIPTION
|
||||
manage credentials
|
||||
```
|
||||
|
||||
_See code: [src/commands/credentials.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/credentials.ts)_
|
||||
_See code: [src/commands/credentials.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/credentials.ts)_
|
||||
|
||||
## `eas device:create`
|
||||
|
||||
@@ -645,7 +619,7 @@ DESCRIPTION
|
||||
register new Apple Devices to use for internal distribution
|
||||
```
|
||||
|
||||
_See code: [src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/device/create.ts)_
|
||||
_See code: [src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/device/create.ts)_
|
||||
|
||||
## `eas device:delete`
|
||||
|
||||
@@ -663,7 +637,7 @@ DESCRIPTION
|
||||
remove a registered device from your account
|
||||
```
|
||||
|
||||
_See code: [src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/device/delete.ts)_
|
||||
_See code: [src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/device/delete.ts)_
|
||||
|
||||
## `eas device:list`
|
||||
|
||||
@@ -680,7 +654,7 @@ DESCRIPTION
|
||||
list all registered devices for your account
|
||||
```
|
||||
|
||||
_See code: [src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/device/list.ts)_
|
||||
_See code: [src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/device/list.ts)_
|
||||
|
||||
## `eas device:view [UDID]`
|
||||
|
||||
@@ -694,7 +668,7 @@ DESCRIPTION
|
||||
view a device for your project
|
||||
```
|
||||
|
||||
_See code: [src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/device/view.ts)_
|
||||
_See code: [src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/device/view.ts)_
|
||||
|
||||
## `eas diagnostics`
|
||||
|
||||
@@ -708,11 +682,11 @@ DESCRIPTION
|
||||
display environment info
|
||||
```
|
||||
|
||||
_See code: [src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/diagnostics.ts)_
|
||||
_See code: [src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/diagnostics.ts)_
|
||||
|
||||
## `eas help [COMMAND]`
|
||||
|
||||
display help for eas-cli
|
||||
Display help for eas.
|
||||
|
||||
```
|
||||
USAGE
|
||||
@@ -725,10 +699,10 @@ FLAGS
|
||||
-n, --nested-commands Include all nested commands in the output.
|
||||
|
||||
DESCRIPTION
|
||||
display help for eas-cli
|
||||
Display help for eas.
|
||||
```
|
||||
|
||||
_See code: [@expo/plugin-help](https://github.com/expo/oclif-plugin-help/blob/v5.3.0/src/commands/help.ts)_
|
||||
_See code: [@expo/plugin-help](https://github.com/expo/oclif-plugin-help/blob/v5.2.0/src/commands/help.ts)_
|
||||
|
||||
## `eas init`
|
||||
|
||||
@@ -790,7 +764,7 @@ DESCRIPTION
|
||||
generate the local store configuration from the app stores
|
||||
```
|
||||
|
||||
_See code: [src/commands/metadata/pull.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/metadata/pull.ts)_
|
||||
_See code: [src/commands/metadata/pull.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/metadata/pull.ts)_
|
||||
|
||||
## `eas metadata:push`
|
||||
|
||||
@@ -807,21 +781,7 @@ DESCRIPTION
|
||||
sync the local store configuration to the app stores
|
||||
```
|
||||
|
||||
_See code: [src/commands/metadata/push.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/metadata/push.ts)_
|
||||
|
||||
## `eas open`
|
||||
|
||||
open the project page in a web browser
|
||||
|
||||
```
|
||||
USAGE
|
||||
$ eas open
|
||||
|
||||
DESCRIPTION
|
||||
open the project page in a web browser
|
||||
```
|
||||
|
||||
_See code: [src/commands/open.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/open.ts)_
|
||||
_See code: [src/commands/metadata/push.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/metadata/push.ts)_
|
||||
|
||||
## `eas project:info`
|
||||
|
||||
@@ -835,7 +795,7 @@ DESCRIPTION
|
||||
information about the current project
|
||||
```
|
||||
|
||||
_See code: [src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/project/info.ts)_
|
||||
_See code: [src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/project/info.ts)_
|
||||
|
||||
## `eas project:init`
|
||||
|
||||
@@ -852,7 +812,7 @@ ALIASES
|
||||
$ eas init
|
||||
```
|
||||
|
||||
_See code: [src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/project/init.ts)_
|
||||
_See code: [src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/project/init.ts)_
|
||||
|
||||
## `eas secret:create`
|
||||
|
||||
@@ -872,7 +832,7 @@ DESCRIPTION
|
||||
create an environment secret on the current project or owner account
|
||||
```
|
||||
|
||||
_See code: [src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/secret/create.ts)_
|
||||
_See code: [src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/secret/create.ts)_
|
||||
|
||||
## `eas secret:delete`
|
||||
|
||||
@@ -889,7 +849,7 @@ DESCRIPTION
|
||||
delete an environment secret by ID
|
||||
```
|
||||
|
||||
_See code: [src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/secret/delete.ts)_
|
||||
_See code: [src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/secret/delete.ts)_
|
||||
|
||||
## `eas secret:list`
|
||||
|
||||
@@ -903,7 +863,7 @@ DESCRIPTION
|
||||
list environment secrets available for your current app
|
||||
```
|
||||
|
||||
_See code: [src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/secret/list.ts)_
|
||||
_See code: [src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/secret/list.ts)_
|
||||
|
||||
## `eas submit`
|
||||
|
||||
@@ -933,7 +893,7 @@ ALIASES
|
||||
$ eas build:submit
|
||||
```
|
||||
|
||||
_See code: [src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/submit.ts)_
|
||||
_See code: [src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/submit.ts)_
|
||||
|
||||
## `eas update`
|
||||
|
||||
@@ -963,7 +923,7 @@ DESCRIPTION
|
||||
publish an update group
|
||||
```
|
||||
|
||||
_See code: [src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/update/index.ts)_
|
||||
_See code: [src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/update/index.ts)_
|
||||
|
||||
## `eas update:configure`
|
||||
|
||||
@@ -980,7 +940,7 @@ DESCRIPTION
|
||||
configure the project to support EAS Update
|
||||
```
|
||||
|
||||
_See code: [src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/update/configure.ts)_
|
||||
_See code: [src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/update/configure.ts)_
|
||||
|
||||
## `eas update:delete GROUPID`
|
||||
|
||||
@@ -1000,7 +960,7 @@ DESCRIPTION
|
||||
delete all the updates in an update group
|
||||
```
|
||||
|
||||
_See code: [src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/update/delete.ts)_
|
||||
_See code: [src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/update/delete.ts)_
|
||||
|
||||
## `eas update:list`
|
||||
|
||||
@@ -1019,7 +979,7 @@ DESCRIPTION
|
||||
view the recent updates for a branch
|
||||
```
|
||||
|
||||
_See code: [src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/update/list.ts)_
|
||||
_See code: [src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/update/list.ts)_
|
||||
|
||||
## `eas update:view GROUPID`
|
||||
|
||||
@@ -1039,7 +999,7 @@ DESCRIPTION
|
||||
update group details
|
||||
```
|
||||
|
||||
_See code: [src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/update/view.ts)_
|
||||
_See code: [src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/update/view.ts)_
|
||||
|
||||
## `eas webhook:create`
|
||||
|
||||
@@ -1059,7 +1019,7 @@ DESCRIPTION
|
||||
create a webhook
|
||||
```
|
||||
|
||||
_See code: [src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/webhook/create.ts)_
|
||||
_See code: [src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/webhook/create.ts)_
|
||||
|
||||
## `eas webhook:delete [ID]`
|
||||
|
||||
@@ -1076,7 +1036,7 @@ DESCRIPTION
|
||||
delete a webhook
|
||||
```
|
||||
|
||||
_See code: [src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/webhook/delete.ts)_
|
||||
_See code: [src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/webhook/delete.ts)_
|
||||
|
||||
## `eas webhook:list`
|
||||
|
||||
@@ -1093,7 +1053,7 @@ DESCRIPTION
|
||||
list webhooks
|
||||
```
|
||||
|
||||
_See code: [src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/webhook/list.ts)_
|
||||
_See code: [src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/webhook/list.ts)_
|
||||
|
||||
## `eas webhook:update`
|
||||
|
||||
@@ -1114,7 +1074,7 @@ DESCRIPTION
|
||||
update a webhook
|
||||
```
|
||||
|
||||
_See code: [src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/webhook/update.ts)_
|
||||
_See code: [src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/webhook/update.ts)_
|
||||
|
||||
## `eas webhook:view ID`
|
||||
|
||||
@@ -1131,7 +1091,7 @@ DESCRIPTION
|
||||
view a webhook
|
||||
```
|
||||
|
||||
_See code: [src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v2.1.0/packages/eas-cli/src/commands/webhook/view.ts)_
|
||||
_See code: [src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v0.60.0/packages/eas-cli/src/commands/webhook/view.ts)_
|
||||
|
||||
## `eas whoami`
|
||||
|
||||
|
||||
Generated
+50
-1447
File diff suppressed because it is too large.
Load diff
@@ -1,27 +1,27 @@
|
||||
{
|
||||
"name": "eas-cli",
|
||||
"description": "EAS command line tool",
|
||||
"version": "2.1.0",
|
||||
"version": "0.60.0",
|
||||
"author": "Expo <[email protected]>",
|
||||
"bin": {
|
||||
"eas": "./bin/run"
|
||||
},
|
||||
"bugs": "https://github.com/expo/eas-cli/issues",
|
||||
"dependencies": {
|
||||
"@expo/apple-utils": "0.0.0-alpha.34",
|
||||
"@expo/apple-utils": "0.0.0-alpha.33",
|
||||
"@expo/code-signing-certificates": "0.0.2",
|
||||
"@expo/config": "7.0.1",
|
||||
"@expo/config-plugins": "5.0.1",
|
||||
"@expo/config-types": "46.0.2",
|
||||
"@expo/eas-build-job": "0.2.90",
|
||||
"@expo/eas-json": "2.1.0",
|
||||
"@expo/eas-build-job": "0.2.85",
|
||||
"@expo/eas-json": "0.60.0",
|
||||
"@expo/json-file": "8.2.36",
|
||||
"@expo/multipart-body-parser": "1.1.0",
|
||||
"@expo/package-manager": "0.0.56",
|
||||
"@expo/pkcs12": "0.0.8",
|
||||
"@expo/plist": "0.0.18",
|
||||
"@expo/plugin-autocomplete": "1.4.0",
|
||||
"@expo/plugin-help": "5.3.0",
|
||||
"@expo/plugin-help": "5.2.0",
|
||||
"@expo/plugin-warn-if-update-available": "2.3.0",
|
||||
"@expo/prebuild-config": "5.0.3",
|
||||
"@expo/results": "1.0.0",
|
||||
@@ -32,7 +32,6 @@
|
||||
"@urql/core": "2.6.1",
|
||||
"@urql/exchange-retry": "0.3.3",
|
||||
"ajv": "^6.12.6",
|
||||
"better-opn": "3.0.2",
|
||||
"chalk": "4.1.2",
|
||||
"cli-progress": "3.11.2",
|
||||
"cli-table3": "0.6.2",
|
||||
@@ -64,12 +63,12 @@
|
||||
"ora": "5.1.0",
|
||||
"pkg-dir": "4.2.0",
|
||||
"promise-limit": "2.7.0",
|
||||
"promise-retry": "2.0.1",
|
||||
"prompts": "2.4.2",
|
||||
"qrcode-terminal": "0.12.0",
|
||||
"resolve-from": "5.0.0",
|
||||
"semver": "7.3.7",
|
||||
"slash": "3.0.0",
|
||||
"strip-ansi": "6.0.0",
|
||||
"tar": "6.1.11",
|
||||
"terminal-link": "2.1.1",
|
||||
"tslib": "2.4.0",
|
||||
@@ -91,7 +90,6 @@
|
||||
"@types/mime": "2.0.3",
|
||||
"@types/node-fetch": "2.6.2",
|
||||
"@types/node-forge": "1.0.4",
|
||||
"@types/promise-retry": "1.1.3",
|
||||
"@types/prompts": "2.0.14",
|
||||
"@types/semver": "7.3.10",
|
||||
"@types/tar": "6.1.2",
|
||||
@@ -100,10 +98,12 @@
|
||||
"@types/wrap-ansi": "3.0.0",
|
||||
"axios": "0.27.2",
|
||||
"eslint-plugin-graphql": "4.0.0",
|
||||
"form-data": "4.0.0",
|
||||
"memfs": "3.4.7",
|
||||
"mockdate": "3.0.5",
|
||||
"nock": "13.2.9",
|
||||
"rimraf": "3.0.2",
|
||||
"tempy": "0.7.0",
|
||||
"ts-deepmerge": "2.0.5",
|
||||
"ts-mockito": "2.6.1",
|
||||
"ts-node": "10.9.1",
|
||||
|
||||
@@ -15,9 +15,6 @@ export enum SubmissionEvent {
|
||||
SUBMIT_REQUEST_ATTEMPT = 'submit cli request attempt',
|
||||
SUBMIT_REQUEST_SUCCESS = 'submit cli request success',
|
||||
SUBMIT_REQUEST_FAIL = 'submit cli request fail',
|
||||
API_KEY_DOWNLOAD_FAIL = 'submit cli credentials api key download fail',
|
||||
API_KEY_DOWNLOAD_RETRY = 'submit cli credentials api key download fail temporary',
|
||||
API_KEY_DOWNLOAD_SUCCESS = 'submit cli credentials api key download succeed',
|
||||
}
|
||||
|
||||
export enum BuildEvent {
|
||||
|
||||
@@ -4,7 +4,7 @@ import fetch, { RequestError, RequestInit } from './fetch';
|
||||
import { getAccessToken, getSessionSecret } from './user/sessionStorage';
|
||||
|
||||
export class ApiV2Error extends Error {
|
||||
override readonly name = 'ApiV2Error';
|
||||
readonly name = 'ApiV2Error';
|
||||
readonly expoApiV2ErrorCode: string;
|
||||
readonly expoApiV2ErrorDetails?: JSONValue;
|
||||
readonly expoApiV2ErrorServerStack?: string;
|
||||
|
||||
@@ -89,21 +89,16 @@ function renderPageOfBranches(
|
||||
});
|
||||
|
||||
table.push(
|
||||
...currentPage.map(branch => {
|
||||
const update: UpdateBranchFragment['updates'][0] | undefined = branch.updates[0];
|
||||
return [
|
||||
branch.name,
|
||||
formatUpdate(update),
|
||||
update?.runtimeVersion ?? 'N/A',
|
||||
update?.group ?? 'N/A',
|
||||
update?.group
|
||||
? getPlatformsForGroup({
|
||||
updates: branch.updates,
|
||||
group: update.group,
|
||||
})
|
||||
: 'N/A',
|
||||
];
|
||||
})
|
||||
...currentPage.map(branch => [
|
||||
branch.name,
|
||||
formatUpdate(branch.updates[0]),
|
||||
branch.updates[0]?.runtimeVersion ?? 'N/A',
|
||||
branch.updates[0]?.group ?? 'N/A',
|
||||
getPlatformsForGroup({
|
||||
updates: branch.updates,
|
||||
group: branch.updates[0]?.group,
|
||||
}),
|
||||
])
|
||||
);
|
||||
|
||||
Log.addNewLineIfNone();
|
||||
|
||||
@@ -73,17 +73,17 @@ describe(bumpVersionAsync, () => {
|
||||
|
||||
await bumpVersionAsync({
|
||||
bumpStrategy: BumpStrategy.VERSION_CODE,
|
||||
projectDir: '/app',
|
||||
projectDir: '/repo',
|
||||
exp: fakeExp,
|
||||
});
|
||||
|
||||
const appJSON = await fs.readJSON('/app/app.json');
|
||||
const appJSON = await fs.readJSON('/repo/app.json');
|
||||
expect(fakeExp.version).toBe('3.0.0');
|
||||
expect(fakeExp.android?.versionCode).toBe(124);
|
||||
expect(appJSON.expo.version).toBe('3.0.0');
|
||||
expect(appJSON.expo.android.versionCode).toBe(124);
|
||||
|
||||
const buildGradle = await getAppBuildGradleAsync('/app');
|
||||
const buildGradle = await getAppBuildGradleAsync('/repo');
|
||||
assert(buildGradle);
|
||||
expect(resolveConfigValue(buildGradle, 'versionCode')).toBe('124');
|
||||
expect(resolveConfigValue(buildGradle, 'versionName')).toBe('3.0.0');
|
||||
@@ -95,17 +95,17 @@ describe(bumpVersionAsync, () => {
|
||||
|
||||
await bumpVersionAsync({
|
||||
bumpStrategy: BumpStrategy.APP_VERSION,
|
||||
projectDir: '/app',
|
||||
projectDir: '/repo',
|
||||
exp: fakeExp,
|
||||
});
|
||||
|
||||
const appJSON = await fs.readJSON('/app/app.json');
|
||||
const appJSON = await fs.readJSON('/repo/app.json');
|
||||
expect(fakeExp.version).toBe('3.0.1');
|
||||
expect(fakeExp.android?.versionCode).toBe(123);
|
||||
expect(appJSON.expo.version).toBe('3.0.1');
|
||||
expect(appJSON.expo.android.versionCode).toBe(123);
|
||||
|
||||
const buildGradle = await getAppBuildGradleAsync('/app');
|
||||
const buildGradle = await getAppBuildGradleAsync('/repo');
|
||||
assert(buildGradle);
|
||||
expect(resolveConfigValue(buildGradle, 'versionCode')).toBe('123');
|
||||
expect(resolveConfigValue(buildGradle, 'versionName')).toBe('3.0.1');
|
||||
@@ -116,17 +116,17 @@ describe(bumpVersionAsync, () => {
|
||||
|
||||
await bumpVersionAsync({
|
||||
bumpStrategy: BumpStrategy.NOOP,
|
||||
projectDir: '/app',
|
||||
projectDir: '/repo',
|
||||
exp: fakeExp,
|
||||
});
|
||||
|
||||
const appJSON = await fs.readJSON('/app/app.json');
|
||||
const appJSON = await fs.readJSON('/repo/app.json');
|
||||
expect(fakeExp.version).toBe('3.0.0');
|
||||
expect(fakeExp.android?.versionCode).toBe(123);
|
||||
expect(appJSON.expo.version).toBe('3.0.0');
|
||||
expect(appJSON.expo.android.versionCode).toBe(123);
|
||||
|
||||
const buildGradle = await getAppBuildGradleAsync('/app');
|
||||
const buildGradle = await getAppBuildGradleAsync('/repo');
|
||||
assert(buildGradle);
|
||||
expect(resolveConfigValue(buildGradle, 'versionCode')).toBe('123');
|
||||
expect(resolveConfigValue(buildGradle, 'versionName')).toBe('3.0.0');
|
||||
@@ -140,11 +140,11 @@ describe(bumpVersionInAppJsonAsync, () => {
|
||||
|
||||
await bumpVersionInAppJsonAsync({
|
||||
bumpStrategy: BumpStrategy.VERSION_CODE,
|
||||
projectDir: '/app',
|
||||
projectDir: '/repo',
|
||||
exp: fakeExp,
|
||||
});
|
||||
|
||||
const appJSON = await fs.readJSON('/app/app.json');
|
||||
const appJSON = await fs.readJSON('/repo/app.json');
|
||||
expect(fakeExp.version).toBe('5.0.0');
|
||||
expect(fakeExp.android?.versionCode).toBe(127);
|
||||
expect(appJSON.expo.version).toBe('5.0.0');
|
||||
@@ -156,11 +156,11 @@ describe(bumpVersionInAppJsonAsync, () => {
|
||||
|
||||
await bumpVersionInAppJsonAsync({
|
||||
bumpStrategy: BumpStrategy.APP_VERSION,
|
||||
projectDir: '/app',
|
||||
projectDir: '/repo',
|
||||
exp: fakeExp,
|
||||
});
|
||||
|
||||
const appJSON = await fs.readJSON('/app/app.json');
|
||||
const appJSON = await fs.readJSON('/repo/app.json');
|
||||
expect(fakeExp.version).toBe('5.0.1');
|
||||
expect(fakeExp.android?.versionCode).toBe(126);
|
||||
expect(appJSON.expo.version).toBe('5.0.1');
|
||||
@@ -172,11 +172,11 @@ describe(bumpVersionInAppJsonAsync, () => {
|
||||
|
||||
await bumpVersionInAppJsonAsync({
|
||||
bumpStrategy: BumpStrategy.NOOP,
|
||||
projectDir: '/app',
|
||||
projectDir: '/repo',
|
||||
exp: fakeExp,
|
||||
});
|
||||
|
||||
const appJSON = await fs.readJSON('/app/app.json');
|
||||
const appJSON = await fs.readJSON('/repo/app.json');
|
||||
expect(fakeExp.version).toBe('5.0.0');
|
||||
expect(fakeExp.android?.versionCode).toBe(126);
|
||||
expect(appJSON.expo.version).toBe('5.0.0');
|
||||
@@ -189,7 +189,7 @@ describe(maybeResolveVersionsAsync, () => {
|
||||
it('reads the versions from native code', async () => {
|
||||
const exp = initBareWorkflowProject();
|
||||
const { appVersion, appBuildVersion } = await maybeResolveVersionsAsync(
|
||||
'/app',
|
||||
'/repo',
|
||||
exp,
|
||||
{} as BuildProfile<Platform.ANDROID>
|
||||
);
|
||||
@@ -201,7 +201,7 @@ describe(maybeResolveVersionsAsync, () => {
|
||||
it('reads the versions from expo config', async () => {
|
||||
const exp = initManagedProject();
|
||||
const { appVersion, appBuildVersion } = await maybeResolveVersionsAsync(
|
||||
'/app',
|
||||
'/repo',
|
||||
exp,
|
||||
{} as BuildProfile<Platform.ANDROID>
|
||||
);
|
||||
@@ -240,7 +240,7 @@ function initBareWorkflowProject({
|
||||
}`,
|
||||
'./android/app/src/main/AndroidManifest.xml': 'fake',
|
||||
},
|
||||
'/app'
|
||||
'/repo'
|
||||
);
|
||||
|
||||
return fakeExp;
|
||||
@@ -261,7 +261,7 @@ function initManagedProject(): ExpoConfig {
|
||||
expo: fakeExp,
|
||||
}),
|
||||
},
|
||||
'/app'
|
||||
'/repo'
|
||||
);
|
||||
|
||||
return fakeExp;
|
||||
|
||||
@@ -47,7 +47,7 @@ This means that it will most likely produce an AAB and you will not be able to i
|
||||
Log.newLine();
|
||||
const confirmed = await toggleConfirmAsync({ message: 'Would you like to proceed?' });
|
||||
if (!confirmed) {
|
||||
Log.error('Update eas.json and come back again.');
|
||||
Log.error('Please update eas.json and come back again.');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,7 @@ export function transformJob(job: Android.Job): AndroidJobInput {
|
||||
cache: job.cache,
|
||||
version: job.version?.versionCode ? { versionCode: job.version.versionCode } : undefined,
|
||||
gradleCommand: job.gradleCommand,
|
||||
applicationArchivePath: job.applicationArchivePath,
|
||||
buildArtifactPaths: job.buildArtifactPaths,
|
||||
artifactPath: job.artifactPath,
|
||||
username: job.username,
|
||||
buildType: job.buildType && transformBuildType(job.buildType),
|
||||
developmentClient: job.developmentClient,
|
||||
|
||||
@@ -72,8 +72,7 @@ export async function prepareJobAsync(
|
||||
updates: { channel: ctx.buildProfile.channel },
|
||||
developmentClient: buildProfile.developmentClient,
|
||||
gradleCommand: buildProfile.gradleCommand,
|
||||
applicationArchivePath: buildProfile.applicationArchivePath ?? buildProfile.artifactPath,
|
||||
buildArtifactPaths: buildProfile.buildArtifactPaths,
|
||||
artifactPath: buildProfile.artifactPath,
|
||||
buildType,
|
||||
username,
|
||||
...(ctx.android.versionCodeOverride && {
|
||||
|
||||
@@ -134,18 +134,18 @@ export async function prepareBuildRequestForPlatformAsync<
|
||||
|
||||
function handleBuildRequestError(error: any, platform: Platform): never {
|
||||
if (error?.graphQLErrors?.[0]?.extensions?.errorCode === 'TURTLE_DEPRECATED_JOB_FORMAT') {
|
||||
Log.error('EAS Build API has changed. Upgrade to the latest eas-cli version.');
|
||||
Log.error('EAS Build API has changed, please upgrade to the latest eas-cli version.');
|
||||
throw new Error('Build request failed.');
|
||||
} else if (
|
||||
error?.graphQLErrors?.[0]?.extensions?.errorCode === 'EAS_BUILD_DOWN_FOR_MAINTENANCE'
|
||||
) {
|
||||
Log.error(
|
||||
'EAS Build is down for maintenance. Try again later. Check https://status.expo.dev/ for updates.'
|
||||
'EAS Build is down for maintenance, please try again later. Check https://status.expo.dev/ for updates.'
|
||||
);
|
||||
throw new Error('Build request failed.');
|
||||
} else if (error?.graphQLErrors?.[0]?.extensions?.errorCode === 'EAS_BUILD_FREE_TIER_DISABLED') {
|
||||
Log.error(
|
||||
'EAS Build free tier is temporarily disabled. Try again later. Check https://status.expo.dev/ for updates.'
|
||||
'EAS Build free tier is temporarily disabled, please try again later. Check https://status.expo.dev/ for updates.'
|
||||
);
|
||||
throw new Error('Build request failed.');
|
||||
} else if (
|
||||
@@ -157,7 +157,7 @@ function handleBuildRequestError(error: any, platform: Platform): never {
|
||||
throw new Error('Build request failed.');
|
||||
} else if (error?.graphQLErrors) {
|
||||
Log.error(
|
||||
'Build request failed. Make sure you are using the latest eas-cli version. If the problem persists, report the issue.'
|
||||
'Build request failed. Make sure you are using the latest eas-cli version. If the problem persists, please report the issue.'
|
||||
);
|
||||
}
|
||||
throw error;
|
||||
@@ -243,7 +243,11 @@ type MaybeBuildFragment = BuildFragment | null;
|
||||
|
||||
export async function waitForBuildEndAsync(
|
||||
{ buildIds, accountName }: { buildIds: string[]; accountName: string },
|
||||
{ intervalSec = 10 } = {}
|
||||
{
|
||||
// 2 hours (max build time limit) + 10 minutes (possible queue time)
|
||||
timeoutSec = 2 * 60 * 60 + 10 * 60,
|
||||
intervalSec = 10,
|
||||
} = {}
|
||||
): Promise<MaybeBuildFragment[]> {
|
||||
let spinner;
|
||||
let originalSpinnerText;
|
||||
@@ -255,7 +259,8 @@ export async function waitForBuildEndAsync(
|
||||
originalSpinnerText = 'Waiting for builds to complete. You can press Ctrl+C to exit.';
|
||||
spinner = ora('Waiting for builds to complete. You can press Ctrl+C to exit.').start();
|
||||
}
|
||||
while (true) {
|
||||
const endTime = new Date().getTime() + timeoutSec * 1000;
|
||||
while (new Date().getTime() <= endTime) {
|
||||
const builds = await getBuildsSafelyAsync(buildIds);
|
||||
const { refetch } =
|
||||
builds.length === 1
|
||||
@@ -266,6 +271,10 @@ export async function waitForBuildEndAsync(
|
||||
}
|
||||
await sleepAsync(intervalSec * 1000);
|
||||
}
|
||||
spinner.fail('Timed out');
|
||||
throw new Error(
|
||||
'Timeout reached! It is taking longer than expected to finish the build, aborting...'
|
||||
);
|
||||
}
|
||||
|
||||
async function getBuildsSafelyAsync(buildIds: string[]): Promise<MaybeBuildFragment[]> {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Platform, Workflow } from '@expo/eas-build-job';
|
||||
import { EasJson, EasJsonAccessor } from '@expo/eas-json';
|
||||
import { EasJson, EasJsonReader } from '@expo/eas-json';
|
||||
import chalk from 'chalk';
|
||||
import fs from 'fs-extra';
|
||||
|
||||
@@ -24,7 +24,7 @@ interface ConfigureParams {
|
||||
export async function ensureProjectConfiguredAsync(
|
||||
configureParams: ConfigureParams
|
||||
): Promise<boolean> {
|
||||
if (await fs.pathExists(EasJsonAccessor.formatEasJsonPath(configureParams.projectDir))) {
|
||||
if (await fs.pathExists(EasJsonReader.formatEasJsonPath(configureParams.projectDir))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ const EAS_JSON_BARE_DEFAULT: EasJson = {
|
||||
};
|
||||
|
||||
async function createEasJsonAsync(projectDir: string): Promise<void> {
|
||||
const easJsonPath = EasJsonAccessor.formatEasJsonPath(projectDir);
|
||||
const easJsonPath = EasJsonReader.formatEasJsonPath(projectDir);
|
||||
|
||||
const hasAndroidNativeProject =
|
||||
(await resolveWorkflowAsync(projectDir, Platform.ANDROID)) === Workflow.GENERIC;
|
||||
|
||||
@@ -60,7 +60,6 @@ export async function createBuildContextAsync<T extends Platform>({
|
||||
projectDir,
|
||||
user,
|
||||
env: buildProfile.env,
|
||||
easJsonCliConfig,
|
||||
});
|
||||
|
||||
const devClientProperties = getDevClientEventProperties({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Ios } from '@expo/eas-build-job';
|
||||
import { Env, Ios } from '@expo/eas-build-job';
|
||||
import nullthrows from 'nullthrows';
|
||||
|
||||
import { IosJobInput, IosJobSecretsInput } from '../../graphql/generated';
|
||||
@@ -17,8 +17,7 @@ export function transformJob(job: Ios.Job): IosJobInput {
|
||||
version: job.version?.buildNumber ? { buildNumber: job.version.buildNumber } : undefined,
|
||||
scheme: job.scheme,
|
||||
buildConfiguration: job.buildConfiguration,
|
||||
applicationArchivePath: job.applicationArchivePath,
|
||||
buildArtifactPaths: job.buildArtifactPaths,
|
||||
artifactPath: job.artifactPath,
|
||||
username: job.username,
|
||||
developmentClient: job.developmentClient,
|
||||
simulator: job.simulator,
|
||||
@@ -28,6 +27,7 @@ export function transformJob(job: Ios.Job): IosJobInput {
|
||||
|
||||
function transformIosSecrets(secrets: {
|
||||
buildCredentials?: Ios.BuildCredentials;
|
||||
env?: Env;
|
||||
}): IosJobSecretsInput {
|
||||
const buildCredentials: IosJobSecretsInput['buildCredentials'] = [];
|
||||
|
||||
@@ -43,5 +43,6 @@ function transformIosSecrets(secrets: {
|
||||
|
||||
return {
|
||||
buildCredentials,
|
||||
environmentSecrets: secrets.env,
|
||||
};
|
||||
}
|
||||
@@ -64,9 +64,7 @@ export async function prepareJobAsync(
|
||||
simulator: ctx.buildProfile.simulator,
|
||||
scheme: jobData.buildScheme,
|
||||
buildConfiguration: ctx.buildProfile.buildConfiguration,
|
||||
applicationArchivePath:
|
||||
ctx.buildProfile.applicationArchivePath ?? ctx.buildProfile.artifactPath,
|
||||
buildArtifactPaths: ctx.buildProfile.buildArtifactPaths,
|
||||
artifactPath: ctx.buildProfile.artifactPath,
|
||||
username,
|
||||
...(ctx.ios.buildNumberOverride && {
|
||||
version: {
|
||||
|
||||
@@ -3,8 +3,7 @@ import {
|
||||
AppVersionSource,
|
||||
BuildProfile,
|
||||
EasJson,
|
||||
EasJsonAccessor,
|
||||
EasJsonUtils,
|
||||
EasJsonReader,
|
||||
SubmitProfile,
|
||||
} from '@expo/eas-json';
|
||||
import chalk from 'chalk';
|
||||
@@ -41,6 +40,7 @@ import {
|
||||
waitToCompleteAsync as waitForSubmissionsToCompleteAsync,
|
||||
} from '../submit/submit';
|
||||
import { printSubmissionDetailsUrls } from '../submit/utils/urls';
|
||||
import { checkBuildProfileConfigMatchesProjectConfigAsync } from '../update/utils';
|
||||
import { printJsonOnlyOutput } from '../utils/json';
|
||||
import { ProfileData, getProfilesAsync } from '../utils/profiles';
|
||||
import { getVcsClient } from '../vcs';
|
||||
@@ -95,14 +95,13 @@ export async function runBuildAndSubmitAsync(projectDir: string, flags: BuildFla
|
||||
projectDir,
|
||||
nonInteractive: flags.nonInteractive,
|
||||
});
|
||||
const easJsonAccessor = new EasJsonAccessor(projectDir);
|
||||
const easJsonCliConfig: EasJson['cli'] =
|
||||
(await EasJsonUtils.getCliConfigAsync(easJsonAccessor)) ?? {};
|
||||
const easJsonReader = new EasJsonReader(projectDir);
|
||||
const easJsonCliConfig: EasJson['cli'] = (await easJsonReader.getCliConfigAsync()) ?? {};
|
||||
|
||||
const platforms = toPlatforms(flags.requestedPlatform);
|
||||
const buildProfiles = await getProfilesAsync({
|
||||
type: 'build',
|
||||
easJsonAccessor,
|
||||
easJsonReader,
|
||||
platforms,
|
||||
profileName: flags.profile ?? undefined,
|
||||
});
|
||||
@@ -123,6 +122,12 @@ export async function runBuildAndSubmitAsync(projectDir: string, flags: BuildFla
|
||||
}[] = [];
|
||||
const buildCtxByPlatform: { [p in AppPlatform]?: BuildContext<Platform> } = {};
|
||||
|
||||
// Check only first buildprofile (there should be only one unique one)
|
||||
// Warn only once
|
||||
if (buildProfiles.length > 0) {
|
||||
await checkBuildProfileConfigMatchesProjectConfigAsync(projectDir, buildProfiles[0]);
|
||||
}
|
||||
|
||||
for (const buildProfile of buildProfiles) {
|
||||
const { build: maybeBuild, buildCtx } = await prepareAndStartBuildAsync({
|
||||
projectDir,
|
||||
@@ -152,7 +157,7 @@ export async function runBuildAndSubmitAsync(projectDir: string, flags: BuildFla
|
||||
const submissions: SubmissionFragment[] = [];
|
||||
if (flags.autoSubmit) {
|
||||
const submitProfiles = await getProfilesAsync({
|
||||
easJsonAccessor,
|
||||
easJsonReader,
|
||||
platforms,
|
||||
profileName: flags.submitProfile,
|
||||
type: 'submit',
|
||||
|
||||
@@ -94,14 +94,14 @@ export function printDeprecationWarnings(deprecationInfo?: EasBuildDeprecationIn
|
||||
return;
|
||||
}
|
||||
if (deprecationInfo.type === EasBuildDeprecationInfoType.Internal) {
|
||||
Log.warn('This command is using API that soon will be deprecated. Upgrade EAS CLI.');
|
||||
Log.warn('This command is using API that soon will be deprecated, please update eas-cli.');
|
||||
Log.warn("Changes won't affect your project config.");
|
||||
Log.warn(deprecationInfo.message);
|
||||
} else if (deprecationInfo.type === EasBuildDeprecationInfoType.UserFacing) {
|
||||
Log.warn('This command is using API that soon will be deprecated.');
|
||||
Log.warn(deprecationInfo.message);
|
||||
} else {
|
||||
Log.warn('An unexpected warning was encountered. Report it as a bug:');
|
||||
Log.warn('An unexpected warning was encountered. Please report it as a bug:');
|
||||
Log.warn(deprecationInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ export async function maybeBailOnRepoStatusAsync(): Promise<void> {
|
||||
});
|
||||
|
||||
if (!answer) {
|
||||
throw new Error('Commit all changes. Aborting...');
|
||||
throw new Error('Please commit all changes. Aborting...');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,12 +39,12 @@ export async function ensureRepoIsCleanAsync(nonInteractive = false): Promise<vo
|
||||
Log.addNewLineIfNone();
|
||||
Log.warn(`${chalk.bold('Warning!')} Your repository working tree is dirty.`);
|
||||
Log.log(
|
||||
`This operation needs to be run on a clean working tree. ${chalk.bold(
|
||||
'Commit all your changes before proceeding'
|
||||
`This operation needs to be run on a clean working tree, please ${chalk.bold(
|
||||
'commit all your changes before proceeding'
|
||||
)}.`
|
||||
);
|
||||
if (nonInteractive) {
|
||||
throw new Error('Commit all changes. Aborting...');
|
||||
throw new Error('Please commit all changes. Aborting...');
|
||||
}
|
||||
const answer = await confirmAsync({
|
||||
message: `Commit changes to git?`,
|
||||
@@ -52,7 +52,7 @@ export async function ensureRepoIsCleanAsync(nonInteractive = false): Promise<vo
|
||||
if (answer) {
|
||||
await commitPromptAsync({ commitAllFiles: true });
|
||||
} else {
|
||||
throw new Error('Commit all changes. Aborting...');
|
||||
throw new Error('Please commit all changes. Aborting...');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
import { EasJsonAccessor, EasJsonUtils } from '@expo/eas-json';
|
||||
import * as PackageManagerUtils from '@expo/package-manager';
|
||||
import { Command, Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
import fs from 'fs-extra';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { Options, Ora } from 'ora';
|
||||
import path from 'path';
|
||||
import { EasJsonReader } from '@expo/eas-json';
|
||||
import { Command } from '@oclif/core';
|
||||
import semver from 'semver';
|
||||
|
||||
import {
|
||||
@@ -14,48 +8,14 @@ import {
|
||||
initAsync as initAnalyticsAsync,
|
||||
logEvent,
|
||||
} from '../analytics/rudderstackClient';
|
||||
import Log, { learnMore } from '../log';
|
||||
import { interactiveOra, nonInteractiveOra } from '../ora';
|
||||
import { findProjectRootAsync } from '../project/projectUtils';
|
||||
import { InteractivePrompts, NonInteractivePrompts, Prompts } from '../prompts';
|
||||
import { getUserAsync } from '../user/User';
|
||||
import { ensureLoggedInAsync } from '../user/actions';
|
||||
import { easCliVersion } from '../utils/easCli';
|
||||
import { setVcsClient } from '../vcs';
|
||||
import GitClient from '../vcs/clients/git';
|
||||
|
||||
type CommandOptions =
|
||||
| {
|
||||
nonInteractive: true;
|
||||
json: true;
|
||||
}
|
||||
| {
|
||||
nonInteractive: boolean;
|
||||
json: false;
|
||||
};
|
||||
|
||||
export type CommandContext = Readonly<
|
||||
CommandOptions & {
|
||||
logger: Log;
|
||||
prompts: Prompts;
|
||||
ora: (options?: Options | string) => Ora;
|
||||
}
|
||||
>;
|
||||
|
||||
export default abstract class EasCommand extends Command {
|
||||
static override globalFlags = {
|
||||
json: Flags.boolean({
|
||||
description: 'Enable JSON output, non-JSON messages will be printed to stderr.',
|
||||
dependsOn: ['non-interactive'],
|
||||
}),
|
||||
'non-interactive': Flags.boolean({
|
||||
description: 'Run the command in non-interactive mode.',
|
||||
}),
|
||||
};
|
||||
|
||||
// disable built in oclif json stuff
|
||||
enableJsonFlag = false;
|
||||
|
||||
/**
|
||||
* When user data is unavailable locally, determines if the command will
|
||||
* force the user to log in
|
||||
@@ -63,35 +23,18 @@ export default abstract class EasCommand extends Command {
|
||||
protected requiresAuthentication = true;
|
||||
protected mustBeRunInsideProject = true;
|
||||
|
||||
protected abstract runAsync({
|
||||
nonInteractive,
|
||||
json,
|
||||
logger,
|
||||
prompts: {
|
||||
promptAsync,
|
||||
confirmAsync,
|
||||
selectAsync,
|
||||
toggleConfirmAsync,
|
||||
pressAnyKeyToContinueAsync,
|
||||
},
|
||||
ora,
|
||||
}: CommandContext): Promise<{ jsonOutput: object }>;
|
||||
protected abstract runAsync(): Promise<any>;
|
||||
|
||||
// eslint-disable-next-line async-protect/async-suffix
|
||||
async run(): Promise<any> {
|
||||
const { flags } = await this.parse();
|
||||
const json = flags.json ?? false;
|
||||
const nonInteractive = (flags as any)['non-interactive'] ?? false;
|
||||
|
||||
await initAnalyticsAsync();
|
||||
|
||||
if (this.mustBeRunInsideProject) {
|
||||
const projectDir = await findProjectRootAsync();
|
||||
await this.applyCliConfigAsync(projectDir);
|
||||
await this.ensureEasCliIsNotInDependenciesAsync(projectDir);
|
||||
await this.applyCliConfigAsync();
|
||||
}
|
||||
|
||||
if (this.requiresAuthentication) {
|
||||
const { flags } = await this.parse();
|
||||
const nonInteractive = (flags as any)['non-interactive'] ?? false;
|
||||
await ensureLoggedInAsync({ nonInteractive });
|
||||
} else {
|
||||
await getUserAsync();
|
||||
@@ -101,29 +44,19 @@ export default abstract class EasCommand extends Command {
|
||||
// commands/submit === submit, commands/build/list === build:list
|
||||
action: `eas ${this.id}`,
|
||||
});
|
||||
|
||||
const jsonOutput = await this.runAsync({
|
||||
nonInteractive,
|
||||
json: json ?? false,
|
||||
logger: new Log(json),
|
||||
prompts: nonInteractive ? new InteractivePrompts() : new NonInteractivePrompts(),
|
||||
ora: nonInteractive ? nonInteractiveOra : interactiveOra,
|
||||
});
|
||||
|
||||
if (json) {
|
||||
this.printJsonOnlyOutput(jsonOutput);
|
||||
}
|
||||
return this.runAsync();
|
||||
}
|
||||
|
||||
// eslint-disable-next-line async-protect/async-suffix
|
||||
override async finally(err: Error): Promise<any> {
|
||||
async finally(err: Error): Promise<any> {
|
||||
await flushAnalyticsAsync();
|
||||
return super.finally(err);
|
||||
}
|
||||
|
||||
private async applyCliConfigAsync(projectDir: string): Promise<void> {
|
||||
const easJsonAccessor = new EasJsonAccessor(projectDir);
|
||||
const config = await EasJsonUtils.getCliConfigAsync(easJsonAccessor);
|
||||
private async applyCliConfigAsync(): Promise<void> {
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const easJsonReader = new EasJsonReader(projectDir);
|
||||
const config = await easJsonReader.getCliConfigAsync();
|
||||
if (config?.version && !semver.satisfies(easCliVersion, config.version)) {
|
||||
throw new Error(
|
||||
`You are on eas-cli@${easCliVersion} which does not satisfy the CLI version constraint in eas.json (${config.version})`
|
||||
@@ -133,72 +66,4 @@ export default abstract class EasCommand extends Command {
|
||||
setVcsClient(new GitClient());
|
||||
}
|
||||
}
|
||||
|
||||
private async ensureEasCliIsNotInDependenciesAsync(projectDir: string): Promise<void> {
|
||||
let printCliVersionWarning = false;
|
||||
|
||||
const consoleWarn = (msg?: string): void => {
|
||||
if (msg) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(chalk.yellow(msg));
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn();
|
||||
}
|
||||
};
|
||||
|
||||
if (await this.isEasCliInDependenciesAsync(projectDir)) {
|
||||
printCliVersionWarning = true;
|
||||
consoleWarn(`Found ${chalk.bold('eas-cli')} in your project dependencies.`);
|
||||
}
|
||||
|
||||
const maybeRepoRoot = PackageManagerUtils.findWorkspaceRoot(projectDir) ?? projectDir;
|
||||
if (maybeRepoRoot !== projectDir && (await this.isEasCliInDependenciesAsync(maybeRepoRoot))) {
|
||||
printCliVersionWarning = true;
|
||||
consoleWarn(`Found ${chalk.bold('eas-cli')} in your monorepo dependencies.`);
|
||||
}
|
||||
|
||||
if (printCliVersionWarning) {
|
||||
consoleWarn(
|
||||
`It's recommended to use the ${chalk.bold(
|
||||
'"cli.version"'
|
||||
)} field in eas.json to enforce the ${chalk.bold('eas-cli')} version for your project.`
|
||||
);
|
||||
consoleWarn(
|
||||
learnMore('https://github.com/expo/eas-cli#enforcing-eas-cli-version-for-your-project')
|
||||
);
|
||||
consoleWarn();
|
||||
}
|
||||
}
|
||||
|
||||
private async isEasCliInDependenciesAsync(dir: string): Promise<boolean> {
|
||||
const packageJsonPath = path.join(dir, 'package.json');
|
||||
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
|
||||
return (
|
||||
packageJson?.dependencies?.['eas-cli'] !== undefined ||
|
||||
packageJson?.devDependencies?.['eas-cli'] !== undefined
|
||||
);
|
||||
}
|
||||
|
||||
private printJsonOnlyOutput(value: object): void {
|
||||
try {
|
||||
new Log(false).log(JSON.stringify(this.sanitizeValue(value), null, 2));
|
||||
} catch {}
|
||||
}
|
||||
|
||||
private sanitizeValue(value: any): unknown {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(val => this.sanitizeValue(val));
|
||||
} else if (value && typeof value === 'object') {
|
||||
const result: Record<string, any> = {};
|
||||
Object.keys(value).forEach(key => {
|
||||
if (key !== '__typename' && value[key] !== null) {
|
||||
result[key] = this.sanitizeValue(value[key]);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ beforeEach(() => {
|
||||
|
||||
const createTestEasCommand = (authValue: boolean): typeof EasCommand => {
|
||||
class TestEasCommand extends EasCommand {
|
||||
override requiresAuthentication = authValue;
|
||||
requiresAuthentication = authValue;
|
||||
|
||||
async runAsync(): Promise<void> {}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
import { Flags } from '@oclif/core';
|
||||
|
||||
export const getPaginatedQueryOptions = (flags: {
|
||||
json: boolean;
|
||||
'non-interactive': boolean;
|
||||
offset: number | undefined;
|
||||
limit: number | undefined;
|
||||
}): PaginatedQueryOptions => {
|
||||
export const getPaginatedQueryOptions = (
|
||||
flags: Record<keyof typeof EasPaginatedQueryFlags, any>
|
||||
): PaginatedQueryOptions => {
|
||||
return {
|
||||
json: flags.json,
|
||||
json: flags.json ?? false,
|
||||
offset: flags.offset ?? 0,
|
||||
nonInteractive: flags['non-interactive'],
|
||||
nonInteractive: flags['non-interactive'] ?? false,
|
||||
...('limit' in flags && { limit: flags.limit }),
|
||||
};
|
||||
};
|
||||
@@ -43,6 +40,12 @@ export const EasPaginatedQueryFlags = {
|
||||
// eslint-disable-next-line async-protect/async-suffix
|
||||
parse: async input => parseFlagInputStringAsInteger(input, 'limit', 1, 100),
|
||||
}),
|
||||
json: Flags.boolean({
|
||||
description: 'Enable JSON output, non-JSON messages will be printed to stderr.',
|
||||
}),
|
||||
'non-interactive': Flags.boolean({
|
||||
description: 'Run the command in non-interactive mode.',
|
||||
}),
|
||||
};
|
||||
|
||||
// options required to control a paginated query
|
||||
|
||||
@@ -3,11 +3,11 @@ import Log from '../../log';
|
||||
import { showLoginPromptAsync } from '../../user/actions';
|
||||
|
||||
export default class AccountLogin extends EasCommand {
|
||||
static override description = 'log in with your Expo account';
|
||||
static override aliases = ['login'];
|
||||
static description = 'log in with your Expo account';
|
||||
static aliases = ['login'];
|
||||
|
||||
protected override mustBeRunInsideProject = false;
|
||||
protected override requiresAuthentication = false;
|
||||
protected mustBeRunInsideProject = false;
|
||||
protected requiresAuthentication = false;
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
await showLoginPromptAsync();
|
||||
|
||||
@@ -3,11 +3,11 @@ import Log from '../../log';
|
||||
import { logoutAsync } from '../../user/User';
|
||||
|
||||
export default class AccountLogout extends EasCommand {
|
||||
static override description = 'log out';
|
||||
static override aliases = ['logout'];
|
||||
static description = 'log out';
|
||||
static aliases = ['logout'];
|
||||
|
||||
protected override mustBeRunInsideProject = false;
|
||||
protected override requiresAuthentication = false;
|
||||
protected mustBeRunInsideProject = false;
|
||||
protected requiresAuthentication = false;
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
await logoutAsync();
|
||||
|
||||
@@ -5,11 +5,11 @@ import Log from '../../log';
|
||||
import { getActorDisplayName, getUserAsync } from '../../user/User';
|
||||
|
||||
export default class AccountView extends EasCommand {
|
||||
static override description = 'show the username you are logged in as';
|
||||
static override aliases = ['whoami'];
|
||||
static description = 'show the username you are logged in as';
|
||||
static aliases = ['whoami'];
|
||||
|
||||
protected override mustBeRunInsideProject = false;
|
||||
protected override requiresAuthentication = false;
|
||||
protected mustBeRunInsideProject = false;
|
||||
protected requiresAuthentication = false;
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const user = await getUserAsync();
|
||||
|
||||
@@ -3,11 +3,11 @@ import Log from '../log';
|
||||
import UserSettings from '../user/UserSettings';
|
||||
|
||||
export default class AnalyticsView extends EasCommand {
|
||||
static override description = 'display or change analytics settings';
|
||||
static description = 'display or change analytics settings';
|
||||
|
||||
static override args = [{ name: 'STATUS', options: ['on', 'off'] }];
|
||||
static args = [{ name: 'STATUS', options: ['on', 'off'] }];
|
||||
|
||||
protected override requiresAuthentication = false;
|
||||
protected requiresAuthentication = false;
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { STATUS: status } = (await this.parse(AnalyticsView)).args;
|
||||
|
||||
@@ -52,9 +52,9 @@ export async function createUpdateBranchOnAppAsync({
|
||||
}
|
||||
|
||||
export default class BranchCreate extends EasCommand {
|
||||
static override description = 'create a branch';
|
||||
static description = 'create a branch';
|
||||
|
||||
static override args = [
|
||||
static args = [
|
||||
{
|
||||
name: 'name',
|
||||
required: false,
|
||||
@@ -62,7 +62,7 @@ export default class BranchCreate extends EasCommand {
|
||||
},
|
||||
];
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
json: Flags.boolean({
|
||||
description: 'return a json with the new branch ID and name.',
|
||||
default: false,
|
||||
@@ -91,7 +91,7 @@ export default class BranchCreate extends EasCommand {
|
||||
({ name } = await promptAsync({
|
||||
type: 'text',
|
||||
name: 'name',
|
||||
message: 'Provide a branch name:',
|
||||
message: 'Please name the branch:',
|
||||
initial:
|
||||
(await getVcsClient().getBranchNameAsync()) ||
|
||||
`branch-${Math.random().toString(36).substr(2, 4)}`,
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
import EasCommand, { CommandContext } from '../../commandUtils/EasCommand';
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
import { graphqlClient, withErrorHandlingAsync } from '../../graphql/client';
|
||||
import {
|
||||
DeleteUpdateBranchMutation,
|
||||
@@ -10,12 +11,15 @@ import {
|
||||
GetBranchInfoQuery,
|
||||
GetBranchInfoQueryVariables,
|
||||
} from '../../graphql/generated';
|
||||
import Log from '../../log';
|
||||
import { getExpoConfig } from '../../project/expoConfig';
|
||||
import {
|
||||
findProjectRootAsync,
|
||||
getProjectFullNameAsync,
|
||||
getProjectIdAsync,
|
||||
} from '../../project/projectUtils';
|
||||
import { promptAsync, toggleConfirmAsync } from '../../prompts';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
|
||||
async function getBranchInfoAsync({
|
||||
appId,
|
||||
@@ -73,24 +77,30 @@ async function deleteBranchOnAppAsync({
|
||||
}
|
||||
|
||||
export default class BranchDelete extends EasCommand {
|
||||
static override description = 'delete a branch';
|
||||
static description = 'delete a branch';
|
||||
|
||||
static override args = [
|
||||
static args = [
|
||||
{
|
||||
name: 'name',
|
||||
required: false,
|
||||
description: 'Name of the branch to delete',
|
||||
},
|
||||
];
|
||||
static flags = {
|
||||
json: Flags.boolean({
|
||||
description: `return JSON with the edited branch's ID and name.`,
|
||||
default: false,
|
||||
}),
|
||||
};
|
||||
|
||||
protected async runAsync({
|
||||
nonInteractive,
|
||||
logger,
|
||||
prompts: { promptAsync, toggleConfirmAsync },
|
||||
}: CommandContext): Promise<{ jsonOutput: object }> {
|
||||
async runAsync(): Promise<void> {
|
||||
let {
|
||||
args: { name },
|
||||
flags: { json: jsonFlag },
|
||||
} = await this.parse(BranchDelete);
|
||||
if (jsonFlag) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const exp = getExpoConfig(projectDir);
|
||||
@@ -99,13 +109,13 @@ export default class BranchDelete extends EasCommand {
|
||||
|
||||
if (!name) {
|
||||
const validationMessage = 'branch name may not be empty.';
|
||||
if (nonInteractive) {
|
||||
if (jsonFlag) {
|
||||
throw new Error(validationMessage);
|
||||
}
|
||||
({ name } = await promptAsync({
|
||||
type: 'text',
|
||||
name: 'name',
|
||||
message: 'Provide the name of the branch to delete:',
|
||||
message: 'Please enter the name of the branch to delete:',
|
||||
validate: value => (value ? true : validationMessage),
|
||||
}));
|
||||
}
|
||||
@@ -116,16 +126,16 @@ export default class BranchDelete extends EasCommand {
|
||||
throw new Error(`Could not find branch ${name} on ${fullName}`);
|
||||
}
|
||||
|
||||
if (!nonInteractive) {
|
||||
logger.addNewLineIfNone();
|
||||
logger.warn(
|
||||
`You are about to permanently delete branch: "${name}" and all of the updates published on it.` +
|
||||
if (!jsonFlag) {
|
||||
Log.addNewLineIfNone();
|
||||
Log.warn(
|
||||
`You are about to permamently delete branch: "${name}" and all of the updates published on it.` +
|
||||
`\nThis action is irreversible.`
|
||||
);
|
||||
logger.newLine();
|
||||
Log.newLine();
|
||||
const confirmed = await toggleConfirmAsync({ message: 'Are you sure you wish to proceed?' });
|
||||
if (!confirmed) {
|
||||
logger.error(`Cancelled deletion of branch: "${name}".`);
|
||||
Log.error(`Cancelled deletion of branch: "${name}".`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
@@ -134,10 +144,12 @@ export default class BranchDelete extends EasCommand {
|
||||
branchId,
|
||||
});
|
||||
|
||||
logger.withTick(
|
||||
`Deleted branch "${name}" and all of its updates on project ${chalk.bold(fullName)}.`
|
||||
);
|
||||
|
||||
return { jsonOutput: deletionResult };
|
||||
if (jsonFlag) {
|
||||
printJsonOnlyOutput(deletionResult);
|
||||
} else {
|
||||
Log.withTick(
|
||||
`️Deleted branch "${name}" and all of its updates on project ${chalk.bold(fullName)}.`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,9 +6,9 @@ import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUt
|
||||
import { enableJsonOutput } from '../../utils/json';
|
||||
|
||||
export default class BranchList extends EasCommand {
|
||||
static override description = 'list all branches';
|
||||
static description = 'list all branches';
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
...EasPaginatedQueryFlags,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
|
||||
export default class BranchPublish extends EasCommand {
|
||||
static override description = 'deprecated, use "eas update"';
|
||||
static override hidden = true;
|
||||
static description = 'deprecated, use "eas update"';
|
||||
static hidden = true;
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
throw new Error(BranchPublish.description);
|
||||
|
||||
@@ -52,9 +52,9 @@ async function renameUpdateBranchOnAppAsync({
|
||||
}
|
||||
|
||||
export default class BranchRename extends EasCommand {
|
||||
static override description = 'rename a branch';
|
||||
static description = 'rename a branch';
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
from: Flags.string({
|
||||
description: 'current name of the branch.',
|
||||
required: false,
|
||||
@@ -90,7 +90,7 @@ export default class BranchRename extends EasCommand {
|
||||
({ currentName } = await promptAsync({
|
||||
type: 'text',
|
||||
name: 'currentName',
|
||||
message: "Provide the name of the branch you'd like to rename:",
|
||||
message: 'Please enter the current name of the branch to rename:',
|
||||
validate: value => (value ? true : validationMessage),
|
||||
}));
|
||||
}
|
||||
@@ -103,7 +103,7 @@ export default class BranchRename extends EasCommand {
|
||||
({ newName } = await promptAsync({
|
||||
type: 'text',
|
||||
name: 'newName',
|
||||
message: `Rename ${currentName}`,
|
||||
message: `Please rename ${currentName}`,
|
||||
validate: value => (value ? true : validationMessage),
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@ import { listAndRenderUpdatesOnBranchByNameAsync } from '../../update/queries';
|
||||
import { enableJsonOutput } from '../../utils/json';
|
||||
|
||||
export default class BranchView extends EasCommand {
|
||||
static override description = 'view a branch';
|
||||
static description = 'view a branch';
|
||||
|
||||
static override args = [
|
||||
static args = [
|
||||
{
|
||||
name: 'name',
|
||||
required: false,
|
||||
@@ -17,7 +17,7 @@ export default class BranchView extends EasCommand {
|
||||
},
|
||||
];
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
...EasPaginatedQueryFlags,
|
||||
};
|
||||
|
||||
|
||||
@@ -110,9 +110,9 @@ async function ensureBuildExistsAsync(buildId: string): Promise<void> {
|
||||
}
|
||||
|
||||
export default class BuildCancel extends EasCommand {
|
||||
static override description = 'cancel a build';
|
||||
static description = 'cancel a build';
|
||||
|
||||
static override args = [{ name: 'BUILD_ID' }];
|
||||
static args = [{ name: 'BUILD_ID' }];
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { BUILD_ID: buildIdFromArg } = (await this.parse(BuildCancel)).args;
|
||||
|
||||
@@ -16,9 +16,9 @@ import { syncUpdatesConfigurationAsync as syncIosUpdatesConfigurationAsync } fro
|
||||
import { getVcsClient } from '../../vcs';
|
||||
|
||||
export default class BuildConfigure extends EasCommand {
|
||||
static override description = 'configure the project to support EAS Build';
|
||||
static description = 'configure the project to support EAS Build';
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
platform: Flags.enum({
|
||||
description: 'Platform to configure',
|
||||
char: 'p',
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
import { Platform } from '@expo/eas-build-job';
|
||||
import { EasJsonAccessor, EasJsonUtils } from '@expo/eas-json';
|
||||
import { Errors, Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
import figures from 'figures';
|
||||
import path from 'path';
|
||||
|
||||
import { BuildFlags, runBuildAndSubmitAsync } from '../../build/runBuildAndSubmit';
|
||||
import { UserInputResourceClass } from '../../build/types';
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
import { StatuspageServiceName } from '../../graphql/generated';
|
||||
import Log, { link } from '../../log';
|
||||
import Log from '../../log';
|
||||
import { RequestedPlatform, selectRequestedPlatformAsync } from '../../platform';
|
||||
import { findProjectRootAsync } from '../../project/projectUtils';
|
||||
import { selectAsync } from '../../prompts';
|
||||
import uniq from '../../utils/expodash/uniq';
|
||||
import { enableJsonOutput } from '../../utils/json';
|
||||
import { maybeWarnAboutEasOutagesAsync } from '../../utils/statuspageService';
|
||||
|
||||
interface RawBuildFlags {
|
||||
platform?: string;
|
||||
@@ -35,9 +27,9 @@ interface RawBuildFlags {
|
||||
}
|
||||
|
||||
export default class Build extends EasCommand {
|
||||
static override description = 'start a build';
|
||||
static description = 'start a build';
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
platform: Flags.enum({
|
||||
char: 'p',
|
||||
options: ['android', 'ios', 'all'],
|
||||
@@ -55,7 +47,6 @@ export default class Build extends EasCommand {
|
||||
hidden: true,
|
||||
}),
|
||||
profile: Flags.string({
|
||||
char: 'e',
|
||||
description:
|
||||
'Name of the build profile from eas.json. Defaults to "production" if defined in eas.json.',
|
||||
helpValue: 'PROFILE_NAME',
|
||||
@@ -104,32 +95,17 @@ export default class Build extends EasCommand {
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { flags: rawFlags } = await this.parse(Build);
|
||||
|
||||
if (rawFlags.json) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
const flags = this.sanitizeFlags(rawFlags);
|
||||
const flags = await this.sanitizeFlagsAsync(rawFlags);
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
|
||||
await handleDeprecatedEasJsonAsync(projectDir, flags.nonInteractive);
|
||||
|
||||
if (!flags.localBuildOptions.enable) {
|
||||
await maybeWarnAboutEasOutagesAsync(
|
||||
flags.autoSubmit
|
||||
? [StatuspageServiceName.EasBuild, StatuspageServiceName.EasSubmit]
|
||||
: [StatuspageServiceName.EasBuild]
|
||||
);
|
||||
}
|
||||
|
||||
const flagsWithPlatform = await this.ensurePlatformSelectedAsync(flags);
|
||||
|
||||
await runBuildAndSubmitAsync(projectDir, flagsWithPlatform);
|
||||
await runBuildAndSubmitAsync(projectDir, flags);
|
||||
}
|
||||
|
||||
private sanitizeFlags(
|
||||
flags: RawBuildFlags
|
||||
): Omit<BuildFlags, 'requestedPlatform'> & { requestedPlatform?: RequestedPlatform } {
|
||||
private async sanitizeFlagsAsync(flags: RawBuildFlags): Promise<BuildFlags> {
|
||||
const nonInteractive = flags['non-interactive'];
|
||||
if (!flags.local && flags.output) {
|
||||
Errors.error('--output is allowed only for local builds', { exit: 1 });
|
||||
@@ -141,11 +117,21 @@ export default class Build extends EasCommand {
|
||||
Errors.error('--json is allowed only when building in non-interactive mode', { exit: 1 });
|
||||
}
|
||||
|
||||
const requestedPlatform =
|
||||
flags.platform &&
|
||||
Object.values(RequestedPlatform).includes(flags.platform.toLowerCase() as RequestedPlatform)
|
||||
? (flags.platform.toLowerCase() as RequestedPlatform)
|
||||
: undefined;
|
||||
const requestedPlatform = await selectRequestedPlatformAsync(flags.platform);
|
||||
if (flags.local) {
|
||||
if (flags['auto-submit'] || flags['auto-submit-with-profile'] !== undefined) {
|
||||
// TODO: implement this
|
||||
Errors.error('Auto-submits are not yet supported when building locally', { exit: 1 });
|
||||
}
|
||||
|
||||
if (requestedPlatform === RequestedPlatform.All) {
|
||||
Errors.error('Builds for multiple platforms are not supported with flag --local', {
|
||||
exit: 1,
|
||||
});
|
||||
} else if (process.platform !== 'darwin' && requestedPlatform === RequestedPlatform.Ios) {
|
||||
Errors.error('Unsupported platform, macOS is required to build apps for iOS', { exit: 1 });
|
||||
}
|
||||
}
|
||||
|
||||
if (flags['skip-credentials-check']) {
|
||||
Log.warnDeprecatedFlag(
|
||||
@@ -190,105 +176,4 @@ export default class Build extends EasCommand {
|
||||
message,
|
||||
};
|
||||
}
|
||||
|
||||
private async ensurePlatformSelectedAsync(
|
||||
flags: Omit<BuildFlags, 'requestedPlatform'> & { requestedPlatform?: RequestedPlatform }
|
||||
): Promise<BuildFlags> {
|
||||
const requestedPlatform = await selectRequestedPlatformAsync(flags.requestedPlatform);
|
||||
|
||||
if (flags.localBuildOptions.enable) {
|
||||
if (flags.autoSubmit) {
|
||||
// TODO: implement this
|
||||
Errors.error('Auto-submits are not yet supported when building locally', { exit: 1 });
|
||||
}
|
||||
|
||||
if (requestedPlatform === RequestedPlatform.All) {
|
||||
Errors.error('Builds for multiple platforms are not supported with flag --local', {
|
||||
exit: 1,
|
||||
});
|
||||
} else if (process.platform !== 'darwin' && requestedPlatform === RequestedPlatform.Ios) {
|
||||
Errors.error('Unsupported platform, macOS is required to build apps for iOS', { exit: 1 });
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...flags,
|
||||
requestedPlatform,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function handleDeprecatedEasJsonAsync(
|
||||
projectDir: string,
|
||||
nonInteractive: boolean
|
||||
): Promise<void> {
|
||||
const easJsonAccessor = new EasJsonAccessor(projectDir);
|
||||
const profileNames = await EasJsonUtils.getBuildProfileNamesAsync(easJsonAccessor);
|
||||
const platformAndProfileNames: [Platform, string][] = profileNames.flatMap(profileName => [
|
||||
[Platform.ANDROID, profileName],
|
||||
[Platform.IOS, profileName],
|
||||
]);
|
||||
|
||||
const deprecatedProfiles: [Platform, string][] = [];
|
||||
|
||||
for (const [platform, profileName] of platformAndProfileNames) {
|
||||
const buildProfile = await EasJsonUtils.getBuildProfileAsync(
|
||||
easJsonAccessor,
|
||||
platform,
|
||||
profileName
|
||||
);
|
||||
if (buildProfile.artifactPath) {
|
||||
deprecatedProfiles.push([platform, profileName]);
|
||||
}
|
||||
}
|
||||
|
||||
if (deprecatedProfiles.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const deprecatedProfileNames = uniq(deprecatedProfiles.map(([, profileName]) => profileName));
|
||||
Log.warn(`Some of your build profiles use deprecated field ${chalk.bold('artifactPath')}:`);
|
||||
for (const profileName of deprecatedProfileNames) {
|
||||
Log.warn(`- ${profileName}`);
|
||||
}
|
||||
Log.newLine();
|
||||
|
||||
if (nonInteractive) {
|
||||
Log.warn(
|
||||
`${figures.warning} Action required: rename ${chalk.bold('artifactPath')} to ${chalk.bold(
|
||||
'applicationArchivePath'
|
||||
)} in all of the build profiles listed above.`
|
||||
);
|
||||
Log.warn(
|
||||
`See ${link('https://docs.expo.dev/build-reference/eas-json/')} for more information.`
|
||||
);
|
||||
Log.warn(
|
||||
`This warning will become an error in a future EAS CLI release. This build will continue to use the ${chalk.bold(
|
||||
'artifactPath'
|
||||
)} setting.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const rename = await selectAsync('Do you want us to handle renaming the field for you?', [
|
||||
{ title: 'Yes', value: true },
|
||||
{ title: 'No, I will edit eas.json manually (EAS CLI exits)', value: false },
|
||||
]);
|
||||
|
||||
if (!rename) {
|
||||
Errors.exit(1);
|
||||
}
|
||||
|
||||
await easJsonAccessor.readRawJsonAsync();
|
||||
for (const [platform, profileName] of deprecatedProfiles) {
|
||||
easJsonAccessor.patch(easJsonRawObject => {
|
||||
easJsonRawObject.build[profileName][platform].applicationArchivePath =
|
||||
easJsonRawObject.build[profileName][platform].artifactPath;
|
||||
delete easJsonRawObject.build[profileName][platform].artifactPath;
|
||||
return easJsonRawObject;
|
||||
});
|
||||
}
|
||||
await easJsonAccessor.writeAsync();
|
||||
|
||||
Log.withTick('Updated eas.json');
|
||||
}
|
||||
@@ -25,17 +25,16 @@ const STAGE_DESCRIPTION = `Stage of the build you want to inspect.
|
||||
post-build - builds the native project and leaves the output directory for inspection`;
|
||||
|
||||
export default class BuildInspect extends EasCommand {
|
||||
static override description =
|
||||
static description =
|
||||
'inspect the state of the project at specific build stages, useful for troubleshooting';
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
platform: Flags.enum({
|
||||
char: 'p',
|
||||
options: [RequestedPlatform.Android, RequestedPlatform.Ios],
|
||||
required: true,
|
||||
}),
|
||||
profile: Flags.string({
|
||||
char: 'e',
|
||||
description:
|
||||
'Name of the build profile from eas.json. Defaults to "production" if defined in eas.json.',
|
||||
helpValue: 'PROFILE_NAME',
|
||||
|
||||
@@ -22,9 +22,9 @@ import {
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
|
||||
export default class BuildList extends EasCommand {
|
||||
static override description = 'list all builds for your project';
|
||||
static description = 'list all builds for your project';
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
platform: Flags.enum({
|
||||
options: [RequestedPlatform.All, RequestedPlatform.Android, RequestedPlatform.Ios],
|
||||
}),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getRuntimeVersionNullable } from '@expo/config-plugins/build/utils/Updates';
|
||||
import { Platform } from '@expo/eas-build-job';
|
||||
import { EasJsonAccessor, EasJsonUtils } from '@expo/eas-json';
|
||||
import { EasJsonReader } from '@expo/eas-json';
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
|
||||
@@ -27,15 +27,14 @@ import {
|
||||
import { promptAsync } from '../../../prompts';
|
||||
|
||||
export default class BuildVersionSetView extends EasCommand {
|
||||
static override description = 'Update version of an app.';
|
||||
static description = 'Update version of an app.';
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
platform: Flags.enum({
|
||||
char: 'p',
|
||||
options: ['android', 'ios'],
|
||||
}),
|
||||
profile: Flags.string({
|
||||
char: 'e',
|
||||
description:
|
||||
'Name of the build profile from eas.json. Defaults to "production" if defined in eas.json.',
|
||||
helpValue: 'PROFILE_NAME',
|
||||
@@ -48,13 +47,9 @@ export default class BuildVersionSetView extends EasCommand {
|
||||
const projectDir = await findProjectRootAsync();
|
||||
|
||||
const platform = await selectPlatformAsync(flags.platform);
|
||||
const easJsonAccessor = new EasJsonAccessor(projectDir);
|
||||
await ensureVersionSourceIsRemoteAsync(easJsonAccessor);
|
||||
const profile = await EasJsonUtils.getBuildProfileAsync(
|
||||
easJsonAccessor,
|
||||
platform,
|
||||
flags.profile ?? undefined
|
||||
);
|
||||
const easJsonReader = new EasJsonReader(projectDir);
|
||||
await ensureVersionSourceIsRemoteAsync(projectDir, easJsonReader);
|
||||
const profile = await easJsonReader.getBuildProfileAsync(platform, flags.profile ?? undefined);
|
||||
|
||||
const exp = getExpoConfig(projectDir, { env: profile.env });
|
||||
const projectId = await getProjectIdAsync(exp);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ExpoConfig } from '@expo/config';
|
||||
import { Platform, Workflow } from '@expo/eas-build-job';
|
||||
import { BuildProfile, EasJsonAccessor } from '@expo/eas-json';
|
||||
import { BuildProfile, EasJsonReader } from '@expo/eas-json';
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
|
||||
@@ -40,16 +40,14 @@ interface SyncContext<T extends Platform> {
|
||||
}
|
||||
|
||||
export default class BuildVersionSyncView extends EasCommand {
|
||||
public static override description =
|
||||
'Update a version in native code with a value stored on EAS servers';
|
||||
public static description = 'Update a version in native code with a value stored on EAS servers';
|
||||
|
||||
public static override flags = {
|
||||
public static flags = {
|
||||
platform: Flags.enum({
|
||||
char: 'p',
|
||||
options: ['android', 'ios', 'all'],
|
||||
}),
|
||||
profile: Flags.string({
|
||||
char: 'e',
|
||||
description:
|
||||
'Name of the build profile from eas.json. Defaults to "production" if defined in eas.json.',
|
||||
helpValue: 'PROFILE_NAME',
|
||||
@@ -61,13 +59,13 @@ export default class BuildVersionSyncView extends EasCommand {
|
||||
const projectDir = await findProjectRootAsync();
|
||||
|
||||
const requestedPlatform = await selectRequestedPlatformAsync(flags.platform);
|
||||
const easJsonAccessor = new EasJsonAccessor(projectDir);
|
||||
await ensureVersionSourceIsRemoteAsync(easJsonAccessor);
|
||||
const easJsonReader = new EasJsonReader(projectDir);
|
||||
await ensureVersionSourceIsRemoteAsync(projectDir, easJsonReader);
|
||||
|
||||
const platforms = toPlatforms(requestedPlatform);
|
||||
const buildProfiles = await getProfilesAsync({
|
||||
type: 'build',
|
||||
easJsonAccessor,
|
||||
easJsonReader,
|
||||
platforms,
|
||||
profileName: flags.profile ?? undefined,
|
||||
});
|
||||
|
||||
@@ -15,11 +15,11 @@ import {
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
|
||||
export default class BuildView extends EasCommand {
|
||||
static override description = 'view a build for your project';
|
||||
static description = 'view a build for your project';
|
||||
|
||||
static override args = [{ name: 'BUILD_ID' }];
|
||||
static args = [{ name: 'BUILD_ID' }];
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
json: Flags.boolean({
|
||||
description: 'Enable JSON output, non-JSON messages will be printed to stderr',
|
||||
}),
|
||||
|
||||
@@ -60,9 +60,9 @@ export async function createUpdateChannelOnAppAsync({
|
||||
}
|
||||
|
||||
export default class ChannelCreate extends EasCommand {
|
||||
static override description = 'create a channel';
|
||||
static description = 'create a channel';
|
||||
|
||||
static override args = [
|
||||
static args = [
|
||||
{
|
||||
name: 'name',
|
||||
required: false,
|
||||
@@ -70,7 +70,7 @@ export default class ChannelCreate extends EasCommand {
|
||||
},
|
||||
];
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
json: Flags.boolean({
|
||||
description:
|
||||
'print output as a JSON object with the new channel ID, name and branch mapping.',
|
||||
@@ -99,7 +99,7 @@ export default class ChannelCreate extends EasCommand {
|
||||
({ name: channelName } = await promptAsync({
|
||||
type: 'text',
|
||||
name: 'name',
|
||||
message: 'Provide a channel name:',
|
||||
message: 'Please name the channel:',
|
||||
validate: value => (value ? true : validationMessage),
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -21,17 +21,17 @@ import { promptAsync, toggleConfirmAsync } from '../../prompts';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
|
||||
export default class ChannelDelete extends EasCommand {
|
||||
static override hidden = true;
|
||||
static override description = 'Delete a channel';
|
||||
static hidden = true;
|
||||
static description = 'Delete a channel';
|
||||
|
||||
static override args = [
|
||||
static args = [
|
||||
{
|
||||
name: 'name',
|
||||
required: false,
|
||||
description: 'Name of the channel to delete',
|
||||
},
|
||||
];
|
||||
static override flags = {
|
||||
static flags = {
|
||||
json: Flags.boolean({
|
||||
description: 'print output as a JSON object',
|
||||
default: false,
|
||||
@@ -70,7 +70,7 @@ export default class ChannelDelete extends EasCommand {
|
||||
await promptAsync({
|
||||
type: 'text',
|
||||
name: 'name',
|
||||
message: 'Provide the name of the channel to delete:',
|
||||
message: 'Please enter the name of the channel to delete:',
|
||||
validate: (value: any) => (value ? true : 'Channel name may not be empty.'),
|
||||
})
|
||||
).name;
|
||||
@@ -85,7 +85,7 @@ export default class ChannelDelete extends EasCommand {
|
||||
if (!nonInteractiveFlag) {
|
||||
Log.addNewLineIfNone();
|
||||
Log.warn(
|
||||
`You are about to permanently delete channel: "${name}".\nThis action is irreversible.`
|
||||
`You are about to permamently delete channel: "${name}".\nThis action is irreversible.`
|
||||
);
|
||||
Log.newLine();
|
||||
const confirmed = await toggleConfirmAsync({ message: 'Are you sure you wish to proceed?' });
|
||||
|
||||
@@ -93,9 +93,9 @@ export async function updateChannelBranchMappingAsync({
|
||||
}
|
||||
|
||||
export default class ChannelEdit extends EasCommand {
|
||||
static override description = 'point a channel at a new branch';
|
||||
static description = 'point a channel at a new branch';
|
||||
|
||||
static override args = [
|
||||
static args = [
|
||||
{
|
||||
name: 'name',
|
||||
required: false,
|
||||
@@ -103,7 +103,7 @@ export default class ChannelEdit extends EasCommand {
|
||||
},
|
||||
];
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
branch: Flags.string({
|
||||
description: 'Name of the branch to point to',
|
||||
}),
|
||||
@@ -127,7 +127,9 @@ export default class ChannelEdit extends EasCommand {
|
||||
|
||||
const existingChannel = await getChannelByNameForAppAsync({ appId: projectId, channelName });
|
||||
if (existingChannel.updateBranches.length > 1) {
|
||||
throw new Error('There is a rollout in progress. Manage it with "channel:rollout" instead.');
|
||||
throw new Error(
|
||||
'There is a rollout in progress. Please manage it with "channel:rollout" instead.'
|
||||
);
|
||||
}
|
||||
|
||||
const branchName = flags.branch ?? (await promptForBranchAsync());
|
||||
@@ -138,7 +140,7 @@ export default class ChannelEdit extends EasCommand {
|
||||
});
|
||||
if (!branch) {
|
||||
throw new Error(
|
||||
`Could not find a branch named "${branchName}". Check what branches exist on this project with ${chalk.bold(
|
||||
`Could not find a branch named "${branchName}". Please check what branches exist on this project with ${chalk.bold(
|
||||
'eas branch:list'
|
||||
)}.`
|
||||
);
|
||||
@@ -171,7 +173,7 @@ async function promptForChannelAsync(): Promise<string> {
|
||||
const { name } = await promptAsync({
|
||||
type: 'text',
|
||||
name: 'name',
|
||||
message: 'Provide the name of the channel to edit:',
|
||||
message: 'Please enter the name of the channel to edit:',
|
||||
validate: value => (value ? true : 'The channel name may not be empty.'),
|
||||
});
|
||||
return name;
|
||||
|
||||
@@ -67,9 +67,9 @@ async function getAllUpdateChannelForAppAsync({
|
||||
}
|
||||
|
||||
export default class ChannelList extends EasCommand {
|
||||
static override description = 'list all channels';
|
||||
static description = 'list all channels';
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
json: Flags.boolean({
|
||||
description: 'print output as a JSON object with the channel ID, name and branch mapping.',
|
||||
default: false,
|
||||
|
||||
@@ -92,7 +92,7 @@ async function startRolloutAsync({
|
||||
});
|
||||
if (!branch) {
|
||||
throw new Error(
|
||||
`Could not find a branch named "${branchName}". Check which branches exist on this project with ${chalk.bold(
|
||||
`Could not find a branch named "${branchName}". Please check what branches exist on this project with ${chalk.bold(
|
||||
'eas branch:list'
|
||||
)}.`
|
||||
);
|
||||
@@ -238,7 +238,7 @@ async function endRolloutAsync({
|
||||
});
|
||||
if (!branch) {
|
||||
throw new Error(
|
||||
`Could not find a branch named "${branchName}". Check which branches exist on this project with ${chalk.bold(
|
||||
`Could not find a branch named "${branchName}". Please check what branches exist on this project with ${chalk.bold(
|
||||
'eas branch:list'
|
||||
)}.`
|
||||
);
|
||||
@@ -304,10 +304,10 @@ async function endRolloutAsync({
|
||||
}
|
||||
|
||||
export default class ChannelRollout extends EasCommand {
|
||||
static override hidden = true;
|
||||
static override description = 'Rollout a new branch out to a channel incrementally.';
|
||||
static hidden = true;
|
||||
static description = 'Rollout a new branch out to a channel incrementally.';
|
||||
|
||||
static override args = [
|
||||
static args = [
|
||||
{
|
||||
name: 'channel',
|
||||
required: true,
|
||||
@@ -315,7 +315,7 @@ export default class ChannelRollout extends EasCommand {
|
||||
},
|
||||
];
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
branch: Flags.string({
|
||||
description: 'branch to rollout',
|
||||
required: false,
|
||||
@@ -354,7 +354,7 @@ export default class ChannelRollout extends EasCommand {
|
||||
});
|
||||
if (!channel) {
|
||||
throw new Error(
|
||||
`Could not find a channel named "${channelName}". Check which channels exist on this project with ${chalk.bold(
|
||||
`Could not find a channel named "${channelName}". Please check what channels exist on this project with ${chalk.bold(
|
||||
'eas channel:list'
|
||||
)}.`
|
||||
);
|
||||
|
||||
@@ -138,9 +138,9 @@ export function logChannelDetails(channel: {
|
||||
}
|
||||
|
||||
export default class ChannelView extends EasCommand {
|
||||
static override description = 'view a channel';
|
||||
static description = 'view a channel';
|
||||
|
||||
static override args = [
|
||||
static args = [
|
||||
{
|
||||
name: 'name',
|
||||
required: false,
|
||||
@@ -148,7 +148,7 @@ export default class ChannelView extends EasCommand {
|
||||
},
|
||||
];
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
json: Flags.boolean({
|
||||
description: 'print output as a JSON object with the channel ID, name and branch mapping.',
|
||||
default: false,
|
||||
@@ -176,7 +176,7 @@ export default class ChannelView extends EasCommand {
|
||||
({ name: channelName } = await promptAsync({
|
||||
type: 'text',
|
||||
name: 'name',
|
||||
message: 'Provide a channel name:',
|
||||
message: 'Please name the channel:',
|
||||
validate: value => (value ? true : validationMessage),
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { getProjectConfigDescription } from '@expo/config';
|
||||
import { Platform } from '@expo/eas-build-job';
|
||||
import { EasJsonAccessor, EasJsonUtils } from '@expo/eas-json';
|
||||
import { EasJsonReader } from '@expo/eas-json';
|
||||
import { Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
|
||||
@@ -13,19 +13,14 @@ import { findProjectRootAsync } from '../project/projectUtils';
|
||||
import { selectAsync } from '../prompts';
|
||||
|
||||
export default class Config extends EasCommand {
|
||||
static override description = 'display project configuration (app.json + eas.json)';
|
||||
static description = 'display project configuration (app.json + eas.json)';
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
platform: Flags.enum({ char: 'p', options: ['android', 'ios'] }),
|
||||
profile: Flags.string({
|
||||
char: 'e',
|
||||
description:
|
||||
'Name of the build profile from eas.json. Defaults to "production" if defined in eas.json.',
|
||||
helpValue: 'PROFILE_NAME',
|
||||
}),
|
||||
profile: Flags.string(),
|
||||
};
|
||||
|
||||
protected override requiresAuthentication = false;
|
||||
protected requiresAuthentication = false;
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { flags } = await this.parse(Config);
|
||||
@@ -36,13 +31,13 @@ export default class Config extends EasCommand {
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
|
||||
const accessor = new EasJsonAccessor(projectDir);
|
||||
const reader = new EasJsonReader(projectDir);
|
||||
const profileName =
|
||||
maybeProfile ??
|
||||
(await selectAsync(
|
||||
'Select build profile',
|
||||
(
|
||||
await EasJsonUtils.getBuildProfileNamesAsync(accessor)
|
||||
await reader.getBuildProfileNamesAsync()
|
||||
).map(profileName => ({
|
||||
title: profileName,
|
||||
value: profileName,
|
||||
@@ -61,7 +56,7 @@ export default class Config extends EasCommand {
|
||||
},
|
||||
]));
|
||||
|
||||
const profile = await EasJsonUtils.getBuildProfileAsync(accessor, platform, profileName);
|
||||
const profile = await reader.getBuildProfileAsync(platform, profileName);
|
||||
const config = getExpoConfig(projectDir, { env: profile.env, isPublicConfig: true });
|
||||
|
||||
Log.addNewLineIfNone();
|
||||
|
||||
@@ -1,17 +1,10 @@
|
||||
import { Flags } from '@oclif/core';
|
||||
|
||||
import EasCommand from '../commandUtils/EasCommand';
|
||||
import { SelectPlatform } from '../credentials/manager/SelectPlatform';
|
||||
|
||||
export default class Credentials extends EasCommand {
|
||||
static override description = 'manage credentials';
|
||||
|
||||
static override flags = {
|
||||
platform: Flags.enum({ char: 'p', options: ['android', 'ios'] }),
|
||||
};
|
||||
static description = 'manage credentials';
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { flags } = await this.parse(Credentials);
|
||||
await new SelectPlatform(flags.platform).runAsync();
|
||||
await new SelectPlatform().runAsync();
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import DeviceManager from '../../devices/manager';
|
||||
import { ensureLoggedInAsync } from '../../user/actions';
|
||||
|
||||
export default class DeviceCreate extends EasCommand {
|
||||
static override description = 'register new Apple Devices to use for internal distribution';
|
||||
static description = 'register new Apple Devices to use for internal distribution';
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const user = await ensureLoggedInAsync();
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Device, DeviceStatus } from '@expo/apple-utils';
|
||||
import { Flags } from '@oclif/core';
|
||||
import assert from 'assert';
|
||||
|
||||
import EasCommand, { CommandContext } from '../../commandUtils/EasCommand';
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
import { chooseDevicesToDeleteAsync } from '../../credentials/ios/actions/DeviceUtils';
|
||||
import { AppleDeviceMutation } from '../../credentials/ios/api/graphql/mutations/AppleDeviceMutation';
|
||||
import {
|
||||
@@ -14,18 +14,21 @@ import { AppleTeamQuery } from '../../credentials/ios/api/graphql/queries/AppleT
|
||||
import { authenticateAsync, getRequestContext } from '../../credentials/ios/appstore/authenticate';
|
||||
import formatDevice from '../../devices/utils/formatDevice';
|
||||
import { AppleDevice, Maybe } from '../../graphql/generated';
|
||||
import Log from '../../log';
|
||||
import { ora } from '../../ora';
|
||||
import { getExpoConfig } from '../../project/expoConfig';
|
||||
import { findProjectRootAsync, getProjectAccountNameAsync } from '../../project/projectUtils';
|
||||
import { promptAsync, toggleConfirmAsync } from '../../prompts';
|
||||
|
||||
export default class DeviceDelete extends EasCommand {
|
||||
static override description = 'remove a registered device from your account';
|
||||
static description = 'remove a registered device from your account';
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
'apple-team-id': Flags.string(),
|
||||
udid: Flags.string({ multiple: true }),
|
||||
};
|
||||
|
||||
protected async runAsync(commandContext: CommandContext): Promise<{ jsonOutput: object }> {
|
||||
async runAsync(): Promise<void> {
|
||||
let {
|
||||
flags: { 'apple-team-id': appleTeamIdentifier, udid: udids },
|
||||
} = await this.parse(DeviceDelete);
|
||||
@@ -35,61 +38,46 @@ export default class DeviceDelete extends EasCommand {
|
||||
const accountName = await getProjectAccountNameAsync(exp);
|
||||
|
||||
if (!appleTeamIdentifier) {
|
||||
if (commandContext.nonInteractive) {
|
||||
throw new Error('Must supply `apple-team-id` in non-interactive mode');
|
||||
}
|
||||
appleTeamIdentifier = await this.askForAppleTeamAsync(commandContext, accountName);
|
||||
appleTeamIdentifier = await this.askForAppleTeamAsync(accountName);
|
||||
}
|
||||
|
||||
assert(appleTeamIdentifier, 'No team identifier is specified');
|
||||
|
||||
const appleDevicesResult = await this.getDevicesForTeamAsync(
|
||||
commandContext,
|
||||
accountName,
|
||||
appleTeamIdentifier
|
||||
);
|
||||
const appleDevicesResult = await this.getDevicesForTeamAsync(accountName, appleTeamIdentifier);
|
||||
|
||||
if (!appleDevicesResult) {
|
||||
return { jsonOutput: [] };
|
||||
return;
|
||||
}
|
||||
|
||||
const { appleTeamName, appleDevices } = appleDevicesResult;
|
||||
|
||||
const chosenDevices = await this.chooseDevicesToDeleteAsync(
|
||||
commandContext,
|
||||
appleDevices,
|
||||
udids
|
||||
);
|
||||
const chosenDevices = await this.chooseDevicesToDeleteAsync(appleDevices, udids);
|
||||
|
||||
if (chosenDevices.length === 0) {
|
||||
commandContext.logger.newLine();
|
||||
commandContext.logger.warn('No devices were chosen to be removed.');
|
||||
return { jsonOutput: [] };
|
||||
Log.newLine();
|
||||
Log.warn('No devices were chosen to be removed.');
|
||||
return;
|
||||
}
|
||||
|
||||
this.logChosenDevices(commandContext, chosenDevices, appleTeamName, appleTeamIdentifier);
|
||||
this.logChosenDevices(chosenDevices, appleTeamName, appleTeamIdentifier);
|
||||
|
||||
const hasRemoved = await this.askAndRemoveFromExpoAsync(chosenDevices);
|
||||
|
||||
const hasRemoved = await this.askAndRemoveFromExpoAsync(commandContext, chosenDevices);
|
||||
if (!hasRemoved) {
|
||||
return { jsonOutput: [] };
|
||||
return;
|
||||
}
|
||||
|
||||
await this.askAndDisableOnAppleAsync(commandContext, chosenDevices, appleTeamIdentifier);
|
||||
|
||||
return { jsonOutput: chosenDevices.map(it => it.id) };
|
||||
await this.askAndDisableOnAppleAsync(chosenDevices, appleTeamIdentifier);
|
||||
}
|
||||
|
||||
async askAndDisableOnAppleAsync(
|
||||
{ nonInteractive, logger, prompts: { toggleConfirmAsync }, ora }: CommandContext,
|
||||
chosenDevices: (AppleDevice | AppleDeviceQueryResult)[],
|
||||
appleTeamIdentifier: string
|
||||
): Promise<void> {
|
||||
logger.newLine();
|
||||
const deleteOnApple = nonInteractive
|
||||
? true
|
||||
: await toggleConfirmAsync({
|
||||
message: 'Do you want to disable these devices on your Apple account as well?',
|
||||
});
|
||||
Log.newLine();
|
||||
const deleteOnApple = await toggleConfirmAsync({
|
||||
message: 'Do you want to disable these devices on your Apple account as well?',
|
||||
});
|
||||
|
||||
if (!deleteOnApple) {
|
||||
return;
|
||||
@@ -98,13 +86,12 @@ export default class DeviceDelete extends EasCommand {
|
||||
const ctx = await authenticateAsync({ teamId: appleTeamIdentifier });
|
||||
const context = getRequestContext(ctx);
|
||||
|
||||
logger.addNewLineIfNone();
|
||||
Log.addNewLineIfNone();
|
||||
const removeAppleSpinner = ora('Disabling devices on Apple').start();
|
||||
try {
|
||||
const chosenDeviceIdentifiers = chosenDevices.map(cd => cd.identifier);
|
||||
const allDevices = await Device.getAsync(context);
|
||||
const realDevices = allDevices.filter(d =>
|
||||
chosenDeviceIdentifiers.includes(d.attributes.udid)
|
||||
let realDevices = await Device.getAllIOSProfileDevicesAsync(context);
|
||||
realDevices = realDevices.filter(d =>
|
||||
chosenDevices.map(cd => cd.identifier).includes(d.attributes.udid)
|
||||
);
|
||||
|
||||
for (const device of realDevices) {
|
||||
@@ -119,21 +106,18 @@ export default class DeviceDelete extends EasCommand {
|
||||
}
|
||||
|
||||
async askAndRemoveFromExpoAsync(
|
||||
{ nonInteractive, logger, prompts: { toggleConfirmAsync }, ora }: CommandContext,
|
||||
chosenDevices: (AppleDevice | AppleDeviceQueryResult)[]
|
||||
): Promise<boolean> {
|
||||
logger.warn(
|
||||
Log.warn(
|
||||
`You are about to remove the Apple device${
|
||||
chosenDevices.length > 1 ? 's' : ''
|
||||
} listed above from your Expo account.`
|
||||
);
|
||||
logger.newLine();
|
||||
Log.newLine();
|
||||
|
||||
const confirmed = nonInteractive
|
||||
? true
|
||||
: await toggleConfirmAsync({
|
||||
message: 'Are you sure you wish to proceed?',
|
||||
});
|
||||
const confirmed = await toggleConfirmAsync({
|
||||
message: 'Are you sure you wish to proceed?',
|
||||
});
|
||||
|
||||
if (confirmed) {
|
||||
const removalSpinner = ora(`Removing Apple devices on Expo`).start();
|
||||
@@ -152,55 +136,49 @@ export default class DeviceDelete extends EasCommand {
|
||||
}
|
||||
|
||||
logChosenDevices(
|
||||
{ logger }: CommandContext,
|
||||
chosenDevices: (AppleDevice | AppleDeviceQueryResult)[],
|
||||
appleTeamName: Maybe<string> | undefined,
|
||||
appleTeamIdentifier: string
|
||||
): void {
|
||||
logger.addNewLineIfNone();
|
||||
Log.addNewLineIfNone();
|
||||
chosenDevices.forEach(device => {
|
||||
logger.log(
|
||||
Log.log(
|
||||
formatDevice(device, {
|
||||
appleTeamName,
|
||||
appleTeamIdentifier: appleTeamIdentifier!,
|
||||
})
|
||||
);
|
||||
logger.newLine();
|
||||
Log.newLine();
|
||||
});
|
||||
}
|
||||
|
||||
async chooseDevicesToDeleteAsync(
|
||||
{ nonInteractive, logger }: CommandContext,
|
||||
appleDevices: AppleDeviceQueryResult[],
|
||||
udids: string[]
|
||||
): Promise<(AppleDevice | AppleDeviceQueryResult)[]> {
|
||||
let chosenDevices: (AppleDeviceQueryResult | AppleDevice)[] = [];
|
||||
logger.newLine();
|
||||
Log.newLine();
|
||||
if (udids) {
|
||||
udids.forEach(udid => {
|
||||
const foundDevice = appleDevices.find(device => device.identifier === udid);
|
||||
if (foundDevice) {
|
||||
chosenDevices.push(foundDevice);
|
||||
} else {
|
||||
logger.warn(`No device found with UDID ${udid}.`);
|
||||
Log.warn(`No device found with UDID ${udid}.`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (chosenDevices.length === 0) {
|
||||
if (nonInteractive) {
|
||||
throw new Error('Must supply `udid` paramter in non-interactive mode');
|
||||
}
|
||||
logger.addNewLineIfNone();
|
||||
Log.addNewLineIfNone();
|
||||
chosenDevices = await chooseDevicesToDeleteAsync(appleDevices);
|
||||
logger.newLine();
|
||||
Log.newLine();
|
||||
}
|
||||
|
||||
return chosenDevices;
|
||||
}
|
||||
|
||||
async getDevicesForTeamAsync(
|
||||
{ ora }: CommandContext,
|
||||
accountName: string,
|
||||
appleTeamIdentifier: string
|
||||
): Promise<AppleDevicesByTeamIdentifierQueryResult | undefined> {
|
||||
@@ -230,10 +208,7 @@ export default class DeviceDelete extends EasCommand {
|
||||
}
|
||||
}
|
||||
|
||||
async askForAppleTeamAsync(
|
||||
{ prompts: { promptAsync }, ora }: CommandContext,
|
||||
accountName: string
|
||||
): Promise<string | undefined> {
|
||||
async askForAppleTeamAsync(accountName: string): Promise<string | undefined> {
|
||||
const teamSpinner = ora().start('Fetching the list of teams for the project…');
|
||||
|
||||
try {
|
||||
|
||||
@@ -13,9 +13,9 @@ import { findProjectRootAsync, getProjectAccountNameAsync } from '../../project/
|
||||
import { promptAsync } from '../../prompts';
|
||||
|
||||
export default class BuildList extends EasCommand {
|
||||
static override description = 'list all registered devices for your account';
|
||||
static description = 'list all registered devices for your account';
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
'apple-team-id': Flags.string(),
|
||||
};
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ import { getExpoConfig } from '../../project/expoConfig';
|
||||
import { findProjectRootAsync, getProjectAccountNameAsync } from '../../project/projectUtils';
|
||||
|
||||
export default class DeviceView extends EasCommand {
|
||||
static override description = 'view a device for your project';
|
||||
static description = 'view a device for your project';
|
||||
|
||||
static override args = [{ name: 'UDID' }];
|
||||
static args = [{ name: 'UDID' }];
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { UDID } = (await this.parse(DeviceView)).args;
|
||||
|
||||
@@ -8,9 +8,9 @@ import { resolveWorkflowAsync } from '../project/workflow';
|
||||
import { easCliVersion } from '../utils/easCli';
|
||||
|
||||
export default class Diagnostics extends EasCommand {
|
||||
static override description = 'display environment info';
|
||||
static description = 'display environment info';
|
||||
|
||||
protected override requiresAuthentication = false;
|
||||
protected requiresAuthentication = false;
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const info = await envinfo.run(
|
||||
|
||||
@@ -14,11 +14,10 @@ import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUt
|
||||
import { ensureLoggedInAsync } from '../../user/actions';
|
||||
|
||||
export default class MetadataPull extends EasCommand {
|
||||
static override description = 'generate the local store configuration from the app stores';
|
||||
static description = 'generate the local store configuration from the app stores';
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
profile: Flags.string({
|
||||
char: 'e',
|
||||
description:
|
||||
'Name of the submit profile from eas.json. Defaults to "production" if defined in eas.json.',
|
||||
}),
|
||||
@@ -52,11 +51,11 @@ export default class MetadataPull extends EasCommand {
|
||||
const relativePath = path.relative(process.cwd(), filePath);
|
||||
|
||||
Log.addNewLineIfNone();
|
||||
Log.log(`🎉 Your store config is ready.
|
||||
Log.log(`🎉 Your store configuration is ready.
|
||||
|
||||
- Update the ${chalk.bold(relativePath)} file to prepare the app information.
|
||||
- Run ${chalk.bold('eas submit')} or manually upload a new app version to the app stores.
|
||||
- Once the app is uploaded, run ${chalk.bold('eas metadata:push')} to sync the store config.
|
||||
- Once the app is uploaded, run ${chalk.bold('eas metadata:push')} to sync the store configuration.
|
||||
- ${learnMore('https://docs.expo.dev/eas-metadata/introduction/')}`);
|
||||
} catch (error: any) {
|
||||
handleMetadataError(error);
|
||||
|
||||
@@ -12,11 +12,10 @@ import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUt
|
||||
import { ensureLoggedInAsync } from '../../user/actions';
|
||||
|
||||
export default class MetadataPush extends EasCommand {
|
||||
static override description = 'sync the local store configuration to the app stores';
|
||||
static description = 'sync the local store configuration to the app stores';
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
profile: Flags.string({
|
||||
char: 'e',
|
||||
description:
|
||||
'Name of the submit profile from eas.json. Defaults to "production" if defined in eas.json.',
|
||||
}),
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
import openBrowserAsync from 'better-opn';
|
||||
|
||||
import { getProjectDashboardUrl } from '../build/utils/url';
|
||||
import EasCommand from '../commandUtils/EasCommand';
|
||||
import { ora } from '../ora';
|
||||
import { getExpoConfig } from '../project/expoConfig';
|
||||
import {
|
||||
fetchProjectIdFromServerAsync,
|
||||
findProjectRootAsync,
|
||||
getProjectAccountName,
|
||||
} from '../project/projectUtils';
|
||||
import { ensureLoggedInAsync } from '../user/actions';
|
||||
|
||||
export default class Open extends EasCommand {
|
||||
static override description = 'open the project page in a web browser';
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const exp = getExpoConfig(projectDir);
|
||||
|
||||
// this ensures the project exists
|
||||
await fetchProjectIdFromServerAsync(exp);
|
||||
|
||||
const user = await ensureLoggedInAsync();
|
||||
const accountName = getProjectAccountName(exp, user);
|
||||
const projectName = exp.slug;
|
||||
|
||||
const projectDashboardUrl = getProjectDashboardUrl(accountName, projectName);
|
||||
const failedMessage = `Unable to open a web browser. Project page is available at: ${projectDashboardUrl}`;
|
||||
const spinner = ora(`Opening ${projectDashboardUrl}`).start();
|
||||
try {
|
||||
const opened = await openBrowserAsync(projectDashboardUrl);
|
||||
|
||||
if (opened) {
|
||||
spinner.succeed(`Opened ${projectDashboardUrl}`);
|
||||
} else {
|
||||
spinner.fail(failedMessage);
|
||||
}
|
||||
return;
|
||||
} catch (error) {
|
||||
spinner.fail(failedMessage);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ async function projectInfoByIdAsync(appId: string): Promise<AppInfoQuery> {
|
||||
}
|
||||
|
||||
export default class ProjectInfo extends EasCommand {
|
||||
static override description = 'information about the current project';
|
||||
static description = 'information about the current project';
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const projectDir = await findProjectRootAsync();
|
||||
|
||||
@@ -3,15 +3,11 @@ import chalk from 'chalk';
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
import Log from '../../log';
|
||||
import { getExpoConfig } from '../../project/expoConfig';
|
||||
import {
|
||||
fetchProjectIdFromServerAsync,
|
||||
findProjectRootAsync,
|
||||
saveProjectIdToAppConfigAsync,
|
||||
} from '../../project/projectUtils';
|
||||
import { findProjectRootAsync, setProjectIdAsync } from '../../project/projectUtils';
|
||||
|
||||
export default class ProjectInit extends EasCommand {
|
||||
static override description = 'create or link an EAS project';
|
||||
static override aliases = ['init'];
|
||||
static description = 'create or link an EAS project';
|
||||
static aliases = ['init'];
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const projectDir = await findProjectRootAsync();
|
||||
@@ -24,9 +20,6 @@ export default class ProjectInit extends EasCommand {
|
||||
return;
|
||||
}
|
||||
|
||||
const projectId = await fetchProjectIdFromServerAsync(exp);
|
||||
await saveProjectIdToAppConfigAsync(projectDir, projectId);
|
||||
|
||||
Log.withTick(`Linked app.json to project with ID ${chalk.bold(projectId)}`);
|
||||
await setProjectIdAsync(projectDir);
|
||||
}
|
||||
}
|
||||
@@ -20,10 +20,9 @@ import { getActorDisplayName } from '../../user/User';
|
||||
import { ensureLoggedInAsync } from '../../user/actions';
|
||||
|
||||
export default class EnvironmentSecretCreate extends EasCommand {
|
||||
static override description =
|
||||
'create an environment secret on the current project or owner account';
|
||||
static description = 'create an environment secret on the current project or owner account';
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
scope: Flags.enum({
|
||||
description: 'Scope for the secret',
|
||||
options: [EnvironmentSecretScope.ACCOUNT, EnvironmentSecretScope.PROJECT],
|
||||
|
||||
@@ -17,9 +17,9 @@ import {
|
||||
import { promptAsync, toggleConfirmAsync } from '../../prompts';
|
||||
|
||||
export default class EnvironmentSecretDelete extends EasCommand {
|
||||
static override description = 'delete an environment secret by ID';
|
||||
static description = 'delete an environment secret by ID';
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
id: Flags.string({
|
||||
description: 'ID of the secret to delete',
|
||||
}),
|
||||
@@ -60,7 +60,7 @@ export default class EnvironmentSecretDelete extends EasCommand {
|
||||
|
||||
Log.addNewLineIfNone();
|
||||
Log.warn(
|
||||
`You are about to permanently delete secret${
|
||||
`You are about to permamently delete secret${
|
||||
secret?.name ? ` "${secret?.name}"` : ''
|
||||
} with id: "${id}".\nThis action is irreversible.`
|
||||
);
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
} from '../../project/projectUtils';
|
||||
|
||||
export default class EnvironmentSecretList extends EasCommand {
|
||||
static override description = 'list environment secrets available for your current app';
|
||||
static description = 'list environment secrets available for your current app';
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const projectDir = await findProjectRootAsync();
|
||||
@@ -22,7 +22,7 @@ export default class EnvironmentSecretList extends EasCommand {
|
||||
const projectAccountName = await getProjectAccountNameAsync(exp);
|
||||
|
||||
if (!projectDir) {
|
||||
throw new Error("Run this command inside your project's directory");
|
||||
throw new Error("Please run this command inside your project's directory");
|
||||
}
|
||||
|
||||
const secrets = await EnvironmentSecretsQuery.allAsync(projectAccountName, projectId);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { EasJsonAccessor } from '@expo/eas-json';
|
||||
import { EasJsonReader } from '@expo/eas-json';
|
||||
import { Errors, Flags } from '@oclif/core';
|
||||
import chalk from 'chalk';
|
||||
|
||||
import EasCommand from '../commandUtils/EasCommand';
|
||||
import { StatuspageServiceName, SubmissionFragment } from '../graphql/generated';
|
||||
import { SubmissionFragment } from '../graphql/generated';
|
||||
import { toAppPlatform } from '../graphql/types/AppPlatform';
|
||||
import Log from '../log';
|
||||
import {
|
||||
@@ -23,7 +23,6 @@ import {
|
||||
} from '../submit/submit';
|
||||
import { printSubmissionDetailsUrls } from '../submit/utils/urls';
|
||||
import { getProfilesAsync } from '../utils/profiles';
|
||||
import { maybeWarnAboutEasOutagesAsync } from '../utils/statuspageService';
|
||||
|
||||
interface RawCommandFlags {
|
||||
platform?: string;
|
||||
@@ -47,16 +46,15 @@ interface CommandFlags {
|
||||
}
|
||||
|
||||
export default class Submit extends EasCommand {
|
||||
static override description = 'submit app binary to App Store and/or Play Store';
|
||||
static override aliases = ['build:submit'];
|
||||
static description = 'submit app binary to App Store and/or Play Store';
|
||||
static aliases = ['build:submit'];
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
platform: Flags.enum({
|
||||
char: 'p',
|
||||
options: ['android', 'ios', 'all'],
|
||||
}),
|
||||
profile: Flags.string({
|
||||
char: 'e',
|
||||
description:
|
||||
'Name of the submit profile from eas.json. Defaults to "production" if defined in eas.json.',
|
||||
}),
|
||||
@@ -93,23 +91,18 @@ export default class Submit extends EasCommand {
|
||||
|
||||
async runAsync(): Promise<void> {
|
||||
const { flags: rawFlags } = await this.parse(Submit);
|
||||
|
||||
const flags = this.sanitizeFlags(rawFlags);
|
||||
const flags = await this.sanitizeFlagsAsync(rawFlags);
|
||||
|
||||
const projectDir = await findProjectRootAsync();
|
||||
const exp = getExpoConfig(projectDir);
|
||||
const projectId = await getProjectIdAsync(exp);
|
||||
|
||||
await maybeWarnAboutEasOutagesAsync([StatuspageServiceName.EasSubmit]);
|
||||
|
||||
const flagsWithPlatform = await this.ensurePlatformSelectedAsync(flags);
|
||||
|
||||
const platforms = toPlatforms(flagsWithPlatform.requestedPlatform);
|
||||
const platforms = toPlatforms(flags.requestedPlatform);
|
||||
const submissionProfiles = await getProfilesAsync({
|
||||
type: 'submit',
|
||||
easJsonAccessor: new EasJsonAccessor(projectDir),
|
||||
easJsonReader: new EasJsonReader(projectDir),
|
||||
platforms,
|
||||
profileName: flagsWithPlatform.profile,
|
||||
profileName: flags.profile,
|
||||
});
|
||||
|
||||
const submissions: SubmissionFragment[] = [];
|
||||
@@ -119,8 +112,8 @@ export default class Submit extends EasCommand {
|
||||
projectDir,
|
||||
projectId,
|
||||
profile: submissionProfile.profile,
|
||||
archiveFlags: flagsWithPlatform.archiveFlags,
|
||||
nonInteractive: flagsWithPlatform.nonInteractive,
|
||||
archiveFlags: flags.archiveFlags,
|
||||
nonInteractive: flags.nonInteractive,
|
||||
});
|
||||
|
||||
if (submissionProfiles.length > 1) {
|
||||
@@ -140,17 +133,15 @@ export default class Submit extends EasCommand {
|
||||
Log.newLine();
|
||||
printSubmissionDetailsUrls(submissions);
|
||||
|
||||
if (flagsWithPlatform.wait) {
|
||||
if (flags.wait) {
|
||||
const completedSubmissions = await waitToCompleteAsync(submissions, {
|
||||
verbose: flagsWithPlatform.verbose,
|
||||
verbose: flags.verbose,
|
||||
});
|
||||
exitWithNonZeroCodeIfSomeSubmissionsDidntFinish(completedSubmissions);
|
||||
}
|
||||
}
|
||||
|
||||
private sanitizeFlags(
|
||||
flags: RawCommandFlags
|
||||
): Omit<CommandFlags, 'requestedPlatform'> & { requestedPlatform?: RequestedPlatform } {
|
||||
private async sanitizeFlagsAsync(flags: RawCommandFlags): Promise<CommandFlags> {
|
||||
const {
|
||||
platform,
|
||||
verbose,
|
||||
@@ -164,11 +155,15 @@ export default class Submit extends EasCommand {
|
||||
Errors.error('--platform is required when building in non-interactive mode', { exit: 1 });
|
||||
}
|
||||
|
||||
const requestedPlatform =
|
||||
flags.platform &&
|
||||
Object.values(RequestedPlatform).includes(flags.platform.toLowerCase() as RequestedPlatform)
|
||||
? (flags.platform.toLowerCase() as RequestedPlatform)
|
||||
: undefined;
|
||||
const requestedPlatform = await selectRequestedPlatformAsync(flags.platform);
|
||||
if (requestedPlatform === RequestedPlatform.All) {
|
||||
if (archiveFlags.id || archiveFlags.path || archiveFlags.url) {
|
||||
Errors.error(
|
||||
'--id, --path, and --url params are only supported when performing a single-platform submit',
|
||||
{ exit: 1 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
archiveFlags,
|
||||
@@ -179,24 +174,4 @@ export default class Submit extends EasCommand {
|
||||
nonInteractive,
|
||||
};
|
||||
}
|
||||
|
||||
private async ensurePlatformSelectedAsync(
|
||||
flags: Omit<CommandFlags, 'requestedPlatform'> & { requestedPlatform?: RequestedPlatform }
|
||||
): Promise<CommandFlags> {
|
||||
const requestedPlatform = await selectRequestedPlatformAsync(flags.requestedPlatform);
|
||||
|
||||
if (requestedPlatform === RequestedPlatform.All) {
|
||||
if (flags.archiveFlags.id || flags.archiveFlags.path || flags.archiveFlags.url) {
|
||||
Errors.error(
|
||||
'--id, --path, and --url params are only supported when performing a single-platform submit',
|
||||
{ exit: 1 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...flags,
|
||||
requestedPlatform,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
import { ExpoConfig, modifyConfigAsync } from '@expo/config';
|
||||
import { Platform, Workflow } from '@expo/eas-build-job';
|
||||
import { EasJsonReader } from '@expo/eas-json';
|
||||
import { Flags } from '@oclif/core';
|
||||
import assert from 'assert';
|
||||
import chalk from 'chalk';
|
||||
import { promises as fs } from 'fs-extra';
|
||||
|
||||
import { getEASUpdateURL } from '../../api';
|
||||
import EasCommand from '../../commandUtils/EasCommand';
|
||||
@@ -24,9 +26,9 @@ const DEFAULT_MANAGED_RUNTIME_VERSION = { policy: 'sdkVersion' } as const;
|
||||
const DEFAULT_BARE_RUNTIME_VERSION = '1.0.0' as const;
|
||||
|
||||
export default class UpdateConfigure extends EasCommand {
|
||||
static override description = 'configure the project to support EAS Update';
|
||||
static description = 'configure the project to support EAS Update';
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
platform: Flags.enum({
|
||||
description: 'Platform to configure',
|
||||
char: 'p',
|
||||
@@ -64,6 +66,11 @@ export default class UpdateConfigure extends EasCommand {
|
||||
});
|
||||
Log.withTick(`Configured ${chalk.bold('app.json')} for EAS Update`);
|
||||
|
||||
const madeChanges = await checkAndConfigureEasJsonReleaseChannelsAsync(projectDir);
|
||||
if (madeChanges) {
|
||||
Log.withTick(`Configured ${chalk.bold('eas.json')} for EAS Update`);
|
||||
}
|
||||
|
||||
// configure native files for EAS Update
|
||||
if (
|
||||
[RequestedPlatform.Android, RequestedPlatform.All].includes(platform) &&
|
||||
@@ -117,7 +124,6 @@ async function configureAppJSONForEASUpdateAsync({
|
||||
exp.ios?.runtimeVersion ?? exp.runtimeVersion ?? iosDefaultRuntimeVersion;
|
||||
|
||||
let newConfig: Partial<ExpoConfig>;
|
||||
let newConfigOnlyAddedValues: Partial<ExpoConfig>;
|
||||
switch (platform) {
|
||||
case RequestedPlatform.All: {
|
||||
if (isRuntimeEqual(newAndroidRuntimeVersion, newIosRuntimeVersion)) {
|
||||
@@ -130,26 +136,6 @@ async function configureAppJSONForEASUpdateAsync({
|
||||
ios: { ...exp.ios, runtimeVersion: undefined },
|
||||
updates,
|
||||
};
|
||||
newConfigOnlyAddedValues = {
|
||||
runtimeVersion: newAndroidRuntimeVersion,
|
||||
...(exp.android && 'runtimeVersion' in exp.android
|
||||
? {
|
||||
android: {
|
||||
runtimeVersion: '<remove this key>',
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
...(exp.ios && 'runtimeVersion' in exp.ios
|
||||
? {
|
||||
ios: {
|
||||
runtimeVersion: '<remove this key>',
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
updates: {
|
||||
url: easUpdateURL,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
newConfig = {
|
||||
runtimeVersion: undefined, // top level runtime is redundant if it is specified in both android and ios
|
||||
@@ -163,22 +149,6 @@ async function configureAppJSONForEASUpdateAsync({
|
||||
},
|
||||
updates,
|
||||
};
|
||||
newConfigOnlyAddedValues = {
|
||||
...('runtimeVersion' in exp
|
||||
? {
|
||||
runtimeVersion: '<remove this key>', // top level runtime is redundant if it is specified in both android and ios
|
||||
}
|
||||
: {}),
|
||||
android: {
|
||||
runtimeVersion: newAndroidRuntimeVersion,
|
||||
},
|
||||
ios: {
|
||||
runtimeVersion: newIosRuntimeVersion,
|
||||
},
|
||||
updates: {
|
||||
url: easUpdateURL,
|
||||
},
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -190,14 +160,6 @@ async function configureAppJSONForEASUpdateAsync({
|
||||
},
|
||||
updates,
|
||||
};
|
||||
newConfigOnlyAddedValues = {
|
||||
android: {
|
||||
runtimeVersion: newAndroidRuntimeVersion,
|
||||
},
|
||||
updates: {
|
||||
url: easUpdateURL,
|
||||
},
|
||||
};
|
||||
break;
|
||||
}
|
||||
case RequestedPlatform.Ios: {
|
||||
@@ -208,14 +170,6 @@ async function configureAppJSONForEASUpdateAsync({
|
||||
},
|
||||
updates,
|
||||
};
|
||||
newConfigOnlyAddedValues = {
|
||||
ios: {
|
||||
runtimeVersion: newIosRuntimeVersion,
|
||||
},
|
||||
updates: {
|
||||
url: easUpdateURL,
|
||||
},
|
||||
};
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -225,8 +179,8 @@ async function configureAppJSONForEASUpdateAsync({
|
||||
|
||||
const result = await modifyConfigAsync(projectDir, newConfig);
|
||||
|
||||
const preexistingAndroidRuntimeVersion = exp.android?.runtimeVersion ?? exp.runtimeVersion;
|
||||
const preexistingIosRuntimeVersion = exp.ios?.runtimeVersion ?? exp.runtimeVersion;
|
||||
const prexistingAndroidRuntimeVersion = exp.android?.runtimeVersion ?? exp.runtimeVersion;
|
||||
const prexistingIosRuntimeVersion = exp.ios?.runtimeVersion ?? exp.runtimeVersion;
|
||||
switch (result.type) {
|
||||
case 'success':
|
||||
if (exp.updates?.url) {
|
||||
@@ -240,7 +194,7 @@ async function configureAppJSONForEASUpdateAsync({
|
||||
}
|
||||
|
||||
if (
|
||||
!preexistingAndroidRuntimeVersion &&
|
||||
!prexistingAndroidRuntimeVersion &&
|
||||
[RequestedPlatform.Android, RequestedPlatform.All].includes(platform)
|
||||
) {
|
||||
Log.withTick(
|
||||
@@ -250,7 +204,7 @@ async function configureAppJSONForEASUpdateAsync({
|
||||
);
|
||||
}
|
||||
if (
|
||||
!preexistingIosRuntimeVersion &&
|
||||
!prexistingIosRuntimeVersion &&
|
||||
[RequestedPlatform.Ios, RequestedPlatform.All].includes(platform)
|
||||
) {
|
||||
Log.withTick(
|
||||
@@ -272,7 +226,7 @@ async function configureAppJSONForEASUpdateAsync({
|
||||
'https://expo.fyi/eas-update-config.md'
|
||||
)}\n`
|
||||
);
|
||||
Log.log(chalk.bold(JSON.stringify(newConfigOnlyAddedValues, null, 2)));
|
||||
Log.log(chalk.bold(JSON.stringify(newConfig, null, 2)));
|
||||
Log.addNewLineIfNone();
|
||||
if (workflows['android'] === Workflow.GENERIC || workflows['ios'] === Workflow.GENERIC) {
|
||||
Log.warn(
|
||||
@@ -294,6 +248,36 @@ async function configureAppJSONForEASUpdateAsync({
|
||||
return result.config.expo;
|
||||
}
|
||||
|
||||
async function checkAndConfigureEasJsonReleaseChannelsAsync(projectDir: string): Promise<boolean> {
|
||||
const reader = new EasJsonReader(projectDir);
|
||||
const easJson = await reader.readAsync();
|
||||
|
||||
let releaseChannelsFound = false;
|
||||
|
||||
if (easJson.build) {
|
||||
for (const [key, value] of Object.entries(easJson.build)) {
|
||||
if (value.releaseChannel) {
|
||||
releaseChannelsFound = true;
|
||||
easJson.build[key].channel = value.releaseChannel;
|
||||
delete easJson.build[key].releaseChannel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (releaseChannelsFound) {
|
||||
try {
|
||||
await fs.writeFile(
|
||||
EasJsonReader.formatEasJsonPath(projectDir),
|
||||
JSON.stringify(easJson, null, 2)
|
||||
);
|
||||
} catch {
|
||||
throw new Error('Error occured updating eas.json file');
|
||||
}
|
||||
}
|
||||
|
||||
return releaseChannelsFound;
|
||||
}
|
||||
|
||||
function isRuntimeEqual(
|
||||
runtimeVersionA: string | { policy: 'sdkVersion' | 'nativeVersion' | 'appVersion' },
|
||||
runtimeVersionB: string | { policy: 'sdkVersion' | 'nativeVersion' | 'appVersion' }
|
||||
|
||||
@@ -36,9 +36,9 @@ async function deleteUpdateGroupAsync({
|
||||
}
|
||||
|
||||
export default class UpdateDelete extends EasCommand {
|
||||
static override description = 'delete all the updates in an update group';
|
||||
static description = 'delete all the updates in an update group';
|
||||
|
||||
static override args = [
|
||||
static args = [
|
||||
{
|
||||
name: 'groupId',
|
||||
required: true,
|
||||
@@ -46,7 +46,7 @@ export default class UpdateDelete extends EasCommand {
|
||||
},
|
||||
];
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
json: Flags.boolean({
|
||||
description: `Return a json with the group ID of the deleted updates.`,
|
||||
default: false,
|
||||
@@ -69,7 +69,7 @@ export default class UpdateDelete extends EasCommand {
|
||||
'This is a permanent operation.'
|
||||
)}\n\n` +
|
||||
`If you want to revert to a previous publish, you should use 'update --republish' targeted at the last working update group instead.\n\n` +
|
||||
`An update group should only be deleted in an emergency like an accidental publish of a secret. In this case user 'update --republish' to revert to the last working update group first and then proceed with the deletion. Deleting an update group when it is the latest publish can lead to inconsistent caching behavior by clients.\n\n` +
|
||||
`An update group should only be deleted in an emergency like an accidental publish of a secret. In this case user 'update --republish' to revert to the last working update group first and then proceed with the deletion. Deleting an update group when it is the latest publish can lead to inconsistent cacheing behavior by clients.\n\n` +
|
||||
`Would you like to abort?`,
|
||||
});
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ import {
|
||||
PublishUpdateGroupInput,
|
||||
Robot,
|
||||
RootQueryUpdatesByGroupArgs,
|
||||
StatuspageServiceName,
|
||||
Update,
|
||||
UpdateInfoGroup,
|
||||
UpdatePublishMutation,
|
||||
@@ -49,7 +48,11 @@ import {
|
||||
} from '../../project/publish';
|
||||
import { resolveWorkflowAsync } from '../../project/workflow';
|
||||
import { confirmAsync, promptAsync, selectAsync } from '../../prompts';
|
||||
import { formatUpdate } from '../../update/utils';
|
||||
import {
|
||||
checkDeprecatedChannelConfigurationAsync,
|
||||
ensureEASUpdateURLIsSetAsync,
|
||||
formatUpdate,
|
||||
} from '../../update/utils';
|
||||
import { ensureLoggedInAsync } from '../../user/actions';
|
||||
import {
|
||||
checkManifestBodyAgainstUpdateInfoGroup,
|
||||
@@ -60,7 +63,6 @@ import {
|
||||
import uniqBy from '../../utils/expodash/uniqBy';
|
||||
import formatFields from '../../utils/formatFields';
|
||||
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
import { maybeWarnAboutEasOutagesAsync } from '../../utils/statuspageService';
|
||||
import { getVcsClient } from '../../vcs';
|
||||
import { createUpdateBranchOnAppAsync } from '../branch/create';
|
||||
import { createUpdateChannelOnAppAsync } from '../channel/create';
|
||||
@@ -161,9 +163,9 @@ export async function ensureBranchExistsAsync({
|
||||
}
|
||||
|
||||
export default class UpdatePublish extends EasCommand {
|
||||
static override description = 'publish an update group';
|
||||
static description = 'publish an update group';
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
branch: Flags.string({
|
||||
description: 'Branch to publish the update group on',
|
||||
required: false,
|
||||
@@ -230,7 +232,6 @@ export default class UpdatePublish extends EasCommand {
|
||||
'non-interactive': nonInteractive,
|
||||
},
|
||||
} = await this.parse(UpdatePublish);
|
||||
|
||||
if (jsonFlag) {
|
||||
enableJsonOutput();
|
||||
}
|
||||
@@ -248,8 +249,6 @@ export default class UpdatePublish extends EasCommand {
|
||||
isPublicConfig: false,
|
||||
});
|
||||
|
||||
await maybeWarnAboutEasOutagesAsync([StatuspageServiceName.EasUpdate]);
|
||||
|
||||
const codeSigningInfo = await getCodeSigningInfoAsync(expPrivate, privateKeyPath);
|
||||
|
||||
const hasExpoUpdates = isExpoUpdatesInstalledOrAvailable(projectDir, exp.sdkVersion);
|
||||
@@ -280,7 +279,7 @@ export default class UpdatePublish extends EasCommand {
|
||||
|
||||
const runtimeVersions = await getRuntimeVersionObjectAsync(exp, platformFlag, projectDir);
|
||||
const projectId = await getProjectIdAsync(exp);
|
||||
await checkEASUpdateURLIsSetAsync(exp);
|
||||
await ensureEASUpdateURLIsSetAsync(exp);
|
||||
|
||||
if (!branchName && autoFlag) {
|
||||
branchName =
|
||||
@@ -307,7 +306,7 @@ export default class UpdatePublish extends EasCommand {
|
||||
({ name: branchName } = await promptAsync({
|
||||
type: 'text',
|
||||
name: 'name',
|
||||
message: 'No branches found. Provide a branch name:',
|
||||
message: 'No branches found. Creating a new one. Please name the new branch:',
|
||||
initial:
|
||||
(await getVcsClient().getBranchNameAsync()) ||
|
||||
`branch-${Math.random().toString(36).substr(2, 4)}`,
|
||||
@@ -329,6 +328,13 @@ export default class UpdatePublish extends EasCommand {
|
||||
assert(branchName, 'Branch name must be specified.');
|
||||
}
|
||||
|
||||
const { id: branchId, updates } = await ensureBranchExistsAsync({
|
||||
appId: projectId,
|
||||
name: branchName,
|
||||
});
|
||||
|
||||
await checkDeprecatedChannelConfigurationAsync(projectDir);
|
||||
|
||||
let unsortedUpdateInfoGroups: UpdateInfoGroup = {};
|
||||
let oldMessage: string, oldRuntimeVersion: string;
|
||||
let uploadedAssetCount = 0;
|
||||
@@ -409,7 +415,7 @@ export default class UpdatePublish extends EasCommand {
|
||||
({ publishMessage: message } = await promptAsync({
|
||||
type: 'text',
|
||||
name: 'publishMessage',
|
||||
message: `Provide an update message.`,
|
||||
message: `Please enter an update message.`,
|
||||
initial: `Republish "${oldMessage!}" - group: ${group}`,
|
||||
validate: (value: any) => (value ? true : validationMessage),
|
||||
}));
|
||||
@@ -431,7 +437,7 @@ export default class UpdatePublish extends EasCommand {
|
||||
({ publishMessage: message } = await promptAsync({
|
||||
type: 'text',
|
||||
name: 'publishMessage',
|
||||
message: `Provide an update message.`,
|
||||
message: `Please enter an update message.`,
|
||||
initial: (await getVcsClient().getLastCommitMessageAsync())?.trim(),
|
||||
validate: (value: any) => (value ? true : validationMessage),
|
||||
}));
|
||||
@@ -754,6 +760,8 @@ function formatUpdateTitle(
|
||||
'mmm dd HH:MM'
|
||||
)} by ${actorName}, runtimeVersion: ${runtimeVersion}] ${message}`;
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
|
||||
async function checkEASUpdateURLIsSetAsync(exp: ExpoConfig): Promise<void> {
|
||||
const configuredURL = exp.updates?.url;
|
||||
@@ -762,9 +770,7 @@ async function checkEASUpdateURLIsSetAsync(exp: ExpoConfig): Promise<void> {
|
||||
|
||||
if (configuredURL !== expectedURL) {
|
||||
throw new Error(
|
||||
`The update URL is incorrectly configured for EAS Update. Set updates.url to ${expectedURL} in your ${chalk.bold(
|
||||
'app.json'
|
||||
)}.`
|
||||
`The update URL is incorrectly configured for EAS Update. Please set updates.url to ${expectedURL} in your app.json.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@ import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||
import { getVcsClient } from '../../vcs';
|
||||
|
||||
export default class BranchView extends EasCommand {
|
||||
static override description = 'view the recent updates for a branch';
|
||||
static description = 'view the recent updates for a branch';
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
branch: Flags.string({
|
||||
description: 'List all updates on this branch',
|
||||
exclusive: ['all'],
|
||||
@@ -73,7 +73,7 @@ export default class BranchView extends EasCommand {
|
||||
({ name: branchInteractive } = await promptAsync({
|
||||
type: 'text',
|
||||
name: 'name',
|
||||
message: 'Provide the name of the branch whose updates you wish to view:',
|
||||
message: 'Please enter the name of the branch whose updates you wish to view:',
|
||||
initial: (await getVcsClient().getBranchNameAsync()) ?? undefined,
|
||||
validate: (value: any) => (value ? true : validationMessage),
|
||||
}));
|
||||
|
||||
@@ -51,9 +51,9 @@ export async function viewUpdateAsync({
|
||||
return data;
|
||||
}
|
||||
export default class UpdateView extends EasCommand {
|
||||
static override description = 'update group details';
|
||||
static description = 'update group details';
|
||||
|
||||
static override args = [
|
||||
static args = [
|
||||
{
|
||||
name: 'groupId',
|
||||
required: true,
|
||||
@@ -61,7 +61,7 @@ export default class UpdateView extends EasCommand {
|
||||
},
|
||||
];
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
json: Flags.boolean({
|
||||
description: `Return a json with the updates belonging to the group.`,
|
||||
default: false,
|
||||
|
||||
@@ -9,9 +9,9 @@ import { findProjectRootAsync, getProjectIdAsync } from '../../project/projectUt
|
||||
import { prepareInputParamsAsync } from '../../webhooks/input';
|
||||
|
||||
export default class WebhookCreate extends EasCommand {
|
||||
static override description = 'create a webhook';
|
||||
static description = 'create a webhook';
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
event: Flags.enum({
|
||||
description: 'Event type that triggers the webhook',
|
||||
options: [WebhookType.Build, WebhookType.Submit],
|
||||
|
||||
@@ -14,9 +14,9 @@ import { promptAsync, toggleConfirmAsync } from '../../prompts';
|
||||
import { formatWebhook } from '../../webhooks/formatWebhook';
|
||||
|
||||
export default class WebhookDelete extends EasCommand {
|
||||
static override description = 'delete a webhook';
|
||||
static description = 'delete a webhook';
|
||||
|
||||
static override args = [
|
||||
static args = [
|
||||
{
|
||||
name: 'ID',
|
||||
required: false,
|
||||
@@ -57,7 +57,7 @@ export default class WebhookDelete extends EasCommand {
|
||||
Log.addNewLineIfNone();
|
||||
Log.log(formatWebhook(webhook));
|
||||
Log.newLine();
|
||||
Log.warn(`You are about to permanently delete this webhook.\nThis action is irreversible.`);
|
||||
Log.warn(`You are about to permamently delete this webhook.\nThis action is irreversible.`);
|
||||
Log.newLine();
|
||||
const confirmed = await toggleConfirmAsync({
|
||||
message: 'Are you sure you wish to proceed?',
|
||||
|
||||
@@ -15,9 +15,9 @@ import {
|
||||
import { formatWebhook } from '../../webhooks/formatWebhook';
|
||||
|
||||
export default class WebhookList extends EasCommand {
|
||||
static override description = 'list webhooks';
|
||||
static description = 'list webhooks';
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
event: Flags.enum({
|
||||
description: 'Event type that triggers the webhook',
|
||||
options: [WebhookType.Build, WebhookType.Submit],
|
||||
|
||||
@@ -9,9 +9,9 @@ import pick from '../../utils/expodash/pick';
|
||||
import { prepareInputParamsAsync } from '../../webhooks/input';
|
||||
|
||||
export default class WebhookUpdate extends EasCommand {
|
||||
static override description = 'update a webhook';
|
||||
static description = 'update a webhook';
|
||||
|
||||
static override flags = {
|
||||
static flags = {
|
||||
id: Flags.string({
|
||||
description: 'Webhook ID',
|
||||
required: true,
|
||||
|
||||
@@ -5,9 +5,9 @@ import { ora } from '../../ora';
|
||||
import { formatWebhook } from '../../webhooks/formatWebhook';
|
||||
|
||||
export default class WebhookView extends EasCommand {
|
||||
static override description = 'view a webhook';
|
||||
static description = 'view a webhook';
|
||||
|
||||
static override args = [
|
||||
static args = [
|
||||
{
|
||||
name: 'ID',
|
||||
required: true,
|
||||
|
||||
@@ -18,7 +18,6 @@ export const jester2: Actor = {
|
||||
|
||||
export const testUsername = jester.username;
|
||||
export const testSlug = 'testApp';
|
||||
export const testProjectId = '7ef93448-3bc7-4b57-be32-99326dcf24f0';
|
||||
export const testBundleIdentifier = 'test.com.app';
|
||||
export const testPackageName = 'test.com.app';
|
||||
export const testExperienceName = `@${testUsername}/${testSlug}`;
|
||||
@@ -36,11 +35,6 @@ export const testAppJson = {
|
||||
sdkVersion: '38.0.0',
|
||||
ios: { bundleIdentifier: testBundleIdentifier },
|
||||
android: { package: testPackageName },
|
||||
extra: {
|
||||
eas: {
|
||||
projectId: testProjectId,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const testAppJsonWithDifferentOwner = {
|
||||
|
||||
@@ -76,13 +76,9 @@ export const testPushKey: ApplePushKeyFragment = {
|
||||
iosAppCredentialsList: [],
|
||||
};
|
||||
|
||||
export const testTarget = {
|
||||
targetName: 'testapp',
|
||||
bundleIdentifier: 'foo.bar.com',
|
||||
entitlements: {},
|
||||
};
|
||||
|
||||
export const testTargets: Target[] = [testTarget];
|
||||
export const testTargets: Target[] = [
|
||||
{ targetName: 'testapp', bundleIdentifier: 'foo.bar.com', entitlements: {} },
|
||||
];
|
||||
|
||||
export const testProvisioningProfileFragment: AppleProvisioningProfileFragment = {
|
||||
id: 'test-prov-prof-id-1',
|
||||
|
||||
@@ -54,7 +54,7 @@ export class RemoveKeystore {
|
||||
)
|
||||
);
|
||||
Log.warn(
|
||||
'Read https://docs.expo.dev/distribution/building-standalone-apps/#if-you-choose-to-build-for-android for more info before proceeding.'
|
||||
'Please read https://docs.expo.dev/distribution/building-standalone-apps/#if-you-choose-to-build-for-android for more info before proceeding.'
|
||||
);
|
||||
Log.newLine();
|
||||
Log.warn(
|
||||
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
CommonAndroidAppCredentialsFragment,
|
||||
GoogleServiceAccountKeyFragment,
|
||||
} from '../../../graphql/generated';
|
||||
import { AppQuery } from '../../../graphql/queries/AppQuery';
|
||||
import { Account } from '../../../user/Account';
|
||||
import { AppQuery } from '../../ios/api/graphql/queries/AppQuery';
|
||||
import { GoogleServiceAccountKey, KeystoreWithType } from '../credentials';
|
||||
import { AndroidAppBuildCredentialsMutation } from './graphql/mutations/AndroidAppBuildCredentialsMutation';
|
||||
import { AndroidAppCredentialsMutation } from './graphql/mutations/AndroidAppCredentialsMutation';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { ExpoConfig } from '@expo/config';
|
||||
import { Env } from '@expo/eas-build-job';
|
||||
import { EasJson } from '@expo/eas-json';
|
||||
import chalk from 'chalk';
|
||||
|
||||
import Log from '../log';
|
||||
@@ -20,7 +19,6 @@ export class CredentialsContext {
|
||||
public readonly nonInteractive: boolean;
|
||||
public readonly projectDir: string;
|
||||
public readonly user: Actor;
|
||||
public readonly easJsonCliConfig?: EasJson['cli'];
|
||||
|
||||
private shouldAskAuthenticateAppStore: boolean = true;
|
||||
private resolvedExp?: ExpoConfig;
|
||||
@@ -28,14 +26,12 @@ export class CredentialsContext {
|
||||
constructor(
|
||||
private options: {
|
||||
exp?: ExpoConfig;
|
||||
easJsonCliConfig?: EasJson['cli'];
|
||||
nonInteractive?: boolean;
|
||||
projectDir: string;
|
||||
user: Actor;
|
||||
env?: Env;
|
||||
}
|
||||
) {
|
||||
this.easJsonCliConfig = options.easJsonCliConfig;
|
||||
this.projectDir = options.projectDir;
|
||||
this.user = options.user;
|
||||
this.nonInteractive = options.nonInteractive ?? false;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
export class MissingCredentialsNonInteractiveError extends Error {
|
||||
constructor(message?: string) {
|
||||
super(message ?? 'Credentials are not set up. Run this command again in interactive mode.');
|
||||
super(
|
||||
message ?? 'Credentials are not set up. Please run this command again in interactive mode.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
import { Platform } from '@expo/eas-build-job';
|
||||
import {
|
||||
CredentialsSource,
|
||||
DistributionType,
|
||||
EasJsonAccessor,
|
||||
IosEnterpriseProvisioning,
|
||||
} from '@expo/eas-json';
|
||||
import { CredentialsSource, DistributionType, IosEnterpriseProvisioning } from '@expo/eas-json';
|
||||
|
||||
import { CommonIosAppCredentialsFragment } from '../../graphql/generated';
|
||||
import Log from '../../log';
|
||||
import { findApplicationTarget } from '../../project/ios/target';
|
||||
import { selectAsync } from '../../prompts';
|
||||
import { confirmAsync } from '../../prompts';
|
||||
import { CredentialsContext } from '../context';
|
||||
import * as credentialsJsonReader from '../credentialsJson/read';
|
||||
import { ensureAllTargetsAreConfigured } from '../credentialsJson/utils';
|
||||
@@ -26,12 +21,6 @@ interface Options {
|
||||
enterpriseProvisioning?: IosEnterpriseProvisioning;
|
||||
}
|
||||
|
||||
enum PushNotificationSetupOption {
|
||||
YES,
|
||||
NO,
|
||||
NO_DONT_ASK_AGAIN,
|
||||
}
|
||||
|
||||
export default class IosCredentialsProvider {
|
||||
public readonly platform = Platform.IOS;
|
||||
|
||||
@@ -100,45 +89,13 @@ export default class IosCredentialsProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (ctx.easJsonCliConfig?.promptToConfigurePushNotifications === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const setupOption = await selectAsync(
|
||||
`Would you like to set up Push Notifications for your project?`,
|
||||
[
|
||||
{ title: 'Yes', value: PushNotificationSetupOption.YES },
|
||||
{ title: 'No', value: PushNotificationSetupOption.NO },
|
||||
{
|
||||
title: `No, don't ask again (preference will be saved to eas.json)`,
|
||||
value: PushNotificationSetupOption.NO_DONT_ASK_AGAIN,
|
||||
},
|
||||
]
|
||||
);
|
||||
if (setupOption === PushNotificationSetupOption.YES) {
|
||||
return await setupPushKeyAction.runAsync(ctx);
|
||||
} else {
|
||||
if (setupOption === PushNotificationSetupOption.NO_DONT_ASK_AGAIN) {
|
||||
await this.disablePushNotificationsSetupInEasJsonAsync(ctx);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private async disablePushNotificationsSetupInEasJsonAsync(
|
||||
ctx: CredentialsContext
|
||||
): Promise<void> {
|
||||
const easJsonAccessor = new EasJsonAccessor(ctx.projectDir);
|
||||
await easJsonAccessor.readRawJsonAsync();
|
||||
easJsonAccessor.patch(easJsonRawObject => {
|
||||
easJsonRawObject.cli = {
|
||||
...easJsonRawObject?.cli,
|
||||
promptToConfigurePushNotifications: false,
|
||||
};
|
||||
return easJsonRawObject;
|
||||
const confirmSetup = await confirmAsync({
|
||||
message: `Would you like to set up Push Notifications for your project?`,
|
||||
});
|
||||
await easJsonAccessor.writeAsync();
|
||||
Log.withTick('Updated eas.json');
|
||||
if (!confirmSetup) {
|
||||
return null;
|
||||
}
|
||||
return await setupPushKeyAction.runAsync(ctx);
|
||||
}
|
||||
|
||||
private assertProvisioningProfileType(provisioningProfile: string, targetName?: string): void {
|
||||
|
||||
@@ -17,7 +17,6 @@ jest.mock('fs');
|
||||
jest.mock('../validators/validateProvisioningProfile', () => ({
|
||||
validateProvisioningProfileAsync: async (
|
||||
_ctx: any,
|
||||
_target: any,
|
||||
_app: any,
|
||||
buildCredentials: Partial<IosAppBuildCredentialsFragment> | null
|
||||
): Promise<boolean> => {
|
||||
|
||||
@@ -7,19 +7,16 @@ import {
|
||||
} from '../../../graphql/generated';
|
||||
import Log from '../../../log';
|
||||
import { ora } from '../../../ora';
|
||||
import { getApplePlatformFromSdkRoot } from '../../../project/ios/target';
|
||||
import { CredentialsContext } from '../../context';
|
||||
import { MissingCredentialsNonInteractiveError } from '../../errors';
|
||||
import { AppLookupParams } from '../api/GraphqlClient';
|
||||
import { AppleProvisioningProfileMutationResult } from '../api/graphql/mutations/AppleProvisioningProfileMutation';
|
||||
import { ProvisioningProfileStoreInfo } from '../appstore/Credentials.types';
|
||||
import { AuthCtx } from '../appstore/authenticateTypes';
|
||||
import { Target } from '../types';
|
||||
|
||||
export class ConfigureProvisioningProfile {
|
||||
constructor(
|
||||
private app: AppLookupParams,
|
||||
private target: Target,
|
||||
private distributionCertificate: AppleDistributionCertificateFragment,
|
||||
private originalProvisioningProfile: AppleProvisioningProfileFragment
|
||||
) {}
|
||||
@@ -46,10 +43,8 @@ export class ConfigureProvisioningProfile {
|
||||
return null;
|
||||
}
|
||||
|
||||
const applePlatform = await getApplePlatformFromSdkRoot(this.target);
|
||||
const profilesFromApple = await ctx.appStore.listProvisioningProfilesAsync(
|
||||
this.app.bundleIdentifier,
|
||||
applePlatform
|
||||
this.app.bundleIdentifier
|
||||
);
|
||||
const [matchingProfile] = profilesFromApple.filter(appleInfo =>
|
||||
developerPortalIdentifier
|
||||
|
||||
@@ -11,14 +11,12 @@ import { AppleProvisioningProfileMutationResult } from '../api/graphql/mutations
|
||||
import { ProvisioningProfile } from '../appstore/Credentials.types';
|
||||
import { AuthCtx } from '../appstore/authenticateTypes';
|
||||
import { provisioningProfileSchema } from '../credentials';
|
||||
import { Target } from '../types';
|
||||
import { resolveAppleTeamIfAuthenticatedAsync } from './AppleTeamUtils';
|
||||
import { generateProvisioningProfileAsync } from './ProvisioningProfileUtils';
|
||||
|
||||
export class CreateProvisioningProfile {
|
||||
constructor(
|
||||
private app: AppLookupParams,
|
||||
private target: Target,
|
||||
private distributionCertificate: AppleDistributionCertificateFragment
|
||||
) {}
|
||||
|
||||
@@ -65,7 +63,7 @@ export class CreateProvisioningProfile {
|
||||
this.distributionCertificate.certificatePassword,
|
||||
'Distribution Certificate must have certificate password'
|
||||
);
|
||||
return await generateProvisioningProfileAsync(ctx, this.target, this.app.bundleIdentifier, {
|
||||
return await generateProvisioningProfileAsync(ctx, this.app.bundleIdentifier, {
|
||||
certId: this.distributionCertificate.developerPortalIdentifier ?? undefined,
|
||||
certP12: this.distributionCertificate.certificateP12,
|
||||
certPassword: this.distributionCertificate.certificatePassword,
|
||||
|
||||
@@ -147,8 +147,8 @@ const APPLE_DIST_CERTS_TOO_MANY_GENERATED_ERROR = `
|
||||
You can have only ${chalk.underline(
|
||||
'three'
|
||||
)} Apple Distribution Certificates generated on your Apple Developer account.
|
||||
Revoke the old ones or reuse existing from your other apps.
|
||||
Remember that Apple Distribution Certificates are not application specific!
|
||||
Please revoke the old ones or reuse existing from your other apps.
|
||||
Please remember that Apple Distribution Certificates are not application specific!
|
||||
`;
|
||||
|
||||
export async function provideOrGenerateDistributionCertificateAsync(
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import chalk from 'chalk';
|
||||
|
||||
import { getApplePlatformFromSdkRoot } from '../../../project/ios/target';
|
||||
import { CredentialsContext } from '../../context';
|
||||
import {
|
||||
DistributionCertificate,
|
||||
ProvisioningProfile,
|
||||
ProvisioningProfileStoreInfo,
|
||||
} from '../appstore/Credentials.types';
|
||||
import { Target } from '../types';
|
||||
|
||||
export function formatProvisioningProfileFromApple(
|
||||
appleInfo: ProvisioningProfileStoreInfo
|
||||
@@ -22,18 +20,11 @@ export function formatProvisioningProfileFromApple(
|
||||
|
||||
export async function generateProvisioningProfileAsync(
|
||||
ctx: CredentialsContext,
|
||||
target: Target,
|
||||
bundleIdentifier: string,
|
||||
distCert: DistributionCertificate
|
||||
): Promise<ProvisioningProfile> {
|
||||
const appleAuthCtx = await ctx.appStore.ensureAuthenticatedAsync();
|
||||
const type = appleAuthCtx.team.inHouse ? 'Enterprise ' : 'AppStore';
|
||||
const profileName = `*[expo] ${bundleIdentifier} ${type} ${new Date().toISOString()}`; // Apple drops [ if its the first char (!!)
|
||||
const applePlatform = await getApplePlatformFromSdkRoot(target);
|
||||
return await ctx.appStore.createProvisioningProfileAsync(
|
||||
bundleIdentifier,
|
||||
distCert,
|
||||
profileName,
|
||||
applePlatform
|
||||
);
|
||||
return await ctx.appStore.createProvisioningProfileAsync(bundleIdentifier, distCert, profileName);
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
import { ProfileType } from '@expo/apple-utils';
|
||||
import assert from 'assert';
|
||||
import chalk from 'chalk';
|
||||
import nullthrows from 'nullthrows';
|
||||
@@ -13,14 +12,11 @@ import {
|
||||
IosDistributionType,
|
||||
} from '../../../graphql/generated';
|
||||
import Log from '../../../log';
|
||||
import { getApplePlatformFromSdkRoot } from '../../../project/ios/target';
|
||||
import { confirmAsync, pressAnyKeyToContinueAsync, promptAsync } from '../../../prompts';
|
||||
import differenceBy from '../../../utils/expodash/differenceBy';
|
||||
import { CredentialsContext } from '../../context';
|
||||
import { MissingCredentialsNonInteractiveError } from '../../errors';
|
||||
import { AppLookupParams } from '../api/GraphqlClient';
|
||||
import { ApplePlatform } from '../appstore/constants';
|
||||
import { Target } from '../types';
|
||||
import { validateProvisioningProfileAsync } from '../validators/validateProvisioningProfile';
|
||||
import { resolveAppleTeamIfAuthenticatedAsync } from './AppleTeamUtils';
|
||||
import { assignBuildCredentialsAsync, getBuildCredentialsAsync } from './BuildCredentialsUtils';
|
||||
@@ -33,18 +29,12 @@ enum ReuseAction {
|
||||
No,
|
||||
}
|
||||
|
||||
interface Options {
|
||||
app: AppLookupParams;
|
||||
target: Target;
|
||||
}
|
||||
|
||||
export class SetUpAdhocProvisioningProfile {
|
||||
constructor(private options: Options) {}
|
||||
constructor(private app: AppLookupParams) {}
|
||||
|
||||
async runAsync(ctx: CredentialsContext): Promise<IosAppBuildCredentialsFragment> {
|
||||
const { app } = this.options;
|
||||
const distCert = await new SetUpDistributionCertificate(
|
||||
app,
|
||||
this.app,
|
||||
IosDistributionType.AdHoc
|
||||
).runAsync(ctx);
|
||||
|
||||
@@ -52,17 +42,17 @@ export class SetUpAdhocProvisioningProfile {
|
||||
|
||||
if (ctx.nonInteractive) {
|
||||
if (areBuildCredentialsSetup) {
|
||||
return nullthrows(await getBuildCredentialsAsync(ctx, app, IosDistributionType.AdHoc));
|
||||
return nullthrows(await getBuildCredentialsAsync(ctx, this.app, IosDistributionType.AdHoc));
|
||||
} else {
|
||||
throw new MissingCredentialsNonInteractiveError(
|
||||
'Provisioning profile is not configured correctly. Run this command again in interactive mode.'
|
||||
'Provisioning profile is not configured correctly. Please run this command again in interactive mode.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const currentBuildCredentials = await getBuildCredentialsAsync(
|
||||
ctx,
|
||||
app,
|
||||
this.app,
|
||||
IosDistributionType.AdHoc
|
||||
);
|
||||
if (areBuildCredentialsSetup) {
|
||||
@@ -79,11 +69,9 @@ export class SetUpAdhocProvisioningProfile {
|
||||
ctx: CredentialsContext,
|
||||
distCert: AppleDistributionCertificateFragment
|
||||
): Promise<IosAppBuildCredentialsFragment> {
|
||||
const { app, target } = this.options;
|
||||
|
||||
const currentBuildCredentials = await getBuildCredentialsAsync(
|
||||
ctx,
|
||||
app,
|
||||
this.app,
|
||||
IosDistributionType.AdHoc
|
||||
);
|
||||
|
||||
@@ -92,12 +80,12 @@ export class SetUpAdhocProvisioningProfile {
|
||||
distCert.appleTeam ?? currentBuildCredentials?.provisioningProfile?.appleTeam ?? null;
|
||||
if (!appleTeam) {
|
||||
await ctx.appStore.ensureAuthenticatedAsync();
|
||||
appleTeam = await resolveAppleTeamIfAuthenticatedAsync(ctx, app);
|
||||
appleTeam = await resolveAppleTeamIfAuthenticatedAsync(ctx, this.app);
|
||||
}
|
||||
assert(appleTeam, 'Apple Team must be defined here');
|
||||
|
||||
// 2. Fetch devices registered on EAS servers
|
||||
let registeredAppleDevices = await ctx.ios.getDevicesForAppleTeamAsync(app, appleTeam);
|
||||
let registeredAppleDevices = await ctx.ios.getDevicesForAppleTeamAsync(this.app, appleTeam);
|
||||
if (registeredAppleDevices.length === 0) {
|
||||
const shouldRegisterDevices = await confirmAsync({
|
||||
message: `You don't have any registered devices yet. Would you like to register them now?`,
|
||||
@@ -121,22 +109,16 @@ export class SetUpAdhocProvisioningProfile {
|
||||
);
|
||||
|
||||
// 4. Reuse or create the profile on Apple Developer Portal
|
||||
const applePlatform = await getApplePlatformFromSdkRoot(target);
|
||||
const profileType =
|
||||
applePlatform === ApplePlatform.TV_OS
|
||||
? ProfileType.TVOS_APP_ADHOC
|
||||
: ProfileType.IOS_APP_ADHOC;
|
||||
const provisioningProfileStoreInfo =
|
||||
await ctx.appStore.createOrReuseAdhocProvisioningProfileAsync(
|
||||
chosenDevices.map(({ identifier }) => identifier),
|
||||
app.bundleIdentifier,
|
||||
distCert.serialNumber,
|
||||
profileType
|
||||
this.app.bundleIdentifier,
|
||||
distCert.serialNumber
|
||||
);
|
||||
|
||||
// 5. Create or update the profile on servers
|
||||
const appleAppIdentifier = await ctx.ios.createOrGetExistingAppleAppIdentifierAsync(
|
||||
app,
|
||||
this.app,
|
||||
appleTeam
|
||||
);
|
||||
let appleProvisioningProfile: AppleProvisioningProfileFragment | null = null;
|
||||
@@ -149,7 +131,7 @@ export class SetUpAdhocProvisioningProfile {
|
||||
currentBuildCredentials.provisioningProfile.id,
|
||||
]);
|
||||
appleProvisioningProfile = await ctx.ios.createProvisioningProfileAsync(
|
||||
app,
|
||||
this.app,
|
||||
appleAppIdentifier,
|
||||
{
|
||||
appleProvisioningProfile: provisioningProfileStoreInfo.provisioningProfile,
|
||||
@@ -161,7 +143,7 @@ export class SetUpAdhocProvisioningProfile {
|
||||
}
|
||||
} else {
|
||||
appleProvisioningProfile = await ctx.ios.createProvisioningProfileAsync(
|
||||
app,
|
||||
this.app,
|
||||
appleAppIdentifier,
|
||||
{
|
||||
appleProvisioningProfile: provisioningProfileStoreInfo.provisioningProfile,
|
||||
@@ -174,7 +156,7 @@ export class SetUpAdhocProvisioningProfile {
|
||||
assert(appleProvisioningProfile);
|
||||
return await assignBuildCredentialsAsync(
|
||||
ctx,
|
||||
app,
|
||||
this.app,
|
||||
IosDistributionType.AdHoc,
|
||||
distCert,
|
||||
appleProvisioningProfile,
|
||||
@@ -183,20 +165,22 @@ export class SetUpAdhocProvisioningProfile {
|
||||
}
|
||||
|
||||
private async areBuildCredentialsSetupAsync(ctx: CredentialsContext): Promise<boolean> {
|
||||
const { app, target } = this.options;
|
||||
const buildCredentials = await getBuildCredentialsAsync(ctx, app, IosDistributionType.AdHoc);
|
||||
return await validateProvisioningProfileAsync(ctx, target, app, buildCredentials);
|
||||
const buildCredentials = await getBuildCredentialsAsync(
|
||||
ctx,
|
||||
this.app,
|
||||
IosDistributionType.AdHoc
|
||||
);
|
||||
return await validateProvisioningProfileAsync(ctx, this.app, buildCredentials);
|
||||
}
|
||||
|
||||
private async shouldUseExistingProfileAsync(
|
||||
ctx: CredentialsContext,
|
||||
buildCredentials: IosAppBuildCredentialsFragment
|
||||
): Promise<boolean> {
|
||||
const { app } = this.options;
|
||||
const provisioningProfile = nullthrows(buildCredentials.provisioningProfile);
|
||||
|
||||
const appleTeam = nullthrows(provisioningProfile.appleTeam);
|
||||
const registeredAppleDevices = await ctx.ios.getDevicesForAppleTeamAsync(app, appleTeam);
|
||||
const registeredAppleDevices = await ctx.ios.getDevicesForAppleTeamAsync(this.app, appleTeam);
|
||||
|
||||
const provisionedDevices = provisioningProfile.appleDevices;
|
||||
|
||||
@@ -270,8 +254,7 @@ export class SetUpAdhocProvisioningProfile {
|
||||
ctx: CredentialsContext,
|
||||
appleTeam: AppleTeamFragment
|
||||
): Promise<AppleDeviceFragment[]> {
|
||||
const { app } = this.options;
|
||||
const action = new DeviceCreateAction(ctx.appStore, app.account, appleTeam);
|
||||
const action = new DeviceCreateAction(ctx.appStore, this.app.account, appleTeam);
|
||||
const method = await action.runAsync();
|
||||
|
||||
while (true) {
|
||||
@@ -282,7 +265,7 @@ export class SetUpAdhocProvisioningProfile {
|
||||
}
|
||||
Log.newLine();
|
||||
|
||||
const devices = await ctx.ios.getDevicesForAppleTeamAsync(app, appleTeam, {
|
||||
const devices = await ctx.ios.getDevicesForAppleTeamAsync(this.app, appleTeam, {
|
||||
useCache: false,
|
||||
});
|
||||
if (devices.length === 0) {
|
||||
|
||||
@@ -51,7 +51,6 @@ export class SetUpBuildCredentials {
|
||||
enterpriseProvisioning: this.options.enterpriseProvisioning,
|
||||
distribution: this.options.distribution,
|
||||
entitlements: target.entitlements,
|
||||
target,
|
||||
app: {
|
||||
...this.options.app,
|
||||
bundleIdentifier: target.bundleIdentifier,
|
||||
|
||||
@@ -3,7 +3,6 @@ import Log, { learnMore } from '../../../log';
|
||||
import { promptAsync } from '../../../prompts';
|
||||
import { CredentialsContext } from '../../context';
|
||||
import { AppLookupParams } from '../api/GraphqlClient';
|
||||
import { Target } from '../types';
|
||||
import { getAllBuildCredentialsAsync } from './BuildCredentialsUtils';
|
||||
import { SetUpAdhocProvisioningProfile } from './SetUpAdhocProvisioningProfile';
|
||||
import { SetUpProvisioningProfile } from './SetUpProvisioningProfile';
|
||||
@@ -15,17 +14,11 @@ import { SetUpProvisioningProfile } from './SetUpProvisioningProfile';
|
||||
* to choose if they want to set up an adhoc or universal distribution provisioning profile. Otherwise, always
|
||||
* set up an adhoc provisioning profile.
|
||||
*/
|
||||
|
||||
interface Options {
|
||||
app: AppLookupParams;
|
||||
target: Target;
|
||||
}
|
||||
|
||||
export class SetUpInternalProvisioningProfile {
|
||||
constructor(private options: Options) {}
|
||||
constructor(private app: AppLookupParams) {}
|
||||
|
||||
async runAsync(ctx: CredentialsContext): Promise<IosAppBuildCredentialsFragment> {
|
||||
const buildCredentials = await getAllBuildCredentialsAsync(ctx, this.options.app);
|
||||
const buildCredentials = await getAllBuildCredentialsAsync(ctx, this.app);
|
||||
|
||||
const adhocBuildCredentialsExist =
|
||||
buildCredentials.filter(
|
||||
@@ -77,7 +70,7 @@ export class SetUpInternalProvisioningProfile {
|
||||
} else {
|
||||
if (adhocBuildCredentialsExist && enterpriseBuildCredentialsExist) {
|
||||
throw new Error(
|
||||
`You're in non-interactive mode. You have set up both adhoc and universal distribution credentials. Set the 'enterpriseProvisioning' property (to 'adhoc' or 'universal') in eas.json to choose the credentials to use.`
|
||||
`You're in non-interactive mode. You have set up both adhoc and universal distribution credentials. Please set the 'enterpriseProvisioning' property (to 'adhoc' or 'universal') in eas.json to choose the credentials to use.`
|
||||
);
|
||||
} else if (adhocBuildCredentialsExist) {
|
||||
return await this.setupAdhocProvisioningProfileAsync(ctx);
|
||||
@@ -85,7 +78,7 @@ export class SetUpInternalProvisioningProfile {
|
||||
return await this.setupUniversalProvisioningProfileAsync(ctx);
|
||||
} else {
|
||||
throw new Error(
|
||||
`You're in non-interactive mode. EAS CLI couldn't find any credentials suitable for internal distribution. Run this command again in interactive mode.`
|
||||
`You're in non-interactive mode. EAS CLI couldn't find any credentials suitable for internal distribution. Please run again in interactive mode.`
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -94,18 +87,15 @@ export class SetUpInternalProvisioningProfile {
|
||||
private async setupAdhocProvisioningProfileAsync(
|
||||
ctx: CredentialsContext
|
||||
): Promise<IosAppBuildCredentialsFragment> {
|
||||
const { app, target } = this.options;
|
||||
return await new SetUpAdhocProvisioningProfile({ app, target }).runAsync(ctx);
|
||||
return await new SetUpAdhocProvisioningProfile(this.app).runAsync(ctx);
|
||||
}
|
||||
|
||||
private async setupUniversalProvisioningProfileAsync(
|
||||
ctx: CredentialsContext
|
||||
): Promise<IosAppBuildCredentialsFragment> {
|
||||
return await new SetUpProvisioningProfile(
|
||||
this.options.app,
|
||||
this.options.target,
|
||||
IosDistributionType.Enterprise
|
||||
).runAsync(ctx);
|
||||
return await new SetUpProvisioningProfile(this.app, IosDistributionType.Enterprise).runAsync(
|
||||
ctx
|
||||
);
|
||||
}
|
||||
|
||||
private async askForDistributionTypeAndSetupAsync(
|
||||
|
||||
@@ -6,13 +6,11 @@ import {
|
||||
IosAppBuildCredentialsFragment,
|
||||
IosDistributionType,
|
||||
} from '../../../graphql/generated';
|
||||
import { getApplePlatformFromSdkRoot } from '../../../project/ios/target';
|
||||
import { confirmAsync } from '../../../prompts';
|
||||
import { CredentialsContext } from '../../context';
|
||||
import { MissingCredentialsNonInteractiveError } from '../../errors';
|
||||
import { AppLookupParams } from '../api/GraphqlClient';
|
||||
import { ProvisioningProfileStoreInfo } from '../appstore/Credentials.types';
|
||||
import { Target } from '../types';
|
||||
import { validateProvisioningProfileAsync } from '../validators/validateProvisioningProfile';
|
||||
import {
|
||||
assignBuildCredentialsAsync,
|
||||
@@ -28,15 +26,11 @@ import { SetUpDistributionCertificate } from './SetUpDistributionCertificate';
|
||||
* Sets up either APP_STORE or ENTERPRISE provisioning profiles
|
||||
*/
|
||||
export class SetUpProvisioningProfile {
|
||||
constructor(
|
||||
private app: AppLookupParams,
|
||||
private target: Target,
|
||||
private distributionType: IosDistributionType
|
||||
) {}
|
||||
constructor(private app: AppLookupParams, private distributionType: IosDistributionType) {}
|
||||
|
||||
async areBuildCredentialsSetupAsync(ctx: CredentialsContext): Promise<boolean> {
|
||||
const buildCredentials = await getBuildCredentialsAsync(ctx, this.app, this.distributionType);
|
||||
return await validateProvisioningProfileAsync(ctx, this.target, this.app, buildCredentials);
|
||||
return await validateProvisioningProfileAsync(ctx, this.app, buildCredentials);
|
||||
}
|
||||
|
||||
async assignNewAndDeleteOldProfileAsync(
|
||||
@@ -54,11 +48,9 @@ export class SetUpProvisioningProfile {
|
||||
ctx: CredentialsContext,
|
||||
distCert: AppleDistributionCertificateFragment
|
||||
): Promise<IosAppBuildCredentialsFragment> {
|
||||
const provisioningProfile = await new CreateProvisioningProfile(
|
||||
this.app,
|
||||
this.target,
|
||||
distCert
|
||||
).runAsync(ctx);
|
||||
const provisioningProfile = await new CreateProvisioningProfile(this.app, distCert).runAsync(
|
||||
ctx
|
||||
);
|
||||
return await assignBuildCredentialsAsync(
|
||||
ctx,
|
||||
this.app,
|
||||
@@ -75,7 +67,6 @@ export class SetUpProvisioningProfile {
|
||||
): Promise<IosAppBuildCredentialsFragment | null> {
|
||||
const profileConfigurator = new ConfigureProvisioningProfile(
|
||||
this.app,
|
||||
this.target,
|
||||
distCert,
|
||||
originalProvisioningProfile
|
||||
);
|
||||
@@ -104,7 +95,7 @@ export class SetUpProvisioningProfile {
|
||||
}
|
||||
if (ctx.nonInteractive) {
|
||||
throw new MissingCredentialsNonInteractiveError(
|
||||
'Provisioning profile is not configured correctly. Run this command again in interactive mode.'
|
||||
'Provisioning profile is not configured correctly. Please run this command again in interactive mode.'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -114,10 +105,8 @@ export class SetUpProvisioningProfile {
|
||||
}
|
||||
|
||||
// See if the profile we have exists on the Apple Servers
|
||||
const applePlatform = await getApplePlatformFromSdkRoot(this.target);
|
||||
const existingProfiles = await ctx.appStore.listProvisioningProfilesAsync(
|
||||
this.app.bundleIdentifier,
|
||||
applePlatform
|
||||
this.app.bundleIdentifier
|
||||
);
|
||||
const currentProfileFromServer = this.getCurrentProfileStoreInfo(
|
||||
existingProfiles,
|
||||
|
||||
@@ -48,7 +48,7 @@ export class SetUpSubmissionCredentials {
|
||||
|
||||
async promptForAppSpecificPasswordAsync(): Promise<string> {
|
||||
Log.addNewLineIfNone();
|
||||
Log.log(`Enter your Apple app-specific password.`);
|
||||
Log.log(`Please enter your Apple app-specific password.`);
|
||||
Log.log(learnMore('https://expo.fyi/apple-app-specific-password'));
|
||||
Log.warn(
|
||||
wrapAnsi(
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
import Log from '../../../log';
|
||||
import { CredentialsContext } from '../../context';
|
||||
import { AppLookupParams as GraphQLAppLookupParams } from '../api/GraphqlClient';
|
||||
import { Target } from '../types';
|
||||
import { SetUpAdhocProvisioningProfile } from './SetUpAdhocProvisioningProfile';
|
||||
import { SetUpInternalProvisioningProfile } from './SetUpInternalProvisioningProfile';
|
||||
import { SetUpProvisioningProfile } from './SetUpProvisioningProfile';
|
||||
@@ -18,7 +17,6 @@ interface Options {
|
||||
distribution: DistributionType;
|
||||
enterpriseProvisioning?: IosEnterpriseProvisioning;
|
||||
entitlements: JSONObject;
|
||||
target: Target;
|
||||
}
|
||||
export class SetUpTargetBuildCredentials {
|
||||
constructor(private options: Options) {}
|
||||
@@ -49,25 +47,22 @@ export class SetUpTargetBuildCredentials {
|
||||
async setupBuildCredentialsAsync(
|
||||
ctx: CredentialsContext
|
||||
): Promise<IosAppBuildCredentialsFragment> {
|
||||
const { app, distribution, enterpriseProvisioning, target } = this.options;
|
||||
const { app, distribution, enterpriseProvisioning } = this.options;
|
||||
if (distribution === 'internal') {
|
||||
if (enterpriseProvisioning === 'adhoc') {
|
||||
return await new SetUpAdhocProvisioningProfile({ app, target }).runAsync(ctx);
|
||||
return await new SetUpAdhocProvisioningProfile(app).runAsync(ctx);
|
||||
} else if (enterpriseProvisioning === 'universal') {
|
||||
return await new SetUpProvisioningProfile(
|
||||
app,
|
||||
target,
|
||||
GraphQLIosDistributionType.Enterprise
|
||||
).runAsync(ctx);
|
||||
} else {
|
||||
return await new SetUpInternalProvisioningProfile({ app, target }).runAsync(ctx);
|
||||
return await new SetUpInternalProvisioningProfile(app).runAsync(ctx);
|
||||
}
|
||||
} else {
|
||||
return await new SetUpProvisioningProfile(
|
||||
app,
|
||||
target,
|
||||
GraphQLIosDistributionType.AppStore
|
||||
).runAsync(ctx);
|
||||
return await new SetUpProvisioningProfile(app, GraphQLIosDistributionType.AppStore).runAsync(
|
||||
ctx
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
-3
@@ -6,7 +6,6 @@ import {
|
||||
testDistCertFragmentNoDependencies,
|
||||
testProvisioningProfile,
|
||||
testProvisioningProfileFragment,
|
||||
testTarget,
|
||||
testTargets,
|
||||
} from '../../../__tests__/fixtures-ios';
|
||||
import { MissingCredentialsNonInteractiveError } from '../../../errors';
|
||||
@@ -37,7 +36,6 @@ describe('ConfigureProvisioningProfile', () => {
|
||||
const appLookupParams = getAppLookupParamsFromContext(ctx, findApplicationTarget(testTargets));
|
||||
const provProfConfigurator = new ConfigureProvisioningProfile(
|
||||
appLookupParams,
|
||||
testTarget,
|
||||
testDistCertFragmentNoDependencies,
|
||||
testProvisioningProfileFragment
|
||||
);
|
||||
@@ -55,7 +53,6 @@ describe('ConfigureProvisioningProfile', () => {
|
||||
const appLookupParams = getAppLookupParamsFromContext(ctx, findApplicationTarget(testTargets));
|
||||
const provProfConfigurator = new ConfigureProvisioningProfile(
|
||||
appLookupParams,
|
||||
testTarget,
|
||||
testDistCertFragmentNoDependencies,
|
||||
testProvisioningProfileFragment
|
||||
);
|
||||
|
||||
-3
@@ -5,7 +5,6 @@ import { createCtxMock } from '../../../__tests__/fixtures-context';
|
||||
import {
|
||||
testDistCertFragmentNoDependencies,
|
||||
testProvisioningProfile,
|
||||
testTarget,
|
||||
testTargets,
|
||||
} from '../../../__tests__/fixtures-ios';
|
||||
import { MissingCredentialsNonInteractiveError } from '../../../errors';
|
||||
@@ -29,7 +28,6 @@ describe('CreateProvisioningProfile', () => {
|
||||
const appLookupParams = getAppLookupParamsFromContext(ctx, findApplicationTarget(testTargets));
|
||||
const createProvProfAction = new CreateProvisioningProfile(
|
||||
appLookupParams,
|
||||
testTarget,
|
||||
testDistCertFragmentNoDependencies
|
||||
);
|
||||
await createProvProfAction.runAsync(ctx);
|
||||
@@ -46,7 +44,6 @@ describe('CreateProvisioningProfile', () => {
|
||||
const appLookupParams = getAppLookupParamsFromContext(ctx, findApplicationTarget(testTargets));
|
||||
const createProvProfAction = new CreateProvisioningProfile(
|
||||
appLookupParams,
|
||||
testTarget,
|
||||
testDistCertFragmentNoDependencies
|
||||
);
|
||||
await expect(createProvProfAction.runAsync(ctx)).rejects.toThrowError(
|
||||
|
||||
+30
-61
@@ -2,7 +2,6 @@ import { IosAppBuildCredentialsFragment, IosDistributionType } from '../../../..
|
||||
import { promptAsync } from '../../../../prompts';
|
||||
import { getAppstoreMock, testAuthCtx } from '../../../__tests__/fixtures-appstore';
|
||||
import { createCtxMock } from '../../../__tests__/fixtures-context';
|
||||
import { testTarget } from '../../../__tests__/fixtures-ios';
|
||||
import { getAllBuildCredentialsAsync } from '../BuildCredentialsUtils';
|
||||
import { SetUpAdhocProvisioningProfile } from '../SetUpAdhocProvisioningProfile';
|
||||
import { SetUpInternalProvisioningProfile } from '../SetUpInternalProvisioningProfile';
|
||||
@@ -42,12 +41,9 @@ describe(SetUpInternalProvisioningProfile, () => {
|
||||
return buildCredentials;
|
||||
});
|
||||
const action = new SetUpInternalProvisioningProfile({
|
||||
app: {
|
||||
account: { id: 'account-id', name: 'account-name' },
|
||||
bundleIdentifier: 'com.expo.test',
|
||||
projectName: 'testproject',
|
||||
},
|
||||
target: testTarget,
|
||||
account: { id: 'account-id', name: 'account-name' },
|
||||
bundleIdentifier: 'com.expo.test',
|
||||
projectName: 'testproject',
|
||||
});
|
||||
const ctx = createCtxMock({
|
||||
nonInteractive: false,
|
||||
@@ -76,12 +72,9 @@ describe(SetUpInternalProvisioningProfile, () => {
|
||||
});
|
||||
|
||||
const action = new SetUpInternalProvisioningProfile({
|
||||
app: {
|
||||
account: { id: 'account-id', name: 'account-name' },
|
||||
bundleIdentifier: 'com.expo.test',
|
||||
projectName: 'testproject',
|
||||
},
|
||||
target: testTarget,
|
||||
account: { id: 'account-id', name: 'account-name' },
|
||||
bundleIdentifier: 'com.expo.test',
|
||||
projectName: 'testproject',
|
||||
});
|
||||
const ctx = createCtxMock({
|
||||
nonInteractive: false,
|
||||
@@ -117,12 +110,9 @@ describe(SetUpInternalProvisioningProfile, () => {
|
||||
});
|
||||
|
||||
const action = new SetUpInternalProvisioningProfile({
|
||||
app: {
|
||||
account: { id: 'account-id', name: 'account-name' },
|
||||
bundleIdentifier: 'com.expo.test',
|
||||
projectName: 'testproject',
|
||||
},
|
||||
target: testTarget,
|
||||
account: { id: 'account-id', name: 'account-name' },
|
||||
bundleIdentifier: 'com.expo.test',
|
||||
projectName: 'testproject',
|
||||
});
|
||||
const ctx = createCtxMock({
|
||||
nonInteractive: false,
|
||||
@@ -151,12 +141,9 @@ describe(SetUpInternalProvisioningProfile, () => {
|
||||
});
|
||||
|
||||
const action = new SetUpInternalProvisioningProfile({
|
||||
app: {
|
||||
account: { id: 'account-id', name: 'account-name' },
|
||||
bundleIdentifier: 'com.expo.test',
|
||||
projectName: 'testproject',
|
||||
},
|
||||
target: testTarget,
|
||||
account: { id: 'account-id', name: 'account-name' },
|
||||
bundleIdentifier: 'com.expo.test',
|
||||
projectName: 'testproject',
|
||||
});
|
||||
const ctx = createCtxMock({
|
||||
nonInteractive: false,
|
||||
@@ -187,12 +174,9 @@ describe(SetUpInternalProvisioningProfile, () => {
|
||||
});
|
||||
|
||||
const action = new SetUpInternalProvisioningProfile({
|
||||
app: {
|
||||
account: { id: 'account-id', name: 'account-name' },
|
||||
bundleIdentifier: 'com.expo.test',
|
||||
projectName: 'testproject',
|
||||
},
|
||||
target: testTarget,
|
||||
account: { id: 'account-id', name: 'account-name' },
|
||||
bundleIdentifier: 'com.expo.test',
|
||||
projectName: 'testproject',
|
||||
});
|
||||
const ctx = createCtxMock({
|
||||
nonInteractive: false,
|
||||
@@ -221,12 +205,9 @@ describe(SetUpInternalProvisioningProfile, () => {
|
||||
});
|
||||
|
||||
const action = new SetUpInternalProvisioningProfile({
|
||||
app: {
|
||||
account: { id: 'account-id', name: 'account-name' },
|
||||
bundleIdentifier: 'com.expo.test',
|
||||
projectName: 'testproject',
|
||||
},
|
||||
target: testTarget,
|
||||
account: { id: 'account-id', name: 'account-name' },
|
||||
bundleIdentifier: 'com.expo.test',
|
||||
projectName: 'testproject',
|
||||
});
|
||||
const ctx = createCtxMock({
|
||||
nonInteractive: false,
|
||||
@@ -254,12 +235,9 @@ describe(SetUpInternalProvisioningProfile, () => {
|
||||
return buildCredentials;
|
||||
});
|
||||
const action = new SetUpInternalProvisioningProfile({
|
||||
app: {
|
||||
account: { id: 'account-id', name: 'account-name' },
|
||||
bundleIdentifier: 'com.expo.test',
|
||||
projectName: 'testproject',
|
||||
},
|
||||
target: testTarget,
|
||||
account: { id: 'account-id', name: 'account-name' },
|
||||
bundleIdentifier: 'com.expo.test',
|
||||
projectName: 'testproject',
|
||||
});
|
||||
const ctx = createCtxMock({
|
||||
nonInteractive: true,
|
||||
@@ -275,12 +253,9 @@ describe(SetUpInternalProvisioningProfile, () => {
|
||||
return buildCredentials;
|
||||
});
|
||||
const action = new SetUpInternalProvisioningProfile({
|
||||
app: {
|
||||
account: { id: 'account-id', name: 'account-name' },
|
||||
bundleIdentifier: 'com.expo.test',
|
||||
projectName: 'testproject',
|
||||
},
|
||||
target: testTarget,
|
||||
account: { id: 'account-id', name: 'account-name' },
|
||||
bundleIdentifier: 'com.expo.test',
|
||||
projectName: 'testproject',
|
||||
});
|
||||
const ctx = createCtxMock({
|
||||
nonInteractive: true,
|
||||
@@ -294,12 +269,9 @@ describe(SetUpInternalProvisioningProfile, () => {
|
||||
return buildCredentials;
|
||||
});
|
||||
const action = new SetUpInternalProvisioningProfile({
|
||||
app: {
|
||||
account: { id: 'account-id', name: 'account-name' },
|
||||
bundleIdentifier: 'com.expo.test',
|
||||
projectName: 'testproject',
|
||||
},
|
||||
target: testTarget,
|
||||
account: { id: 'account-id', name: 'account-name' },
|
||||
bundleIdentifier: 'com.expo.test',
|
||||
projectName: 'testproject',
|
||||
});
|
||||
const ctx = createCtxMock({
|
||||
nonInteractive: true,
|
||||
@@ -319,12 +291,9 @@ describe(SetUpInternalProvisioningProfile, () => {
|
||||
return buildCredentials;
|
||||
});
|
||||
const action = new SetUpInternalProvisioningProfile({
|
||||
app: {
|
||||
account: { id: 'account-id', name: 'account-name' },
|
||||
bundleIdentifier: 'com.expo.test',
|
||||
projectName: 'testproject',
|
||||
},
|
||||
target: testTarget,
|
||||
account: { id: 'account-id', name: 'account-name' },
|
||||
bundleIdentifier: 'com.expo.test',
|
||||
projectName: 'testproject',
|
||||
});
|
||||
const ctx = createCtxMock({
|
||||
nonInteractive: true,
|
||||
|
||||
-6
@@ -10,7 +10,6 @@ import {
|
||||
testAppleAppIdentifierFragment,
|
||||
testCommonIosAppCredentialsFragment,
|
||||
testIosAppBuildCredentialsFragment,
|
||||
testTarget,
|
||||
testTargets,
|
||||
} from '../../../__tests__/fixtures-ios';
|
||||
import { MissingCredentialsNonInteractiveError } from '../../../errors';
|
||||
@@ -56,7 +55,6 @@ describe('SetUpProvisioningProfile', () => {
|
||||
const appLookupParams = getAppLookupParamsFromContext(ctx, findApplicationTarget(testTargets));
|
||||
const setupProvisioningProfileAction = new SetUpProvisioningProfile(
|
||||
appLookupParams,
|
||||
testTarget,
|
||||
IosDistributionType.AppStore
|
||||
);
|
||||
await setupProvisioningProfileAction.runAsync(ctx);
|
||||
@@ -89,7 +87,6 @@ describe('SetUpProvisioningProfile', () => {
|
||||
const appLookupParams = getAppLookupParamsFromContext(ctx, findApplicationTarget(testTargets));
|
||||
const setupProvisioningProfileAction = new SetUpProvisioningProfile(
|
||||
appLookupParams,
|
||||
testTarget,
|
||||
IosDistributionType.AppStore
|
||||
);
|
||||
await setupProvisioningProfileAction.runAsync(ctx);
|
||||
@@ -122,7 +119,6 @@ describe('SetUpProvisioningProfile', () => {
|
||||
const appLookupParams = getAppLookupParamsFromContext(ctx, findApplicationTarget(testTargets));
|
||||
const setupProvisioningProfileAction = new SetUpProvisioningProfile(
|
||||
appLookupParams,
|
||||
testTarget,
|
||||
IosDistributionType.AppStore
|
||||
);
|
||||
await setupProvisioningProfileAction.runAsync(ctx);
|
||||
@@ -151,7 +147,6 @@ describe('SetUpProvisioningProfile', () => {
|
||||
const appLookupParams = getAppLookupParamsFromContext(ctx, findApplicationTarget(testTargets));
|
||||
const setupProvisioningProfileAction = new SetUpProvisioningProfile(
|
||||
appLookupParams,
|
||||
testTarget,
|
||||
IosDistributionType.AppStore
|
||||
);
|
||||
await setupProvisioningProfileAction.runAsync(ctx);
|
||||
@@ -171,7 +166,6 @@ describe('SetUpProvisioningProfile', () => {
|
||||
const appLookupParams = getAppLookupParamsFromContext(ctx, findApplicationTarget(testTargets));
|
||||
const setupProvisioningProfileAction = new SetUpProvisioningProfile(
|
||||
appLookupParams,
|
||||
testTarget,
|
||||
IosDistributionType.AppStore
|
||||
);
|
||||
await expect(setupProvisioningProfileAction.runAsync(ctx)).rejects.toThrowError(
|
||||
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
IosAppBuildCredentialsFragment,
|
||||
IosDistributionType,
|
||||
} from '../../../graphql/generated';
|
||||
import { AppQuery } from '../../../graphql/queries/AppQuery';
|
||||
import { isWildcardBundleIdentifier } from '../../../project/ios/bundleIdentifier';
|
||||
import { Account } from '../../../user/Account';
|
||||
import { DistributionCertificate, PushKey } from '../appstore/Credentials.types';
|
||||
@@ -34,6 +33,7 @@ import { ApplePushKeyMutation } from './graphql/mutations/ApplePushKeyMutation';
|
||||
import { AppleTeamMutation } from './graphql/mutations/AppleTeamMutation';
|
||||
import { IosAppBuildCredentialsMutation } from './graphql/mutations/IosAppBuildCredentialsMutation';
|
||||
import { IosAppCredentialsMutation } from './graphql/mutations/IosAppCredentialsMutation';
|
||||
import { AppQuery } from './graphql/queries/AppQuery';
|
||||
import { AppStoreConnectApiKeyQuery } from './graphql/queries/AppStoreConnectApiKeyQuery';
|
||||
import { AppleAppIdentifierQuery } from './graphql/queries/AppleAppIdentifierQuery';
|
||||
import { AppleDeviceQuery } from './graphql/queries/AppleDeviceQuery';
|
||||
|
||||
+3
-3
@@ -2,9 +2,9 @@ import assert from 'assert';
|
||||
import { print } from 'graphql';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
import { graphqlClient, withErrorHandlingAsync } from '../client';
|
||||
import { AppByFullNameQuery, AppFragment } from '../generated';
|
||||
import { AppFragmentNode } from '../types/App';
|
||||
import { graphqlClient, withErrorHandlingAsync } from '../../../../../graphql/client';
|
||||
import { AppByFullNameQuery, AppFragment } from '../../../../../graphql/generated';
|
||||
import { AppFragmentNode } from '../../../../../graphql/types/App';
|
||||
|
||||
export const AppQuery = {
|
||||
async byFullNameAsync(fullName: string): Promise<AppFragment> {
|
||||
@@ -1,5 +1,3 @@
|
||||
import { ProfileType } from '@expo/app-store';
|
||||
|
||||
import Log from '../../../log';
|
||||
import {
|
||||
AscApiKey,
|
||||
@@ -24,7 +22,6 @@ import {
|
||||
isUserAuthCtx,
|
||||
} from './authenticate';
|
||||
import { AuthCtx, AuthenticationMode, UserAuthCtx } from './authenticateTypes';
|
||||
import { ApplePlatform } from './constants';
|
||||
import {
|
||||
createDistributionCertificateAsync,
|
||||
listDistributionCertificatesAsync,
|
||||
@@ -132,18 +129,16 @@ export default class AppStoreApi {
|
||||
|
||||
public async listProvisioningProfilesAsync(
|
||||
bundleIdentifier: string,
|
||||
applePlatform: ApplePlatform,
|
||||
profileClass?: ProfileClass
|
||||
): Promise<ProvisioningProfileStoreInfo[]> {
|
||||
const ctx = await this.ensureAuthenticatedAsync();
|
||||
return await listProvisioningProfilesAsync(ctx, bundleIdentifier, applePlatform, profileClass);
|
||||
return await listProvisioningProfilesAsync(ctx, bundleIdentifier, profileClass);
|
||||
}
|
||||
|
||||
public async createProvisioningProfileAsync(
|
||||
bundleIdentifier: string,
|
||||
distCert: DistributionCertificate,
|
||||
profileName: string,
|
||||
applePlatform: ApplePlatform,
|
||||
profileClass?: ProfileClass
|
||||
): Promise<ProvisioningProfile> {
|
||||
const ctx = await this.ensureAuthenticatedAsync();
|
||||
@@ -152,33 +147,29 @@ export default class AppStoreApi {
|
||||
bundleIdentifier,
|
||||
distCert,
|
||||
profileName,
|
||||
applePlatform,
|
||||
profileClass
|
||||
);
|
||||
}
|
||||
|
||||
public async revokeProvisioningProfileAsync(
|
||||
bundleIdentifier: string,
|
||||
applePlatform: ApplePlatform,
|
||||
profileClass?: ProfileClass
|
||||
): Promise<void> {
|
||||
const ctx = await this.ensureAuthenticatedAsync();
|
||||
return await revokeProvisioningProfileAsync(ctx, bundleIdentifier, applePlatform, profileClass);
|
||||
return await revokeProvisioningProfileAsync(ctx, bundleIdentifier, profileClass);
|
||||
}
|
||||
|
||||
public async createOrReuseAdhocProvisioningProfileAsync(
|
||||
udids: string[],
|
||||
bundleIdentifier: string,
|
||||
distCertSerialNumber: string,
|
||||
profileType: ProfileType
|
||||
distCertSerialNumber: string
|
||||
): Promise<ProvisioningProfile> {
|
||||
const ctx = await this.ensureAuthenticatedAsync();
|
||||
return await createOrReuseAdhocProvisioningProfileAsync(
|
||||
ctx,
|
||||
udids,
|
||||
bundleIdentifier,
|
||||
distCertSerialNumber,
|
||||
profileType
|
||||
distCertSerialNumber
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,21 @@
|
||||
import { UserRole } from '@expo/apple-utils';
|
||||
|
||||
export interface Device {
|
||||
id: string;
|
||||
teamId: string;
|
||||
identifier: string;
|
||||
name?: string;
|
||||
model?: string;
|
||||
deviceClass?: DeviceClass;
|
||||
softwareVersion?: string;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export enum DeviceClass {
|
||||
IPHONE = 'iphone',
|
||||
IPAD = 'ipad',
|
||||
}
|
||||
|
||||
export interface DistributionCertificateStoreInfo {
|
||||
id: string;
|
||||
name: string;
|
||||
|
||||
Loaded 100 of 194 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user