mirror of
https://github.com/expo/eas-cli.git
synced 2026-11-15 03:38:08 -10:00
Compare commits
60
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b3074e436 | ||
|
|
63502586f8 | ||
|
|
714532a532 | ||
|
|
8cbed45be9 | ||
|
|
3466a0c3dc | ||
|
|
b28943d8f1 | ||
|
|
e01a70943b | ||
|
|
56510f0925 | ||
|
|
1540b1354e | ||
|
|
61455420b1 | ||
|
|
d3fdc1a95b | ||
|
|
a28439a485 | ||
|
|
8af8569f16 | ||
|
|
9b49fe3a9f | ||
|
|
2c8f9a67c8 | ||
|
|
9597ea2832 | ||
|
|
5976dc7346 | ||
|
|
75b310e7e0 | ||
|
|
63009b0437 | ||
|
|
7994676f3e | ||
|
|
987c23fc2d | ||
|
|
2bf5819075 | ||
|
|
fdbeb862ec | ||
|
|
9a05359dcb | ||
|
|
ce76d4d7d0 | ||
|
|
3c58bd4515 | ||
|
|
f4f4756e07 | ||
|
|
31b3d81b1a | ||
|
|
5cf526592c | ||
|
|
8646dc81d9 | ||
|
|
54ae76e85e | ||
|
|
63381b8ee4 | ||
|
|
52ab2d5792 | ||
|
|
ade09fe6dc | ||
|
|
71261b5b26 | ||
|
|
37cec329d4 | ||
|
|
fc88d65691 | ||
|
|
4699ae51f0 | ||
|
|
aabe1ff806 | ||
|
|
c8bd95535e | ||
|
|
71184cbcd5 | ||
|
|
1629e2b585 | ||
|
|
4a82ac90d3 | ||
|
|
5745639bb2 | ||
|
|
17ecdb2a95 | ||
|
|
42b105c869 | ||
|
|
ac04891b28 | ||
|
|
14a454edfa | ||
|
|
c0651a880c | ||
|
|
c39f76392d | ||
|
|
f2ed434828 | ||
|
|
9344fba85f | ||
|
|
e5bfcf4e90 | ||
|
|
40a7b144ea | ||
|
|
97d1e25908 | ||
|
|
2b23c11d6e | ||
|
|
1c61465c5f | ||
|
|
0516b507bc | ||
|
|
2e14870b60 | ||
|
|
559baf9150 |
No files matched your search
@@ -5,3 +5,4 @@
|
|||||||
packages/eas-cli/src/graphql/generated.ts
|
packages/eas-cli/src/graphql/generated.ts
|
||||||
|
|
||||||
node_modules
|
node_modules
|
||||||
|
ts-declarations
|
||||||
@@ -30,12 +30,6 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
'no-underscore-dangle': ['error', { allow: ['__typename'] }],
|
'no-underscore-dangle': ['error', { allow: ['__typename'] }],
|
||||||
'@typescript-eslint/explicit-function-return-type': [
|
|
||||||
'warn',
|
|
||||||
{
|
|
||||||
allowExpressions: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'async-protect/async-suffix': 'error',
|
'async-protect/async-suffix': 'error',
|
||||||
'node/no-sync': 'error',
|
'node/no-sync': 'error',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,6 +12,78 @@ This is the log of notable changes to EAS CLI and related packages.
|
|||||||
|
|
||||||
### 🧹 Chores
|
### 🧹 Chores
|
||||||
|
|
||||||
|
## [11.0.1](https://github.com/expo/eas-cli/releases/tag/v11.0.1) - 2024-08-26
|
||||||
|
|
||||||
|
### 🐛 Bug fixes
|
||||||
|
|
||||||
|
- Make `eas config` command not require authentication when running in `--eas-json-only` mode. ([#2517](https://github.com/expo/eas-cli/pull/2517) by [@szdziedzic](https://github.com/szdziedzic))
|
||||||
|
|
||||||
|
## [11.0.0](https://github.com/expo/eas-cli/releases/tag/v11.0.0) - 2024-08-26
|
||||||
|
|
||||||
|
### 🛠 Breaking changes
|
||||||
|
|
||||||
|
- Remove long-deprecated `eas update` flags. ([#2501](https://github.com/expo/eas-cli/pull/2501) by [@wschurman](https://github.com/wschurman))
|
||||||
|
|
||||||
|
### 🎉 New features
|
||||||
|
|
||||||
|
- Add new rollout update type for `eas update` and `eas update:edit`. ([#2502](https://github.com/expo/eas-cli/pull/2502), [#2503](https://github.com/expo/eas-cli/pull/2503) by [@wschurman](https://github.com/wschurman))
|
||||||
|
|
||||||
|
### 🧹 Chores
|
||||||
|
|
||||||
|
- Upgrade packages to SDK 51 release. ([#2498](https://github.com/expo/eas-cli/pull/2498) by [@wschurman](https://github.com/wschurman))
|
||||||
|
- Enable typescript linting and various lint rules. ([#2505](https://github.com/expo/eas-cli/pull/2505), [#2507](https://github.com/expo/eas-cli/pull/2507), [#2508](https://github.com/expo/eas-cli/pull/2508), [#2509](https://github.com/expo/eas-cli/pull/2509), [#2510](https://github.com/expo/eas-cli/pull/2510) by [@wschurman](https://github.com/wschurman))
|
||||||
|
- Include debug info in fingerprint metadata during build. ([#2513](https://github.com/expo/eas-cli/pull/2513) by [@wschurman](https://github.com/wschurman))
|
||||||
|
|
||||||
|
## [10.2.4](https://github.com/expo/eas-cli/releases/tag/v10.2.4) - 2024-08-19
|
||||||
|
|
||||||
|
## [10.2.3](https://github.com/expo/eas-cli/releases/tag/v10.2.3) - 2024-08-13
|
||||||
|
|
||||||
|
### 🧹 Chores
|
||||||
|
|
||||||
|
- Add support for `EAS_DANGEROUS_OVERRIDE_IOS_BUNDLE_IDENTIFIER` for bare workflow iOS builds. ([#2469](https://github.com/expo/eas-cli/pull/2469) by [@szdziedzic](https://github.com/szdziedzic))
|
||||||
|
- Update images list in `eas.schema.json` and warn users when using the deprecated Android images. ([#2450](https://github.com/expo/eas-cli/pull/2450) by [@szdziedzic](https://github.com/szdziedzic))
|
||||||
|
|
||||||
|
## [10.2.2](https://github.com/expo/eas-cli/releases/tag/v10.2.2) - 2024-07-31
|
||||||
|
|
||||||
|
### 🐛 Bug fixes
|
||||||
|
|
||||||
|
- Pass correct path to `vcsClient.isFileIgnoredAsync` check for monorepos to validate that custom build config file is not ignored. ([#2470](https://github.com/expo/eas-cli/pull/2470) by [@szdziedzic](https://github.com/szdziedzic))
|
||||||
|
|
||||||
|
### 🧹 Chores
|
||||||
|
|
||||||
|
- Bump asset upload timeout from 90 to 180 seconds. ([#2466](https://github.com/expo/eas-cli/pull/2466) by [@quinlanj](https://github.com/quinlanj))
|
||||||
|
|
||||||
|
## [10.2.1](https://github.com/expo/eas-cli/releases/tag/v10.2.1) - 2024-07-18
|
||||||
|
|
||||||
|
### 🧹 Chores
|
||||||
|
|
||||||
|
- Indicate if a user is logged in using `EXPO_TOKEN` when running `eas whoami` command. ([#2461](https://github.com/expo/eas-cli/pull/2461) by [@szdziedzic](https://github.com/szdziedzic))
|
||||||
|
- Throw error when `eas login` command is run with `EXPO_TOKEN` environment variable set. ([#2461](https://github.com/expo/eas-cli/pull/2461) by [@szdziedzic](https://github.com/szdziedzic))
|
||||||
|
- Check if user is already logged in when running `eas login` command. ([#2461](https://github.com/expo/eas-cli/pull/2461) by [@szdziedzic](https://github.com/szdziedzic))
|
||||||
|
|
||||||
|
## [10.2.0](https://github.com/expo/eas-cli/releases/tag/v10.2.0) - 2024-07-15
|
||||||
|
|
||||||
|
### 🎉 New features
|
||||||
|
|
||||||
|
- Added flag `--emit-metadata` to emit `eas-update-metadata.json` in the bundle folder with detailed information about the generated updates ([#2451](https://github.com/expo/eas-cli/pull/2451) by [@rainst](https://github.com/rainst))
|
||||||
|
|
||||||
|
### 🐛 Bug fixes
|
||||||
|
|
||||||
|
- Bump `@expo/apple-utils` version to use the fallback Apple Developer Portal domain on every internal server error. ([#2459](https://github.com/expo/eas-cli/pull/2459) by [@szdziedzic](https://github.com/szdziedzic))
|
||||||
|
|
||||||
|
## [10.1.1](https://github.com/expo/eas-cli/releases/tag/v10.1.1) - 2024-07-04
|
||||||
|
|
||||||
|
## [10.1.0](https://github.com/expo/eas-cli/releases/tag/v10.1.0) - 2024-07-02
|
||||||
|
|
||||||
|
### 🎉 New features
|
||||||
|
|
||||||
|
- Save local fingeprint sources during build. ([#2422](https://github.com/expo/eas-cli/pull/2422) by [@kadikraman](https://github.com/kadikraman))
|
||||||
|
|
||||||
|
## [10.0.3](https://github.com/expo/eas-cli/releases/tag/v10.0.3) - 2024-06-26
|
||||||
|
|
||||||
|
### 🧹 Chores
|
||||||
|
|
||||||
|
- Track usage of `--local` build mode in analytics. ([#2445](https://github.com/expo/eas-cli/pull/2445) by [@szdziedzic](https://github.com/szdziedzic))
|
||||||
- Remove any mentions of deleted Xcode < 15 images. ([#2438](https://github.com/expo/eas-cli/pull/2438) by [@szdziedzic](https://github.com/szdziedzic))
|
- Remove any mentions of deleted Xcode < 15 images. ([#2438](https://github.com/expo/eas-cli/pull/2438) by [@szdziedzic](https://github.com/szdziedzic))
|
||||||
|
|
||||||
## [10.0.2](https://github.com/expo/eas-cli/releases/tag/v10.0.2) - 2024-06-17
|
## [10.0.2](https://github.com/expo/eas-cli/releases/tag/v10.0.2) - 2024-06-17
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"version": "10.0.2",
|
"version": "11.0.1",
|
||||||
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
|
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
|
||||||
}
|
}
|
||||||
+1
-1
@@ -23,7 +23,7 @@
|
|||||||
"@types/jest": "29.5.11",
|
"@types/jest": "29.5.11",
|
||||||
"@types/node": "20.11.0",
|
"@types/node": "20.11.0",
|
||||||
"eslint": "8.56.0",
|
"eslint": "8.56.0",
|
||||||
"eslint-config-universe": "12.0.0",
|
"eslint-config-universe": "13.0.0",
|
||||||
"eslint-plugin-async-protect": "3.1.0",
|
"eslint-plugin-async-protect": "3.1.0",
|
||||||
"eslint-plugin-node": "11.1.0",
|
"eslint-plugin-node": "11.1.0",
|
||||||
"jest": "29.7.0",
|
"jest": "29.7.0",
|
||||||
|
|||||||
+66
-66
@@ -39,7 +39,7 @@ An example of **eas.json** that enforces `eas-cli` in version `1.0.0` or newer:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Learn more: https://docs.expo.dev/build-reference/eas-json/
|
Learn more: https://docs.expo.dev/build/eas-json/
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ ALIASES
|
|||||||
$ eas login
|
$ eas login
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/account/login.ts)_
|
_See code: [packages/eas-cli/src/commands/account/login.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/account/login.ts)_
|
||||||
|
|
||||||
## `eas account:logout`
|
## `eas account:logout`
|
||||||
|
|
||||||
@@ -160,7 +160,7 @@ ALIASES
|
|||||||
$ eas logout
|
$ eas logout
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/account/logout.ts)_
|
_See code: [packages/eas-cli/src/commands/account/logout.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/account/logout.ts)_
|
||||||
|
|
||||||
## `eas account:view`
|
## `eas account:view`
|
||||||
|
|
||||||
@@ -177,7 +177,7 @@ ALIASES
|
|||||||
$ eas whoami
|
$ eas whoami
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/account/view.ts)_
|
_See code: [packages/eas-cli/src/commands/account/view.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/account/view.ts)_
|
||||||
|
|
||||||
## `eas analytics [STATUS]`
|
## `eas analytics [STATUS]`
|
||||||
|
|
||||||
@@ -191,7 +191,7 @@ DESCRIPTION
|
|||||||
display or change analytics settings
|
display or change analytics settings
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/analytics.ts)_
|
_See code: [packages/eas-cli/src/commands/analytics.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/analytics.ts)_
|
||||||
|
|
||||||
## `eas autocomplete [SHELL]`
|
## `eas autocomplete [SHELL]`
|
||||||
|
|
||||||
@@ -243,7 +243,7 @@ DESCRIPTION
|
|||||||
create a branch
|
create a branch
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/branch/create.ts)_
|
_See code: [packages/eas-cli/src/commands/branch/create.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/branch/create.ts)_
|
||||||
|
|
||||||
## `eas branch:delete [NAME]`
|
## `eas branch:delete [NAME]`
|
||||||
|
|
||||||
@@ -264,7 +264,7 @@ DESCRIPTION
|
|||||||
delete a branch
|
delete a branch
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/branch/delete.ts)_
|
_See code: [packages/eas-cli/src/commands/branch/delete.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/branch/delete.ts)_
|
||||||
|
|
||||||
## `eas branch:list`
|
## `eas branch:list`
|
||||||
|
|
||||||
@@ -284,7 +284,7 @@ DESCRIPTION
|
|||||||
list all branches
|
list all branches
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/branch/list.ts)_
|
_See code: [packages/eas-cli/src/commands/branch/list.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/branch/list.ts)_
|
||||||
|
|
||||||
## `eas branch:rename`
|
## `eas branch:rename`
|
||||||
|
|
||||||
@@ -304,7 +304,7 @@ DESCRIPTION
|
|||||||
rename a branch
|
rename a branch
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/branch/rename.ts)_
|
_See code: [packages/eas-cli/src/commands/branch/rename.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/branch/rename.ts)_
|
||||||
|
|
||||||
## `eas branch:view [NAME]`
|
## `eas branch:view [NAME]`
|
||||||
|
|
||||||
@@ -327,7 +327,7 @@ DESCRIPTION
|
|||||||
view a branch
|
view a branch
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/branch/view.ts)_
|
_See code: [packages/eas-cli/src/commands/branch/view.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/branch/view.ts)_
|
||||||
|
|
||||||
## `eas build`
|
## `eas build`
|
||||||
|
|
||||||
@@ -364,7 +364,7 @@ DESCRIPTION
|
|||||||
start a build
|
start a build
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/build/index.ts)_
|
_See code: [packages/eas-cli/src/commands/build/index.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/build/index.ts)_
|
||||||
|
|
||||||
## `eas build:cancel [BUILD_ID]`
|
## `eas build:cancel [BUILD_ID]`
|
||||||
|
|
||||||
@@ -383,7 +383,7 @@ DESCRIPTION
|
|||||||
cancel a build
|
cancel a build
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/build/cancel.ts)_
|
_See code: [packages/eas-cli/src/commands/build/cancel.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/build/cancel.ts)_
|
||||||
|
|
||||||
## `eas build:configure`
|
## `eas build:configure`
|
||||||
|
|
||||||
@@ -400,7 +400,7 @@ DESCRIPTION
|
|||||||
configure the project to support EAS Build
|
configure the project to support EAS Build
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/build/configure.ts)_
|
_See code: [packages/eas-cli/src/commands/build/configure.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/build/configure.ts)_
|
||||||
|
|
||||||
## `eas build:delete [BUILD_ID]`
|
## `eas build:delete [BUILD_ID]`
|
||||||
|
|
||||||
@@ -419,7 +419,7 @@ DESCRIPTION
|
|||||||
delete a build
|
delete a build
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/build/delete.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/build/delete.ts)_
|
_See code: [packages/eas-cli/src/commands/build/delete.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/build/delete.ts)_
|
||||||
|
|
||||||
## `eas build:inspect`
|
## `eas build:inspect`
|
||||||
|
|
||||||
@@ -454,7 +454,7 @@ DESCRIPTION
|
|||||||
inspect the state of the project at specific build stages, useful for troubleshooting
|
inspect the state of the project at specific build stages, useful for troubleshooting
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/build/inspect.ts)_
|
_See code: [packages/eas-cli/src/commands/build/inspect.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/build/inspect.ts)_
|
||||||
|
|
||||||
## `eas build:list`
|
## `eas build:list`
|
||||||
|
|
||||||
@@ -504,7 +504,7 @@ DESCRIPTION
|
|||||||
list all builds for your project
|
list all builds for your project
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/build/list.ts)_
|
_See code: [packages/eas-cli/src/commands/build/list.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/build/list.ts)_
|
||||||
|
|
||||||
## `eas build:resign`
|
## `eas build:resign`
|
||||||
|
|
||||||
@@ -533,7 +533,7 @@ DESCRIPTION
|
|||||||
re-sign a build archive
|
re-sign a build archive
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/build/resign.ts)_
|
_See code: [packages/eas-cli/src/commands/build/resign.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/build/resign.ts)_
|
||||||
|
|
||||||
## `eas build:run`
|
## `eas build:run`
|
||||||
|
|
||||||
@@ -559,7 +559,7 @@ DESCRIPTION
|
|||||||
run simulator/emulator builds from eas-cli
|
run simulator/emulator builds from eas-cli
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/build/run.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/build/run.ts)_
|
_See code: [packages/eas-cli/src/commands/build/run.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/build/run.ts)_
|
||||||
|
|
||||||
## `eas build:submit`
|
## `eas build:submit`
|
||||||
|
|
||||||
@@ -609,7 +609,7 @@ DESCRIPTION
|
|||||||
get the latest version from EAS servers
|
get the latest version from EAS servers
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/build/version/get.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/build/version/get.ts)_
|
_See code: [packages/eas-cli/src/commands/build/version/get.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/build/version/get.ts)_
|
||||||
|
|
||||||
## `eas build:version:set`
|
## `eas build:version:set`
|
||||||
|
|
||||||
@@ -628,7 +628,7 @@ DESCRIPTION
|
|||||||
update version of an app
|
update version of an app
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/build/version/set.ts)_
|
_See code: [packages/eas-cli/src/commands/build/version/set.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/build/version/set.ts)_
|
||||||
|
|
||||||
## `eas build:version:sync`
|
## `eas build:version:sync`
|
||||||
|
|
||||||
@@ -647,7 +647,7 @@ DESCRIPTION
|
|||||||
update a version in native code with a value stored on EAS servers
|
update a version in native code with a value stored on EAS servers
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/build/version/sync.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/build/version/sync.ts)_
|
_See code: [packages/eas-cli/src/commands/build/version/sync.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/build/version/sync.ts)_
|
||||||
|
|
||||||
## `eas build:view [BUILD_ID]`
|
## `eas build:view [BUILD_ID]`
|
||||||
|
|
||||||
@@ -664,7 +664,7 @@ DESCRIPTION
|
|||||||
view a build for your project
|
view a build for your project
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/build/view.ts)_
|
_See code: [packages/eas-cli/src/commands/build/view.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/build/view.ts)_
|
||||||
|
|
||||||
## `eas channel:create [NAME]`
|
## `eas channel:create [NAME]`
|
||||||
|
|
||||||
@@ -685,7 +685,7 @@ DESCRIPTION
|
|||||||
create a channel
|
create a channel
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/channel/create.ts)_
|
_See code: [packages/eas-cli/src/commands/channel/create.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/channel/create.ts)_
|
||||||
|
|
||||||
## `eas channel:edit [NAME]`
|
## `eas channel:edit [NAME]`
|
||||||
|
|
||||||
@@ -707,7 +707,7 @@ DESCRIPTION
|
|||||||
point a channel at a new branch
|
point a channel at a new branch
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/channel/edit.ts)_
|
_See code: [packages/eas-cli/src/commands/channel/edit.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/channel/edit.ts)_
|
||||||
|
|
||||||
## `eas channel:list`
|
## `eas channel:list`
|
||||||
|
|
||||||
@@ -727,7 +727,7 @@ DESCRIPTION
|
|||||||
list all channels
|
list all channels
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/channel/list.ts)_
|
_See code: [packages/eas-cli/src/commands/channel/list.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/channel/list.ts)_
|
||||||
|
|
||||||
## `eas channel:rollout [CHANNEL]`
|
## `eas channel:rollout [CHANNEL]`
|
||||||
|
|
||||||
@@ -760,7 +760,7 @@ DESCRIPTION
|
|||||||
Roll a new branch out on a channel incrementally.
|
Roll a new branch out on a channel incrementally.
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/channel/rollout.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/channel/rollout.ts)_
|
_See code: [packages/eas-cli/src/commands/channel/rollout.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/channel/rollout.ts)_
|
||||||
|
|
||||||
## `eas channel:view [NAME]`
|
## `eas channel:view [NAME]`
|
||||||
|
|
||||||
@@ -783,7 +783,7 @@ DESCRIPTION
|
|||||||
view a channel
|
view a channel
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/channel/view.ts)_
|
_See code: [packages/eas-cli/src/commands/channel/view.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/channel/view.ts)_
|
||||||
|
|
||||||
## `eas config`
|
## `eas config`
|
||||||
|
|
||||||
@@ -804,7 +804,7 @@ DESCRIPTION
|
|||||||
display project configuration (app.json + eas.json)
|
display project configuration (app.json + eas.json)
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/config.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/config.ts)_
|
_See code: [packages/eas-cli/src/commands/config.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/config.ts)_
|
||||||
|
|
||||||
## `eas credentials`
|
## `eas credentials`
|
||||||
|
|
||||||
@@ -821,7 +821,7 @@ DESCRIPTION
|
|||||||
manage credentials
|
manage credentials
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/credentials/index.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/credentials/index.ts)_
|
_See code: [packages/eas-cli/src/commands/credentials/index.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/credentials/index.ts)_
|
||||||
|
|
||||||
## `eas credentials:configure-build`
|
## `eas credentials:configure-build`
|
||||||
|
|
||||||
@@ -839,7 +839,7 @@ DESCRIPTION
|
|||||||
Set up credentials for building your project.
|
Set up credentials for building your project.
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/credentials/configure-build.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/credentials/configure-build.ts)_
|
_See code: [packages/eas-cli/src/commands/credentials/configure-build.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/credentials/configure-build.ts)_
|
||||||
|
|
||||||
## `eas device:create`
|
## `eas device:create`
|
||||||
|
|
||||||
@@ -853,7 +853,7 @@ DESCRIPTION
|
|||||||
register new Apple Devices to use for internal distribution
|
register new Apple Devices to use for internal distribution
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/device/create.ts)_
|
_See code: [packages/eas-cli/src/commands/device/create.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/device/create.ts)_
|
||||||
|
|
||||||
## `eas device:delete`
|
## `eas device:delete`
|
||||||
|
|
||||||
@@ -873,7 +873,7 @@ DESCRIPTION
|
|||||||
remove a registered device from your account
|
remove a registered device from your account
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/device/delete.ts)_
|
_See code: [packages/eas-cli/src/commands/device/delete.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/device/delete.ts)_
|
||||||
|
|
||||||
## `eas device:list`
|
## `eas device:list`
|
||||||
|
|
||||||
@@ -894,7 +894,7 @@ DESCRIPTION
|
|||||||
list all registered devices for your account
|
list all registered devices for your account
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/device/list.ts)_
|
_See code: [packages/eas-cli/src/commands/device/list.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/device/list.ts)_
|
||||||
|
|
||||||
## `eas device:rename`
|
## `eas device:rename`
|
||||||
|
|
||||||
@@ -915,7 +915,7 @@ DESCRIPTION
|
|||||||
rename a registered device
|
rename a registered device
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/device/rename.ts)_
|
_See code: [packages/eas-cli/src/commands/device/rename.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/device/rename.ts)_
|
||||||
|
|
||||||
## `eas device:view [UDID]`
|
## `eas device:view [UDID]`
|
||||||
|
|
||||||
@@ -929,7 +929,7 @@ DESCRIPTION
|
|||||||
view a device for your project
|
view a device for your project
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/device/view.ts)_
|
_See code: [packages/eas-cli/src/commands/device/view.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/device/view.ts)_
|
||||||
|
|
||||||
## `eas diagnostics`
|
## `eas diagnostics`
|
||||||
|
|
||||||
@@ -943,7 +943,7 @@ DESCRIPTION
|
|||||||
display environment info
|
display environment info
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/diagnostics.ts)_
|
_See code: [packages/eas-cli/src/commands/diagnostics.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/diagnostics.ts)_
|
||||||
|
|
||||||
## `eas help [COMMAND]`
|
## `eas help [COMMAND]`
|
||||||
|
|
||||||
@@ -1050,7 +1050,7 @@ DESCRIPTION
|
|||||||
validate the local store configuration
|
validate the local store configuration
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/metadata/lint.ts)_
|
_See code: [packages/eas-cli/src/commands/metadata/lint.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/metadata/lint.ts)_
|
||||||
|
|
||||||
## `eas metadata:pull`
|
## `eas metadata:pull`
|
||||||
|
|
||||||
@@ -1067,7 +1067,7 @@ DESCRIPTION
|
|||||||
generate the local store configuration from the app stores
|
generate the local store configuration from the app stores
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/metadata/pull.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/metadata/pull.ts)_
|
_See code: [packages/eas-cli/src/commands/metadata/pull.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/metadata/pull.ts)_
|
||||||
|
|
||||||
## `eas metadata:push`
|
## `eas metadata:push`
|
||||||
|
|
||||||
@@ -1084,7 +1084,7 @@ DESCRIPTION
|
|||||||
sync the local store configuration to the app stores
|
sync the local store configuration to the app stores
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/metadata/push.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/metadata/push.ts)_
|
_See code: [packages/eas-cli/src/commands/metadata/push.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/metadata/push.ts)_
|
||||||
|
|
||||||
## `eas onboarding [TARGET_PROJECT_DIRECTORY]`
|
## `eas onboarding [TARGET_PROJECT_DIRECTORY]`
|
||||||
|
|
||||||
@@ -1114,7 +1114,7 @@ DESCRIPTION
|
|||||||
open the project page in a web browser
|
open the project page in a web browser
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/open.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/open.ts)_
|
_See code: [packages/eas-cli/src/commands/open.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/open.ts)_
|
||||||
|
|
||||||
## `eas project:info`
|
## `eas project:info`
|
||||||
|
|
||||||
@@ -1128,7 +1128,7 @@ DESCRIPTION
|
|||||||
information about the current project
|
information about the current project
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/project/info.ts)_
|
_See code: [packages/eas-cli/src/commands/project/info.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/project/info.ts)_
|
||||||
|
|
||||||
## `eas project:init`
|
## `eas project:init`
|
||||||
|
|
||||||
@@ -1150,7 +1150,7 @@ ALIASES
|
|||||||
$ eas init
|
$ eas init
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/project/init.ts)_
|
_See code: [packages/eas-cli/src/commands/project/init.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/project/init.ts)_
|
||||||
|
|
||||||
## `eas project:onboarding [TARGET_PROJECT_DIRECTORY]`
|
## `eas project:onboarding [TARGET_PROJECT_DIRECTORY]`
|
||||||
|
|
||||||
@@ -1168,7 +1168,7 @@ ALIASES
|
|||||||
$ eas onboarding
|
$ eas onboarding
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/project/onboarding.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/project/onboarding.ts)_
|
_See code: [packages/eas-cli/src/commands/project/onboarding.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/project/onboarding.ts)_
|
||||||
|
|
||||||
## `eas secret:create`
|
## `eas secret:create`
|
||||||
|
|
||||||
@@ -1191,7 +1191,7 @@ DESCRIPTION
|
|||||||
create an environment secret on the current project or owner account
|
create an environment secret on the current project or owner account
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/secret/create.ts)_
|
_See code: [packages/eas-cli/src/commands/secret/create.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/secret/create.ts)_
|
||||||
|
|
||||||
## `eas secret:delete`
|
## `eas secret:delete`
|
||||||
|
|
||||||
@@ -1209,7 +1209,7 @@ DESCRIPTION
|
|||||||
delete an environment secret by ID
|
delete an environment secret by ID
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/secret/delete.ts)_
|
_See code: [packages/eas-cli/src/commands/secret/delete.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/secret/delete.ts)_
|
||||||
|
|
||||||
## `eas secret:list`
|
## `eas secret:list`
|
||||||
|
|
||||||
@@ -1223,7 +1223,7 @@ DESCRIPTION
|
|||||||
list environment secrets available for your current app
|
list environment secrets available for your current app
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/secret/list.ts)_
|
_See code: [packages/eas-cli/src/commands/secret/list.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/secret/list.ts)_
|
||||||
|
|
||||||
## `eas secret:push`
|
## `eas secret:push`
|
||||||
|
|
||||||
@@ -1243,7 +1243,7 @@ DESCRIPTION
|
|||||||
read environment secrets from env file and store on the server
|
read environment secrets from env file and store on the server
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/secret/push.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/secret/push.ts)_
|
_See code: [packages/eas-cli/src/commands/secret/push.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/secret/push.ts)_
|
||||||
|
|
||||||
## `eas submit`
|
## `eas submit`
|
||||||
|
|
||||||
@@ -1274,7 +1274,7 @@ ALIASES
|
|||||||
$ eas build:submit
|
$ eas build:submit
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/submit.ts)_
|
_See code: [packages/eas-cli/src/commands/submit.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/submit.ts)_
|
||||||
|
|
||||||
## `eas update`
|
## `eas update`
|
||||||
|
|
||||||
@@ -1282,9 +1282,9 @@ publish an update group
|
|||||||
|
|
||||||
```
|
```
|
||||||
USAGE
|
USAGE
|
||||||
$ eas update [--branch <value>] [--channel <value>] [-m <value>] [--republish | --input-dir <value> |
|
$ eas update [--branch <value>] [--channel <value>] [-m <value>] [--input-dir <value>] [--skip-bundler]
|
||||||
--skip-bundler] [--group <value> | | ] [--clear-cache] [-p android|ios|all] [--auto] [--private-key-path <value>]
|
[--clear-cache] [--emit-metadata] [-p android|ios|all] [--auto] [--private-key-path <value>] [--json
|
||||||
[--json --non-interactive]
|
--non-interactive]
|
||||||
|
|
||||||
FLAGS
|
FLAGS
|
||||||
-m, --message=<value> A short message describing the update
|
-m, --message=<value> A short message describing the update
|
||||||
@@ -1293,7 +1293,8 @@ FLAGS
|
|||||||
--branch=<value> Branch to publish the update group on
|
--branch=<value> Branch to publish the update group on
|
||||||
--channel=<value> Channel that the published update should affect
|
--channel=<value> Channel that the published update should affect
|
||||||
--clear-cache Clear the bundler cache before publishing
|
--clear-cache Clear the bundler cache before publishing
|
||||||
--group=<value> Update group to republish (deprecated, see republish command)
|
--emit-metadata Emit "eas-update-metadata.json" in the bundle folder with detailed information about
|
||||||
|
the generated updates
|
||||||
--input-dir=<value> [default: dist] Location of the bundle
|
--input-dir=<value> [default: dist] Location of the bundle
|
||||||
--json Enable JSON output, non-JSON messages will be printed to stderr.
|
--json Enable JSON output, non-JSON messages will be printed to stderr.
|
||||||
--non-interactive Run the command in non-interactive mode.
|
--non-interactive Run the command in non-interactive mode.
|
||||||
@@ -1301,14 +1302,13 @@ FLAGS
|
|||||||
expo-updates' configuration. Defaults to a file named "private-key.pem" in the
|
expo-updates' configuration. Defaults to a file named "private-key.pem" in the
|
||||||
certificate's directory. Only relevant if you are using code signing:
|
certificate's directory. Only relevant if you are using code signing:
|
||||||
https://docs.expo.dev/eas-update/code-signing/
|
https://docs.expo.dev/eas-update/code-signing/
|
||||||
--republish Republish an update group (deprecated, see republish command)
|
|
||||||
--skip-bundler Skip running Expo CLI to bundle the app before publishing
|
--skip-bundler Skip running Expo CLI to bundle the app before publishing
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
publish an update group
|
publish an update group
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/update/index.ts)_
|
_See code: [packages/eas-cli/src/commands/update/index.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/update/index.ts)_
|
||||||
|
|
||||||
## `eas update:configure`
|
## `eas update:configure`
|
||||||
|
|
||||||
@@ -1326,7 +1326,7 @@ DESCRIPTION
|
|||||||
configure the project to support EAS Update
|
configure the project to support EAS Update
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/update/configure.ts)_
|
_See code: [packages/eas-cli/src/commands/update/configure.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/update/configure.ts)_
|
||||||
|
|
||||||
## `eas update:delete GROUPID`
|
## `eas update:delete GROUPID`
|
||||||
|
|
||||||
@@ -1347,7 +1347,7 @@ DESCRIPTION
|
|||||||
delete all the updates in an update group
|
delete all the updates in an update group
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/update/delete.ts)_
|
_See code: [packages/eas-cli/src/commands/update/delete.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/update/delete.ts)_
|
||||||
|
|
||||||
## `eas update:list`
|
## `eas update:list`
|
||||||
|
|
||||||
@@ -1369,7 +1369,7 @@ DESCRIPTION
|
|||||||
view the recent updates
|
view the recent updates
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/update/list.ts)_
|
_See code: [packages/eas-cli/src/commands/update/list.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/update/list.ts)_
|
||||||
|
|
||||||
## `eas update:republish`
|
## `eas update:republish`
|
||||||
|
|
||||||
@@ -1397,7 +1397,7 @@ DESCRIPTION
|
|||||||
roll back to an existing update
|
roll back to an existing update
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/update/republish.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/update/republish.ts)_
|
_See code: [packages/eas-cli/src/commands/update/republish.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/update/republish.ts)_
|
||||||
|
|
||||||
## `eas update:roll-back-to-embedded`
|
## `eas update:roll-back-to-embedded`
|
||||||
|
|
||||||
@@ -1425,7 +1425,7 @@ DESCRIPTION
|
|||||||
roll back to the embedded update
|
roll back to the embedded update
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/update/roll-back-to-embedded.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/update/roll-back-to-embedded.ts)_
|
_See code: [packages/eas-cli/src/commands/update/roll-back-to-embedded.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/update/roll-back-to-embedded.ts)_
|
||||||
|
|
||||||
## `eas update:rollback`
|
## `eas update:rollback`
|
||||||
|
|
||||||
@@ -1445,7 +1445,7 @@ DESCRIPTION
|
|||||||
roll back to an embedded update or an existing update
|
roll back to an embedded update or an existing update
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/update/rollback.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/update/rollback.ts)_
|
_See code: [packages/eas-cli/src/commands/update/rollback.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/update/rollback.ts)_
|
||||||
|
|
||||||
## `eas update:view GROUPID`
|
## `eas update:view GROUPID`
|
||||||
|
|
||||||
@@ -1465,7 +1465,7 @@ DESCRIPTION
|
|||||||
update group details
|
update group details
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/update/view.ts)_
|
_See code: [packages/eas-cli/src/commands/update/view.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/update/view.ts)_
|
||||||
|
|
||||||
## `eas webhook:create`
|
## `eas webhook:create`
|
||||||
|
|
||||||
@@ -1486,7 +1486,7 @@ DESCRIPTION
|
|||||||
create a webhook
|
create a webhook
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/webhook/create.ts)_
|
_See code: [packages/eas-cli/src/commands/webhook/create.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/webhook/create.ts)_
|
||||||
|
|
||||||
## `eas webhook:delete [ID]`
|
## `eas webhook:delete [ID]`
|
||||||
|
|
||||||
@@ -1506,7 +1506,7 @@ DESCRIPTION
|
|||||||
delete a webhook
|
delete a webhook
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/webhook/delete.ts)_
|
_See code: [packages/eas-cli/src/commands/webhook/delete.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/webhook/delete.ts)_
|
||||||
|
|
||||||
## `eas webhook:list`
|
## `eas webhook:list`
|
||||||
|
|
||||||
@@ -1524,7 +1524,7 @@ DESCRIPTION
|
|||||||
list webhooks
|
list webhooks
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/webhook/list.ts)_
|
_See code: [packages/eas-cli/src/commands/webhook/list.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/webhook/list.ts)_
|
||||||
|
|
||||||
## `eas webhook:update`
|
## `eas webhook:update`
|
||||||
|
|
||||||
@@ -1546,7 +1546,7 @@ DESCRIPTION
|
|||||||
update a webhook
|
update a webhook
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/webhook/update.ts)_
|
_See code: [packages/eas-cli/src/commands/webhook/update.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/webhook/update.ts)_
|
||||||
|
|
||||||
## `eas webhook:view ID`
|
## `eas webhook:view ID`
|
||||||
|
|
||||||
@@ -1563,7 +1563,7 @@ DESCRIPTION
|
|||||||
view a webhook
|
view a webhook
|
||||||
```
|
```
|
||||||
|
|
||||||
_See code: [packages/eas-cli/src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v10.0.2/packages/eas-cli/src/commands/webhook/view.ts)_
|
_See code: [packages/eas-cli/src/commands/webhook/view.ts](https://github.com/expo/eas-cli/blob/v11.0.1/packages/eas-cli/src/commands/webhook/view.ts)_
|
||||||
|
|
||||||
## `eas whoami`
|
## `eas whoami`
|
||||||
|
|
||||||
|
|||||||
Generated
+5303
-297
File diff suppressed because it is too large.
Load diff
@@ -1,34 +1,34 @@
|
|||||||
{
|
{
|
||||||
"name": "eas-cli",
|
"name": "eas-cli",
|
||||||
"description": "EAS command line tool",
|
"description": "EAS command line tool",
|
||||||
"version": "10.0.2",
|
"version": "11.0.1",
|
||||||
"author": "Expo <[email protected]>",
|
"author": "Expo <[email protected]>",
|
||||||
"bin": {
|
"bin": {
|
||||||
"eas": "./bin/run"
|
"eas": "./bin/run"
|
||||||
},
|
},
|
||||||
"bugs": "https://github.com/expo/eas-cli/issues",
|
"bugs": "https://github.com/expo/eas-cli/issues",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@expo/apple-utils": "1.7.0",
|
"@expo/apple-utils": "1.7.1",
|
||||||
"@expo/code-signing-certificates": "0.0.5",
|
"@expo/code-signing-certificates": "0.0.5",
|
||||||
"@expo/config": "8.5.4",
|
"@expo/config": "9.0.3",
|
||||||
"@expo/config-plugins": "7.8.4",
|
"@expo/config-plugins": "8.0.8",
|
||||||
"@expo/config-types": "50.0.0",
|
"@expo/config-types": "51.0.2",
|
||||||
"@expo/eas-build-job": "1.0.117",
|
"@expo/eas-build-job": "1.0.133",
|
||||||
"@expo/eas-json": "10.0.0",
|
"@expo/eas-json": "11.0.0",
|
||||||
"@expo/json-file": "8.2.37",
|
"@expo/json-file": "8.3.3",
|
||||||
"@expo/logger": "1.0.117",
|
"@expo/logger": "1.0.117",
|
||||||
"@expo/multipart-body-parser": "1.1.0",
|
"@expo/multipart-body-parser": "1.1.0",
|
||||||
"@expo/osascript": "2.0.33",
|
"@expo/osascript": "2.1.3",
|
||||||
"@expo/package-manager": "1.1.2",
|
"@expo/package-manager": "1.5.2",
|
||||||
"@expo/pkcs12": "0.0.8",
|
"@expo/pkcs12": "0.1.2",
|
||||||
"@expo/plist": "0.0.20",
|
"@expo/plist": "0.1.3",
|
||||||
"@expo/plugin-help": "5.1.23",
|
"@expo/plugin-help": "5.1.23",
|
||||||
"@expo/plugin-warn-if-update-available": "2.5.1",
|
"@expo/plugin-warn-if-update-available": "2.5.1",
|
||||||
"@expo/prebuild-config": "6.7.3",
|
"@expo/prebuild-config": "7.0.8",
|
||||||
"@expo/results": "1.0.0",
|
"@expo/results": "1.0.0",
|
||||||
"@expo/rudder-sdk-node": "1.1.1",
|
"@expo/rudder-sdk-node": "1.1.1",
|
||||||
"@expo/spawn-async": "1.7.0",
|
"@expo/spawn-async": "1.7.2",
|
||||||
"@expo/steps": "1.0.118",
|
"@expo/steps": "1.0.130",
|
||||||
"@expo/timeago.js": "1.0.0",
|
"@expo/timeago.js": "1.0.0",
|
||||||
"@oclif/core": "^1.26.2",
|
"@oclif/core": "^1.26.2",
|
||||||
"@oclif/plugin-autocomplete": "^2.3.10",
|
"@oclif/plugin-autocomplete": "^2.3.10",
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
"@types/tough-cookie": "4.0.2",
|
"@types/tough-cookie": "4.0.2",
|
||||||
"@types/uuid": "9.0.7",
|
"@types/uuid": "9.0.7",
|
||||||
"@types/wrap-ansi": "3.0.0",
|
"@types/wrap-ansi": "3.0.0",
|
||||||
"axios": "0.27.2",
|
"axios": "0.28.1",
|
||||||
"eslint-plugin-graphql": "4.0.0",
|
"eslint-plugin-graphql": "4.0.0",
|
||||||
"express": "4.19.2",
|
"express": "4.19.2",
|
||||||
"memfs": "3.4.13",
|
"memfs": "3.4.13",
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: ['universe/shared/typescript-analysis'],
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ['*.ts', '*.d.ts'],
|
||||||
|
parserOptions: {
|
||||||
|
project: './packages/eas-cli/tsconfig.json',
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/explicit-function-return-type': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
allowExpressions: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'@typescript-eslint/prefer-nullish-coalescing': ['warn', { ignorePrimitives: true }],
|
||||||
|
'@typescript-eslint/no-confusing-void-expression': 'warn',
|
||||||
|
'@typescript-eslint/await-thenable': 'error',
|
||||||
|
'@typescript-eslint/no-misused-promises': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
checksVoidReturn: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'@typescript-eslint/no-floating-promises': 'error',
|
||||||
|
'no-void': ['warn', { allowAsStatement: true }],
|
||||||
|
'no-return-await': 'off',
|
||||||
|
'@typescript-eslint/return-await': ['error', 'always'],
|
||||||
|
'@typescript-eslint/no-confusing-non-null-assertion': 'warn',
|
||||||
|
'@typescript-eslint/no-extra-non-null-assertion': 'warn',
|
||||||
|
'@typescript-eslint/prefer-as-const': 'warn',
|
||||||
|
'@typescript-eslint/prefer-includes': 'warn',
|
||||||
|
'@typescript-eslint/prefer-readonly': 'warn',
|
||||||
|
'@typescript-eslint/prefer-string-starts-ends-with': 'warn',
|
||||||
|
'@typescript-eslint/prefer-ts-expect-error': 'warn',
|
||||||
|
'@typescript-eslint/no-unnecessary-type-assertion': 'warn',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
@@ -28,7 +28,7 @@ import {
|
|||||||
*/
|
*/
|
||||||
export class SelectBranch implements EASUpdateAction<UpdateBranchBasicInfoFragment | null> {
|
export class SelectBranch implements EASUpdateAction<UpdateBranchBasicInfoFragment | null> {
|
||||||
constructor(
|
constructor(
|
||||||
private options: {
|
private readonly options: {
|
||||||
filterPredicate?: (branchInfo: UpdateBranchBasicInfoFragment) => boolean;
|
filterPredicate?: (branchInfo: UpdateBranchBasicInfoFragment) => boolean;
|
||||||
printedType?: string;
|
printedType?: string;
|
||||||
pageSize?: number;
|
pageSize?: number;
|
||||||
@@ -91,8 +91,8 @@ export class SelectBranch implements EASUpdateAction<UpdateBranchBasicInfoFragme
|
|||||||
queryParams: QueryParams
|
queryParams: QueryParams
|
||||||
): Promise<Connection<UpdateBranchBasicInfoFragment>> =>
|
): Promise<Connection<UpdateBranchBasicInfoFragment>> =>
|
||||||
filterPredicate
|
filterPredicate
|
||||||
? this.filterQueryAsync(ctx, queryParams, filterPredicate)
|
? await this.filterQueryAsync(ctx, queryParams, filterPredicate)
|
||||||
: this.queryAsync(ctx, queryParams);
|
: await this.queryAsync(ctx, queryParams);
|
||||||
|
|
||||||
const getTitleAsync = async (branchInfo: UpdateBranchBasicInfoFragment): Promise<string> =>
|
const getTitleAsync = async (branchInfo: UpdateBranchBasicInfoFragment): Promise<string> =>
|
||||||
branchInfo.name;
|
branchInfo.name;
|
||||||
|
|||||||
@@ -84,7 +84,9 @@ export async function listAndRenderBranchesOnAppAsync(
|
|||||||
queryBranchesOnProjectAsync(graphqlClient, limit, offset, projectId),
|
queryBranchesOnProjectAsync(graphqlClient, limit, offset, projectId),
|
||||||
promptOptions: {
|
promptOptions: {
|
||||||
title: 'Load more branches?',
|
title: 'Load more branches?',
|
||||||
renderListItems: branches => renderPageOfBranches(branches, paginatedQueryOptions),
|
renderListItems: branches => {
|
||||||
|
renderPageOfBranches(branches, paginatedQueryOptions);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,14 +47,14 @@ describe(selectBuildToCancelAsync.name, () => {
|
|||||||
it('does not return build id when confirmation is rejected', async () => {
|
it('does not return build id when confirmation is rejected', async () => {
|
||||||
const graphqlClient = instance(mock<ExpoGraphqlClient>());
|
const graphqlClient = instance(mock<ExpoGraphqlClient>());
|
||||||
jest.mocked(confirmAsync).mockResolvedValueOnce(false);
|
jest.mocked(confirmAsync).mockResolvedValueOnce(false);
|
||||||
expect(selectBuildToCancelAsync(graphqlClient, projectId, 'blah')).resolves.toEqual(null);
|
await expect(selectBuildToCancelAsync(graphqlClient, projectId, 'blah')).resolves.toEqual(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns build id when confirmation is confirmed', async () => {
|
it('returns build id when confirmation is confirmed', async () => {
|
||||||
const graphqlClient = instance(mock<ExpoGraphqlClient>());
|
const graphqlClient = instance(mock<ExpoGraphqlClient>());
|
||||||
jest.mocked(selectAsync).mockResolvedValueOnce(selectedBuildId);
|
jest.mocked(selectAsync).mockResolvedValueOnce(selectedBuildId);
|
||||||
jest.mocked(confirmAsync).mockResolvedValueOnce(true);
|
jest.mocked(confirmAsync).mockResolvedValueOnce(true);
|
||||||
expect(selectBuildToCancelAsync(graphqlClient, projectId, 'blah')).resolves.toEqual(
|
await expect(selectBuildToCancelAsync(graphqlClient, projectId, 'blah')).resolves.toEqual(
|
||||||
selectedBuildId
|
selectedBuildId
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -47,14 +47,14 @@ describe(selectBuildToDeleteAsync.name, () => {
|
|||||||
it('does not return build id when confirmation is rejected', async () => {
|
it('does not return build id when confirmation is rejected', async () => {
|
||||||
const graphqlClient = instance(mock<ExpoGraphqlClient>());
|
const graphqlClient = instance(mock<ExpoGraphqlClient>());
|
||||||
jest.mocked(confirmAsync).mockResolvedValueOnce(false);
|
jest.mocked(confirmAsync).mockResolvedValueOnce(false);
|
||||||
expect(selectBuildToDeleteAsync(graphqlClient, projectId, 'blah')).resolves.toEqual(null);
|
await expect(selectBuildToDeleteAsync(graphqlClient, projectId, 'blah')).resolves.toEqual(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns build id when confirmation is confirmed', async () => {
|
it('returns build id when confirmation is confirmed', async () => {
|
||||||
const graphqlClient = instance(mock<ExpoGraphqlClient>());
|
const graphqlClient = instance(mock<ExpoGraphqlClient>());
|
||||||
jest.mocked(selectAsync).mockResolvedValueOnce(selectedBuildId);
|
jest.mocked(selectAsync).mockResolvedValueOnce(selectedBuildId);
|
||||||
jest.mocked(confirmAsync).mockResolvedValueOnce(true);
|
jest.mocked(confirmAsync).mockResolvedValueOnce(true);
|
||||||
expect(selectBuildToDeleteAsync(graphqlClient, projectId, 'blah')).resolves.toEqual(
|
await expect(selectBuildToDeleteAsync(graphqlClient, projectId, 'blah')).resolves.toEqual(
|
||||||
selectedBuildId
|
selectedBuildId
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export async function bumpVersionAsync({
|
|||||||
|
|
||||||
const buildGradle = await getAppBuildGradleAsync(projectDir);
|
const buildGradle = await getAppBuildGradleAsync(projectDir);
|
||||||
const isMultiFlavor =
|
const isMultiFlavor =
|
||||||
buildGradle.android?.productFlavors || buildGradle.android?.flavorDimensions;
|
buildGradle.android?.productFlavors ?? buildGradle.android?.flavorDimensions;
|
||||||
if (isMultiFlavor) {
|
if (isMultiFlavor) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Automatic version bumping is not supported for multi-flavor Android projects.'
|
'Automatic version bumping is not supported for multi-flavor Android projects.'
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import {
|
|||||||
ArchiveSource,
|
ArchiveSource,
|
||||||
ArchiveSourceType,
|
ArchiveSourceType,
|
||||||
BuildJob,
|
BuildJob,
|
||||||
|
FingerprintSourceType,
|
||||||
Metadata,
|
Metadata,
|
||||||
Platform,
|
Platform,
|
||||||
} from '@expo/eas-build-job';
|
} from '@expo/eas-build-job';
|
||||||
@@ -12,6 +13,8 @@ import cliProgress from 'cli-progress';
|
|||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import { GraphQLError } from 'graphql/error';
|
import { GraphQLError } from 'graphql/error';
|
||||||
import nullthrows from 'nullthrows';
|
import nullthrows from 'nullthrows';
|
||||||
|
import path from 'path';
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
import { BuildContext } from './context';
|
import { BuildContext } from './context';
|
||||||
import {
|
import {
|
||||||
@@ -56,13 +59,16 @@ import { BuildQuery } from '../graphql/queries/BuildQuery';
|
|||||||
import Log, { learnMore, link } from '../log';
|
import Log, { learnMore, link } from '../log';
|
||||||
import { Ora, ora } from '../ora';
|
import { Ora, ora } from '../ora';
|
||||||
import {
|
import {
|
||||||
|
RequestedPlatform,
|
||||||
appPlatformDisplayNames,
|
appPlatformDisplayNames,
|
||||||
appPlatformEmojis,
|
appPlatformEmojis,
|
||||||
requestedPlatformDisplayNames,
|
requestedPlatformDisplayNames,
|
||||||
} from '../platform';
|
} from '../platform';
|
||||||
|
import { resolveRuntimeVersionAsync } from '../project/resolveRuntimeVersionAsync';
|
||||||
import { uploadFileAtPathToGCSAsync } from '../uploads';
|
import { uploadFileAtPathToGCSAsync } from '../uploads';
|
||||||
import { formatBytes } from '../utils/files';
|
import { formatBytes } from '../utils/files';
|
||||||
import { printJsonOnlyOutput } from '../utils/json';
|
import { printJsonOnlyOutput } from '../utils/json';
|
||||||
|
import { getTmpDirectory } from '../utils/paths';
|
||||||
import { createProgressTracker } from '../utils/progress';
|
import { createProgressTracker } from '../utils/progress';
|
||||||
import { sleepAsync } from '../utils/promise';
|
import { sleepAsync } from '../utils/promise';
|
||||||
|
|
||||||
@@ -124,7 +130,9 @@ export async function prepareBuildRequestForPlatformAsync<
|
|||||||
|
|
||||||
await withAnalyticsAsync(
|
await withAnalyticsAsync(
|
||||||
ctx.analytics,
|
ctx.analytics,
|
||||||
async () => await builder.syncProjectConfigurationAsync(ctx),
|
async () => {
|
||||||
|
await builder.syncProjectConfigurationAsync(ctx);
|
||||||
|
},
|
||||||
{
|
{
|
||||||
attemptEvent: BuildEvent.CONFIGURE_PROJECT_ATTEMPT,
|
attemptEvent: BuildEvent.CONFIGURE_PROJECT_ATTEMPT,
|
||||||
successEvent: BuildEvent.CONFIGURE_PROJECT_SUCCESS,
|
successEvent: BuildEvent.CONFIGURE_PROJECT_SUCCESS,
|
||||||
@@ -135,9 +143,15 @@ export async function prepareBuildRequestForPlatformAsync<
|
|||||||
|
|
||||||
if (await ctx.vcsClient.isCommitRequiredAsync()) {
|
if (await ctx.vcsClient.isCommitRequiredAsync()) {
|
||||||
Log.addNewLineIfNone();
|
Log.addNewLineIfNone();
|
||||||
|
const platformToRequestedPlatform: Record<Platform, RequestedPlatform> = {
|
||||||
|
[Platform.ANDROID]: RequestedPlatform.Android,
|
||||||
|
[Platform.IOS]: RequestedPlatform.Ios,
|
||||||
|
};
|
||||||
await reviewAndCommitChangesAsync(
|
await reviewAndCommitChangesAsync(
|
||||||
ctx.vcsClient,
|
ctx.vcsClient,
|
||||||
`[EAS Build] Run EAS Build for ${requestedPlatformDisplayNames[ctx.platform as Platform]}`,
|
`[EAS Build] Run EAS Build for ${
|
||||||
|
requestedPlatformDisplayNames[platformToRequestedPlatform[ctx.platform]]
|
||||||
|
}`,
|
||||||
{ nonInteractive: ctx.nonInteractive }
|
{ nonInteractive: ctx.nonInteractive }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -162,7 +176,8 @@ export async function prepareBuildRequestForPlatformAsync<
|
|||||||
}
|
}
|
||||||
assert(projectArchive);
|
assert(projectArchive);
|
||||||
|
|
||||||
const metadata = await collectMetadataAsync(ctx);
|
const runtimeMetadata = await createAndMaybeUploadFingerprintAsync(ctx);
|
||||||
|
const metadata = await collectMetadataAsync(ctx, runtimeMetadata);
|
||||||
const buildParams = resolveBuildParamsInput(ctx, metadata);
|
const buildParams = resolveBuildParamsInput(ctx, metadata);
|
||||||
const job = await builder.prepareJobAsync(ctx, {
|
const job = await builder.prepareJobAsync(ctx, {
|
||||||
projectArchive,
|
projectArchive,
|
||||||
@@ -649,3 +664,83 @@ function formatAccountSubscriptionsUrl(accountName: string): string {
|
|||||||
getExpoWebsiteBaseUrl()
|
getExpoWebsiteBaseUrl()
|
||||||
).toString();
|
).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function createAndMaybeUploadFingerprintAsync<T extends Platform>(
|
||||||
|
ctx: BuildContext<T>
|
||||||
|
): Promise<{
|
||||||
|
runtimeVersion?: string;
|
||||||
|
fingerprintSource?: Metadata['fingerprintSource'];
|
||||||
|
}> {
|
||||||
|
const resolvedRuntimeVersion = await resolveRuntimeVersionAsync({
|
||||||
|
exp: ctx.exp,
|
||||||
|
platform: ctx.platform,
|
||||||
|
workflow: ctx.workflow,
|
||||||
|
projectDir: ctx.projectDir,
|
||||||
|
env: ctx.buildProfile.env,
|
||||||
|
cwd: ctx.projectDir,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!resolvedRuntimeVersion) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It's ok for fingerprintSources to be empty
|
||||||
|
* fingerprintSources only exist if the project is using runtimeVersion.policy: fingerprint
|
||||||
|
*/
|
||||||
|
if (!resolvedRuntimeVersion.fingerprint) {
|
||||||
|
return {
|
||||||
|
runtimeVersion: resolvedRuntimeVersion.runtimeVersion ?? undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
await fs.mkdirp(getTmpDirectory());
|
||||||
|
const fingerprintLocation = path.join(getTmpDirectory(), `${uuidv4()}-runtime-fingerprint.json`);
|
||||||
|
|
||||||
|
await fs.writeJSON(fingerprintLocation, {
|
||||||
|
hash: resolvedRuntimeVersion.runtimeVersion,
|
||||||
|
sources: resolvedRuntimeVersion.fingerprint.fingerprintSources,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (ctx.localBuildOptions.localBuildMode === LocalBuildMode.LOCAL_BUILD_PLUGIN) {
|
||||||
|
return {
|
||||||
|
runtimeVersion: resolvedRuntimeVersion.runtimeVersion ?? undefined,
|
||||||
|
fingerprintSource: {
|
||||||
|
type: FingerprintSourceType.PATH,
|
||||||
|
path: fingerprintLocation,
|
||||||
|
isDebugFingerprint: resolvedRuntimeVersion.fingerprint.isDebugFingerprintSource,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let fingerprintGCSBucketKey = undefined;
|
||||||
|
try {
|
||||||
|
fingerprintGCSBucketKey = await uploadFileAtPathToGCSAsync(
|
||||||
|
ctx.graphqlClient,
|
||||||
|
UploadSessionType.EasUpdateFingerprint,
|
||||||
|
fingerprintLocation
|
||||||
|
);
|
||||||
|
} catch (err: any) {
|
||||||
|
let errMessage = 'Failed to upload fingerprint to EAS';
|
||||||
|
|
||||||
|
if (err.message) {
|
||||||
|
errMessage += `\n\nReason: ${err.message}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.warn(errMessage);
|
||||||
|
return {
|
||||||
|
runtimeVersion: resolvedRuntimeVersion.runtimeVersion ?? undefined,
|
||||||
|
};
|
||||||
|
} finally {
|
||||||
|
await fs.remove(fingerprintLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
runtimeVersion: resolvedRuntimeVersion.runtimeVersion ?? undefined,
|
||||||
|
fingerprintSource: {
|
||||||
|
type: FingerprintSourceType.GCS,
|
||||||
|
bucketKey: fingerprintGCSBucketKey,
|
||||||
|
isDebugFingerprint: resolvedRuntimeVersion.fingerprint.isDebugFingerprintSource,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ import { v4 as uuidv4 } from 'uuid';
|
|||||||
import { createAndroidContextAsync } from './android/build';
|
import { createAndroidContextAsync } from './android/build';
|
||||||
import { BuildContext, CommonContext } from './context';
|
import { BuildContext, CommonContext } from './context';
|
||||||
import { createIosContextAsync } from './ios/build';
|
import { createIosContextAsync } from './ios/build';
|
||||||
import { LocalBuildOptions } from './local';
|
import { LocalBuildMode, LocalBuildOptions } from './local';
|
||||||
import { resolveBuildResourceClassAsync } from './utils/resourceClass';
|
import { resolveBuildResourceClassAsync } from './utils/resourceClass';
|
||||||
import { Analytics, AnalyticsEventProperties, BuildEvent } from '../analytics/AnalyticsManager';
|
import { Analytics, AnalyticsEventProperties, BuildEvent } from '../analytics/AnalyticsManager';
|
||||||
import { DynamicConfigContextFn } from '../commandUtils/context/DynamicProjectConfigContextField';
|
import { DynamicConfigContextFn } from '../commandUtils/context/DynamicProjectConfigContextField';
|
||||||
@@ -108,6 +108,7 @@ export async function createBuildContextAsync<T extends Platform>({
|
|||||||
...devClientProperties,
|
...devClientProperties,
|
||||||
no_wait: noWait,
|
no_wait: noWait,
|
||||||
run_from_ci: runFromCI,
|
run_from_ci: runFromCI,
|
||||||
|
local: localBuildOptions.localBuildMode === LocalBuildMode.LOCAL_BUILD_PLUGIN,
|
||||||
};
|
};
|
||||||
analytics.logEvent(BuildEvent.BUILD_COMMAND, analyticsEventProperties);
|
analytics.logEvent(BuildEvent.BUILD_COMMAND, analyticsEventProperties);
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ export function transformProjectArchive(archiveSource: ArchiveSource): ProjectAr
|
|||||||
export function transformMetadata(metadata: Metadata): BuildMetadataInput {
|
export function transformMetadata(metadata: Metadata): BuildMetadataInput {
|
||||||
return {
|
return {
|
||||||
...metadata,
|
...metadata,
|
||||||
|
fingerprintSource: metadata.fingerprintSource as BuildMetadataInput['fingerprintSource'],
|
||||||
credentialsSource:
|
credentialsSource:
|
||||||
metadata.credentialsSource && transformCredentialsSource(metadata.credentialsSource),
|
metadata.credentialsSource && transformCredentialsSource(metadata.credentialsSource),
|
||||||
distribution: metadata.distribution && transformDistribution(metadata.distribution),
|
distribution: metadata.distribution && transformDistribution(metadata.distribution),
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ export async function prepareIosBuildAsync(
|
|||||||
return await prepareBuildRequestForPlatformAsync({
|
return await prepareBuildRequestForPlatformAsync({
|
||||||
ctx,
|
ctx,
|
||||||
ensureCredentialsAsync: async (ctx: BuildContext<Platform.IOS>) => {
|
ensureCredentialsAsync: async (ctx: BuildContext<Platform.IOS>) => {
|
||||||
return ensureIosCredentialsAsync(ctx, ctx.ios.targets);
|
return await ensureIosCredentialsAsync(ctx, ctx.ios.targets);
|
||||||
},
|
},
|
||||||
syncProjectConfigurationAsync: async () => {
|
syncProjectConfigurationAsync: async () => {
|
||||||
await syncProjectConfigurationAsync({
|
await syncProjectConfigurationAsync({
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import semver from 'semver';
|
|||||||
import { ora } from '../ora';
|
import { ora } from '../ora';
|
||||||
|
|
||||||
const PLUGIN_PACKAGE_NAME = 'eas-cli-local-build-plugin';
|
const PLUGIN_PACKAGE_NAME = 'eas-cli-local-build-plugin';
|
||||||
const PLUGIN_PACKAGE_VERSION = '1.0.118';
|
const PLUGIN_PACKAGE_VERSION = '1.0.131';
|
||||||
|
|
||||||
export enum LocalBuildMode {
|
export enum LocalBuildMode {
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Metadata, Platform, sanitizeMetadata } from '@expo/eas-build-job';
|
import { FingerprintSource, Metadata, Platform, sanitizeMetadata } from '@expo/eas-build-job';
|
||||||
import { IosEnterpriseProvisioning } from '@expo/eas-json';
|
import { IosEnterpriseProvisioning } from '@expo/eas-json';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import resolveFrom from 'resolve-from';
|
import resolveFrom from 'resolve-from';
|
||||||
@@ -10,13 +10,16 @@ import { LocalBuildMode } from './local';
|
|||||||
import { BuildDistributionType } from './types';
|
import { BuildDistributionType } from './types';
|
||||||
import Log from '../log';
|
import Log from '../log';
|
||||||
import { getUsername, isExpoUpdatesInstalled } from '../project/projectUtils';
|
import { getUsername, isExpoUpdatesInstalled } from '../project/projectUtils';
|
||||||
import { resolveRuntimeVersionAsync } from '../project/resolveRuntimeVersionAsync';
|
|
||||||
import { readChannelSafelyAsync as readAndroidChannelSafelyAsync } from '../update/android/UpdatesModule';
|
import { readChannelSafelyAsync as readAndroidChannelSafelyAsync } from '../update/android/UpdatesModule';
|
||||||
import { readChannelSafelyAsync as readIosChannelSafelyAsync } from '../update/ios/UpdatesModule';
|
import { readChannelSafelyAsync as readIosChannelSafelyAsync } from '../update/ios/UpdatesModule';
|
||||||
import { easCliVersion } from '../utils/easCli';
|
import { easCliVersion } from '../utils/easCli';
|
||||||
|
|
||||||
export async function collectMetadataAsync<T extends Platform>(
|
export async function collectMetadataAsync<T extends Platform>(
|
||||||
ctx: BuildContext<T>
|
ctx: BuildContext<T>,
|
||||||
|
runtimeMetadata: {
|
||||||
|
runtimeVersion?: string | undefined;
|
||||||
|
fingerprintSource?: FingerprintSource | undefined;
|
||||||
|
}
|
||||||
): Promise<Metadata> {
|
): Promise<Metadata> {
|
||||||
const channelObject = await resolveChannelAsync(ctx);
|
const channelObject = await resolveChannelAsync(ctx);
|
||||||
const distribution = ctx.buildProfile.distribution ?? BuildDistributionType.STORE;
|
const distribution = ctx.buildProfile.distribution ?? BuildDistributionType.STORE;
|
||||||
@@ -27,15 +30,8 @@ export async function collectMetadataAsync<T extends Platform>(
|
|||||||
workflow: ctx.workflow,
|
workflow: ctx.workflow,
|
||||||
credentialsSource: ctx.buildProfile.credentialsSource,
|
credentialsSource: ctx.buildProfile.credentialsSource,
|
||||||
sdkVersion: ctx.exp.sdkVersion,
|
sdkVersion: ctx.exp.sdkVersion,
|
||||||
runtimeVersion:
|
runtimeVersion: runtimeMetadata?.runtimeVersion,
|
||||||
(await resolveRuntimeVersionAsync({
|
fingerprintSource: runtimeMetadata?.fingerprintSource,
|
||||||
exp: ctx.exp,
|
|
||||||
platform: ctx.platform,
|
|
||||||
workflow: ctx.workflow,
|
|
||||||
projectDir: ctx.projectDir,
|
|
||||||
env: ctx.buildProfile.env,
|
|
||||||
cwd: ctx.projectDir,
|
|
||||||
})) ?? undefined,
|
|
||||||
reactNativeVersion: await getReactNativeVersionAsync(ctx.projectDir),
|
reactNativeVersion: await getReactNativeVersionAsync(ctx.projectDir),
|
||||||
...channelObject,
|
...channelObject,
|
||||||
distribution,
|
distribution,
|
||||||
@@ -64,6 +60,7 @@ export async function collectMetadataAsync<T extends Platform>(
|
|||||||
requiredPackageManager: ctx.requiredPackageManager ?? undefined,
|
requiredPackageManager: ctx.requiredPackageManager ?? undefined,
|
||||||
selectedImage: ctx.buildProfile.image,
|
selectedImage: ctx.buildProfile.image,
|
||||||
customNodeVersion: ctx.buildProfile.node,
|
customNodeVersion: ctx.buildProfile.node,
|
||||||
|
environment: ctx.buildProfile.environment,
|
||||||
simulator: 'simulator' in ctx.buildProfile && ctx.buildProfile.simulator,
|
simulator: 'simulator' in ctx.buildProfile && ctx.buildProfile.simulator,
|
||||||
};
|
};
|
||||||
return sanitizeMetadata(metadata);
|
return sanitizeMetadata(metadata);
|
||||||
|
|||||||
@@ -50,8 +50,9 @@ export async function listAndRenderBuildsOnAppAsync(
|
|||||||
}),
|
}),
|
||||||
promptOptions: {
|
promptOptions: {
|
||||||
title: 'Load more builds?',
|
title: 'Load more builds?',
|
||||||
renderListItems: builds =>
|
renderListItems: builds => {
|
||||||
renderPageOfBuilds({ builds, projectDisplayName, paginatedQueryOptions }),
|
renderPageOfBuilds({ builds, projectDisplayName, paginatedQueryOptions });
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,6 +142,24 @@ export async function runBuildAndSubmitAsync(
|
|||||||
Log.warn(
|
Log.warn(
|
||||||
`The "image" field in the build profile "${buildProfile.profileName}" is set to "${buildProfile.profile.image}". This tag is deprecated and will be removed in the future. Use other images or tags listed here: https://docs.expo.dev/build-reference/infrastructure/`
|
`The "image" field in the build profile "${buildProfile.profileName}" is set to "${buildProfile.profile.image}". This tag is deprecated and will be removed in the future. Use other images or tags listed here: https://docs.expo.dev/build-reference/infrastructure/`
|
||||||
);
|
);
|
||||||
|
} else if (
|
||||||
|
buildProfile.profile.image &&
|
||||||
|
[
|
||||||
|
'ubuntu-20.04-jdk-11-ndk-r19c',
|
||||||
|
'ubuntu-20.04-jdk-8-ndk-r19c',
|
||||||
|
'ubuntu-20.04-jdk-11-ndk-r21e',
|
||||||
|
'ubuntu-20.04-jdk-8-ndk-r21e',
|
||||||
|
'ubuntu-22.04-jdk-8-ndk-r21e',
|
||||||
|
'ubuntu-20.04-jdk-11-ndk-r23b',
|
||||||
|
].includes(buildProfile.profile.image)
|
||||||
|
) {
|
||||||
|
Log.warn(
|
||||||
|
`The "image" field in the build profile "${buildProfile.profileName}" is set to "${
|
||||||
|
buildProfile.profile.image
|
||||||
|
}". This image is deprecated and will be removed on September 1st, 2024. ${learnMore(
|
||||||
|
'https://expo.dev/changelog/2024/07-12-eas-build-upcoming-android-images-updates'
|
||||||
|
)}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,9 @@ export function printBuildResults(builds: (BuildFragment | null)[]): void {
|
|||||||
assert(build, 'Build should be defined');
|
assert(build, 'Build should be defined');
|
||||||
printBuildResult(build);
|
printBuildResult(build);
|
||||||
} else {
|
} else {
|
||||||
(builds.filter(i => i) as BuildFragment[]).forEach(build => printBuildResult(build));
|
(builds.filter(i => i) as BuildFragment[]).forEach(build => {
|
||||||
|
printBuildResult(build);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,9 +99,9 @@ function printBuildResult(build: BuildFragment): void {
|
|||||||
// to the build details page and let people press the button to download there
|
// to the build details page and let people press the button to download there
|
||||||
const qrcodeUrl =
|
const qrcodeUrl =
|
||||||
build.platform === AppPlatform.Ios ? getInternalDistributionInstallUrl(build) : logsUrl;
|
build.platform === AppPlatform.Ios ? getInternalDistributionInstallUrl(build) : logsUrl;
|
||||||
qrcodeTerminal.generate(qrcodeUrl, { small: true }, code =>
|
qrcodeTerminal.generate(qrcodeUrl, { small: true }, code => {
|
||||||
Log.log(`${indentString(code, 2)}\n`)
|
Log.log(`${indentString(code, 2)}\n`);
|
||||||
);
|
});
|
||||||
Log.log(
|
Log.log(
|
||||||
`${appPlatformEmojis[build.platform]} Open this link on your ${
|
`${appPlatformEmojis[build.platform]} Open this link on your ${
|
||||||
appPlatformDisplayNames[build.platform]
|
appPlatformDisplayNames[build.platform]
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ export type LocalFile = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export async function makeProjectMetadataFileAsync(archivePath: string): Promise<LocalFile> {
|
export async function makeProjectMetadataFileAsync(archivePath: string): Promise<LocalFile> {
|
||||||
|
await fs.mkdirp(getTmpDirectory());
|
||||||
const metadataLocation = path.join(getTmpDirectory(), `${uuidv4()}-eas-build-metadata.json`);
|
const metadataLocation = path.join(getTmpDirectory(), `${uuidv4()}-eas-build-metadata.json`);
|
||||||
const archiveContent: string[] = [];
|
const archiveContent: string[] = [];
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ import {
|
|||||||
|
|
||||||
describe(assertVersion, () => {
|
describe(assertVersion, () => {
|
||||||
it('throws if the branch mapping is not the correct version', () => {
|
it('throws if the branch mapping is not the correct version', () => {
|
||||||
expect(() => assertVersion(testChannelBasicInfo, 5)).toThrowError(BranchMappingValidationError);
|
expect(() => {
|
||||||
|
assertVersion(testChannelBasicInfo, 5);
|
||||||
|
}).toThrowError(BranchMappingValidationError);
|
||||||
});
|
});
|
||||||
it('asserts the correct version', () => {
|
it('asserts the correct version', () => {
|
||||||
assertVersion(testChannelBasicInfo, 0);
|
assertVersion(testChannelBasicInfo, 0);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import {
|
|||||||
*/
|
*/
|
||||||
export class SelectChannel implements EASUpdateAction<UpdateChannelBasicInfoFragment | null> {
|
export class SelectChannel implements EASUpdateAction<UpdateChannelBasicInfoFragment | null> {
|
||||||
constructor(
|
constructor(
|
||||||
private options: {
|
private readonly options: {
|
||||||
filterPredicate?: (channelInfo: UpdateChannelBasicInfoFragment) => boolean;
|
filterPredicate?: (channelInfo: UpdateChannelBasicInfoFragment) => boolean;
|
||||||
printedType?: string;
|
printedType?: string;
|
||||||
pageSize?: number;
|
pageSize?: number;
|
||||||
@@ -91,8 +91,8 @@ export class SelectChannel implements EASUpdateAction<UpdateChannelBasicInfoFrag
|
|||||||
queryParams: QueryParams
|
queryParams: QueryParams
|
||||||
): Promise<Connection<UpdateChannelBasicInfoFragment>> =>
|
): Promise<Connection<UpdateChannelBasicInfoFragment>> =>
|
||||||
filterPredicate
|
filterPredicate
|
||||||
? this.filterQueryAsync(ctx, queryParams, filterPredicate)
|
? await this.filterQueryAsync(ctx, queryParams, filterPredicate)
|
||||||
: this.queryAsync(ctx, queryParams);
|
: await this.queryAsync(ctx, queryParams);
|
||||||
|
|
||||||
const getTitleAsync = async (channelInfo: UpdateChannelBasicInfoFragment): Promise<string> =>
|
const getTitleAsync = async (channelInfo: UpdateChannelBasicInfoFragment): Promise<string> =>
|
||||||
channelInfo.name;
|
channelInfo.name;
|
||||||
|
|||||||
@@ -89,7 +89,9 @@ export async function listAndRenderChannelsOnAppAsync(
|
|||||||
queryChannelsOnAppAsync(graphqlClient, { limit, offset, appId: projectId }),
|
queryChannelsOnAppAsync(graphqlClient, { limit, offset, appId: projectId }),
|
||||||
promptOptions: {
|
promptOptions: {
|
||||||
title: 'Load more channels?',
|
title: 'Load more channels?',
|
||||||
renderListItems: channels => renderPageOfChannels(channels, paginatedQueryOptions),
|
renderListItems: channels => {
|
||||||
|
renderPageOfChannels(channels, paginatedQueryOptions);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -131,8 +133,9 @@ export async function listAndRenderBranchesAndUpdatesOnChannelAsync(
|
|||||||
}),
|
}),
|
||||||
promptOptions: {
|
promptOptions: {
|
||||||
title: 'Load more channels?',
|
title: 'Load more channels?',
|
||||||
renderListItems: branches =>
|
renderListItems: branches => {
|
||||||
renderPageOfBranchesOnChannel(channel, branches, paginatedQueryOptions),
|
renderPageOfBranchesOnChannel(channel, branches, paginatedQueryOptions);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,13 +187,13 @@ export default abstract class EasCommand extends Command {
|
|||||||
action: `eas ${this.id}`,
|
action: `eas ${this.id}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.runAsync();
|
return await this.runAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line async-protect/async-suffix
|
// eslint-disable-next-line async-protect/async-suffix
|
||||||
override async finally(err: Error): Promise<any> {
|
override async finally(err: Error): Promise<any> {
|
||||||
await this.analytics.flushAsync();
|
await this.analytics.flushAsync();
|
||||||
return super.finally(err);
|
return await super.finally(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override catch(err: Error): Promise<any> {
|
protected override catch(err: Error): Promise<any> {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export function createGraphqlClient(authInfo: {
|
|||||||
return !!(
|
return !!(
|
||||||
err &&
|
err &&
|
||||||
!operation.context.noRetry &&
|
!operation.context.noRetry &&
|
||||||
(err.networkError || err.graphQLErrors.some(e => e?.extensions?.isTransient))
|
(err.networkError ?? err.graphQLErrors.some(e => e?.extensions?.isTransient))
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -1,5 +1,21 @@
|
|||||||
import { Flags } from '@oclif/core';
|
import { Flags } from '@oclif/core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
EnvironmentVariableEnvironment,
|
||||||
|
EnvironmentVariableScope,
|
||||||
|
EnvironmentVariableVisibility,
|
||||||
|
} from '../graphql/generated';
|
||||||
|
|
||||||
|
// NOTE: not exactly true, but, provided mapToLowercase and upperCaseAsync
|
||||||
|
// are used in tandem, it saves on unnecessary typying in commands
|
||||||
|
async function upperCaseAsync<T>(input: string): Promise<T> {
|
||||||
|
return input.toUpperCase() as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapToLowercase<T extends string>(options: T[]): T[] {
|
||||||
|
return options.map(option => option.toLowerCase()) as T[];
|
||||||
|
}
|
||||||
|
|
||||||
export const EasNonInteractiveAndJsonFlags = {
|
export const EasNonInteractiveAndJsonFlags = {
|
||||||
json: Flags.boolean({
|
json: Flags.boolean({
|
||||||
description: 'Enable JSON output, non-JSON messages will be printed to stderr.',
|
description: 'Enable JSON output, non-JSON messages will be printed to stderr.',
|
||||||
@@ -10,6 +26,47 @@ export const EasNonInteractiveAndJsonFlags = {
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const EASEnvironmentFlag = {
|
||||||
|
environment: Flags.enum<EnvironmentVariableEnvironment>({
|
||||||
|
description: "Environment variable's environment",
|
||||||
|
parse: upperCaseAsync,
|
||||||
|
options: mapToLowercase([
|
||||||
|
EnvironmentVariableEnvironment.Development,
|
||||||
|
EnvironmentVariableEnvironment.Preview,
|
||||||
|
EnvironmentVariableEnvironment.Production,
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const EASVariableFormatFlag = {
|
||||||
|
format: Flags.enum({
|
||||||
|
description: 'Output format',
|
||||||
|
options: ['long', 'short'],
|
||||||
|
default: 'short',
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const EASVariableVisibilityFlag = {
|
||||||
|
visibility: Flags.enum<EnvironmentVariableVisibility>({
|
||||||
|
description: 'Visibility of the variable',
|
||||||
|
options: mapToLowercase([
|
||||||
|
EnvironmentVariableVisibility.Secret,
|
||||||
|
EnvironmentVariableVisibility.Sensitive,
|
||||||
|
EnvironmentVariableVisibility.Public,
|
||||||
|
]),
|
||||||
|
parse: upperCaseAsync,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const EASVariableScopeFlag = {
|
||||||
|
scope: Flags.enum<EnvironmentVariableScope>({
|
||||||
|
description: 'Scope for the variable',
|
||||||
|
options: mapToLowercase([EnvironmentVariableScope.Shared, EnvironmentVariableScope.Project]),
|
||||||
|
parse: upperCaseAsync,
|
||||||
|
default: EnvironmentVariableScope.Project,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
export const EASNonInteractiveFlag = {
|
export const EASNonInteractiveFlag = {
|
||||||
'non-interactive': Flags.boolean({
|
'non-interactive': Flags.boolean({
|
||||||
description: 'Run the command in non-interactive mode.',
|
description: 'Run the command in non-interactive mode.',
|
||||||
|
|||||||
@@ -63,7 +63,11 @@ export default class FeatureGating {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static overrideKeyForEachInTest(key: FeatureGateKey, enabled: boolean): void {
|
public static overrideKeyForEachInTest(key: FeatureGateKey, enabled: boolean): void {
|
||||||
beforeEach(() => FeatureGateTestOverrides.setOverride(key, enabled));
|
beforeEach(() => {
|
||||||
afterEach(() => FeatureGateTestOverrides.removeOverride(key));
|
FeatureGateTestOverrides.setOverride(key, enabled);
|
||||||
|
});
|
||||||
|
afterEach(() => {
|
||||||
|
FeatureGateTestOverrides.removeOverride(key);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
import { Flags } from '@oclif/core';
|
import { Errors, Flags } from '@oclif/core';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
|
||||||
import EasCommand from '../../commandUtils/EasCommand';
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
import Log from '../../log';
|
import Log from '../../log';
|
||||||
|
import { confirmAsync } from '../../prompts';
|
||||||
|
import { getActorDisplayName } from '../../user/User';
|
||||||
|
|
||||||
export default class AccountLogin extends EasCommand {
|
export default class AccountLogin extends EasCommand {
|
||||||
static override description = 'log in with your Expo account';
|
static override description = 'log in with your Expo account';
|
||||||
@@ -17,6 +20,7 @@ export default class AccountLogin extends EasCommand {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static override contextDefinition = {
|
static override contextDefinition = {
|
||||||
|
...this.ContextOptions.MaybeLoggedIn,
|
||||||
...this.ContextOptions.SessionManagment,
|
...this.ContextOptions.SessionManagment,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -25,7 +29,28 @@ export default class AccountLogin extends EasCommand {
|
|||||||
flags: { sso },
|
flags: { sso },
|
||||||
} = await this.parse(AccountLogin);
|
} = await this.parse(AccountLogin);
|
||||||
|
|
||||||
const { sessionManager } = await this.getContextAsync(AccountLogin, { nonInteractive: false });
|
const {
|
||||||
|
sessionManager,
|
||||||
|
maybeLoggedIn: { actor },
|
||||||
|
} = await this.getContextAsync(AccountLogin, { nonInteractive: false });
|
||||||
|
|
||||||
|
if (sessionManager.getAccessToken()) {
|
||||||
|
throw new Error(
|
||||||
|
'EXPO_TOKEN is set in your environment, and is being used for all EAS authentication. To use username/password authentication, unset EXPO_TOKEN in your environment and re-run the command.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actor) {
|
||||||
|
Log.warn(`You are already logged in as ${chalk.bold(getActorDisplayName(actor))}.`);
|
||||||
|
|
||||||
|
const shouldContinue = await confirmAsync({
|
||||||
|
message: 'Do you want to continue?',
|
||||||
|
});
|
||||||
|
if (!shouldContinue) {
|
||||||
|
Errors.error('Aborted', { exit: 1 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await sessionManager.showLoginPromptAsync({ sso });
|
await sessionManager.showLoginPromptAsync({ sso });
|
||||||
Log.log('Logged in');
|
Log.log('Logged in');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,14 +12,19 @@ export default class AccountView extends EasCommand {
|
|||||||
|
|
||||||
static override contextDefinition = {
|
static override contextDefinition = {
|
||||||
...this.ContextOptions.MaybeLoggedIn,
|
...this.ContextOptions.MaybeLoggedIn,
|
||||||
|
...this.ContextOptions.SessionManagment,
|
||||||
};
|
};
|
||||||
|
|
||||||
async runAsync(): Promise<void> {
|
async runAsync(): Promise<void> {
|
||||||
const {
|
const {
|
||||||
maybeLoggedIn: { actor },
|
maybeLoggedIn: { actor },
|
||||||
|
sessionManager,
|
||||||
} = await this.getContextAsync(AccountView, { nonInteractive: true });
|
} = await this.getContextAsync(AccountView, { nonInteractive: true });
|
||||||
if (actor) {
|
if (actor) {
|
||||||
Log.log(chalk.green(getActorDisplayName(actor)));
|
const loggedInAs = sessionManager.getAccessToken()
|
||||||
|
? `${getActorDisplayName(actor)} (authenticated using EXPO_TOKEN)`
|
||||||
|
: getActorDisplayName(actor);
|
||||||
|
Log.log(chalk.green(loggedInAs));
|
||||||
|
|
||||||
// personal account is included, only show if more accounts that personal account
|
// personal account is included, only show if more accounts that personal account
|
||||||
// but do show personal account in list if there are more
|
// but do show personal account in list if there are more
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default class AnalyticsView extends EasCommand {
|
|||||||
async runAsync(): Promise<void> {
|
async runAsync(): Promise<void> {
|
||||||
const { STATUS: status } = (await this.parse(AnalyticsView)).args;
|
const { STATUS: status } = (await this.parse(AnalyticsView)).args;
|
||||||
if (status) {
|
if (status) {
|
||||||
setAnalyticsEnabledAsync(status === 'on');
|
await setAnalyticsEnabledAsync(status === 'on');
|
||||||
Log.withTick(`${status === 'on' ? 'Enabling' : 'Disabling'} analytics.`);
|
Log.withTick(`${status === 'on' ? 'Enabling' : 'Disabling'} analytics.`);
|
||||||
} else {
|
} else {
|
||||||
const analyticsEnabled = await getAnalyticsEnabledAsync();
|
const analyticsEnabled = await getAnalyticsEnabledAsync();
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ async function cancelBuildAsync(
|
|||||||
)
|
)
|
||||||
.toPromise()
|
.toPromise()
|
||||||
);
|
);
|
||||||
return data.build!.cancel;
|
return data.build.cancel;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function selectBuildToCancelAsync(
|
export async function selectBuildToCancelAsync(
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ async function deleteBuildAsync(
|
|||||||
)
|
)
|
||||||
.toPromise()
|
.toPromise()
|
||||||
);
|
);
|
||||||
return data.build!.deleteBuild;
|
return data.build.deleteBuild;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function selectBuildToDeleteAsync(
|
export async function selectBuildToDeleteAsync(
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ export default class BuildVersionSyncView extends EasCommand {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (profileInfo.platform === Platform.ANDROID) {
|
if (profileInfo.platform === Platform.ANDROID) {
|
||||||
this.syncAndroidAsync({
|
await this.syncAndroidAsync({
|
||||||
projectDir,
|
projectDir,
|
||||||
exp,
|
exp,
|
||||||
profile: profileInfo.profile as BuildProfile<Platform.ANDROID>,
|
profile: profileInfo.profile as BuildProfile<Platform.ANDROID>,
|
||||||
@@ -137,7 +137,7 @@ export default class BuildVersionSyncView extends EasCommand {
|
|||||||
vcsClient,
|
vcsClient,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.syncIosAsync({
|
await this.syncIosAsync({
|
||||||
projectDir,
|
projectDir,
|
||||||
exp,
|
exp,
|
||||||
profile: profileInfo.profile as BuildProfile<Platform.IOS>,
|
profile: profileInfo.profile as BuildProfile<Platform.IOS>,
|
||||||
@@ -199,7 +199,7 @@ export default class BuildVersionSyncView extends EasCommand {
|
|||||||
if (workflow === Workflow.GENERIC) {
|
if (workflow === Workflow.GENERIC) {
|
||||||
const buildGradle = await getAppBuildGradleAsync(projectDir);
|
const buildGradle = await getAppBuildGradleAsync(projectDir);
|
||||||
const isMultiFlavor =
|
const isMultiFlavor =
|
||||||
buildGradle.android?.productFlavors || buildGradle.android?.flavorDimensions;
|
buildGradle.android?.productFlavors ?? buildGradle.android?.flavorDimensions;
|
||||||
if (isMultiFlavor) {
|
if (isMultiFlavor) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Versions in native code can't be automatically synced in multi-flavor Android projects. If you are using EAS Build with app version source set to remote, the correct values will be injected at the build time."
|
"Versions in native code can't be automatically synced in multi-flavor Android projects. If you are using EAS Build with app version source set to remote, the correct values will be injected at the build time."
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ export default class DeviceDelete extends EasCommand {
|
|||||||
Log.log(
|
Log.log(
|
||||||
formatDevice(device, {
|
formatDevice(device, {
|
||||||
appleTeamName,
|
appleTeamName,
|
||||||
appleTeamIdentifier: appleTeamIdentifier!,
|
appleTeamIdentifier,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
Log.newLine();
|
Log.newLine();
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ export default class DeviceRename extends EasCommand {
|
|||||||
Log.log(
|
Log.log(
|
||||||
formatDevice(device, {
|
formatDevice(device, {
|
||||||
appleTeamName,
|
appleTeamName,
|
||||||
appleTeamIdentifier: appleTeamIdentifier!,
|
appleTeamIdentifier,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
Log.newLine();
|
Log.newLine();
|
||||||
|
|||||||
+275
@@ -0,0 +1,275 @@
|
|||||||
|
import { Flags } from '@oclif/core';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
|
||||||
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
|
import {
|
||||||
|
EASEnvironmentFlag,
|
||||||
|
EASNonInteractiveFlag,
|
||||||
|
EASVariableScopeFlag,
|
||||||
|
EASVariableVisibilityFlag,
|
||||||
|
} from '../../commandUtils/flags';
|
||||||
|
import {
|
||||||
|
EnvironmentVariableEnvironment,
|
||||||
|
EnvironmentVariableScope,
|
||||||
|
EnvironmentVariableVisibility,
|
||||||
|
} from '../../graphql/generated';
|
||||||
|
import { EnvironmentVariableMutation } from '../../graphql/mutations/EnvironmentVariableMutation';
|
||||||
|
import { EnvironmentVariablesQuery } from '../../graphql/queries/EnvironmentVariablesQuery';
|
||||||
|
import Log from '../../log';
|
||||||
|
import {
|
||||||
|
getDisplayNameForProjectIdAsync,
|
||||||
|
getOwnerAccountForProjectIdAsync,
|
||||||
|
} from '../../project/projectUtils';
|
||||||
|
import { confirmAsync } from '../../prompts';
|
||||||
|
import {
|
||||||
|
promptVariableEnvironmentAsync,
|
||||||
|
promptVariableNameAsync,
|
||||||
|
promptVariableValueAsync,
|
||||||
|
} from '../../utils/prompts';
|
||||||
|
|
||||||
|
type CreateFlags = {
|
||||||
|
name?: string;
|
||||||
|
value?: string;
|
||||||
|
link?: boolean;
|
||||||
|
force?: boolean;
|
||||||
|
visibility?: EnvironmentVariableVisibility;
|
||||||
|
scope?: EnvironmentVariableScope;
|
||||||
|
environment?: EnvironmentVariableEnvironment;
|
||||||
|
'non-interactive': boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class EnvironmentVariableCreate extends EasCommand {
|
||||||
|
static override description =
|
||||||
|
'create an environment variable on the current project or owner account';
|
||||||
|
|
||||||
|
static override hidden = true;
|
||||||
|
|
||||||
|
static override flags = {
|
||||||
|
name: Flags.string({
|
||||||
|
description: 'Name of the variable',
|
||||||
|
}),
|
||||||
|
value: Flags.string({
|
||||||
|
description: 'Text value or the variable',
|
||||||
|
}),
|
||||||
|
link: Flags.boolean({
|
||||||
|
description: 'Link shared variable to the current project',
|
||||||
|
}),
|
||||||
|
force: Flags.boolean({
|
||||||
|
description: 'Overwrite existing variable',
|
||||||
|
default: false,
|
||||||
|
}),
|
||||||
|
...EASVariableVisibilityFlag,
|
||||||
|
...EASVariableScopeFlag,
|
||||||
|
...EASEnvironmentFlag,
|
||||||
|
...EASNonInteractiveFlag,
|
||||||
|
};
|
||||||
|
|
||||||
|
static override contextDefinition = {
|
||||||
|
...this.ContextOptions.ProjectConfig,
|
||||||
|
...this.ContextOptions.Analytics,
|
||||||
|
...this.ContextOptions.LoggedIn,
|
||||||
|
};
|
||||||
|
|
||||||
|
async runAsync(): Promise<void> {
|
||||||
|
const { flags } = await this.parse(EnvironmentVariableCreate);
|
||||||
|
|
||||||
|
let {
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
scope,
|
||||||
|
'non-interactive': nonInteractive,
|
||||||
|
environment,
|
||||||
|
visibility,
|
||||||
|
link,
|
||||||
|
force,
|
||||||
|
} = this.validateFlags(flags);
|
||||||
|
|
||||||
|
const {
|
||||||
|
privateProjectConfig: { projectId },
|
||||||
|
loggedIn: { graphqlClient },
|
||||||
|
} = await this.getContextAsync(EnvironmentVariableCreate, {
|
||||||
|
nonInteractive,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [projectDisplayName, ownerAccount] = await Promise.all([
|
||||||
|
getDisplayNameForProjectIdAsync(graphqlClient, projectId),
|
||||||
|
getOwnerAccountForProjectIdAsync(graphqlClient, projectId),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!name) {
|
||||||
|
name = await promptVariableNameAsync(nonInteractive);
|
||||||
|
}
|
||||||
|
|
||||||
|
let overwrite = false;
|
||||||
|
visibility = visibility ?? EnvironmentVariableVisibility.Public;
|
||||||
|
|
||||||
|
if (!value) {
|
||||||
|
value = await promptVariableValueAsync({
|
||||||
|
nonInteractive,
|
||||||
|
hidden: visibility !== EnvironmentVariableVisibility.Public,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scope === EnvironmentVariableScope.Project) {
|
||||||
|
if (!environment) {
|
||||||
|
environment = await promptVariableEnvironmentAsync(nonInteractive);
|
||||||
|
}
|
||||||
|
const existingVariables = await EnvironmentVariablesQuery.byAppIdAsync(
|
||||||
|
graphqlClient,
|
||||||
|
projectId,
|
||||||
|
environment
|
||||||
|
);
|
||||||
|
const existingVariable = existingVariables.find(variable => variable.name === name);
|
||||||
|
|
||||||
|
if (existingVariable) {
|
||||||
|
if (existingVariable.scope === EnvironmentVariableScope.Shared) {
|
||||||
|
if (!nonInteractive) {
|
||||||
|
const confirmation = await confirmAsync({
|
||||||
|
message: `Shared variable ${name} already exists on this project. Do you want to unlink it first?`,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!confirmation) {
|
||||||
|
Log.log('Aborting');
|
||||||
|
throw new Error(`Shared variable ${name} already exists on this project.`);
|
||||||
|
}
|
||||||
|
} else if (!force) {
|
||||||
|
throw new Error(
|
||||||
|
`Shared variable ${name} already exists on this project. Use --force to overwrite it.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await EnvironmentVariableMutation.unlinkSharedEnvironmentVariableAsync(
|
||||||
|
graphqlClient,
|
||||||
|
existingVariable.id,
|
||||||
|
projectId,
|
||||||
|
environment
|
||||||
|
);
|
||||||
|
Log.withTick(
|
||||||
|
`Unlinking shared variable ${chalk.bold(name)} on project ${chalk.bold(
|
||||||
|
projectDisplayName
|
||||||
|
)}.`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (!nonInteractive) {
|
||||||
|
const confirmation = await confirmAsync({
|
||||||
|
message: `Variable ${name} already exists on this project. Do you want to overwrite it?`,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!confirmation) {
|
||||||
|
Log.log('Aborting');
|
||||||
|
throw new Error(
|
||||||
|
`Variable ${name} already exists on this project. Use --force to overwrite it.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (!force) {
|
||||||
|
throw new Error(
|
||||||
|
`Variable ${name} already exists on this project. Use --force to overwrite it.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
overwrite = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const variable = await EnvironmentVariableMutation.createForAppAsync(
|
||||||
|
graphqlClient,
|
||||||
|
{
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
environment,
|
||||||
|
visibility,
|
||||||
|
overwrite,
|
||||||
|
},
|
||||||
|
projectId
|
||||||
|
);
|
||||||
|
if (!variable) {
|
||||||
|
throw new Error(
|
||||||
|
`Could not create variable with name ${name} on project ${projectDisplayName}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.withTick(
|
||||||
|
`Created a new variable ${chalk.bold(name)} on project ${chalk.bold(projectDisplayName)}.`
|
||||||
|
);
|
||||||
|
} else if (scope === EnvironmentVariableScope.Shared) {
|
||||||
|
const sharedVariables = await EnvironmentVariablesQuery.sharedAsync(graphqlClient, projectId);
|
||||||
|
const existingVariable = sharedVariables.find(variable => variable.name === name);
|
||||||
|
if (existingVariable) {
|
||||||
|
throw new Error(
|
||||||
|
`Shared variable with ${name} name already exists on this account.\n` +
|
||||||
|
`Use a different name or delete the existing variable on website or by using eas env:delete --name ${name} --scope shared command.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (environment && !link) {
|
||||||
|
const confirmation = await confirmAsync({
|
||||||
|
message: `Unexpected argument: --environment can only be used with --link flag. Do you want to link the variable to the current project?`,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!confirmation) {
|
||||||
|
Log.log('Aborting');
|
||||||
|
throw new Error('Unexpected argument: --environment can only be used with --link flag.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!environment && link) {
|
||||||
|
environment = await promptVariableEnvironmentAsync(nonInteractive);
|
||||||
|
}
|
||||||
|
|
||||||
|
const variable = await EnvironmentVariableMutation.createSharedVariableAsync(
|
||||||
|
graphqlClient,
|
||||||
|
{
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
visibility,
|
||||||
|
},
|
||||||
|
ownerAccount.id
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!variable) {
|
||||||
|
throw new Error(
|
||||||
|
`Could not create variable with name ${name} on account ${ownerAccount.name}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.withTick(
|
||||||
|
`Created a new variable ${chalk.bold(name)} on account ${chalk.bold(ownerAccount.name)}.`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (link && environment) {
|
||||||
|
Log.withTick(
|
||||||
|
`Linking shared variable ${chalk.bold(name)} to project ${chalk.bold(
|
||||||
|
projectDisplayName
|
||||||
|
)}.`
|
||||||
|
);
|
||||||
|
await EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync(
|
||||||
|
graphqlClient,
|
||||||
|
variable.id,
|
||||||
|
projectId,
|
||||||
|
environment
|
||||||
|
);
|
||||||
|
Log.withTick(
|
||||||
|
`Linked shared variable ${chalk.bold(name)} to project ${chalk.bold(projectDisplayName)}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private validateFlags(flags: CreateFlags): CreateFlags {
|
||||||
|
if (flags.scope !== EnvironmentVariableScope.Shared && flags.link) {
|
||||||
|
throw new Error(
|
||||||
|
`Unexpected argument: --link can only be used when creating shared variables`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
flags.scope === EnvironmentVariableScope.Shared &&
|
||||||
|
flags.environment &&
|
||||||
|
!flags.link &&
|
||||||
|
flags['non-interactive']
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
'Unexpected argument: --environment in non-interactive mode can only be used with --link flag.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
+128
@@ -0,0 +1,128 @@
|
|||||||
|
import { Flags } from '@oclif/core';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
|
||||||
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
|
import {
|
||||||
|
EASEnvironmentFlag,
|
||||||
|
EASNonInteractiveFlag,
|
||||||
|
EASVariableScopeFlag,
|
||||||
|
} from '../../commandUtils/flags';
|
||||||
|
import { EnvironmentVariableEnvironment, EnvironmentVariableScope } from '../../graphql/generated';
|
||||||
|
import { EnvironmentVariableMutation } from '../../graphql/mutations/EnvironmentVariableMutation';
|
||||||
|
import { EnvironmentVariablesQuery } from '../../graphql/queries/EnvironmentVariablesQuery';
|
||||||
|
import Log from '../../log';
|
||||||
|
import { promptAsync, toggleConfirmAsync } from '../../prompts';
|
||||||
|
import { promptVariableEnvironmentAsync } from '../../utils/prompts';
|
||||||
|
|
||||||
|
type DeleteFlags = {
|
||||||
|
name?: string;
|
||||||
|
environment?: EnvironmentVariableEnvironment;
|
||||||
|
'non-interactive': boolean;
|
||||||
|
scope?: EnvironmentVariableScope;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class EnvironmentVariableDelete extends EasCommand {
|
||||||
|
static override description = 'delete an environment variable by name';
|
||||||
|
|
||||||
|
static override hidden = true;
|
||||||
|
|
||||||
|
static override flags = {
|
||||||
|
name: Flags.string({
|
||||||
|
description: 'Name of the variable to delete',
|
||||||
|
}),
|
||||||
|
...EASVariableScopeFlag,
|
||||||
|
...EASEnvironmentFlag,
|
||||||
|
...EASNonInteractiveFlag,
|
||||||
|
};
|
||||||
|
|
||||||
|
static override contextDefinition = {
|
||||||
|
...this.ContextOptions.ProjectConfig,
|
||||||
|
...this.ContextOptions.LoggedIn,
|
||||||
|
};
|
||||||
|
|
||||||
|
async runAsync(): Promise<void> {
|
||||||
|
const { flags } = await this.parse(EnvironmentVariableDelete);
|
||||||
|
let { name, environment, 'non-interactive': nonInteractive, scope } = this.validateFlags(flags);
|
||||||
|
const {
|
||||||
|
privateProjectConfig: { projectId },
|
||||||
|
loggedIn: { graphqlClient },
|
||||||
|
} = await this.getContextAsync(EnvironmentVariableDelete, {
|
||||||
|
nonInteractive,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (scope === EnvironmentVariableScope.Project) {
|
||||||
|
if (!environment) {
|
||||||
|
environment = await promptVariableEnvironmentAsync(nonInteractive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const variables =
|
||||||
|
scope === EnvironmentVariableScope.Project && environment
|
||||||
|
? await EnvironmentVariablesQuery.byAppIdAsync(graphqlClient, projectId, environment)
|
||||||
|
: await EnvironmentVariablesQuery.sharedAsync(graphqlClient, projectId);
|
||||||
|
|
||||||
|
if (!name) {
|
||||||
|
({ name } = await promptAsync({
|
||||||
|
type: 'select',
|
||||||
|
name: 'name',
|
||||||
|
message: 'Pick the variable to be deleted:',
|
||||||
|
choices: variables
|
||||||
|
.filter(({ scope: variableScope }) => scope === variableScope)
|
||||||
|
.map(variable => ({
|
||||||
|
title: variable.name,
|
||||||
|
value: variable.name,
|
||||||
|
})),
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!name) {
|
||||||
|
throw new Error(
|
||||||
|
`Environment variable wasn't selected. Run the command again and select existing variable or run it with ${chalk.bold(
|
||||||
|
'--name VARIABLE_NAME'
|
||||||
|
)} flag to fix the issue.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedVariable = variables.find(variable => variable.name === name);
|
||||||
|
|
||||||
|
if (!selectedVariable) {
|
||||||
|
throw new Error(`Variable "${name}" not found.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nonInteractive) {
|
||||||
|
Log.addNewLineIfNone();
|
||||||
|
Log.warn(`You are about to permanently delete variable ${selectedVariable.name}.`);
|
||||||
|
Log.warn('This action is irreversible.');
|
||||||
|
Log.newLine();
|
||||||
|
const confirmed = await toggleConfirmAsync({
|
||||||
|
message: `Are you sure you wish to proceed?${
|
||||||
|
selectedVariable.scope === EnvironmentVariableScope.Shared
|
||||||
|
? ' This variable is applied across your whole account and may affect multiple apps.'
|
||||||
|
: ''
|
||||||
|
}`,
|
||||||
|
});
|
||||||
|
if (!confirmed) {
|
||||||
|
Log.error(`Canceled deletion of variable ${selectedVariable.name}.`);
|
||||||
|
throw new Error(`Variable "${name}" not deleted.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await EnvironmentVariableMutation.deleteAsync(graphqlClient, selectedVariable.id);
|
||||||
|
|
||||||
|
Log.withTick(`️Deleted variable ${selectedVariable.name}".`);
|
||||||
|
}
|
||||||
|
|
||||||
|
private validateFlags(flags: DeleteFlags): DeleteFlags {
|
||||||
|
if (flags['non-interactive']) {
|
||||||
|
if (!flags.name) {
|
||||||
|
throw new Error(
|
||||||
|
`Environment variable needs 'name' to be specified when running in non-interactive mode. Run the command with ${chalk.bold(
|
||||||
|
'--name VARIABLE_NAME'
|
||||||
|
)} flag to fix the issue`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
+144
@@ -0,0 +1,144 @@
|
|||||||
|
import { Flags } from '@oclif/core';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
|
||||||
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
|
import { ExpoGraphqlClient } from '../../commandUtils/context/contextUtils/createGraphqlClient';
|
||||||
|
import {
|
||||||
|
EASEnvironmentFlag,
|
||||||
|
EASNonInteractiveFlag,
|
||||||
|
EASVariableFormatFlag,
|
||||||
|
EASVariableScopeFlag,
|
||||||
|
} from '../../commandUtils/flags';
|
||||||
|
import {
|
||||||
|
EnvironmentVariableEnvironment,
|
||||||
|
EnvironmentVariableFragment,
|
||||||
|
EnvironmentVariableScope,
|
||||||
|
} from '../../graphql/generated';
|
||||||
|
import { EnvironmentVariablesQuery } from '../../graphql/queries/EnvironmentVariablesQuery';
|
||||||
|
import Log from '../../log';
|
||||||
|
import { formatVariable } from '../../utils/formatVariable';
|
||||||
|
import { promptVariableEnvironmentAsync, promptVariableNameAsync } from '../../utils/prompts';
|
||||||
|
|
||||||
|
type GetFlags = {
|
||||||
|
name?: string;
|
||||||
|
environment?: EnvironmentVariableEnvironment;
|
||||||
|
'non-interactive': boolean;
|
||||||
|
format?: string;
|
||||||
|
scope: EnvironmentVariableScope;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class EnvironmentVariableGet extends EasCommand {
|
||||||
|
static override description = 'get environment variable';
|
||||||
|
|
||||||
|
static override hidden = true;
|
||||||
|
|
||||||
|
static override contextDefinition = {
|
||||||
|
...this.ContextOptions.ProjectConfig,
|
||||||
|
...this.ContextOptions.LoggedIn,
|
||||||
|
};
|
||||||
|
|
||||||
|
static override flags = {
|
||||||
|
name: Flags.string({
|
||||||
|
description: 'Name of the variable',
|
||||||
|
}),
|
||||||
|
...EASVariableFormatFlag,
|
||||||
|
...EASVariableScopeFlag,
|
||||||
|
...EASNonInteractiveFlag,
|
||||||
|
...EASEnvironmentFlag,
|
||||||
|
};
|
||||||
|
|
||||||
|
async runAsync(): Promise<void> {
|
||||||
|
const { flags } = await this.parse(EnvironmentVariableGet);
|
||||||
|
|
||||||
|
let {
|
||||||
|
environment,
|
||||||
|
name,
|
||||||
|
'non-interactive': nonInteractive,
|
||||||
|
format,
|
||||||
|
scope,
|
||||||
|
} = this.validateFlags(flags);
|
||||||
|
|
||||||
|
const {
|
||||||
|
privateProjectConfig: { projectId },
|
||||||
|
loggedIn: { graphqlClient },
|
||||||
|
} = await this.getContextAsync(EnvironmentVariableGet, {
|
||||||
|
nonInteractive,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!name) {
|
||||||
|
name = await promptVariableNameAsync(nonInteractive);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!environment && scope === EnvironmentVariableScope.Project) {
|
||||||
|
environment = await promptVariableEnvironmentAsync(nonInteractive);
|
||||||
|
}
|
||||||
|
|
||||||
|
const variable = await getVariableAsync(graphqlClient, scope, projectId, name, environment);
|
||||||
|
|
||||||
|
if (!variable) {
|
||||||
|
Log.error(`Variable with name "${name}" not found`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!variable.value) {
|
||||||
|
throw new Error(
|
||||||
|
`${chalk.bold(
|
||||||
|
variable.name
|
||||||
|
)} is a secret variable and cannot be displayed once it has been created.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format === 'short') {
|
||||||
|
Log.log(`${chalk.bold(variable.name)}=${variable.value}`);
|
||||||
|
} else {
|
||||||
|
Log.log(formatVariable(variable));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private validateFlags(flags: GetFlags): GetFlags {
|
||||||
|
if (flags.environment && flags.scope === EnvironmentVariableScope.Shared) {
|
||||||
|
throw new Error(`Unexpected argument: --environment can only be used with project variables`);
|
||||||
|
}
|
||||||
|
if (flags['non-interactive']) {
|
||||||
|
if (!flags.name) {
|
||||||
|
throw new Error('Variable name is required. Run the command with --name flag.');
|
||||||
|
}
|
||||||
|
if (!flags.scope) {
|
||||||
|
throw new Error('Scope is required. Run the command with --scope flag.');
|
||||||
|
}
|
||||||
|
if (!flags.environment && flags.scope === EnvironmentVariableScope.Project) {
|
||||||
|
throw new Error('Environment is required.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getVariableAsync(
|
||||||
|
graphqlClient: ExpoGraphqlClient,
|
||||||
|
scope: string,
|
||||||
|
projectId: string,
|
||||||
|
name: string,
|
||||||
|
environment: string | undefined
|
||||||
|
): Promise<EnvironmentVariableFragment | null> {
|
||||||
|
if (!environment && scope === EnvironmentVariableScope.Project) {
|
||||||
|
throw new Error('Environment is required.');
|
||||||
|
}
|
||||||
|
if (environment && scope === EnvironmentVariableScope.Project) {
|
||||||
|
const appVariables = await EnvironmentVariablesQuery.byAppIdAsync(
|
||||||
|
graphqlClient,
|
||||||
|
projectId,
|
||||||
|
environment,
|
||||||
|
[name]
|
||||||
|
);
|
||||||
|
return appVariables[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scope === EnvironmentVariableScope.Shared) {
|
||||||
|
const sharedVariables = await EnvironmentVariablesQuery.sharedAsync(graphqlClient, projectId, [
|
||||||
|
name,
|
||||||
|
]);
|
||||||
|
return sharedVariables[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
+83
@@ -0,0 +1,83 @@
|
|||||||
|
import { Flags } from '@oclif/core';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
|
||||||
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
|
import { EASEnvironmentFlag, EASNonInteractiveFlag } from '../../commandUtils/flags';
|
||||||
|
import { EnvironmentVariableMutation } from '../../graphql/mutations/EnvironmentVariableMutation';
|
||||||
|
import { EnvironmentVariablesQuery } from '../../graphql/queries/EnvironmentVariablesQuery';
|
||||||
|
import Log from '../../log';
|
||||||
|
import { getDisplayNameForProjectIdAsync } from '../../project/projectUtils';
|
||||||
|
import { selectAsync } from '../../prompts';
|
||||||
|
import { promptVariableEnvironmentAsync } from '../../utils/prompts';
|
||||||
|
|
||||||
|
export default class EnvironmentVariableLink extends EasCommand {
|
||||||
|
static override description = 'link a shared environment variable to the current project';
|
||||||
|
|
||||||
|
static override hidden = true;
|
||||||
|
|
||||||
|
static override flags = {
|
||||||
|
name: Flags.string({
|
||||||
|
description: 'Name of the variable',
|
||||||
|
}),
|
||||||
|
...EASEnvironmentFlag,
|
||||||
|
...EASNonInteractiveFlag,
|
||||||
|
};
|
||||||
|
|
||||||
|
static override contextDefinition = {
|
||||||
|
...this.ContextOptions.ProjectConfig,
|
||||||
|
...this.ContextOptions.LoggedIn,
|
||||||
|
};
|
||||||
|
|
||||||
|
async runAsync(): Promise<void> {
|
||||||
|
let {
|
||||||
|
flags: { name, 'non-interactive': nonInteractive, environment },
|
||||||
|
} = await this.parse(EnvironmentVariableLink);
|
||||||
|
const {
|
||||||
|
privateProjectConfig: { projectId },
|
||||||
|
loggedIn: { graphqlClient },
|
||||||
|
} = await this.getContextAsync(EnvironmentVariableLink, {
|
||||||
|
nonInteractive,
|
||||||
|
});
|
||||||
|
|
||||||
|
const projectDisplayName = await getDisplayNameForProjectIdAsync(graphqlClient, projectId);
|
||||||
|
const variables = await EnvironmentVariablesQuery.sharedAsync(graphqlClient, projectId);
|
||||||
|
|
||||||
|
if (!name) {
|
||||||
|
name = await selectAsync(
|
||||||
|
'Select shared variable',
|
||||||
|
variables.map(variable => ({
|
||||||
|
title: variable.name,
|
||||||
|
value: variable.name,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedVariable = variables.find(variable => variable.name === name);
|
||||||
|
|
||||||
|
if (!selectedVariable) {
|
||||||
|
throw new Error(`Shared variable ${name} doesn't exist`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!environment) {
|
||||||
|
environment = await promptVariableEnvironmentAsync(nonInteractive);
|
||||||
|
}
|
||||||
|
|
||||||
|
const linkedVariable = await EnvironmentVariableMutation.linkSharedEnvironmentVariableAsync(
|
||||||
|
graphqlClient,
|
||||||
|
selectedVariable.id,
|
||||||
|
projectId,
|
||||||
|
environment
|
||||||
|
);
|
||||||
|
if (!linkedVariable) {
|
||||||
|
throw new Error(
|
||||||
|
`Could not link variable with name ${selectedVariable.name} to project with id ${projectId}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.withTick(
|
||||||
|
`Linked variable ${chalk.bold(linkedVariable.name)} to project ${chalk.bold(
|
||||||
|
projectDisplayName
|
||||||
|
)}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+72
@@ -0,0 +1,72 @@
|
|||||||
|
import chalk from 'chalk';
|
||||||
|
|
||||||
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
|
import {
|
||||||
|
EASEnvironmentFlag,
|
||||||
|
EASVariableFormatFlag,
|
||||||
|
EASVariableScopeFlag,
|
||||||
|
} from '../../commandUtils/flags';
|
||||||
|
import { EnvironmentVariableScope } from '../../graphql/generated';
|
||||||
|
import { EnvironmentVariablesQuery } from '../../graphql/queries/EnvironmentVariablesQuery';
|
||||||
|
import Log from '../../log';
|
||||||
|
import { formatVariable } from '../../utils/formatVariable';
|
||||||
|
import { promptVariableEnvironmentAsync } from '../../utils/prompts';
|
||||||
|
|
||||||
|
export default class EnvironmentValueList extends EasCommand {
|
||||||
|
static override description = 'list environment variables for the current project';
|
||||||
|
|
||||||
|
static override hidden = true;
|
||||||
|
|
||||||
|
static override contextDefinition = {
|
||||||
|
...this.ContextOptions.ProjectConfig,
|
||||||
|
...this.ContextOptions.LoggedIn,
|
||||||
|
};
|
||||||
|
|
||||||
|
static override flags = {
|
||||||
|
...EASVariableFormatFlag,
|
||||||
|
...EASVariableScopeFlag,
|
||||||
|
...EASEnvironmentFlag,
|
||||||
|
};
|
||||||
|
|
||||||
|
async runAsync(): Promise<void> {
|
||||||
|
let {
|
||||||
|
flags: { environment, format, scope },
|
||||||
|
} = await this.parse(EnvironmentValueList);
|
||||||
|
const {
|
||||||
|
privateProjectConfig: { projectId },
|
||||||
|
loggedIn: { graphqlClient },
|
||||||
|
} = await this.getContextAsync(EnvironmentValueList, {
|
||||||
|
nonInteractive: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (scope === EnvironmentVariableScope.Project && !environment) {
|
||||||
|
environment = await promptVariableEnvironmentAsync(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const variables =
|
||||||
|
scope === EnvironmentVariableScope.Project && environment
|
||||||
|
? await EnvironmentVariablesQuery.byAppIdAsync(graphqlClient, projectId, environment)
|
||||||
|
: await EnvironmentVariablesQuery.sharedAsync(graphqlClient, projectId);
|
||||||
|
|
||||||
|
if (format === 'short') {
|
||||||
|
for (const variable of variables) {
|
||||||
|
// TODO: Add Learn more link
|
||||||
|
Log.log(
|
||||||
|
`${chalk.bold(variable.name)}=${
|
||||||
|
variable.value ??
|
||||||
|
"***** (This is a secret env variable that can only be accessed on EAS builder and can't be read in any UI. Learn more.)"
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (scope === EnvironmentVariableScope.Shared) {
|
||||||
|
Log.log(chalk.bold('Shared variables for this account:'));
|
||||||
|
} else {
|
||||||
|
Log.log(chalk.bold(`Variables for this project for environment ${environment}:`));
|
||||||
|
}
|
||||||
|
Log.log(
|
||||||
|
variables.map(variable => formatVariable(variable)).join(`\n\n${chalk.dim('———')}\n\n`)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+97
@@ -0,0 +1,97 @@
|
|||||||
|
import { Flags } from '@oclif/core';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
|
||||||
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
|
import { EASEnvironmentFlag, EASNonInteractiveFlag } from '../../commandUtils/flags';
|
||||||
|
import { EnvironmentVariableScope } from '../../graphql/generated';
|
||||||
|
import { EnvironmentVariableMutation } from '../../graphql/mutations/EnvironmentVariableMutation';
|
||||||
|
import { EnvironmentVariablesQuery } from '../../graphql/queries/EnvironmentVariablesQuery';
|
||||||
|
import Log from '../../log';
|
||||||
|
import { getDisplayNameForProjectIdAsync } from '../../project/projectUtils';
|
||||||
|
import { selectAsync } from '../../prompts';
|
||||||
|
import { promptVariableEnvironmentAsync } from '../../utils/prompts';
|
||||||
|
|
||||||
|
export default class EnvironmentVariableUnlink extends EasCommand {
|
||||||
|
static override description = 'unlink a shared environment variable to the current project';
|
||||||
|
|
||||||
|
static override hidden = true;
|
||||||
|
|
||||||
|
static override flags = {
|
||||||
|
name: Flags.string({
|
||||||
|
description: 'Name of the variable',
|
||||||
|
}),
|
||||||
|
...EASEnvironmentFlag,
|
||||||
|
...EASNonInteractiveFlag,
|
||||||
|
};
|
||||||
|
|
||||||
|
static override contextDefinition = {
|
||||||
|
...this.ContextOptions.ProjectConfig,
|
||||||
|
...this.ContextOptions.LoggedIn,
|
||||||
|
};
|
||||||
|
|
||||||
|
async runAsync(): Promise<void> {
|
||||||
|
let {
|
||||||
|
flags: { name, 'non-interactive': nonInteractive, environment },
|
||||||
|
} = await this.parse(EnvironmentVariableUnlink);
|
||||||
|
const {
|
||||||
|
privateProjectConfig: { projectId },
|
||||||
|
loggedIn: { graphqlClient },
|
||||||
|
} = await this.getContextAsync(EnvironmentVariableUnlink, {
|
||||||
|
nonInteractive,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!environment) {
|
||||||
|
environment = await promptVariableEnvironmentAsync(nonInteractive);
|
||||||
|
}
|
||||||
|
|
||||||
|
const projectDisplayName = await getDisplayNameForProjectIdAsync(graphqlClient, projectId);
|
||||||
|
|
||||||
|
const appVariables = await EnvironmentVariablesQuery.byAppIdAsync(
|
||||||
|
graphqlClient,
|
||||||
|
projectId,
|
||||||
|
environment
|
||||||
|
);
|
||||||
|
const linkedVariables = appVariables.filter(
|
||||||
|
({ scope }) => scope === EnvironmentVariableScope.Shared
|
||||||
|
);
|
||||||
|
|
||||||
|
if (linkedVariables.length === 0) {
|
||||||
|
throw new Error(`There are no linked shared env variables for project ${projectDisplayName}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!name) {
|
||||||
|
name = await selectAsync(
|
||||||
|
'Select shared variable to unlink',
|
||||||
|
linkedVariables.map(variable => ({
|
||||||
|
title: variable.name,
|
||||||
|
value: variable.name,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedVariable = linkedVariables.find(variable => variable.name === name);
|
||||||
|
|
||||||
|
if (!selectedVariable) {
|
||||||
|
throw new Error(`Shared variable ${name} doesn't exist`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const unlinkedVariable = await EnvironmentVariableMutation.unlinkSharedEnvironmentVariableAsync(
|
||||||
|
graphqlClient,
|
||||||
|
selectedVariable.id,
|
||||||
|
projectId,
|
||||||
|
environment
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!unlinkedVariable) {
|
||||||
|
throw new Error(
|
||||||
|
`Could not unlink variable with name ${selectedVariable.name} from project ${projectDisplayName}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.withTick(
|
||||||
|
`Unlinked variable ${chalk.bold(unlinkedVariable.name)} from the project ${chalk.bold(
|
||||||
|
projectDisplayName
|
||||||
|
)}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+206
@@ -0,0 +1,206 @@
|
|||||||
|
import { Flags } from '@oclif/core';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
|
||||||
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
|
import {
|
||||||
|
EASEnvironmentFlag,
|
||||||
|
EASNonInteractiveFlag,
|
||||||
|
EASVariableScopeFlag,
|
||||||
|
EASVariableVisibilityFlag,
|
||||||
|
} from '../../commandUtils/flags';
|
||||||
|
import { EnvironmentVariableScope, EnvironmentVariableVisibility } from '../../graphql/generated';
|
||||||
|
import { EnvironmentVariableMutation } from '../../graphql/mutations/EnvironmentVariableMutation';
|
||||||
|
import { EnvironmentVariablesQuery } from '../../graphql/queries/EnvironmentVariablesQuery';
|
||||||
|
import Log from '../../log';
|
||||||
|
import {
|
||||||
|
getDisplayNameForProjectIdAsync,
|
||||||
|
getOwnerAccountForProjectIdAsync,
|
||||||
|
} from '../../project/projectUtils';
|
||||||
|
import { selectAsync } from '../../prompts';
|
||||||
|
import { promptVariableEnvironmentAsync, promptVariableValueAsync } from '../../utils/prompts';
|
||||||
|
|
||||||
|
type UpdateFlags = {
|
||||||
|
name?: string;
|
||||||
|
value?: string;
|
||||||
|
scope?: EnvironmentVariableScope;
|
||||||
|
environment?: string;
|
||||||
|
visibility?: EnvironmentVariableVisibility;
|
||||||
|
'non-interactive': boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class EnvironmentVariableUpdate extends EasCommand {
|
||||||
|
static override description =
|
||||||
|
'update an environment variable on the current project or owner account';
|
||||||
|
|
||||||
|
static override hidden = true;
|
||||||
|
|
||||||
|
static override flags = {
|
||||||
|
name: Flags.string({
|
||||||
|
description: 'Name of the variable',
|
||||||
|
}),
|
||||||
|
value: Flags.string({
|
||||||
|
description: 'Text value or the variable',
|
||||||
|
}),
|
||||||
|
...EASVariableVisibilityFlag,
|
||||||
|
...EASVariableScopeFlag,
|
||||||
|
...EASEnvironmentFlag,
|
||||||
|
...EASNonInteractiveFlag,
|
||||||
|
};
|
||||||
|
|
||||||
|
static override contextDefinition = {
|
||||||
|
...this.ContextOptions.ProjectConfig,
|
||||||
|
...this.ContextOptions.Analytics,
|
||||||
|
...this.ContextOptions.LoggedIn,
|
||||||
|
};
|
||||||
|
|
||||||
|
async runAsync(): Promise<void> {
|
||||||
|
const { flags } = await this.parse(EnvironmentVariableUpdate);
|
||||||
|
let {
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
scope,
|
||||||
|
'non-interactive': nonInteractive,
|
||||||
|
environment,
|
||||||
|
visibility,
|
||||||
|
} = this.validateFlags(flags);
|
||||||
|
|
||||||
|
const {
|
||||||
|
privateProjectConfig: { projectId },
|
||||||
|
loggedIn: { graphqlClient },
|
||||||
|
} = await this.getContextAsync(EnvironmentVariableUpdate, {
|
||||||
|
nonInteractive,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [projectDisplayName, ownerAccount] = await Promise.all([
|
||||||
|
getDisplayNameForProjectIdAsync(graphqlClient, projectId),
|
||||||
|
getOwnerAccountForProjectIdAsync(graphqlClient, projectId),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (scope === EnvironmentVariableScope.Project) {
|
||||||
|
if (!environment) {
|
||||||
|
environment = await promptVariableEnvironmentAsync(nonInteractive);
|
||||||
|
}
|
||||||
|
const existingVariables = await EnvironmentVariablesQuery.byAppIdAsync(
|
||||||
|
graphqlClient,
|
||||||
|
projectId,
|
||||||
|
environment
|
||||||
|
);
|
||||||
|
if (!name) {
|
||||||
|
name = await selectAsync(
|
||||||
|
'Select variable',
|
||||||
|
existingVariables.map(variable => ({
|
||||||
|
title: variable.name,
|
||||||
|
value: variable.name,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingVariable = existingVariables.find(variable => variable.name === name);
|
||||||
|
if (!existingVariable) {
|
||||||
|
throw new Error(
|
||||||
|
`Variable with name ${name} does not exist on project ${projectDisplayName}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!value) {
|
||||||
|
value = await promptVariableValueAsync({
|
||||||
|
nonInteractive,
|
||||||
|
required: false,
|
||||||
|
initial: existingVariable.value,
|
||||||
|
});
|
||||||
|
if (!value || value.length === 0) {
|
||||||
|
value = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const variable = await EnvironmentVariableMutation.createForAppAsync(
|
||||||
|
graphqlClient,
|
||||||
|
{
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
environment,
|
||||||
|
visibility,
|
||||||
|
overwrite: true,
|
||||||
|
},
|
||||||
|
projectId
|
||||||
|
);
|
||||||
|
if (!variable) {
|
||||||
|
throw new Error(
|
||||||
|
`Could not update variable with name ${name} on project ${projectDisplayName}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.withTick(
|
||||||
|
`Updated variable ${chalk.bold(name)} on project ${chalk.bold(projectDisplayName)}.`
|
||||||
|
);
|
||||||
|
} else if (scope === EnvironmentVariableScope.Shared) {
|
||||||
|
const sharedVariables = await EnvironmentVariablesQuery.sharedAsync(graphqlClient, projectId);
|
||||||
|
|
||||||
|
if (!name) {
|
||||||
|
name = await selectAsync(
|
||||||
|
'Select variable',
|
||||||
|
sharedVariables.map(variable => ({
|
||||||
|
title: variable.name,
|
||||||
|
value: variable.name,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingVariable = sharedVariables.find(variable => variable.name === name);
|
||||||
|
if (!existingVariable) {
|
||||||
|
throw new Error(
|
||||||
|
"Variable with this name doesn't exist on this account. Use a different name."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!value) {
|
||||||
|
value = await promptVariableValueAsync({
|
||||||
|
nonInteractive,
|
||||||
|
required: false,
|
||||||
|
initial: existingVariable.value,
|
||||||
|
});
|
||||||
|
if (!value || value.length === 0) {
|
||||||
|
value = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const variable = await EnvironmentVariableMutation.createSharedVariableAsync(
|
||||||
|
graphqlClient,
|
||||||
|
{
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
visibility,
|
||||||
|
overwrite: true,
|
||||||
|
},
|
||||||
|
ownerAccount.id
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!variable) {
|
||||||
|
throw new Error(
|
||||||
|
`Could not update variable with name ${name} on account ${ownerAccount.name}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.withTick(
|
||||||
|
`Updated shared variable ${chalk.bold(name)} on account ${chalk.bold(ownerAccount.name)}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private validateFlags(flags: UpdateFlags): UpdateFlags {
|
||||||
|
if (flags['non-interactive']) {
|
||||||
|
if (!flags.name) {
|
||||||
|
throw new Error(
|
||||||
|
'Variable name is required in non-interactive mode. Run the command with --name flag.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags.scope === EnvironmentVariableScope.Project && !flags.environment) {
|
||||||
|
throw new Error(
|
||||||
|
'Environment is required when updating project-wide variable in non-interactive mode. Run the command with --environment flag.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -60,7 +60,8 @@ export default class MetadataLint extends EasCommand {
|
|||||||
await loadConfigAsync({ projectDir, profile: submitProfile });
|
await loadConfigAsync({ projectDir, profile: submitProfile });
|
||||||
|
|
||||||
if (flags.json) {
|
if (flags.json) {
|
||||||
return printJsonOnlyOutput([]);
|
printJsonOnlyOutput([]);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.log('✅ Store configuration is valid.');
|
Log.log('✅ Store configuration is valid.');
|
||||||
@@ -70,7 +71,8 @@ export default class MetadataLint extends EasCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (flags.json) {
|
if (flags.json) {
|
||||||
return printJsonOnlyOutput(error.errors);
|
printJsonOnlyOutput(error.errors);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
logMetadataValidationError(error);
|
logMetadataValidationError(error);
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ export default class Onboarding extends EasCommand {
|
|||||||
Log.log('🎉 We finished configuring your project.');
|
Log.log('🎉 We finished configuring your project.');
|
||||||
Log.log();
|
Log.log();
|
||||||
if (
|
if (
|
||||||
app.githubRepository ||
|
!!app.githubRepository ||
|
||||||
actor.preferences.onboarding.environment === OnboardingEnvironment.ExpoGo
|
actor.preferences.onboarding.environment === OnboardingEnvironment.ExpoGo
|
||||||
) {
|
) {
|
||||||
Log.log('🚀 You can now go back to the website to continue:');
|
Log.log('🚀 You can now go back to the website to continue:');
|
||||||
|
|||||||
@@ -70,20 +70,6 @@ describe(UpdatePublish.name, () => {
|
|||||||
jest.mocked(PublishMutation.publishUpdateGroupAsync).mockClear();
|
jest.mocked(PublishMutation.publishUpdateGroupAsync).mockClear();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Deprecated and split to a new command: update:republish
|
|
||||||
it('errors with --republish', async () => {
|
|
||||||
await expect(new UpdatePublish(['--republish'], commandOptions).run()).rejects.toThrow(
|
|
||||||
'--group and --republish flags are deprecated'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Deprecated and split to a new command: update:republish
|
|
||||||
it('errors with --group', async () => {
|
|
||||||
await expect(new UpdatePublish(['--group=abc123'], commandOptions).run()).rejects.toThrow(
|
|
||||||
'--group and --republish flags are deprecated'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('errors with both --channel and --branch', async () => {
|
it('errors with both --channel and --branch', async () => {
|
||||||
const flags = ['--channel=channel123', '--branch=branch123'];
|
const flags = ['--channel=channel123', '--branch=branch123'];
|
||||||
|
|
||||||
@@ -152,16 +138,7 @@ describe(UpdatePublish.name, () => {
|
|||||||
|
|
||||||
// Add configuration to the project that should not be included in the update
|
// Add configuration to the project that should not be included in the update
|
||||||
const { appJson } = mockTestProject({
|
const { appJson } = mockTestProject({
|
||||||
expoConfig: {
|
expoConfig: {},
|
||||||
hooks: {
|
|
||||||
postPublish: [
|
|
||||||
{
|
|
||||||
file: 'custom-hook.js',
|
|
||||||
config: { some: 'config' },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const { platforms, runtimeVersion } = mockTestExport({ platforms: ['ios'] });
|
const { platforms, runtimeVersion } = mockTestExport({ platforms: ['ios'] });
|
||||||
|
|||||||
@@ -55,7 +55,9 @@ jest.mock('../../../utils/code-signing');
|
|||||||
jest.mock('../../../fetch');
|
jest.mock('../../../fetch');
|
||||||
|
|
||||||
describe(UpdateRepublish.name, () => {
|
describe(UpdateRepublish.name, () => {
|
||||||
afterEach(() => vol.reset());
|
afterEach(() => {
|
||||||
|
vol.reset();
|
||||||
|
});
|
||||||
|
|
||||||
it('errors when providing both --group and --branch', async () => {
|
it('errors when providing both --group and --branch', async () => {
|
||||||
const flags = ['--group=1234', '--branch=main'];
|
const flags = ['--group=1234', '--branch=main'];
|
||||||
|
|||||||
@@ -68,7 +68,9 @@ jest.mock('../../../project/publish', () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
describe(UpdateRollBackToEmbedded.name, () => {
|
describe(UpdateRollBackToEmbedded.name, () => {
|
||||||
afterEach(() => vol.reset());
|
afterEach(() => {
|
||||||
|
vol.reset();
|
||||||
|
});
|
||||||
|
|
||||||
it('errors with both --channel and --branch', async () => {
|
it('errors with both --channel and --branch', async () => {
|
||||||
const flags = ['--channel=channel123', '--branch=branch123'];
|
const flags = ['--channel=channel123', '--branch=branch123'];
|
||||||
@@ -142,16 +144,7 @@ describe(UpdateRollBackToEmbedded.name, () => {
|
|||||||
|
|
||||||
// Add configuration to the project that should not be included in the update
|
// Add configuration to the project that should not be included in the update
|
||||||
mockTestProject({
|
mockTestProject({
|
||||||
expoConfig: {
|
expoConfig: {},
|
||||||
hooks: {
|
|
||||||
postPublish: [
|
|
||||||
{
|
|
||||||
file: 'custom-hook.js',
|
|
||||||
config: { some: 'config' },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const platforms = ['ios'];
|
const platforms = ['ios'];
|
||||||
|
|||||||
@@ -0,0 +1,143 @@
|
|||||||
|
import { Flags } from '@oclif/core';
|
||||||
|
import assert from 'assert';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
|
||||||
|
import EasCommand from '../../commandUtils/EasCommand';
|
||||||
|
import { EasNonInteractiveAndJsonFlags } from '../../commandUtils/flags';
|
||||||
|
import { PublishMutation } from '../../graphql/mutations/PublishMutation';
|
||||||
|
import { UpdateQuery } from '../../graphql/queries/UpdateQuery';
|
||||||
|
import Log from '../../log';
|
||||||
|
import { promptAsync } from '../../prompts';
|
||||||
|
import {
|
||||||
|
formatUpdateGroup,
|
||||||
|
getUpdateGroupDescriptions,
|
||||||
|
getUpdateJsonInfosForUpdates,
|
||||||
|
} from '../../update/utils';
|
||||||
|
import { enableJsonOutput, printJsonOnlyOutput } from '../../utils/json';
|
||||||
|
|
||||||
|
export default class UpdateEdit extends EasCommand {
|
||||||
|
static override description = 'edit all the updates in an update group';
|
||||||
|
static override hidden = true;
|
||||||
|
|
||||||
|
static override args = [
|
||||||
|
{
|
||||||
|
name: 'groupId',
|
||||||
|
required: true,
|
||||||
|
description: 'The ID of an update group to edit.',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
static override flags = {
|
||||||
|
'rollout-percentage': Flags.integer({
|
||||||
|
description: `Rollout percentage to set for a rollout update. The specified number must be an integer between 1 and 100.`,
|
||||||
|
required: false,
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
}),
|
||||||
|
...EasNonInteractiveAndJsonFlags,
|
||||||
|
};
|
||||||
|
|
||||||
|
static override contextDefinition = {
|
||||||
|
...this.ContextOptions.LoggedIn,
|
||||||
|
};
|
||||||
|
|
||||||
|
async runAsync(): Promise<void> {
|
||||||
|
const {
|
||||||
|
args: { groupId },
|
||||||
|
flags: {
|
||||||
|
'rollout-percentage': rolloutPercentage,
|
||||||
|
json: jsonFlag,
|
||||||
|
'non-interactive': nonInteractive,
|
||||||
|
},
|
||||||
|
} = await this.parse(UpdateEdit);
|
||||||
|
|
||||||
|
const {
|
||||||
|
loggedIn: { graphqlClient },
|
||||||
|
} = await this.getContextAsync(UpdateEdit, { nonInteractive });
|
||||||
|
|
||||||
|
if (jsonFlag) {
|
||||||
|
enableJsonOutput();
|
||||||
|
}
|
||||||
|
|
||||||
|
const proposedUpdatesToEdit = (
|
||||||
|
await UpdateQuery.viewUpdateGroupAsync(graphqlClient, { groupId })
|
||||||
|
).map(u => ({ updateId: u.id, rolloutPercentage: u.rolloutPercentage }));
|
||||||
|
|
||||||
|
const updatesToEdit = proposedUpdatesToEdit.filter(
|
||||||
|
(u): u is { updateId: string; rolloutPercentage: number } =>
|
||||||
|
u.rolloutPercentage !== null && u.rolloutPercentage !== undefined
|
||||||
|
);
|
||||||
|
|
||||||
|
if (updatesToEdit.length === 0) {
|
||||||
|
throw new Error('Cannot edit rollout percentage on update group that is not a rollout.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const rolloutPercentagesSet = new Set(updatesToEdit.map(u => u.rolloutPercentage));
|
||||||
|
if (rolloutPercentagesSet.size !== 1) {
|
||||||
|
throw new Error(
|
||||||
|
'Cannot edit rollout percentage for a group with non-equal percentages for updates in the group.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const previousPercentage = updatesToEdit[0].rolloutPercentage;
|
||||||
|
|
||||||
|
if (nonInteractive && rolloutPercentage === undefined) {
|
||||||
|
throw new Error('Must specify --rollout-percentage in non-interactive mode');
|
||||||
|
}
|
||||||
|
|
||||||
|
let rolloutPercentageToSet = rolloutPercentage;
|
||||||
|
if (rolloutPercentageToSet === undefined) {
|
||||||
|
const { percentage } = await promptAsync({
|
||||||
|
type: 'number',
|
||||||
|
message: `New rollout percentage (min: ${previousPercentage}, max: 100)`,
|
||||||
|
validate: value => {
|
||||||
|
if (value <= previousPercentage) {
|
||||||
|
return `Rollout percentage must be greater than previous rollout percentage (${previousPercentage})`;
|
||||||
|
} else if (value > 100) {
|
||||||
|
return `Rollout percentage must not be greater than 100`;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: 'percentage',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!percentage) {
|
||||||
|
Log.log('Aborted.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rolloutPercentageToSet = percentage;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(rolloutPercentageToSet !== undefined);
|
||||||
|
|
||||||
|
if (rolloutPercentageToSet < previousPercentage) {
|
||||||
|
throw new Error(
|
||||||
|
`Rollout percentage must be greater than previous rollout percentage (${previousPercentage})`
|
||||||
|
);
|
||||||
|
} else if (rolloutPercentageToSet > 100) {
|
||||||
|
throw new Error('Rollout percentage must not be greater than 100');
|
||||||
|
}
|
||||||
|
|
||||||
|
const updatedUpdates = await Promise.all(
|
||||||
|
updatesToEdit.map(async u => {
|
||||||
|
return await PublishMutation.setRolloutPercentageAsync(
|
||||||
|
graphqlClient,
|
||||||
|
u.updateId,
|
||||||
|
rolloutPercentageToSet!
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
if (jsonFlag) {
|
||||||
|
printJsonOnlyOutput(getUpdateJsonInfosForUpdates(updatedUpdates));
|
||||||
|
} else {
|
||||||
|
const [updateGroupDescription] = getUpdateGroupDescriptions([updatedUpdates]);
|
||||||
|
|
||||||
|
Log.log(chalk.bold('Update group:'));
|
||||||
|
|
||||||
|
Log.log(formatUpdateGroup(updateGroupDescription));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import { Platform as PublishPlatform } from '@expo/config';
|
|
||||||
import { Workflow } from '@expo/eas-build-job';
|
import { Workflow } from '@expo/eas-build-job';
|
||||||
import { Errors, Flags } from '@oclif/core';
|
import { Errors, Flags } from '@oclif/core';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
@@ -16,6 +15,7 @@ import {
|
|||||||
StatuspageServiceName,
|
StatuspageServiceName,
|
||||||
UpdateInfoGroup,
|
UpdateInfoGroup,
|
||||||
UpdatePublishMutation,
|
UpdatePublishMutation,
|
||||||
|
UpdateRolloutInfoGroup,
|
||||||
} from '../../graphql/generated';
|
} from '../../graphql/generated';
|
||||||
import { PublishMutation } from '../../graphql/mutations/PublishMutation';
|
import { PublishMutation } from '../../graphql/mutations/PublishMutation';
|
||||||
import Log, { learnMore, link } from '../../log';
|
import Log, { learnMore, link } from '../../log';
|
||||||
@@ -23,16 +23,17 @@ import { ora } from '../../ora';
|
|||||||
import { RequestedPlatform } from '../../platform';
|
import { RequestedPlatform } from '../../platform';
|
||||||
import { getOwnerAccountForProjectIdAsync } from '../../project/projectUtils';
|
import { getOwnerAccountForProjectIdAsync } from '../../project/projectUtils';
|
||||||
import {
|
import {
|
||||||
ExpoCLIExportPlatformFlag,
|
|
||||||
RawAsset,
|
RawAsset,
|
||||||
|
UpdatePublishPlatform,
|
||||||
buildBundlesAsync,
|
buildBundlesAsync,
|
||||||
buildUnsortedUpdateInfoGroupAsync,
|
buildUnsortedUpdateInfoGroupAsync,
|
||||||
collectAssetsAsync,
|
collectAssetsAsync,
|
||||||
defaultPublishPlatforms,
|
defaultPublishPlatforms,
|
||||||
filterExportedPlatformsByFlag,
|
filterCollectedAssetsByRequestedPlatforms,
|
||||||
|
generateEasMetadataAsync,
|
||||||
getBranchNameForCommandAsync,
|
getBranchNameForCommandAsync,
|
||||||
getRequestedPlatform,
|
|
||||||
getRuntimeToPlatformMappingFromRuntimeVersions,
|
getRuntimeToPlatformMappingFromRuntimeVersions,
|
||||||
|
getRuntimeToUpdateRolloutInfoGroupMappingAsync,
|
||||||
getRuntimeVersionObjectAsync,
|
getRuntimeVersionObjectAsync,
|
||||||
getUpdateMessageForCommandAsync,
|
getUpdateMessageForCommandAsync,
|
||||||
isUploadedAssetCountAboveWarningThreshold,
|
isUploadedAssetCountAboveWarningThreshold,
|
||||||
@@ -65,17 +66,15 @@ type RawUpdateFlags = {
|
|||||||
'skip-bundler': boolean;
|
'skip-bundler': boolean;
|
||||||
'clear-cache': boolean;
|
'clear-cache': boolean;
|
||||||
'private-key-path'?: string;
|
'private-key-path'?: string;
|
||||||
|
'emit-metadata': boolean;
|
||||||
|
'rollout-percentage'?: number;
|
||||||
'non-interactive': boolean;
|
'non-interactive': boolean;
|
||||||
json: boolean;
|
json: boolean;
|
||||||
/** @deprecated see UpdateRepublish command */
|
|
||||||
group?: string;
|
|
||||||
/** @deprecated see UpdateRepublish command */
|
|
||||||
republish?: boolean;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type UpdateFlags = {
|
type UpdateFlags = {
|
||||||
auto: boolean;
|
auto: boolean;
|
||||||
platform: ExpoCLIExportPlatformFlag;
|
platform: RequestedPlatform;
|
||||||
branchName?: string;
|
branchName?: string;
|
||||||
channelName?: string;
|
channelName?: string;
|
||||||
updateMessage?: string;
|
updateMessage?: string;
|
||||||
@@ -83,6 +82,8 @@ type UpdateFlags = {
|
|||||||
skipBundler: boolean;
|
skipBundler: boolean;
|
||||||
clearCache: boolean;
|
clearCache: boolean;
|
||||||
privateKeyPath?: string;
|
privateKeyPath?: string;
|
||||||
|
emitMetadata: boolean;
|
||||||
|
rolloutPercentage?: number;
|
||||||
json: boolean;
|
json: boolean;
|
||||||
nonInteractive: boolean;
|
nonInteractive: boolean;
|
||||||
};
|
};
|
||||||
@@ -104,14 +105,6 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
description: 'A short message describing the update',
|
description: 'A short message describing the update',
|
||||||
required: false,
|
required: false,
|
||||||
}),
|
}),
|
||||||
republish: Flags.boolean({
|
|
||||||
description: 'Republish an update group (deprecated, see republish command)',
|
|
||||||
exclusive: ['input-dir', 'skip-bundler'],
|
|
||||||
}),
|
|
||||||
group: Flags.string({
|
|
||||||
description: 'Update group to republish (deprecated, see republish command)',
|
|
||||||
exclusive: ['input-dir', 'skip-bundler'],
|
|
||||||
}),
|
|
||||||
'input-dir': Flags.string({
|
'input-dir': Flags.string({
|
||||||
description: 'Location of the bundle',
|
description: 'Location of the bundle',
|
||||||
default: 'dist',
|
default: 'dist',
|
||||||
@@ -125,6 +118,17 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
description: `Clear the bundler cache before publishing`,
|
description: `Clear the bundler cache before publishing`,
|
||||||
default: false,
|
default: false,
|
||||||
}),
|
}),
|
||||||
|
'emit-metadata': Flags.boolean({
|
||||||
|
description: `Emit "eas-update-metadata.json" in the bundle folder with detailed information about the generated updates`,
|
||||||
|
default: false,
|
||||||
|
}),
|
||||||
|
'rollout-percentage': Flags.integer({
|
||||||
|
description: `Percentage of users this update should be immediately available to. Users not in the rollout will be served the previous latest update on the branch, even if that update is itself being rolled out. The specified number must be an integer between 1 and 100. When not specified, this defaults to 100.`,
|
||||||
|
required: false,
|
||||||
|
hidden: true,
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
}),
|
||||||
platform: Flags.enum({
|
platform: Flags.enum({
|
||||||
char: 'p',
|
char: 'p',
|
||||||
options: [
|
options: [
|
||||||
@@ -158,7 +162,7 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
const paginatedQueryOptions = getPaginatedQueryOptions(rawFlags);
|
const paginatedQueryOptions = getPaginatedQueryOptions(rawFlags);
|
||||||
const {
|
const {
|
||||||
auto: autoFlag,
|
auto: autoFlag,
|
||||||
platform: platformFlag,
|
platform: requestedPlatform,
|
||||||
channelName: channelNameArg,
|
channelName: channelNameArg,
|
||||||
updateMessage: updateMessageArg,
|
updateMessage: updateMessageArg,
|
||||||
inputDir,
|
inputDir,
|
||||||
@@ -168,6 +172,8 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
json: jsonFlag,
|
json: jsonFlag,
|
||||||
nonInteractive,
|
nonInteractive,
|
||||||
branchName: branchNameArg,
|
branchName: branchNameArg,
|
||||||
|
emitMetadata,
|
||||||
|
rolloutPercentage,
|
||||||
} = this.sanitizeFlags(rawFlags);
|
} = this.sanitizeFlags(rawFlags);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -196,7 +202,7 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
|
|
||||||
await ensureEASUpdateIsConfiguredAsync({
|
await ensureEASUpdateIsConfiguredAsync({
|
||||||
exp: expPossiblyWithoutEasUpdateConfigured,
|
exp: expPossiblyWithoutEasUpdateConfigured,
|
||||||
platform: getRequestedPlatform(platformFlag),
|
platform: requestedPlatform,
|
||||||
projectDir,
|
projectDir,
|
||||||
projectId,
|
projectId,
|
||||||
vcsClient,
|
vcsClient,
|
||||||
@@ -229,7 +235,13 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
if (!skipBundler) {
|
if (!skipBundler) {
|
||||||
const bundleSpinner = ora().start('Exporting...');
|
const bundleSpinner = ora().start('Exporting...');
|
||||||
try {
|
try {
|
||||||
await buildBundlesAsync({ projectDir, inputDir, exp, platformFlag, clearCache });
|
await buildBundlesAsync({
|
||||||
|
projectDir,
|
||||||
|
inputDir,
|
||||||
|
exp,
|
||||||
|
platformFlag: requestedPlatform,
|
||||||
|
clearCache,
|
||||||
|
});
|
||||||
bundleSpinner.succeed('Exported bundle(s)');
|
bundleSpinner.succeed('Exported bundle(s)');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
bundleSpinner.fail('Export failed');
|
bundleSpinner.fail('Export failed');
|
||||||
@@ -244,15 +256,15 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
let unsortedUpdateInfoGroups: UpdateInfoGroup = {};
|
let unsortedUpdateInfoGroups: UpdateInfoGroup = {};
|
||||||
let uploadedAssetCount = 0;
|
let uploadedAssetCount = 0;
|
||||||
let assetLimitPerUpdateGroup = 0;
|
let assetLimitPerUpdateGroup = 0;
|
||||||
let realizedPlatforms: PublishPlatform[] = [];
|
let realizedPlatforms: UpdatePublishPlatform[] = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const collectedAssets = await collectAssetsAsync(distRoot);
|
const collectedAssets = await collectAssetsAsync(distRoot);
|
||||||
const assets = filterExportedPlatformsByFlag(collectedAssets, platformFlag);
|
const assets = filterCollectedAssetsByRequestedPlatforms(collectedAssets, requestedPlatform);
|
||||||
realizedPlatforms = Object.keys(assets) as PublishPlatform[];
|
realizedPlatforms = Object.keys(assets) as UpdatePublishPlatform[];
|
||||||
|
|
||||||
// Timeout mechanism:
|
// Timeout mechanism:
|
||||||
// - Start with NO_ACTIVITY_TIMEOUT. 90 seconds is chosen because the cloud function that processes
|
// - Start with NO_ACTIVITY_TIMEOUT. 180 seconds is chosen because the cloud function that processes
|
||||||
// uploaded assets has a timeout of 60 seconds and uploading can take some time on a slow connection.
|
// uploaded assets has a timeout of 60 seconds and uploading can take some time on a slow connection.
|
||||||
// - Each time one or more assets reports as ready, reset the timeout.
|
// - Each time one or more assets reports as ready, reset the timeout.
|
||||||
// - Each time an asset upload begins, reset the timeout. This includes retries.
|
// - Each time an asset upload begins, reset the timeout. This includes retries.
|
||||||
@@ -261,7 +273,7 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
// - At the same time as upload is started, start timeout checker which checks every 1 second to see
|
// - At the same time as upload is started, start timeout checker which checks every 1 second to see
|
||||||
// if timeout has been reached. When timeout expires, send a cancellation signal to currently running
|
// if timeout has been reached. When timeout expires, send a cancellation signal to currently running
|
||||||
// upload function call to instruct it to stop uploading or checking for successful processing.
|
// upload function call to instruct it to stop uploading or checking for successful processing.
|
||||||
const NO_ACTIVITY_TIMEOUT = 90 * 1000; // 90 seconds
|
const NO_ACTIVITY_TIMEOUT = 180 * 1000; // 180 seconds
|
||||||
let lastUploadedStorageKeys = new Set<string>();
|
let lastUploadedStorageKeys = new Set<string>();
|
||||||
let lastAssetUploadResults: {
|
let lastAssetUploadResults: {
|
||||||
asset: RawAsset & { storageKey: string };
|
asset: RawAsset & { storageKey: string };
|
||||||
@@ -342,7 +354,7 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
Log.debug(chalk.dim(`- ${uploadedAssetPath}`));
|
Log.debug(chalk.dim(`- ${uploadedAssetPath}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
const platformString = (Object.keys(assets) as PublishPlatform[])
|
const platformString = realizedPlatforms
|
||||||
.map(platform => {
|
.map(platform => {
|
||||||
const collectedAssetForPlatform = nullthrows(assets[platform]);
|
const collectedAssetForPlatform = nullthrows(assets[platform]);
|
||||||
const totalAssetsForPlatform = collectedAssetForPlatform.assets.length + 1; // launch asset
|
const totalAssetsForPlatform = collectedAssetForPlatform.assets.length + 1; // launch asset
|
||||||
@@ -380,6 +392,16 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
branchName,
|
branchName,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const runtimeVersionToRolloutInfoGroup =
|
||||||
|
rolloutPercentage !== undefined
|
||||||
|
? await getRuntimeToUpdateRolloutInfoGroupMappingAsync(graphqlClient, {
|
||||||
|
appId: projectId,
|
||||||
|
branchName,
|
||||||
|
rolloutPercentage,
|
||||||
|
runtimeToPlatformMapping,
|
||||||
|
})
|
||||||
|
: undefined;
|
||||||
|
|
||||||
const gitCommitHash = await vcsClient.getCommitHashAsync();
|
const gitCommitHash = await vcsClient.getCommitHashAsync();
|
||||||
const isGitWorkingTreeDirty = await vcsClient.hasUncommittedChangesAsync();
|
const isGitWorkingTreeDirty = await vcsClient.hasUncommittedChangesAsync();
|
||||||
|
|
||||||
@@ -393,9 +415,22 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const rolloutInfoGroupForRuntimeVersion = runtimeVersionToRolloutInfoGroup
|
||||||
|
? runtimeVersionToRolloutInfoGroup.get(runtimeVersion)
|
||||||
|
: null;
|
||||||
|
const localRolloutInfoGroup = rolloutInfoGroupForRuntimeVersion
|
||||||
|
? Object.fromEntries(
|
||||||
|
platforms.map(platform => [
|
||||||
|
platform,
|
||||||
|
rolloutInfoGroupForRuntimeVersion[platform as keyof UpdateRolloutInfoGroup],
|
||||||
|
])
|
||||||
|
)
|
||||||
|
: null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
branchId,
|
branchId,
|
||||||
updateInfoGroup: localUpdateInfoGroup,
|
updateInfoGroup: localUpdateInfoGroup,
|
||||||
|
rolloutInfoGroup: localRolloutInfoGroup,
|
||||||
runtimeVersion,
|
runtimeVersion,
|
||||||
message: updateMessage,
|
message: updateMessage,
|
||||||
gitCommitHash,
|
gitCommitHash,
|
||||||
@@ -462,6 +497,10 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!skipBundler && emitMetadata) {
|
||||||
|
Log.log('Generating eas-update-metadata.json');
|
||||||
|
await generateEasMetadataAsync(distRoot, getUpdateJsonInfosForUpdates(newUpdates));
|
||||||
|
}
|
||||||
if (jsonFlag) {
|
if (jsonFlag) {
|
||||||
printJsonOnlyOutput(getUpdateJsonInfosForUpdates(newUpdates));
|
printJsonOnlyOutput(getUpdateJsonInfosForUpdates(newUpdates));
|
||||||
} else {
|
} else {
|
||||||
@@ -505,6 +544,22 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
? [{ label: 'Android update ID', value: newAndroidUpdate.id }]
|
? [{ label: 'Android update ID', value: newAndroidUpdate.id }]
|
||||||
: []),
|
: []),
|
||||||
...(newIosUpdate ? [{ label: 'iOS update ID', value: newIosUpdate.id }] : []),
|
...(newIosUpdate ? [{ label: 'iOS update ID', value: newIosUpdate.id }] : []),
|
||||||
|
...(newAndroidUpdate?.rolloutControlUpdate
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
label: 'Android Rollout',
|
||||||
|
value: `${newAndroidUpdate.rolloutPercentage}% (Base update ID: ${newAndroidUpdate.rolloutControlUpdate.id})`,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
...(newIosUpdate?.rolloutControlUpdate
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
label: 'iOS Rollout',
|
||||||
|
value: `${newIosUpdate.rolloutPercentage}% (Base update ID: ${newIosUpdate.rolloutControlUpdate.id})`,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
{ label: 'Message', value: updateMessage ?? '' },
|
{ label: 'Message', value: updateMessage ?? '' },
|
||||||
...(gitCommitHash
|
...(gitCommitHash
|
||||||
? [
|
? [
|
||||||
@@ -545,21 +600,14 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags.group || flags.republish) {
|
const skipBundler = flags['skip-bundler'] ?? false;
|
||||||
// Pick the first flag set that is defined, in this specific order
|
let emitMetadata = flags['emit-metadata'] ?? false;
|
||||||
const args = [
|
|
||||||
['--group', flags.group],
|
|
||||||
['--branch', flags.branch],
|
|
||||||
].filter(([_, value]) => value)[0];
|
|
||||||
|
|
||||||
Log.newLine();
|
if (skipBundler && emitMetadata) {
|
||||||
|
emitMetadata = false;
|
||||||
Log.warn(
|
Log.warn(
|
||||||
'The --group and --republish flags are deprecated, use the republish command instead:'
|
'ignoring flag --emit-metadata as metadata cannot be generated when skipping bundle generation'
|
||||||
);
|
);
|
||||||
Log.warn(` ${chalk.bold([`eas update:republish`, ...(args ?? [])].join(' '))}`);
|
|
||||||
Log.newLine();
|
|
||||||
|
|
||||||
Errors.error('--group and --republish flags are deprecated', { exit: 1 });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -568,11 +616,13 @@ export default class UpdatePublish extends EasCommand {
|
|||||||
channelName,
|
channelName,
|
||||||
updateMessage,
|
updateMessage,
|
||||||
inputDir: flags['input-dir'],
|
inputDir: flags['input-dir'],
|
||||||
skipBundler: flags['skip-bundler'],
|
skipBundler,
|
||||||
clearCache: flags['clear-cache'],
|
clearCache: flags['clear-cache'],
|
||||||
platform: flags.platform as RequestedPlatform,
|
platform: flags.platform as RequestedPlatform,
|
||||||
privateKeyPath: flags['private-key-path'],
|
privateKeyPath: flags['private-key-path'],
|
||||||
|
rolloutPercentage: flags['rollout-percentage'],
|
||||||
nonInteractive,
|
nonInteractive,
|
||||||
|
emitMetadata,
|
||||||
json: flags.json ?? false,
|
json: flags.json ?? false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,10 +53,13 @@ export default class UpdateList extends EasCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (all) {
|
if (all) {
|
||||||
listAndRenderUpdateGroupsOnAppAsync(graphqlClient, { projectId, paginatedQueryOptions });
|
await listAndRenderUpdateGroupsOnAppAsync(graphqlClient, {
|
||||||
|
projectId,
|
||||||
|
paginatedQueryOptions,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
if (branchFlag) {
|
if (branchFlag) {
|
||||||
listAndRenderUpdateGroupsOnBranchAsync(graphqlClient, {
|
await listAndRenderUpdateGroupsOnBranchAsync(graphqlClient, {
|
||||||
projectId,
|
projectId,
|
||||||
branchName: branchFlag,
|
branchName: branchFlag,
|
||||||
paginatedQueryOptions,
|
paginatedQueryOptions,
|
||||||
@@ -81,7 +84,7 @@ export default class UpdateList extends EasCommand {
|
|||||||
offset: 0,
|
offset: 0,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
listAndRenderUpdateGroupsOnBranchAsync(graphqlClient, {
|
await listAndRenderUpdateGroupsOnBranchAsync(graphqlClient, {
|
||||||
projectId,
|
projectId,
|
||||||
branchName: selectedBranch.name,
|
branchName: selectedBranch.name,
|
||||||
paginatedQueryOptions,
|
paginatedQueryOptions,
|
||||||
|
|||||||
@@ -24,10 +24,9 @@ import {
|
|||||||
getOwnerAccountForProjectIdAsync,
|
getOwnerAccountForProjectIdAsync,
|
||||||
} from '../../project/projectUtils';
|
} from '../../project/projectUtils';
|
||||||
import {
|
import {
|
||||||
ExpoCLIExportPlatformFlag,
|
UpdatePublishPlatform,
|
||||||
defaultPublishPlatforms,
|
defaultPublishPlatforms,
|
||||||
getBranchNameForCommandAsync,
|
getBranchNameForCommandAsync,
|
||||||
getRequestedPlatform,
|
|
||||||
getRuntimeToPlatformMappingFromRuntimeVersions,
|
getRuntimeToPlatformMappingFromRuntimeVersions,
|
||||||
getRuntimeVersionObjectAsync,
|
getRuntimeVersionObjectAsync,
|
||||||
getUpdateMessageForCommandAsync,
|
getUpdateMessageForCommandAsync,
|
||||||
@@ -60,7 +59,7 @@ type RawUpdateFlags = {
|
|||||||
|
|
||||||
type UpdateFlags = {
|
type UpdateFlags = {
|
||||||
auto: boolean;
|
auto: boolean;
|
||||||
platform: ExpoCLIExportPlatformFlag;
|
platform: RequestedPlatform;
|
||||||
branchName?: string;
|
branchName?: string;
|
||||||
channelName?: string;
|
channelName?: string;
|
||||||
updateMessage?: string;
|
updateMessage?: string;
|
||||||
@@ -150,7 +149,7 @@ export default class UpdateRollBackToEmbedded extends EasCommand {
|
|||||||
|
|
||||||
await ensureEASUpdateIsConfiguredAsync({
|
await ensureEASUpdateIsConfiguredAsync({
|
||||||
exp: expPossiblyWithoutEasUpdateConfigured,
|
exp: expPossiblyWithoutEasUpdateConfigured,
|
||||||
platform: getRequestedPlatform(platformFlag),
|
platform: platformFlag,
|
||||||
projectDir,
|
projectDir,
|
||||||
projectId,
|
projectId,
|
||||||
vcsClient,
|
vcsClient,
|
||||||
@@ -182,7 +181,7 @@ export default class UpdateRollBackToEmbedded extends EasCommand {
|
|||||||
jsonFlag,
|
jsonFlag,
|
||||||
});
|
});
|
||||||
|
|
||||||
const realizedPlatforms: PublishPlatform[] =
|
const realizedPlatforms: UpdatePublishPlatform[] =
|
||||||
platformFlag === 'all' ? defaultPublishPlatforms : [platformFlag];
|
platformFlag === 'all' ? defaultPublishPlatforms : [platformFlag];
|
||||||
|
|
||||||
const { branchId } = await ensureBranchExistsAsync(graphqlClient, {
|
const { branchId } = await ensureBranchExistsAsync(graphqlClient, {
|
||||||
@@ -300,7 +299,7 @@ export default class UpdateRollBackToEmbedded extends EasCommand {
|
|||||||
updateMessage: string | undefined;
|
updateMessage: string | undefined;
|
||||||
branchId: string;
|
branchId: string;
|
||||||
codeSigningInfo: CodeSigningInfo | undefined;
|
codeSigningInfo: CodeSigningInfo | undefined;
|
||||||
runtimeVersions: { platform: string; runtimeVersion: string }[];
|
runtimeVersions: { platform: UpdatePublishPlatform; runtimeVersion: string }[];
|
||||||
realizedPlatforms: PublishPlatform[];
|
realizedPlatforms: PublishPlatform[];
|
||||||
}): Promise<UpdatePublishMutation['updateBranch']['publishUpdateGroups']> {
|
}): Promise<UpdatePublishMutation['updateBranch']['publishUpdateGroups']> {
|
||||||
const runtimeToPlatformMapping =
|
const runtimeToPlatformMapping =
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ export default class AndroidCredentialsProvider {
|
|||||||
public readonly platform = Platform.ANDROID;
|
public readonly platform = Platform.ANDROID;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private ctx: CredentialsContext,
|
private readonly ctx: CredentialsContext,
|
||||||
private options: Options
|
private readonly options: Options
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async getCredentialsAsync(
|
public async getCredentialsAsync(
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { CredentialsContext } from '../../context';
|
|||||||
import { AppLookupParams } from '../api/GraphqlClient';
|
import { AppLookupParams } from '../api/GraphqlClient';
|
||||||
|
|
||||||
export class AssignFcm {
|
export class AssignFcm {
|
||||||
constructor(private app: AppLookupParams) {}
|
constructor(private readonly app: AppLookupParams) {}
|
||||||
|
|
||||||
public async runAsync(
|
public async runAsync(
|
||||||
ctx: CredentialsContext,
|
ctx: CredentialsContext,
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ import { CredentialsContext } from '../../context';
|
|||||||
import { AppLookupParams } from '../api/GraphqlClient';
|
import { AppLookupParams } from '../api/GraphqlClient';
|
||||||
|
|
||||||
export class AssignGoogleServiceAccountKeyForFcmV1 {
|
export class AssignGoogleServiceAccountKeyForFcmV1 {
|
||||||
constructor(private app: AppLookupParams) {}
|
constructor(private readonly app: AppLookupParams) {}
|
||||||
|
|
||||||
public async runAsync(
|
public async runAsync(
|
||||||
ctx: CredentialsContext,
|
ctx: CredentialsContext,
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ import { CredentialsContext } from '../../context';
|
|||||||
import { AppLookupParams } from '../api/GraphqlClient';
|
import { AppLookupParams } from '../api/GraphqlClient';
|
||||||
|
|
||||||
export class AssignGoogleServiceAccountKeyForSubmissions {
|
export class AssignGoogleServiceAccountKeyForSubmissions {
|
||||||
constructor(private app: AppLookupParams) {}
|
constructor(private readonly app: AppLookupParams) {}
|
||||||
|
|
||||||
public async runAsync(
|
public async runAsync(
|
||||||
ctx: CredentialsContext,
|
ctx: CredentialsContext,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { promptAsync } from '../../../prompts';
|
|||||||
import { CredentialsContext } from '../../context';
|
import { CredentialsContext } from '../../context';
|
||||||
|
|
||||||
export class CreateFcm {
|
export class CreateFcm {
|
||||||
constructor(private account: AccountFragment) {}
|
constructor(private readonly account: AccountFragment) {}
|
||||||
|
|
||||||
public async runAsync(ctx: CredentialsContext): Promise<AndroidFcmFragment> {
|
public async runAsync(ctx: CredentialsContext): Promise<AndroidFcmFragment> {
|
||||||
if (ctx.nonInteractive) {
|
if (ctx.nonInteractive) {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import {
|
|||||||
} from '../utils/googleServiceAccountKey';
|
} from '../utils/googleServiceAccountKey';
|
||||||
|
|
||||||
export class CreateGoogleServiceAccountKey {
|
export class CreateGoogleServiceAccountKey {
|
||||||
constructor(private account: AccountFragment) {}
|
constructor(private readonly account: AccountFragment) {}
|
||||||
|
|
||||||
public async runAsync(ctx: CredentialsContext): Promise<GoogleServiceAccountKeyFragment> {
|
public async runAsync(ctx: CredentialsContext): Promise<GoogleServiceAccountKeyFragment> {
|
||||||
if (ctx.nonInteractive) {
|
if (ctx.nonInteractive) {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { generateRandomKeystoreAsync } from '../utils/keystore';
|
|||||||
import { getKeystoreWithType, validateKeystore } from '../utils/keystoreNew';
|
import { getKeystoreWithType, validateKeystore } from '../utils/keystoreNew';
|
||||||
|
|
||||||
export class CreateKeystore {
|
export class CreateKeystore {
|
||||||
constructor(private account: AccountFragment) {}
|
constructor(private readonly account: AccountFragment) {}
|
||||||
|
|
||||||
public async runAsync(ctx: CredentialsContext): Promise<AndroidKeystoreFragment> {
|
public async runAsync(ctx: CredentialsContext): Promise<AndroidKeystoreFragment> {
|
||||||
if (ctx.nonInteractive) {
|
if (ctx.nonInteractive) {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ interface DownloadKeystoreOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class DownloadKeystore {
|
export class DownloadKeystore {
|
||||||
constructor(private options: DownloadKeystoreOptions) {}
|
constructor(private readonly options: DownloadKeystoreOptions) {}
|
||||||
|
|
||||||
public async runAsync(
|
public async runAsync(
|
||||||
ctx: CredentialsContext,
|
ctx: CredentialsContext,
|
||||||
@@ -62,7 +62,7 @@ export class DownloadKeystore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class BackupKeystore {
|
export class BackupKeystore {
|
||||||
constructor(private app: AppLookupParams) {}
|
constructor(private readonly app: AppLookupParams) {}
|
||||||
|
|
||||||
public async runAsync(
|
public async runAsync(
|
||||||
ctx: CredentialsContext,
|
ctx: CredentialsContext,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { CredentialsContext } from '../../context';
|
|||||||
import { AppLookupParams, formatProjectFullName } from '../api/GraphqlClient';
|
import { AppLookupParams, formatProjectFullName } from '../api/GraphqlClient';
|
||||||
|
|
||||||
export class RemoveFcm {
|
export class RemoveFcm {
|
||||||
constructor(private app: AppLookupParams) {}
|
constructor(private readonly app: AppLookupParams) {}
|
||||||
|
|
||||||
async runAsync(ctx: CredentialsContext): Promise<void> {
|
async runAsync(ctx: CredentialsContext): Promise<void> {
|
||||||
if (ctx.nonInteractive) {
|
if (ctx.nonInteractive) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { CredentialsContext } from '../../context';
|
|||||||
import { selectGoogleServiceAccountKeyAsync } from '../utils/googleServiceAccountKey';
|
import { selectGoogleServiceAccountKeyAsync } from '../utils/googleServiceAccountKey';
|
||||||
|
|
||||||
export class SelectAndRemoveGoogleServiceAccountKey {
|
export class SelectAndRemoveGoogleServiceAccountKey {
|
||||||
constructor(private account: AccountFragment) {}
|
constructor(private readonly account: AccountFragment) {}
|
||||||
|
|
||||||
async runAsync(ctx: CredentialsContext): Promise<void> {
|
async runAsync(ctx: CredentialsContext): Promise<void> {
|
||||||
if (ctx.nonInteractive) {
|
if (ctx.nonInteractive) {
|
||||||
@@ -31,7 +31,7 @@ export class SelectAndRemoveGoogleServiceAccountKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class RemoveGoogleServiceAccountKey {
|
export class RemoveGoogleServiceAccountKey {
|
||||||
constructor(private googleServiceAccountKey: GoogleServiceAccountKeyFragment) {}
|
constructor(private readonly googleServiceAccountKey: GoogleServiceAccountKeyFragment) {}
|
||||||
|
|
||||||
public async runAsync(ctx: CredentialsContext): Promise<void> {
|
public async runAsync(ctx: CredentialsContext): Promise<void> {
|
||||||
if (ctx.nonInteractive) {
|
if (ctx.nonInteractive) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { CredentialsContext } from '../../context';
|
|||||||
import { AppLookupParams } from '../api/GraphqlClient';
|
import { AppLookupParams } from '../api/GraphqlClient';
|
||||||
|
|
||||||
export class RemoveKeystore {
|
export class RemoveKeystore {
|
||||||
constructor(private app: AppLookupParams) {}
|
constructor(private readonly app: AppLookupParams) {}
|
||||||
|
|
||||||
async runAsync(
|
async runAsync(
|
||||||
ctx: CredentialsContext,
|
ctx: CredentialsContext,
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ interface Options {
|
|||||||
* @name: sets up build credentials for the specified configuration. If no name is specified, the default configuration is setup
|
* @name: sets up build credentials for the specified configuration. If no name is specified, the default configuration is setup
|
||||||
*/
|
*/
|
||||||
export class SetUpBuildCredentials {
|
export class SetUpBuildCredentials {
|
||||||
constructor(private options: Options) {}
|
constructor(private readonly options: Options) {}
|
||||||
|
|
||||||
async runAsync(ctx: CredentialsContext): Promise<AndroidAppBuildCredentialsFragment> {
|
async runAsync(ctx: CredentialsContext): Promise<AndroidAppBuildCredentialsFragment> {
|
||||||
const { app, name: maybeName } = this.options;
|
const { app, name: maybeName } = this.options;
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ import { AppLookupParams } from '../api/GraphqlClient';
|
|||||||
import { getKeystoreWithType } from '../utils/keystoreNew';
|
import { getKeystoreWithType } from '../utils/keystoreNew';
|
||||||
|
|
||||||
export class SetUpBuildCredentialsFromCredentialsJson {
|
export class SetUpBuildCredentialsFromCredentialsJson {
|
||||||
constructor(private app: AppLookupParams) {}
|
constructor(private readonly app: AppLookupParams) {}
|
||||||
|
|
||||||
async runAsync(ctx: CredentialsContext): Promise<AndroidAppBuildCredentialsFragment | null> {
|
async runAsync(ctx: CredentialsContext): Promise<AndroidAppBuildCredentialsFragment | null> {
|
||||||
if (ctx.nonInteractive) {
|
if (ctx.nonInteractive) {
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@ import { MissingCredentialsNonInteractiveError } from '../../errors';
|
|||||||
import { AppLookupParams } from '../api/GraphqlClient';
|
import { AppLookupParams } from '../api/GraphqlClient';
|
||||||
|
|
||||||
export class SetUpGoogleServiceAccountKeyForFcmV1 {
|
export class SetUpGoogleServiceAccountKeyForFcmV1 {
|
||||||
constructor(private app: AppLookupParams) {}
|
constructor(private readonly app: AppLookupParams) {}
|
||||||
|
|
||||||
public async runAsync(ctx: CredentialsContext): Promise<CommonAndroidAppCredentialsFragment> {
|
public async runAsync(ctx: CredentialsContext): Promise<CommonAndroidAppCredentialsFragment> {
|
||||||
const isKeySetup = await this.isGoogleServiceAccountKeySetupAsync(ctx);
|
const isKeySetup = await this.isGoogleServiceAccountKeySetupAsync(ctx);
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@ import { MissingCredentialsNonInteractiveError } from '../../errors';
|
|||||||
import { AppLookupParams } from '../api/GraphqlClient';
|
import { AppLookupParams } from '../api/GraphqlClient';
|
||||||
|
|
||||||
export class SetUpGoogleServiceAccountKeyForSubmissions {
|
export class SetUpGoogleServiceAccountKeyForSubmissions {
|
||||||
constructor(private app: AppLookupParams) {}
|
constructor(private readonly app: AppLookupParams) {}
|
||||||
|
|
||||||
public async runAsync(ctx: CredentialsContext): Promise<CommonAndroidAppCredentialsFragment> {
|
public async runAsync(ctx: CredentialsContext): Promise<CommonAndroidAppCredentialsFragment> {
|
||||||
const isKeySetup = await this.isGoogleServiceAccountKeySetupAsync(ctx);
|
const isKeySetup = await this.isGoogleServiceAccountKeySetupAsync(ctx);
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ import { CredentialsContext } from '../../context';
|
|||||||
import { selectGoogleServiceAccountKeyAsync } from '../utils/googleServiceAccountKey';
|
import { selectGoogleServiceAccountKeyAsync } from '../utils/googleServiceAccountKey';
|
||||||
|
|
||||||
export class UseExistingGoogleServiceAccountKey {
|
export class UseExistingGoogleServiceAccountKey {
|
||||||
constructor(private account: AccountFragment) {}
|
constructor(private readonly account: AccountFragment) {}
|
||||||
|
|
||||||
public async runAsync(ctx: CredentialsContext): Promise<GoogleServiceAccountKeyFragment | null> {
|
public async runAsync(ctx: CredentialsContext): Promise<GoogleServiceAccountKeyFragment | null> {
|
||||||
if (ctx.nonInteractive) {
|
if (ctx.nonInteractive) {
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ export async function deleteKeystoreAsync(
|
|||||||
graphqlClient: ExpoGraphqlClient,
|
graphqlClient: ExpoGraphqlClient,
|
||||||
keystore: AndroidKeystoreFragment
|
keystore: AndroidKeystoreFragment
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return await AndroidKeystoreMutation.deleteAndroidKeystoreAsync(graphqlClient, keystore.id);
|
await AndroidKeystoreMutation.deleteAndroidKeystoreAsync(graphqlClient, keystore.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createFcmAsync(
|
export async function createFcmAsync(
|
||||||
@@ -299,7 +299,7 @@ export async function deleteFcmAsync(
|
|||||||
graphqlClient: ExpoGraphqlClient,
|
graphqlClient: ExpoGraphqlClient,
|
||||||
fcm: AndroidFcmFragment
|
fcm: AndroidFcmFragment
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return await AndroidFcmMutation.deleteAndroidFcmAsync(graphqlClient, fcm.id);
|
await AndroidFcmMutation.deleteAndroidFcmAsync(graphqlClient, fcm.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createGoogleServiceAccountKeyAsync(
|
export async function createGoogleServiceAccountKeyAsync(
|
||||||
@@ -318,7 +318,7 @@ export async function deleteGoogleServiceAccountKeyAsync(
|
|||||||
graphqlClient: ExpoGraphqlClient,
|
graphqlClient: ExpoGraphqlClient,
|
||||||
googleServiceAccountKey: GoogleServiceAccountKeyFragment
|
googleServiceAccountKey: GoogleServiceAccountKeyFragment
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return await GoogleServiceAccountKeyMutation.deleteGoogleServiceAccountKeyAsync(
|
await GoogleServiceAccountKeyMutation.deleteGoogleServiceAccountKeyAsync(
|
||||||
graphqlClient,
|
graphqlClient,
|
||||||
googleServiceAccountKey.id
|
googleServiceAccountKey.id
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -39,37 +39,49 @@ describe('validateKeystore', () => {
|
|||||||
it('validates a correctly formatted jks keystore', async () => {
|
it('validates a correctly formatted jks keystore', async () => {
|
||||||
const keystoreWithType = getKeystoreWithType(testKeystore);
|
const keystoreWithType = getKeystoreWithType(testKeystore);
|
||||||
expect(keystoreWithType.type).toBe(AndroidKeystoreType.Jks);
|
expect(keystoreWithType.type).toBe(AndroidKeystoreType.Jks);
|
||||||
expect(() => validateKeystore(keystoreWithType)).not.toThrow();
|
expect(() => {
|
||||||
|
validateKeystore(keystoreWithType);
|
||||||
|
}).not.toThrow();
|
||||||
});
|
});
|
||||||
it('doesnt validate a jks keystore with wrong alias', async () => {
|
it('doesnt validate a jks keystore with wrong alias', async () => {
|
||||||
const keystoreWithType = getKeystoreWithType({
|
const keystoreWithType = getKeystoreWithType({
|
||||||
...testKeystore,
|
...testKeystore,
|
||||||
keyAlias: 'non-existent-alias',
|
keyAlias: 'non-existent-alias',
|
||||||
});
|
});
|
||||||
expect(() => validateKeystore(keystoreWithType)).toThrow();
|
expect(() => {
|
||||||
|
validateKeystore(keystoreWithType);
|
||||||
|
}).toThrow();
|
||||||
});
|
});
|
||||||
it('doesnt validate a jks keystore with wrong key password', async () => {
|
it('doesnt validate a jks keystore with wrong key password', async () => {
|
||||||
const keystoreWithType = getKeystoreWithType({
|
const keystoreWithType = getKeystoreWithType({
|
||||||
...testKeystore,
|
...testKeystore,
|
||||||
keyPassword: 'not-the-password',
|
keyPassword: 'not-the-password',
|
||||||
});
|
});
|
||||||
expect(() => validateKeystore(keystoreWithType)).toThrow();
|
expect(() => {
|
||||||
|
validateKeystore(keystoreWithType);
|
||||||
|
}).toThrow();
|
||||||
});
|
});
|
||||||
it('validates a correctly formatted pkcs 12 keystore', async () => {
|
it('validates a correctly formatted pkcs 12 keystore', async () => {
|
||||||
const keystoreWithType = getKeystoreWithType(testPKCS12Keystore);
|
const keystoreWithType = getKeystoreWithType(testPKCS12Keystore);
|
||||||
expect(keystoreWithType.type).toBe(AndroidKeystoreType.Pkcs12);
|
expect(keystoreWithType.type).toBe(AndroidKeystoreType.Pkcs12);
|
||||||
expect(() => validateKeystore(keystoreWithType)).not.toThrow();
|
expect(() => {
|
||||||
|
validateKeystore(keystoreWithType);
|
||||||
|
}).not.toThrow();
|
||||||
});
|
});
|
||||||
it('doesnt validate a PKCS 12 keystore with wrong alias', async () => {
|
it('doesnt validate a PKCS 12 keystore with wrong alias', async () => {
|
||||||
const keystoreWithType = getKeystoreWithType({
|
const keystoreWithType = getKeystoreWithType({
|
||||||
...testPKCS12Keystore,
|
...testPKCS12Keystore,
|
||||||
keyAlias: 'non-existent-alias',
|
keyAlias: 'non-existent-alias',
|
||||||
});
|
});
|
||||||
expect(() => validateKeystore(keystoreWithType)).toThrow();
|
expect(() => {
|
||||||
|
validateKeystore(keystoreWithType);
|
||||||
|
}).toThrow();
|
||||||
});
|
});
|
||||||
it('validates an PKCS 12 Keystore with an empty password', async () => {
|
it('validates an PKCS 12 Keystore with an empty password', async () => {
|
||||||
const keystoreWithType = getKeystoreWithType(testPKCS12EmptyPasswordKeystore);
|
const keystoreWithType = getKeystoreWithType(testPKCS12EmptyPasswordKeystore);
|
||||||
expect(keystoreWithType.type).toBe(AndroidKeystoreType.Pkcs12);
|
expect(keystoreWithType.type).toBe(AndroidKeystoreType.Pkcs12);
|
||||||
expect(() => validateKeystore(keystoreWithType)).not.toThrow();
|
expect(() => {
|
||||||
|
validateKeystore(keystoreWithType);
|
||||||
|
}).not.toThrow();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -35,10 +35,10 @@ export class CredentialsContext {
|
|||||||
|
|
||||||
private shouldAskAuthenticateAppStore: boolean = true;
|
private shouldAskAuthenticateAppStore: boolean = true;
|
||||||
|
|
||||||
private projectInfo: CredentialsContextProjectInfo | null;
|
private readonly projectInfo: CredentialsContextProjectInfo | null;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private options: {
|
private readonly options: {
|
||||||
// if null, this implies not running in a project context
|
// if null, this implies not running in a project context
|
||||||
projectInfo: CredentialsContextProjectInfo | null;
|
projectInfo: CredentialsContextProjectInfo | null;
|
||||||
easJsonCliConfig?: EasJson['cli'];
|
easJsonCliConfig?: EasJson['cli'];
|
||||||
@@ -86,7 +86,7 @@ export class CredentialsContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async bestEffortAppStoreAuthenticateAsync(): Promise<void> {
|
async bestEffortAppStoreAuthenticateAsync(): Promise<void> {
|
||||||
if (this.appStore.authCtx || !this.shouldAskAuthenticateAppStore) {
|
if (!!this.appStore.authCtx || !this.shouldAskAuthenticateAppStore) {
|
||||||
// skip prompts if already have apple ctx or already asked about it
|
// skip prompts if already have apple ctx or already asked about it
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ export default class IosCredentialsProvider {
|
|||||||
public readonly platform = Platform.IOS;
|
public readonly platform = Platform.IOS;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private ctx: CredentialsContext,
|
private readonly ctx: CredentialsContext,
|
||||||
private options: Options
|
private readonly options: Options
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async getCredentialsAsync(
|
public async getCredentialsAsync(
|
||||||
@@ -108,7 +108,7 @@ export default class IosCredentialsProvider {
|
|||||||
return null;
|
return null;
|
||||||
} else if (
|
} else if (
|
||||||
ctx.easJsonCliConfig?.promptToConfigurePushNotifications === undefined &&
|
ctx.easJsonCliConfig?.promptToConfigurePushNotifications === undefined &&
|
||||||
!(await isExpoNotificationsInstalled(ctx.projectDir))
|
!isExpoNotificationsInstalled(ctx.projectDir)
|
||||||
) {
|
) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,11 +23,7 @@ jest.mock('../validators/validateProvisioningProfile', () => ({
|
|||||||
_app: any,
|
_app: any,
|
||||||
buildCredentials: Partial<IosAppBuildCredentialsFragment> | null
|
buildCredentials: Partial<IosAppBuildCredentialsFragment> | null
|
||||||
): Promise<boolean> => {
|
): Promise<boolean> => {
|
||||||
return !!(
|
return !!(buildCredentials?.distributionCertificate && buildCredentials.provisioningProfile);
|
||||||
buildCredentials &&
|
|
||||||
buildCredentials.distributionCertificate &&
|
|
||||||
buildCredentials.provisioningProfile
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
jest.mock('../../../project/ios/bundleIdentifier');
|
jest.mock('../../../project/ios/bundleIdentifier');
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ export async function selectAscApiKeysFromAccountAsync(
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return selectAscApiKeysAsync(ascApiKeysForAccount);
|
return await selectAscApiKeysAsync(ascApiKeysForAccount);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function selectAscApiKeysAsync(
|
async function selectAscApiKeysAsync(
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { CredentialsContext } from '../../context';
|
|||||||
import { AppLookupParams } from '../api/graphql/types/AppLookupParams';
|
import { AppLookupParams } from '../api/graphql/types/AppLookupParams';
|
||||||
|
|
||||||
export class AssignAscApiKey {
|
export class AssignAscApiKey {
|
||||||
constructor(private app: AppLookupParams) {}
|
constructor(private readonly app: AppLookupParams) {}
|
||||||
|
|
||||||
public async runAsync(
|
public async runAsync(
|
||||||
ctx: CredentialsContext,
|
ctx: CredentialsContext,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { CredentialsContext } from '../../context';
|
|||||||
import { AppLookupParams } from '../api/graphql/types/AppLookupParams';
|
import { AppLookupParams } from '../api/graphql/types/AppLookupParams';
|
||||||
|
|
||||||
export class AssignPushKey {
|
export class AssignPushKey {
|
||||||
constructor(private app: AppLookupParams) {}
|
constructor(private readonly app: AppLookupParams) {}
|
||||||
|
|
||||||
public async runAsync(
|
public async runAsync(
|
||||||
ctx: CredentialsContext,
|
ctx: CredentialsContext,
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ import { Target } from '../types';
|
|||||||
|
|
||||||
export class ConfigureProvisioningProfile {
|
export class ConfigureProvisioningProfile {
|
||||||
constructor(
|
constructor(
|
||||||
private app: AppLookupParams,
|
private readonly app: AppLookupParams,
|
||||||
private target: Target,
|
private readonly target: Target,
|
||||||
private distributionCertificate: AppleDistributionCertificateFragment,
|
private readonly distributionCertificate: AppleDistributionCertificateFragment,
|
||||||
private originalProvisioningProfile: AppleProvisioningProfileFragment
|
private readonly originalProvisioningProfile: AppleProvisioningProfileFragment
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async runAsync(
|
public async runAsync(
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { AccountFragment, AppStoreConnectApiKeyFragment } from '../../../graphql
|
|||||||
import { CredentialsContext } from '../../context';
|
import { CredentialsContext } from '../../context';
|
||||||
|
|
||||||
export class CreateAscApiKey {
|
export class CreateAscApiKey {
|
||||||
constructor(private account: AccountFragment) {}
|
constructor(private readonly account: AccountFragment) {}
|
||||||
|
|
||||||
public async runAsync(
|
public async runAsync(
|
||||||
ctx: CredentialsContext,
|
ctx: CredentialsContext,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { CredentialsContext } from '../../context';
|
|||||||
import { AppleDistributionCertificateMutationResult } from '../api/graphql/mutations/AppleDistributionCertificateMutation';
|
import { AppleDistributionCertificateMutationResult } from '../api/graphql/mutations/AppleDistributionCertificateMutation';
|
||||||
|
|
||||||
export class CreateDistributionCertificate {
|
export class CreateDistributionCertificate {
|
||||||
constructor(private account: AccountFragment) {}
|
constructor(private readonly account: AccountFragment) {}
|
||||||
|
|
||||||
public async runAsync(
|
public async runAsync(
|
||||||
ctx: CredentialsContext
|
ctx: CredentialsContext
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ import { Target } from '../types';
|
|||||||
|
|
||||||
export class CreateProvisioningProfile {
|
export class CreateProvisioningProfile {
|
||||||
constructor(
|
constructor(
|
||||||
private app: AppLookupParams,
|
private readonly app: AppLookupParams,
|
||||||
private target: Target,
|
private readonly target: Target,
|
||||||
private distributionCertificate: AppleDistributionCertificateFragment
|
private readonly distributionCertificate: AppleDistributionCertificateFragment
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async runAsync(ctx: CredentialsContext): Promise<AppleProvisioningProfileMutationResult> {
|
async runAsync(ctx: CredentialsContext): Promise<AppleProvisioningProfileMutationResult> {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import Log from '../../../log';
|
|||||||
import { CredentialsContext } from '../../context';
|
import { CredentialsContext } from '../../context';
|
||||||
|
|
||||||
export class CreatePushKey {
|
export class CreatePushKey {
|
||||||
constructor(private account: AccountFragment) {}
|
constructor(private readonly account: AccountFragment) {}
|
||||||
|
|
||||||
public async runAsync(ctx: CredentialsContext): Promise<ApplePushKeyFragment> {
|
public async runAsync(ctx: CredentialsContext): Promise<ApplePushKeyFragment> {
|
||||||
if (ctx.nonInteractive) {
|
if (ctx.nonInteractive) {
|
||||||
|
|||||||
@@ -100,17 +100,17 @@ export async function selectDistributionCertificateWithDependenciesAsync(
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!ctx.appStore.authCtx) {
|
if (!ctx.appStore.authCtx) {
|
||||||
return selectDistributionCertificateAsync(distCertsForAccount);
|
return await selectDistributionCertificateAsync(distCertsForAccount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get valid certs on the developer portal
|
// get valid certs on the developer portal
|
||||||
const certInfoFromApple = await ctx.appStore.listDistributionCertificatesAsync();
|
const certInfoFromApple = await ctx.appStore.listDistributionCertificatesAsync();
|
||||||
const validDistCerts = await filterRevokedDistributionCertsFromEasServers(
|
const validDistCerts = filterRevokedDistributionCertsFromEasServers(
|
||||||
distCertsForAccount,
|
distCertsForAccount,
|
||||||
certInfoFromApple
|
certInfoFromApple
|
||||||
);
|
);
|
||||||
|
|
||||||
return selectDistributionCertificateAsync(distCertsForAccount, validDistCerts);
|
return await selectDistributionCertificateAsync(distCertsForAccount, validDistCerts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -129,7 +129,7 @@ export async function selectValidDistributionCertificateAsync(
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!ctx.appStore.authCtx) {
|
if (!ctx.appStore.authCtx) {
|
||||||
return selectDistributionCertificateAsync(distCertsForAccount);
|
return await selectDistributionCertificateAsync(distCertsForAccount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter by apple team
|
// filter by apple team
|
||||||
@@ -148,7 +148,7 @@ export async function selectValidDistributionCertificateAsync(
|
|||||||
Log.log(
|
Log.log(
|
||||||
`${validDistCerts.length}/${distCertsForAccount.length} Distribution Certificates are currently valid for Apple Team ${ctx.appStore.authCtx?.team.id}.`
|
`${validDistCerts.length}/${distCertsForAccount.length} Distribution Certificates are currently valid for Apple Team ${ctx.appStore.authCtx?.team.id}.`
|
||||||
);
|
);
|
||||||
return selectDistributionCertificateAsync(validDistCerts);
|
return await selectDistributionCertificateAsync(validDistCerts);
|
||||||
}
|
}
|
||||||
|
|
||||||
const APPLE_DIST_CERTS_TOO_MANY_GENERATED_ERROR = `
|
const APPLE_DIST_CERTS_TOO_MANY_GENERATED_ERROR = `
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export async function generateProvisioningProfileAsync(
|
|||||||
const appleAuthCtx = await ctx.appStore.ensureAuthenticatedAsync();
|
const appleAuthCtx = await ctx.appStore.ensureAuthenticatedAsync();
|
||||||
const type = appleAuthCtx.team.inHouse ? 'Enterprise ' : 'AppStore';
|
const type = appleAuthCtx.team.inHouse ? 'Enterprise ' : 'AppStore';
|
||||||
const profileName = `*[expo] ${bundleIdentifier} ${type} ${new Date().toISOString()}`; // Apple drops [ if its the first char (!!)
|
const profileName = `*[expo] ${bundleIdentifier} ${type} ${new Date().toISOString()}`; // Apple drops [ if its the first char (!!)
|
||||||
const applePlatform = await getApplePlatformFromTarget(target);
|
const applePlatform = getApplePlatformFromTarget(target);
|
||||||
return await ctx.appStore.createProvisioningProfileAsync(
|
return await ctx.appStore.createProvisioningProfileAsync(
|
||||||
bundleIdentifier,
|
bundleIdentifier,
|
||||||
distCert,
|
distCert,
|
||||||
|
|||||||
@@ -121,11 +121,11 @@ export async function selectPushKeyAsync(
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!ctx.appStore.authCtx) {
|
if (!ctx.appStore.authCtx) {
|
||||||
return selectPushKeysAsync(pushKeysForAccount);
|
return await selectPushKeysAsync(pushKeysForAccount);
|
||||||
}
|
}
|
||||||
|
|
||||||
const validPushKeys = await getValidAndTrackedPushKeysOnEasServersAsync(ctx, pushKeysForAccount);
|
const validPushKeys = await getValidAndTrackedPushKeysOnEasServersAsync(ctx, pushKeysForAccount);
|
||||||
return selectPushKeysAsync(pushKeysForAccount, validPushKeys);
|
return await selectPushKeysAsync(pushKeysForAccount, validPushKeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getValidAndTrackedPushKeysOnEasServersAsync(
|
export async function getValidAndTrackedPushKeysOnEasServersAsync(
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { confirmAsync } from '../../../prompts';
|
|||||||
import { CredentialsContext } from '../../context';
|
import { CredentialsContext } from '../../context';
|
||||||
|
|
||||||
export class SelectAndRemoveAscApiKey {
|
export class SelectAndRemoveAscApiKey {
|
||||||
constructor(private account: AccountFragment) {}
|
constructor(private readonly account: AccountFragment) {}
|
||||||
|
|
||||||
async runAsync(ctx: CredentialsContext): Promise<void> {
|
async runAsync(ctx: CredentialsContext): Promise<void> {
|
||||||
const selected = await selectAscApiKeysFromAccountAsync(ctx, this.account);
|
const selected = await selectAscApiKeysFromAccountAsync(ctx, this.account);
|
||||||
@@ -18,7 +18,7 @@ export class SelectAndRemoveAscApiKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class RemoveAscApiKey {
|
export class RemoveAscApiKey {
|
||||||
constructor(private ascApiKey: AppStoreConnectApiKeyFragment) {}
|
constructor(private readonly ascApiKey: AppStoreConnectApiKeyFragment) {}
|
||||||
|
|
||||||
public async runAsync(ctx: CredentialsContext): Promise<void> {
|
public async runAsync(ctx: CredentialsContext): Promise<void> {
|
||||||
if (ctx.nonInteractive) {
|
if (ctx.nonInteractive) {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { CredentialsContext } from '../../context';
|
|||||||
import { AppLookupParams } from '../api/graphql/types/AppLookupParams';
|
import { AppLookupParams } from '../api/graphql/types/AppLookupParams';
|
||||||
|
|
||||||
export class SelectAndRemoveDistributionCertificate {
|
export class SelectAndRemoveDistributionCertificate {
|
||||||
constructor(private account: AccountFragment) {}
|
constructor(private readonly account: AccountFragment) {}
|
||||||
|
|
||||||
async runAsync(ctx: CredentialsContext): Promise<void> {
|
async runAsync(ctx: CredentialsContext): Promise<void> {
|
||||||
const selected = await selectDistributionCertificateWithDependenciesAsync(ctx, this.account);
|
const selected = await selectDistributionCertificateWithDependenciesAsync(ctx, this.account);
|
||||||
@@ -25,8 +25,8 @@ export class SelectAndRemoveDistributionCertificate {
|
|||||||
|
|
||||||
export class RemoveDistributionCertificate {
|
export class RemoveDistributionCertificate {
|
||||||
constructor(
|
constructor(
|
||||||
private account: AccountFragment,
|
private readonly account: AccountFragment,
|
||||||
private distributionCertificate: AppleDistributionCertificateFragment
|
private readonly distributionCertificate: AppleDistributionCertificateFragment
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async runAsync(ctx: CredentialsContext): Promise<void> {
|
public async runAsync(ctx: CredentialsContext): Promise<void> {
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import { AppLookupParams } from '../api/graphql/types/AppLookupParams';
|
|||||||
|
|
||||||
export class RemoveProvisioningProfiles {
|
export class RemoveProvisioningProfiles {
|
||||||
constructor(
|
constructor(
|
||||||
private apps: AppLookupParams[],
|
private readonly apps: AppLookupParams[],
|
||||||
private provisioningProfiles: AppleProvisioningProfileIdentifiersFragment[]
|
private readonly provisioningProfiles: AppleProvisioningProfileIdentifiersFragment[]
|
||||||
) {
|
) {
|
||||||
assert(
|
assert(
|
||||||
apps.length === provisioningProfiles.length,
|
apps.length === provisioningProfiles.length,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { confirmAsync } from '../../../prompts';
|
|||||||
import { CredentialsContext } from '../../context';
|
import { CredentialsContext } from '../../context';
|
||||||
|
|
||||||
export class SelectAndRemovePushKey {
|
export class SelectAndRemovePushKey {
|
||||||
constructor(private account: AccountFragment) {}
|
constructor(private readonly account: AccountFragment) {}
|
||||||
|
|
||||||
async runAsync(ctx: CredentialsContext): Promise<void> {
|
async runAsync(ctx: CredentialsContext): Promise<void> {
|
||||||
const selected = await selectPushKeyAsync(ctx, this.account);
|
const selected = await selectPushKeyAsync(ctx, this.account);
|
||||||
@@ -18,7 +18,7 @@ export class SelectAndRemovePushKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class RemovePushKey {
|
export class RemovePushKey {
|
||||||
constructor(private pushKey: ApplePushKeyFragment) {}
|
constructor(private readonly pushKey: ApplePushKeyFragment) {}
|
||||||
|
|
||||||
public async runAsync(ctx: CredentialsContext): Promise<void> {
|
public async runAsync(ctx: CredentialsContext): Promise<void> {
|
||||||
if (ctx.nonInteractive) {
|
if (ctx.nonInteractive) {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ interface Options {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class SetUpAdhocProvisioningProfile {
|
export class SetUpAdhocProvisioningProfile {
|
||||||
constructor(private options: Options) {}
|
constructor(private readonly options: Options) {}
|
||||||
|
|
||||||
async runAsync(ctx: CredentialsContext): Promise<IosAppBuildCredentialsFragment> {
|
async runAsync(ctx: CredentialsContext): Promise<IosAppBuildCredentialsFragment> {
|
||||||
const { app } = this.options;
|
const { app } = this.options;
|
||||||
@@ -133,7 +133,7 @@ export class SetUpAdhocProvisioningProfile {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 4. Reuse or create the profile on Apple Developer Portal
|
// 4. Reuse or create the profile on Apple Developer Portal
|
||||||
const applePlatform = await getApplePlatformFromTarget(target);
|
const applePlatform = getApplePlatformFromTarget(target);
|
||||||
const profileType =
|
const profileType =
|
||||||
applePlatform === ApplePlatform.TV_OS
|
applePlatform === ApplePlatform.TV_OS
|
||||||
? ProfileType.TVOS_APP_ADHOC
|
? ProfileType.TVOS_APP_ADHOC
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ export class SetUpAscApiKey {
|
|||||||
];
|
];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private app: AppLookupParams,
|
private readonly app: AppLookupParams,
|
||||||
private purpose: AppStoreApiKeyPurpose
|
private readonly purpose: AppStoreApiKeyPurpose
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async runAsync(ctx: CredentialsContext): Promise<CommonIosAppCredentialsFragment> {
|
public async runAsync(ctx: CredentialsContext): Promise<CommonIosAppCredentialsFragment> {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ interface Options {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class SetUpBuildCredentials {
|
export class SetUpBuildCredentials {
|
||||||
constructor(private options: Options) {}
|
constructor(private readonly options: Options) {}
|
||||||
|
|
||||||
async runAsync(ctx: CredentialsContext): Promise<IosCredentials> {
|
async runAsync(ctx: CredentialsContext): Promise<IosCredentials> {
|
||||||
const hasManyTargets = this.options.targets.length > 1;
|
const hasManyTargets = this.options.targets.length > 1;
|
||||||
|
|||||||
+3
-3
@@ -12,9 +12,9 @@ import { App, Target } from '../types';
|
|||||||
|
|
||||||
export class SetUpBuildCredentialsFromCredentialsJson {
|
export class SetUpBuildCredentialsFromCredentialsJson {
|
||||||
constructor(
|
constructor(
|
||||||
private app: App,
|
private readonly app: App,
|
||||||
private targets: Target[],
|
private readonly targets: Target[],
|
||||||
private distributionType: IosDistributionType
|
private readonly distributionType: IosDistributionType
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async runAsync(ctx: CredentialsContext): Promise<void> {
|
async runAsync(ctx: CredentialsContext): Promise<void> {
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ export class SetUpDistributionCertificate {
|
|||||||
private validDistCerts?: AppleDistributionCertificateFragment[];
|
private validDistCerts?: AppleDistributionCertificateFragment[];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private app: AppLookupParams,
|
private readonly app: AppLookupParams,
|
||||||
private distributionType: IosDistributionType
|
private readonly distributionType: IosDistributionType
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async runAsync(ctx: CredentialsContext): Promise<AppleDistributionCertificateFragment> {
|
public async runAsync(ctx: CredentialsContext): Promise<AppleDistributionCertificateFragment> {
|
||||||
@@ -153,7 +153,7 @@ export class SetUpDistributionCertificate {
|
|||||||
private async createNewDistCertAsync(
|
private async createNewDistCertAsync(
|
||||||
ctx: CredentialsContext
|
ctx: CredentialsContext
|
||||||
): Promise<AppleDistributionCertificateMutationResult> {
|
): Promise<AppleDistributionCertificateMutationResult> {
|
||||||
return new CreateDistributionCertificate(this.app.account).runAsync(ctx);
|
return await new CreateDistributionCertificate(this.app.account).runAsync(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
async reuseDistCertAsync(ctx: CredentialsContext): Promise<AppleDistributionCertificate> {
|
async reuseDistCertAsync(ctx: CredentialsContext): Promise<AppleDistributionCertificate> {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ interface Options {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class SetUpInternalProvisioningProfile {
|
export class SetUpInternalProvisioningProfile {
|
||||||
constructor(private options: Options) {}
|
constructor(private readonly options: Options) {}
|
||||||
|
|
||||||
async runAsync(ctx: CredentialsContext): Promise<IosAppBuildCredentialsFragment> {
|
async runAsync(ctx: CredentialsContext): Promise<IosAppBuildCredentialsFragment> {
|
||||||
const buildCredentials = await getAllBuildCredentialsAsync(ctx, this.options.app);
|
const buildCredentials = await getAllBuildCredentialsAsync(ctx, this.options.app);
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ import { validateProvisioningProfileAsync } from '../validators/validateProvisio
|
|||||||
*/
|
*/
|
||||||
export class SetUpProvisioningProfile {
|
export class SetUpProvisioningProfile {
|
||||||
constructor(
|
constructor(
|
||||||
private app: AppLookupParams,
|
private readonly app: AppLookupParams,
|
||||||
private target: Target,
|
private readonly target: Target,
|
||||||
private distributionType: IosDistributionType
|
private readonly distributionType: IosDistributionType
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async areBuildCredentialsSetupAsync(ctx: CredentialsContext): Promise<boolean> {
|
async areBuildCredentialsSetupAsync(ctx: CredentialsContext): Promise<boolean> {
|
||||||
@@ -128,7 +128,7 @@ export class SetUpProvisioningProfile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// See if the profile we have exists on the Apple Servers
|
// See if the profile we have exists on the Apple Servers
|
||||||
const applePlatform = await getApplePlatformFromTarget(this.target);
|
const applePlatform = getApplePlatformFromTarget(this.target);
|
||||||
const existingProfiles = await ctx.appStore.listProvisioningProfilesAsync(
|
const existingProfiles = await ctx.appStore.listProvisioningProfilesAsync(
|
||||||
this.app.bundleIdentifier,
|
this.app.bundleIdentifier,
|
||||||
applePlatform
|
applePlatform
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import { CredentialsContext } from '../../context';
|
|||||||
import { AppLookupParams } from '../api/graphql/types/AppLookupParams';
|
import { AppLookupParams } from '../api/graphql/types/AppLookupParams';
|
||||||
|
|
||||||
export class SetUpPushKey {
|
export class SetUpPushKey {
|
||||||
constructor(private app: AppLookupParams) {}
|
constructor(private readonly app: AppLookupParams) {}
|
||||||
|
|
||||||
async isPushKeySetupAsync(ctx: CredentialsContext): Promise<boolean> {
|
async isPushKeySetupAsync(ctx: CredentialsContext): Promise<boolean> {
|
||||||
const pushKey = await ctx.ios.getPushKeyForAppAsync(ctx.graphqlClient, this.app);
|
const pushKey = await ctx.ios.getPushKeyForAppAsync(ctx.graphqlClient, this.app);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ interface Options {
|
|||||||
target: Target;
|
target: Target;
|
||||||
}
|
}
|
||||||
export class SetUpTargetBuildCredentials {
|
export class SetUpTargetBuildCredentials {
|
||||||
constructor(private options: Options) {}
|
constructor(private readonly options: Options) {}
|
||||||
|
|
||||||
async runAsync(ctx: CredentialsContext): Promise<IosAppBuildCredentialsFragment> {
|
async runAsync(ctx: CredentialsContext): Promise<IosAppBuildCredentialsFragment> {
|
||||||
const { app, entitlements } = this.options;
|
const { app, entitlements } = this.options;
|
||||||
|
|||||||
Loaded 100 of 203 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user